awslabs.postgres-mcp-server 1.0.3__tar.gz → 1.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/PKG-INFO +73 -1
  2. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/README.md +71 -0
  3. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/awslabs/postgres_mcp_server/__init__.py +1 -1
  4. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/__init__.py +18 -0
  5. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/abstract_db_connection.py +68 -0
  6. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/db_connection_singleton.py +117 -0
  7. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/psycopg_pool_connection.py +287 -0
  8. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/rds_api_connection.py +157 -0
  9. awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/server.py +323 -0
  10. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/pyproject.toml +2 -1
  11. awslabs_postgres_mcp_server-1.0.4/tests/conftest.py +597 -0
  12. awslabs_postgres_mcp_server-1.0.4/tests/test_psycopg_connector.py +402 -0
  13. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/tests/test_server.py +179 -4
  14. awslabs_postgres_mcp_server-1.0.4/tests/test_singleton.py +116 -0
  15. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/uv.lock +488 -447
  16. awslabs_postgres_mcp_server-1.0.3/awslabs/postgres_mcp_server/server.py +0 -429
  17. awslabs_postgres_mcp_server-1.0.3/tests/conftest.py +0 -217
  18. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/.gitignore +0 -0
  19. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/.python-version +0 -0
  20. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/CHANGELOG.md +0 -0
  21. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/Dockerfile +0 -0
  22. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/LICENSE +0 -0
  23. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/NOTICE +0 -0
  24. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/awslabs/__init__.py +0 -0
  25. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/awslabs/postgres_mcp_server/mutable_sql_detector.py +0 -0
  26. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/docker-healthcheck.sh +0 -0
  27. {awslabs_postgres_mcp_server-1.0.3 → awslabs_postgres_mcp_server-1.0.4}/uv-requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awslabs.postgres-mcp-server
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: An AWS Labs Model Context Protocol (MCP) server for postgres
5
5
  Project-URL: homepage, https://awslabs.github.io/mcp/
6
6
  Project-URL: docs, https://awslabs.github.io/mcp/servers/postgres-mcp-server/
@@ -25,6 +25,7 @@ Requires-Dist: boto3>=1.38.5
25
25
  Requires-Dist: botocore>=1.38.5
26
26
  Requires-Dist: loguru>=0.7.0
27
27
  Requires-Dist: mcp[cli]>=1.11.0
28
+ Requires-Dist: psycopg[pool]>=3.1.12
28
29
  Requires-Dist: pydantic>=2.10.6
29
30
  Description-Content-Type: text/markdown
30
31
 
@@ -58,6 +59,8 @@ An AWS Labs Model Context Protocol (MCP) server for Aurora Postgres
58
59
 
59
60
  Configure the MCP server in your MCP client configuration (e.g., for Amazon Q Developer CLI, edit `~/.aws/amazonq/mcp.json`):
60
61
 
62
+ ### Option 1: Using RDS Data API Connection (for Aurora Postgres)
63
+
61
64
  ```json
62
65
  {
63
66
  "mcpServers": {
@@ -83,6 +86,35 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
83
86
  }
84
87
  ```
85
88
 
89
+ ### Option 2: Using Direct PostgreSQL(psycopg) Connection (for Aurora Postgres and RDS Postgres)
90
+
91
+ ```json
92
+ {
93
+ "mcpServers": {
94
+ "awslabs.postgres-mcp-server": {
95
+ "command": "uvx",
96
+ "args": [
97
+ "awslabs.postgres-mcp-server@latest",
98
+ "--hostname", "[your data]",
99
+ "--secret_arn", "[your data]",
100
+ "--database", "[your data]",
101
+ "--region", "[your data]",
102
+ "--readonly", "True"
103
+ ],
104
+ "env": {
105
+ "AWS_PROFILE": "your-aws-profile",
106
+ "AWS_REGION": "us-east-1",
107
+ "FASTMCP_LOG_LEVEL": "ERROR"
108
+ },
109
+ "disabled": false,
110
+ "autoApprove": []
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ Note: The `--port` parameter is optional and defaults to 5432 (the standard PostgreSQL port). You only need to specify it if your PostgreSQL instance uses a non-standard port.
117
+
86
118
  ### Build and install docker image locally on the same host of your LLM client
87
119
 
88
120
  1. 'git clone https://github.com/awslabs/mcp.git'
@@ -91,6 +123,8 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
91
123
 
92
124
  ### Add or update your LLM client's config with following:
93
125
 
126
+ #### Option 1: Using RDS Data API Connection (for Aurora Postgres)
127
+
94
128
  ```json
95
129
  {
96
130
  "mcpServers": {
@@ -115,8 +149,46 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
115
149
  }
116
150
  ```
117
151
 
152
+ #### Option 2: Using Direct PostgreSQL (psycopg) Connection (for Aurora Postgres and RDS Postgres)
153
+
154
+ ```
155
+ {
156
+ "mcpServers": {
157
+ "awslabs.postgres-mcp-server": {
158
+ "command": "docker",
159
+ "args": [
160
+ "run",
161
+ "-i",
162
+ "--rm",
163
+ "-e", "AWS_ACCESS_KEY_ID=[your data]",
164
+ "-e", "AWS_SECRET_ACCESS_KEY=[your data]",
165
+ "-e", "AWS_REGION=[your data]",
166
+ "awslabs/postgres-mcp-server:latest",
167
+ "--hostname", "[your data]",
168
+ "--secret_arn", "[your data]",
169
+ "--database", "[your data]",
170
+ "--region", "[your data]",
171
+ "--readonly", "True"
172
+ ]
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ Note: The `--port` parameter is optional and defaults to 5432 (the standard PostgreSQL port). You only need to specify it if your PostgreSQL instance uses a non-standard port.
179
+
118
180
  NOTE: By default, only read-only queries are allowed and it is controlled by --readonly parameter above. Set it to False if you also want to allow writable DML or DDL.
119
181
 
182
+ ## Connection Methods
183
+
184
+ This MCP server supports two connection methods:
185
+
186
+ 1. **RDS Data API Connection** (using `--resource_arn`): Uses the AWS RDS Data API to connect to Aurora PostgreSQL. This method requires that your Aurora cluster has the Data API enabled.
187
+
188
+ 2. **Direct PostgreSQL Connection** (using `--hostname`): Uses psycopg to connect directly to any PostgreSQL database, including Aurora PostgreSQL, RDS PostgreSQL, or self-hosted PostgreSQL instances. This method provides better performance for frequent queries but requires direct network access to the database.
189
+
190
+ Choose the connection method that best fits your environment and requirements.
191
+
120
192
  ### AWS Authentication
121
193
 
122
194
  The MCP server uses the AWS profile specified in the `AWS_PROFILE` environment variable. If not provided, it defaults to the "default" profile in your AWS configuration file.
@@ -28,6 +28,8 @@ An AWS Labs Model Context Protocol (MCP) server for Aurora Postgres
28
28
 
29
29
  Configure the MCP server in your MCP client configuration (e.g., for Amazon Q Developer CLI, edit `~/.aws/amazonq/mcp.json`):
30
30
 
31
+ ### Option 1: Using RDS Data API Connection (for Aurora Postgres)
32
+
31
33
  ```json
32
34
  {
33
35
  "mcpServers": {
@@ -53,6 +55,35 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
53
55
  }
54
56
  ```
55
57
 
58
+ ### Option 2: Using Direct PostgreSQL(psycopg) Connection (for Aurora Postgres and RDS Postgres)
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "awslabs.postgres-mcp-server": {
64
+ "command": "uvx",
65
+ "args": [
66
+ "awslabs.postgres-mcp-server@latest",
67
+ "--hostname", "[your data]",
68
+ "--secret_arn", "[your data]",
69
+ "--database", "[your data]",
70
+ "--region", "[your data]",
71
+ "--readonly", "True"
72
+ ],
73
+ "env": {
74
+ "AWS_PROFILE": "your-aws-profile",
75
+ "AWS_REGION": "us-east-1",
76
+ "FASTMCP_LOG_LEVEL": "ERROR"
77
+ },
78
+ "disabled": false,
79
+ "autoApprove": []
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ Note: The `--port` parameter is optional and defaults to 5432 (the standard PostgreSQL port). You only need to specify it if your PostgreSQL instance uses a non-standard port.
86
+
56
87
  ### Build and install docker image locally on the same host of your LLM client
57
88
 
58
89
  1. 'git clone https://github.com/awslabs/mcp.git'
@@ -61,6 +92,8 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
61
92
 
62
93
  ### Add or update your LLM client's config with following:
63
94
 
95
+ #### Option 1: Using RDS Data API Connection (for Aurora Postgres)
96
+
64
97
  ```json
65
98
  {
66
99
  "mcpServers": {
@@ -85,8 +118,46 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
85
118
  }
86
119
  ```
87
120
 
121
+ #### Option 2: Using Direct PostgreSQL (psycopg) Connection (for Aurora Postgres and RDS Postgres)
122
+
123
+ ```
124
+ {
125
+ "mcpServers": {
126
+ "awslabs.postgres-mcp-server": {
127
+ "command": "docker",
128
+ "args": [
129
+ "run",
130
+ "-i",
131
+ "--rm",
132
+ "-e", "AWS_ACCESS_KEY_ID=[your data]",
133
+ "-e", "AWS_SECRET_ACCESS_KEY=[your data]",
134
+ "-e", "AWS_REGION=[your data]",
135
+ "awslabs/postgres-mcp-server:latest",
136
+ "--hostname", "[your data]",
137
+ "--secret_arn", "[your data]",
138
+ "--database", "[your data]",
139
+ "--region", "[your data]",
140
+ "--readonly", "True"
141
+ ]
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ Note: The `--port` parameter is optional and defaults to 5432 (the standard PostgreSQL port). You only need to specify it if your PostgreSQL instance uses a non-standard port.
148
+
88
149
  NOTE: By default, only read-only queries are allowed and it is controlled by --readonly parameter above. Set it to False if you also want to allow writable DML or DDL.
89
150
 
151
+ ## Connection Methods
152
+
153
+ This MCP server supports two connection methods:
154
+
155
+ 1. **RDS Data API Connection** (using `--resource_arn`): Uses the AWS RDS Data API to connect to Aurora PostgreSQL. This method requires that your Aurora cluster has the Data API enabled.
156
+
157
+ 2. **Direct PostgreSQL Connection** (using `--hostname`): Uses psycopg to connect directly to any PostgreSQL database, including Aurora PostgreSQL, RDS PostgreSQL, or self-hosted PostgreSQL instances. This method provides better performance for frequent queries but requires direct network access to the database.
158
+
159
+ Choose the connection method that best fits your environment and requirements.
160
+
90
161
  ### AWS Authentication
91
162
 
92
163
  The MCP server uses the AWS profile specified in the `AWS_PROFILE` environment variable. If not provided, it defaults to the "default" profile in your AWS configuration file.
@@ -14,4 +14,4 @@
14
14
 
15
15
  """awslabs.postgres-mcp-server"""
16
16
 
17
- __version__ = '0.0.4'
17
+ __version__ = '1.0.4'
@@ -0,0 +1,18 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """aws.postgres-mcp-server.connection"""
16
+
17
+ from awslabs.postgres_mcp_server.connection.db_connection_singleton import DBConnectionSingleton
18
+ from awslabs.postgres_mcp_server.connection.abstract_db_connection import AbstractDBConnection
@@ -0,0 +1,68 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Abstract database connection interface for postgres MCP Server."""
16
+
17
+ from abc import ABC, abstractmethod
18
+ from typing import Any, Dict, List, Optional
19
+
20
+
21
+ class AbstractDBConnection(ABC):
22
+ """Abstract base class for database connections."""
23
+
24
+ def __init__(self, readonly: bool):
25
+ """Initialize the database connection.
26
+
27
+ Args:
28
+ readonly: Whether the connection should be read-only
29
+ """
30
+ self._readonly = readonly
31
+
32
+ @property
33
+ def readonly_query(self) -> bool:
34
+ """Get whether this connection is read-only.
35
+
36
+ Returns:
37
+ bool: True if the connection is read-only, False otherwise
38
+ """
39
+ return self._readonly
40
+
41
+ @abstractmethod
42
+ async def execute_query(
43
+ self, sql: str, parameters: Optional[List[Dict[str, Any]]] = None
44
+ ) -> Dict[str, Any]:
45
+ """Execute a SQL query.
46
+
47
+ Args:
48
+ sql: The SQL query to execute
49
+ parameters: Optional parameters for the query
50
+
51
+ Returns:
52
+ Dict containing query results with column metadata and records
53
+ """
54
+ pass
55
+
56
+ @abstractmethod
57
+ async def close(self) -> None:
58
+ """Close the database connection."""
59
+ pass
60
+
61
+ @abstractmethod
62
+ async def check_connection_health(self) -> bool:
63
+ """Check if the database connection is healthy.
64
+
65
+ Returns:
66
+ bool: True if the connection is healthy, False otherwise
67
+ """
68
+ pass
@@ -0,0 +1,117 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Database connection singleton for postgres MCP Server."""
16
+
17
+ import asyncio
18
+ from awslabs.postgres_mcp_server.connection.rds_api_connection import RDSDataAPIConnection
19
+ from loguru import logger
20
+
21
+
22
+ class DBConnectionSingleton:
23
+ """Manages a single RDS Data API connection instance across the application."""
24
+
25
+ _instance = None
26
+
27
+ def __init__(
28
+ self,
29
+ resource_arn: str,
30
+ secret_arn: str,
31
+ database: str,
32
+ region: str,
33
+ readonly: bool = True,
34
+ is_test: bool = False,
35
+ ):
36
+ """Initialize a new DB connection singleton for RDS Data API.
37
+
38
+ Args:
39
+ resource_arn: The ARN of the RDS cluster
40
+ secret_arn: The ARN of the secret containing credentials
41
+ database: The name of the database to connect to
42
+ region: The AWS region where the RDS instance is located
43
+ readonly: Whether the connection should be read-only (default: True)
44
+ is_test: Whether this is a test connection (default: False)
45
+ """
46
+ if not all([resource_arn, secret_arn, database, region]):
47
+ raise ValueError(
48
+ 'Missing required connection parameters for RDS Data API. '
49
+ 'Please provide resource_arn, secret_arn, database, and region.'
50
+ )
51
+
52
+ self._db_connection = RDSDataAPIConnection(
53
+ cluster_arn=resource_arn,
54
+ secret_arn=secret_arn,
55
+ database=database,
56
+ region=region,
57
+ readonly=readonly,
58
+ is_test=is_test,
59
+ )
60
+
61
+ @classmethod
62
+ def initialize(
63
+ cls,
64
+ resource_arn: str,
65
+ secret_arn: str,
66
+ database: str,
67
+ region: str,
68
+ readonly: bool = True,
69
+ is_test: bool = False,
70
+ ):
71
+ """Initialize the singleton instance if it doesn't exist.
72
+
73
+ Args:
74
+ resource_arn: The ARN of the RDS cluster
75
+ secret_arn: The ARN of the secret containing credentials
76
+ database: The name of the database to connect to
77
+ region: The AWS region where the RDS instance is located
78
+ readonly: Whether the connection should be read-only (default: True)
79
+ is_test: Whether this is a test connection (default: False)
80
+ """
81
+ if cls._instance is None:
82
+ cls._instance = cls(
83
+ resource_arn=resource_arn,
84
+ secret_arn=secret_arn,
85
+ database=database,
86
+ region=region,
87
+ readonly=readonly,
88
+ is_test=is_test,
89
+ )
90
+
91
+ @classmethod
92
+ def get(cls):
93
+ """Get the singleton instance."""
94
+ if cls._instance is None:
95
+ raise RuntimeError('DBConnectionSingleton is not initialized.')
96
+ return cls._instance
97
+
98
+ @property
99
+ def db_connection(self):
100
+ """Get the database connection."""
101
+ return self._db_connection
102
+
103
+ @classmethod
104
+ def cleanup(cls):
105
+ """Clean up resources when shutting down."""
106
+ if cls._instance and cls._instance._db_connection:
107
+ # Handle calling async close method from sync context
108
+ try:
109
+ loop = asyncio.get_event_loop()
110
+ if loop.is_running():
111
+ # If we're in an async context, create a task
112
+ asyncio.create_task(cls._instance._db_connection.close())
113
+ else:
114
+ # If we're in a sync context, run the coroutine to completion
115
+ loop.run_until_complete(cls._instance._db_connection.close())
116
+ except Exception as e:
117
+ logger.error(f'Error during connection cleanup: {str(e)}')