From 0bc9083d8644e0447caa7d7aeca9b42c0fd7a5ad Mon Sep 17 00:00:00 2001 From: Vrajesh Babu Date: Wed, 15 Oct 2025 20:45:55 +0530 Subject: [PATCH 1/4] mcp-agent-for-postgres --- .../samples/mcp_postgres_agent/README.md | 65 +++++++++++++++++++ .../samples/mcp_postgres_agent/__init__.py | 15 +++++ .../samples/mcp_postgres_agent/agent.py | 60 +++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 contributing/samples/mcp_postgres_agent/README.md create mode 100755 contributing/samples/mcp_postgres_agent/__init__.py create mode 100644 contributing/samples/mcp_postgres_agent/agent.py diff --git a/contributing/samples/mcp_postgres_agent/README.md b/contributing/samples/mcp_postgres_agent/README.md new file mode 100644 index 0000000000..eb93f60981 --- /dev/null +++ b/contributing/samples/mcp_postgres_agent/README.md @@ -0,0 +1,65 @@ +# PostgreSQL MCP Agent + +This agent uses the PostgreSQL MCP server to interact with PostgreSQL databases. It demonstrates how to: +- Connect to a PostgreSQL database using MCP (Model Context Protocol) +- Use `uvx` to run the MCP server without manual installation +- Pass database credentials securely via environment variables + +## Prerequisites + +* **PostgreSQL Database**: You need access to a PostgreSQL database with a connection string +* **uvx**: The agent uses `uvx` (part of the `uv` package manager) to run the MCP server + +## Setup Instructions + +### 1. Configure Database Connection + +Create a `.env` file in the `mcp_postgres_agent` directory: + +```bash +POSTGRES_CONNECTION_STRING=postgresql://user:password@host:port/database +``` + +Example connection string format: +``` +postgresql://username:password@localhost:5432/mydb +postgresql://postgres.xyz:password@aws-region.pooler.supabase.com:5432/postgres +``` + +### 2. Run the Agent + +Start the ADK Web UI from the samples directory: + +```bash +adk web +``` + +The agent will automatically: +- Load the connection string from the `.env` file +- Use `uvx` to run the `postgres-mcp` server with unrestricted access mode +- Connect to your PostgreSQL database + +### 3. Example Queries + +Once the agent is running, try these queries: + +* "What tables are in the database?" +* "Show me the schema for the users table" +* "Query the first 10 rows from the products table" +* "What indexes exist on the orders table?" +* "Create a new table called test_table with columns id and name" + +## Configuration Details + +The agent uses: +- **Model**: Gemini 2.0 Flash +- **MCP Server**: `postgres-mcp` (via `uvx`) +- **Access Mode**: Unrestricted (allows read/write operations) +- **Connection**: StdioConnectionParams with 60-second timeout +- **Environment Variable**: `DATABASE_URI` (mapped from `POSTGRES_CONNECTION_STRING`) + +## Troubleshooting + +- Ensure your `POSTGRES_CONNECTION_STRING` is correctly formatted +- Verify database credentials and network access +- Check that `uv` is installed (`pip install uv` or `brew install uv`) diff --git a/contributing/samples/mcp_postgres_agent/__init__.py b/contributing/samples/mcp_postgres_agent/__init__.py new file mode 100755 index 0000000000..c48963cdc7 --- /dev/null +++ b/contributing/samples/mcp_postgres_agent/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from . import agent diff --git a/contributing/samples/mcp_postgres_agent/agent.py b/contributing/samples/mcp_postgres_agent/agent.py new file mode 100644 index 0000000000..35f8756a73 --- /dev/null +++ b/contributing/samples/mcp_postgres_agent/agent.py @@ -0,0 +1,60 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from dotenv import load_dotenv +from google.adk.models.gemma_llm import Gemma +from google.genai.types import GenerateContentConfig + +from google.adk.agents.llm_agent import LlmAgent +from google.adk.tools.mcp_tool import StdioConnectionParams +from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset +from mcp import StdioServerParameters + +load_dotenv() + +POSTGRES_CONNECTION_STRING = os.getenv("POSTGRES_CONNECTION_STRING") + +root_agent = LlmAgent( + model="gemini-2.0-flash", + name="postgres_agent", + instruction=( + "You are a PostgreSQL database assistant. " + "Use the provided tools to query, manage, and interact with " + "the PostgreSQL database. Ask clarifying questions when unsure." + ), + + tools=[ + MCPToolset( + connection_params=StdioConnectionParams( + server_params=StdioServerParameters( + command='uvx', + args=[ + 'postgres-mcp', + '--access-mode=unrestricted' + ], + env={ + "DATABASE_URI": POSTGRES_CONNECTION_STRING + } + ), + timeout=60, + ), + ) + ], + generate_content_config=GenerateContentConfig( + temperature=1.0, + top_p=0.95, + ) +) From 09a127e06541fffa7dcca33b29da599c45c4498a Mon Sep 17 00:00:00 2001 From: Vrajesh Babu Date: Wed, 15 Oct 2025 20:52:59 +0530 Subject: [PATCH 2/4] Apply code formatting (isort, black) --- .../samples/mcp_postgres_agent/agent.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/contributing/samples/mcp_postgres_agent/agent.py b/contributing/samples/mcp_postgres_agent/agent.py index 35f8756a73..a0544e69eb 100644 --- a/contributing/samples/mcp_postgres_agent/agent.py +++ b/contributing/samples/mcp_postgres_agent/agent.py @@ -15,12 +15,10 @@ import os from dotenv import load_dotenv -from google.adk.models.gemma_llm import Gemma -from google.genai.types import GenerateContentConfig - from google.adk.agents.llm_agent import LlmAgent from google.adk.tools.mcp_tool import StdioConnectionParams from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset +from google.genai.types import GenerateContentConfig from mcp import StdioServerParameters load_dotenv() @@ -35,19 +33,13 @@ "Use the provided tools to query, manage, and interact with " "the PostgreSQL database. Ask clarifying questions when unsure." ), - tools=[ MCPToolset( connection_params=StdioConnectionParams( server_params=StdioServerParameters( - command='uvx', - args=[ - 'postgres-mcp', - '--access-mode=unrestricted' - ], - env={ - "DATABASE_URI": POSTGRES_CONNECTION_STRING - } + command="uvx", + args=["postgres-mcp", "--access-mode=unrestricted"], + env={"DATABASE_URI": POSTGRES_CONNECTION_STRING}, ), timeout=60, ), @@ -56,5 +48,5 @@ generate_content_config=GenerateContentConfig( temperature=1.0, top_p=0.95, - ) + ), ) From 6f20c39093d6b806a5ff6094529bf6089bd5a534 Mon Sep 17 00:00:00 2001 From: Vrajesh Babu Date: Wed, 15 Oct 2025 20:57:05 +0530 Subject: [PATCH 3/4] review-pr-comments --- contributing/samples/mcp_postgres_agent/README.md | 2 +- contributing/samples/mcp_postgres_agent/agent.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/contributing/samples/mcp_postgres_agent/README.md b/contributing/samples/mcp_postgres_agent/README.md index eb93f60981..92095e6102 100644 --- a/contributing/samples/mcp_postgres_agent/README.md +++ b/contributing/samples/mcp_postgres_agent/README.md @@ -54,7 +54,7 @@ Once the agent is running, try these queries: The agent uses: - **Model**: Gemini 2.0 Flash - **MCP Server**: `postgres-mcp` (via `uvx`) -- **Access Mode**: Unrestricted (allows read/write operations) +- **Access Mode**: Unrestricted (allows read/write operations). **Warning**: Using unrestricted mode in a production environment can pose significant security risks. It is recommended to use a more restrictive access mode or configure database user permissions appropriately for production use. - **Connection**: StdioConnectionParams with 60-second timeout - **Environment Variable**: `DATABASE_URI` (mapped from `POSTGRES_CONNECTION_STRING`) diff --git a/contributing/samples/mcp_postgres_agent/agent.py b/contributing/samples/mcp_postgres_agent/agent.py index a0544e69eb..4050a6e532 100644 --- a/contributing/samples/mcp_postgres_agent/agent.py +++ b/contributing/samples/mcp_postgres_agent/agent.py @@ -24,6 +24,11 @@ load_dotenv() POSTGRES_CONNECTION_STRING = os.getenv("POSTGRES_CONNECTION_STRING") +if not POSTGRES_CONNECTION_STRING: + raise ValueError( + "POSTGRES_CONNECTION_STRING environment variable not set. " + "Please create a .env file with this variable." + ) root_agent = LlmAgent( model="gemini-2.0-flash", @@ -46,7 +51,7 @@ ) ], generate_content_config=GenerateContentConfig( - temperature=1.0, + temperature=0.2, top_p=0.95, ), ) From 8d7b42870d7ff70ea090e7332284adec9454a91a Mon Sep 17 00:00:00 2001 From: Vrajesh Babu Date: Fri, 17 Oct 2025 09:28:43 +0530 Subject: [PATCH 4/4] pylink --- contributing/samples/mcp_postgres_agent/agent.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contributing/samples/mcp_postgres_agent/agent.py b/contributing/samples/mcp_postgres_agent/agent.py index 4050a6e532..7298e25004 100644 --- a/contributing/samples/mcp_postgres_agent/agent.py +++ b/contributing/samples/mcp_postgres_agent/agent.py @@ -25,10 +25,10 @@ POSTGRES_CONNECTION_STRING = os.getenv("POSTGRES_CONNECTION_STRING") if not POSTGRES_CONNECTION_STRING: - raise ValueError( - "POSTGRES_CONNECTION_STRING environment variable not set. " - "Please create a .env file with this variable." - ) + raise ValueError( + "POSTGRES_CONNECTION_STRING environment variable not set. " + "Please create a .env file with this variable." + ) root_agent = LlmAgent( model="gemini-2.0-flash",