awslabs.postgres-mcp-server 1.0.2__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.
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/Dockerfile +33 -23
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/PKG-INFO +80 -5
- awslabs_postgres_mcp_server-1.0.4/README.md +171 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/awslabs/postgres_mcp_server/__init__.py +1 -1
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/__init__.py +18 -0
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/abstract_db_connection.py +68 -0
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/db_connection_singleton.py +117 -0
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/psycopg_pool_connection.py +287 -0
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/rds_api_connection.py +157 -0
- awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/server.py +323 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/docker-healthcheck.sh +7 -8
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/pyproject.toml +3 -2
- awslabs_postgres_mcp_server-1.0.4/tests/conftest.py +597 -0
- awslabs_postgres_mcp_server-1.0.4/tests/test_psycopg_connector.py +402 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/tests/test_server.py +179 -4
- awslabs_postgres_mcp_server-1.0.4/tests/test_singleton.py +116 -0
- awslabs_postgres_mcp_server-1.0.4/uv-requirements.txt +26 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/uv.lock +707 -456
- awslabs_postgres_mcp_server-1.0.2/README.md +0 -97
- awslabs_postgres_mcp_server-1.0.2/awslabs/postgres_mcp_server/server.py +0 -429
- awslabs_postgres_mcp_server-1.0.2/tests/conftest.py +0 -217
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/.gitignore +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/.python-version +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/CHANGELOG.md +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/LICENSE +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/NOTICE +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/awslabs/__init__.py +0 -0
- {awslabs_postgres_mcp_server-1.0.2 → awslabs_postgres_mcp_server-1.0.4}/awslabs/postgres_mcp_server/mutable_sql_detector.py +0 -0
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
#
|
|
16
|
-
FROM public.ecr.aws/
|
|
15
|
+
# dependabot should continue to update this to the latest hash.
|
|
16
|
+
FROM public.ecr.aws/docker/library/python:3.13.5-alpine3.21@sha256:c9a09c45a4bcc618c7f7128585b8dd0d41d0c31a8a107db4c8255ffe0b69375d AS uv
|
|
17
17
|
|
|
18
18
|
# Install the project into `/app`
|
|
19
19
|
WORKDIR /app
|
|
@@ -31,40 +31,50 @@ ENV UV_PYTHON_PREFERENCE=only-system
|
|
|
31
31
|
ENV UV_FROZEN=true
|
|
32
32
|
|
|
33
33
|
# Copy the required files first
|
|
34
|
-
COPY pyproject.toml uv.lock ./
|
|
34
|
+
COPY pyproject.toml uv.lock uv-requirements.txt ./
|
|
35
|
+
|
|
36
|
+
# Python optimization and uv configuration
|
|
37
|
+
ENV PIP_NO_CACHE_DIR=1 \
|
|
38
|
+
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
39
|
+
|
|
40
|
+
# Install system dependencies and Python package manager
|
|
41
|
+
RUN apk update && \
|
|
42
|
+
apk add --no-cache --virtual .build-deps \
|
|
43
|
+
build-base \
|
|
44
|
+
gcc \
|
|
45
|
+
musl-dev \
|
|
46
|
+
libffi-dev \
|
|
47
|
+
openssl-dev \
|
|
48
|
+
cargo
|
|
35
49
|
|
|
36
50
|
# Install the project's dependencies using the lockfile and settings
|
|
37
51
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
38
|
-
pip install uv
|
|
39
|
-
uv sync --frozen --no-install-project --no-dev --no-editable
|
|
52
|
+
pip install --require-hashes --requirement uv-requirements.txt --no-cache-dir && \
|
|
53
|
+
uv sync --python 3.13 --frozen --no-install-project --no-dev --no-editable
|
|
40
54
|
|
|
41
55
|
# Then, add the rest of the project source code and install it
|
|
42
56
|
# Installing separately from its dependencies allows optimal layer caching
|
|
43
57
|
COPY . /app
|
|
44
58
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
45
|
-
uv sync --frozen --no-dev --no-editable
|
|
59
|
+
uv sync --python 3.13 --frozen --no-dev --no-editable
|
|
46
60
|
|
|
47
61
|
# Make the directory just in case it doesn't exist
|
|
48
62
|
RUN mkdir -p /root/.local
|
|
49
63
|
|
|
50
|
-
FROM public.ecr.aws/
|
|
64
|
+
FROM public.ecr.aws/docker/library/python:3.13.5-alpine3.21@sha256:c9a09c45a4bcc618c7f7128585b8dd0d41d0c31a8a107db4c8255ffe0b69375d
|
|
51
65
|
|
|
52
66
|
# Place executables in the environment at the front of the path and include other binaries
|
|
53
|
-
ENV PATH="/app/.venv/bin:$PATH
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Install
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
chmod o+x /root
|
|
65
|
-
|
|
66
|
-
# Get the project from the uv layer
|
|
67
|
-
COPY --from=uv --chown=app:app /root/.local /root/.local
|
|
67
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
68
|
+
PYTHONUNBUFFERED=1
|
|
69
|
+
|
|
70
|
+
# Install runtime dependencies and create application user
|
|
71
|
+
RUN apk update && \
|
|
72
|
+
apk add --no-cache ca-certificates && \
|
|
73
|
+
update-ca-certificates && \
|
|
74
|
+
addgroup -S app && \
|
|
75
|
+
adduser -S app -G app -h /app
|
|
76
|
+
|
|
77
|
+
# Copy application artifacts from build stage
|
|
68
78
|
COPY --from=uv --chown=app:app /app/.venv /app/.venv
|
|
69
79
|
|
|
70
80
|
# Get healthcheck script
|
|
@@ -74,5 +84,5 @@ COPY ./docker-healthcheck.sh /usr/local/bin/docker-healthcheck.sh
|
|
|
74
84
|
USER app
|
|
75
85
|
|
|
76
86
|
# When running the container, add --db-path and a bind mount to the host's db file
|
|
77
|
-
HEALTHCHECK --interval=
|
|
87
|
+
HEALTHCHECK --interval=60s --timeout=10s --start-period=10s --retries=3 CMD ["docker-healthcheck.sh"]
|
|
78
88
|
ENTRYPOINT ["awslabs.postgres-mcp-server"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.postgres-mcp-server
|
|
3
|
-
Version: 1.0.
|
|
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/
|
|
@@ -24,7 +24,8 @@ Requires-Python: >=3.10
|
|
|
24
24
|
Requires-Dist: boto3>=1.38.5
|
|
25
25
|
Requires-Dist: botocore>=1.38.5
|
|
26
26
|
Requires-Dist: loguru>=0.7.0
|
|
27
|
-
Requires-Dist: mcp[cli]>=1.
|
|
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
|
|
|
@@ -52,10 +53,14 @@ An AWS Labs Model Context Protocol (MCP) server for Aurora Postgres
|
|
|
52
53
|
|
|
53
54
|
## Installation
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
| Cursor | VS Code |
|
|
57
|
+
|:------:|:-------:|
|
|
58
|
+
| [](https://cursor.com/install-mcp?name=awslabs.postgres-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMucG9zdGdyZXMtbWNwLXNlcnZlckBsYXRlc3QgLS1jb25uZWN0aW9uLXN0cmluZyBwb3N0Z3Jlc3FsOi8vW3VzZXJuYW1lXTpbcGFzc3dvcmRdQFtob3N0XTpbcG9ydF0vW2RhdGFiYXNlXSIsImVudiI6eyJGQVNUTUNQX0xPR19MRVZFTCI6IkVSUk9SIn0sImRpc2FibGVkIjpmYWxzZSwiYXV0b0FwcHJvdmUiOltdLCJ0cmFuc3BvcnRUeXBlIjoic3RkaW8iLCJhdXRvU3RhcnQiOnRydWV9) | [](https://insiders.vscode.dev/redirect/mcp/install?name=PostgreSQL%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.postgres-mcp-server%40latest%22%2C%22--connection-string%22%2C%22postgresql%3A%2F%2F%5Busername%5D%3A%5Bpassword%5D%40%5Bhost%5D%3A%5Bport%5D%2F%5Bdatabase%5D%22%5D%2C%22env%22%3A%7B%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%2C%22transportType%22%3A%22stdio%22%2C%22autoStart%22%3Atrue%7D) |
|
|
56
59
|
|
|
57
60
|
Configure the MCP server in your MCP client configuration (e.g., for Amazon Q Developer CLI, edit `~/.aws/amazonq/mcp.json`):
|
|
58
61
|
|
|
62
|
+
### Option 1: Using RDS Data API Connection (for Aurora Postgres)
|
|
63
|
+
|
|
59
64
|
```json
|
|
60
65
|
{
|
|
61
66
|
"mcpServers": {
|
|
@@ -81,6 +86,35 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
|
|
|
81
86
|
}
|
|
82
87
|
```
|
|
83
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
|
+
|
|
84
118
|
### Build and install docker image locally on the same host of your LLM client
|
|
85
119
|
|
|
86
120
|
1. 'git clone https://github.com/awslabs/mcp.git'
|
|
@@ -88,7 +122,10 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
|
|
|
88
122
|
3. Run 'docker build -t awslabs/postgres-mcp-server:latest .'
|
|
89
123
|
|
|
90
124
|
### Add or update your LLM client's config with following:
|
|
91
|
-
|
|
125
|
+
|
|
126
|
+
#### Option 1: Using RDS Data API Connection (for Aurora Postgres)
|
|
127
|
+
|
|
128
|
+
```json
|
|
92
129
|
{
|
|
93
130
|
"mcpServers": {
|
|
94
131
|
"awslabs.postgres-mcp-server": {
|
|
@@ -110,10 +147,48 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
|
|
|
110
147
|
}
|
|
111
148
|
}
|
|
112
149
|
}
|
|
113
|
-
|
|
150
|
+
```
|
|
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.
|
|
114
179
|
|
|
115
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.
|
|
116
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
|
+
|
|
117
192
|
### AWS Authentication
|
|
118
193
|
|
|
119
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.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# AWS Labs postgres MCP Server
|
|
2
|
+
|
|
3
|
+
An AWS Labs Model Context Protocol (MCP) server for Aurora Postgres
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Natural language to Postgres SQL query
|
|
8
|
+
|
|
9
|
+
- Converting human-readable questions and commands into structured Postgres-compatible SQL queries and executing them against the configured Aurora Postgres database.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
|
|
14
|
+
2. Install Python using `uv python install 3.10`
|
|
15
|
+
3. Aurora Postgres Cluster with Postgres username and password stored in AWS Secrets Manager
|
|
16
|
+
4. Enable RDS Data API for your Aurora Postgres Cluster, see [instructions here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html)
|
|
17
|
+
5. This MCP server can only be run locally on the same host as your LLM client.
|
|
18
|
+
6. Docker runtime
|
|
19
|
+
7. Set up AWS credentials with access to AWS services
|
|
20
|
+
- You need an AWS account with appropriate permissions
|
|
21
|
+
- Configure AWS credentials with `aws configure` or environment variables
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
| Cursor | VS Code |
|
|
26
|
+
|:------:|:-------:|
|
|
27
|
+
| [](https://cursor.com/install-mcp?name=awslabs.postgres-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMucG9zdGdyZXMtbWNwLXNlcnZlckBsYXRlc3QgLS1jb25uZWN0aW9uLXN0cmluZyBwb3N0Z3Jlc3FsOi8vW3VzZXJuYW1lXTpbcGFzc3dvcmRdQFtob3N0XTpbcG9ydF0vW2RhdGFiYXNlXSIsImVudiI6eyJGQVNUTUNQX0xPR19MRVZFTCI6IkVSUk9SIn0sImRpc2FibGVkIjpmYWxzZSwiYXV0b0FwcHJvdmUiOltdLCJ0cmFuc3BvcnRUeXBlIjoic3RkaW8iLCJhdXRvU3RhcnQiOnRydWV9) | [](https://insiders.vscode.dev/redirect/mcp/install?name=PostgreSQL%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.postgres-mcp-server%40latest%22%2C%22--connection-string%22%2C%22postgresql%3A%2F%2F%5Busername%5D%3A%5Bpassword%5D%40%5Bhost%5D%3A%5Bport%5D%2F%5Bdatabase%5D%22%5D%2C%22env%22%3A%7B%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%2C%22transportType%22%3A%22stdio%22%2C%22autoStart%22%3Atrue%7D) |
|
|
28
|
+
|
|
29
|
+
Configure the MCP server in your MCP client configuration (e.g., for Amazon Q Developer CLI, edit `~/.aws/amazonq/mcp.json`):
|
|
30
|
+
|
|
31
|
+
### Option 1: Using RDS Data API Connection (for Aurora Postgres)
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"awslabs.postgres-mcp-server": {
|
|
37
|
+
"command": "uvx",
|
|
38
|
+
"args": [
|
|
39
|
+
"awslabs.postgres-mcp-server@latest",
|
|
40
|
+
"--resource_arn", "[your data]",
|
|
41
|
+
"--secret_arn", "[your data]",
|
|
42
|
+
"--database", "[your data]",
|
|
43
|
+
"--region", "[your data]",
|
|
44
|
+
"--readonly", "True"
|
|
45
|
+
],
|
|
46
|
+
"env": {
|
|
47
|
+
"AWS_PROFILE": "your-aws-profile",
|
|
48
|
+
"AWS_REGION": "us-east-1",
|
|
49
|
+
"FASTMCP_LOG_LEVEL": "ERROR"
|
|
50
|
+
},
|
|
51
|
+
"disabled": false,
|
|
52
|
+
"autoApprove": []
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
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
|
+
|
|
87
|
+
### Build and install docker image locally on the same host of your LLM client
|
|
88
|
+
|
|
89
|
+
1. 'git clone https://github.com/awslabs/mcp.git'
|
|
90
|
+
2. Go to sub-directory 'src/postgres-mcp-server/'
|
|
91
|
+
3. Run 'docker build -t awslabs/postgres-mcp-server:latest .'
|
|
92
|
+
|
|
93
|
+
### Add or update your LLM client's config with following:
|
|
94
|
+
|
|
95
|
+
#### Option 1: Using RDS Data API Connection (for Aurora Postgres)
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"awslabs.postgres-mcp-server": {
|
|
101
|
+
"command": "docker",
|
|
102
|
+
"args": [
|
|
103
|
+
"run",
|
|
104
|
+
"-i",
|
|
105
|
+
"--rm",
|
|
106
|
+
"-e", "AWS_ACCESS_KEY_ID=[your data]",
|
|
107
|
+
"-e", "AWS_SECRET_ACCESS_KEY=[your data]",
|
|
108
|
+
"-e", "AWS_REGION=[your data]",
|
|
109
|
+
"awslabs/postgres-mcp-server:latest",
|
|
110
|
+
"--resource_arn", "[your data]",
|
|
111
|
+
"--secret_arn", "[your data]",
|
|
112
|
+
"--database", "[your data]",
|
|
113
|
+
"--region", "[your data]",
|
|
114
|
+
"--readonly", "True"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
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
|
+
|
|
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.
|
|
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
|
+
|
|
161
|
+
### AWS Authentication
|
|
162
|
+
|
|
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.
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
"env": {
|
|
167
|
+
"AWS_PROFILE": "your-aws-profile"
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Make sure the AWS profile has permissions to access the [RDS data API](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html#data-api.access), and the secret from AWS Secrets Manager. The MCP server creates a boto3 session using the specified profile to authenticate with AWS services. Your AWS IAM credentials remain on your local machine and are strictly used for accessing AWS services.
|
|
@@ -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
|
awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/abstract_db_connection.py
ADDED
|
@@ -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
|
awslabs_postgres_mcp_server-1.0.4/awslabs/postgres_mcp_server/connection/db_connection_singleton.py
ADDED
|
@@ -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)}')
|