@marcelo-ochoa/server-postgres 0.6.2 → 0.6.3
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.
- package/README.md +86 -10
- package/dist/db.js +41 -4
- package/dist/server.js +1 -1
- package/dist/tools/connect.js +12 -5
- package/dist/tools.js +14 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,10 @@ A Model Context Protocol server that provides read-only access to PostgreSQL dat
|
|
|
21
21
|
|
|
22
22
|
- **pg-connect**
|
|
23
23
|
- Connect to a PostgreSQL database
|
|
24
|
-
-
|
|
24
|
+
- Inputs:
|
|
25
|
+
- `connectionString` (string): The PostgreSQL connection string without credentials (e.g. postgresql://host:port/dbname or host:port/dbname)
|
|
26
|
+
- `user` (string): The PostgreSQL username
|
|
27
|
+
- `password` (string): The PostgreSQL password
|
|
25
28
|
|
|
26
29
|
- **pg-awr**
|
|
27
30
|
- Generate a PostgreSQL performance report similar to Oracle AWR. Includes database statistics, top queries (requires pg_stat_statements extension), table/index statistics, connection info, and optimization recommendations.
|
|
@@ -35,16 +38,45 @@ The server provides schema information for each table in the database:
|
|
|
35
38
|
- Includes column names and data types
|
|
36
39
|
- Automatically discovered from database metadata
|
|
37
40
|
|
|
41
|
+
## Change Log
|
|
42
|
+
|
|
43
|
+
### 2025-11-22
|
|
44
|
+
- **feat**: Implement secure PostgreSQL authentication via environment variables and update tool descriptions
|
|
45
|
+
- Added `PG_USER` and `PG_PASSWORD` environment variables for secure credential management
|
|
46
|
+
- Updated `pg-connect` tool to accept explicit user/password arguments
|
|
47
|
+
- Enhanced tool descriptions for better clarity and documentation
|
|
48
|
+
|
|
49
|
+
### 2025-11-20
|
|
50
|
+
- **feat**: Add initial Postgres server implementation, integrate ModelContextProtocol SDK, and update Oracle tools
|
|
51
|
+
- Complete refactoring of PostgreSQL MCP server
|
|
52
|
+
- Modularized code structure with separate tool handlers
|
|
53
|
+
- Implemented `pg-stats`, `pg-connect`, `pg-explain`, and `pg-awr` tools
|
|
54
|
+
- Renamed query tool to `pg-query` to avoid naming collisions
|
|
55
|
+
- Added Docker image build support for postgres service
|
|
56
|
+
|
|
38
57
|
## Configuration
|
|
39
58
|
|
|
59
|
+
### Authentication
|
|
60
|
+
|
|
61
|
+
The PostgreSQL server uses environment variables for secure credential management:
|
|
62
|
+
|
|
63
|
+
- **`PG_USER`**: PostgreSQL username (required)
|
|
64
|
+
- **`PG_PASSWORD`**: PostgreSQL password (required)
|
|
65
|
+
|
|
66
|
+
The connection string should contain only the host, port, and database information (without embedded credentials).
|
|
67
|
+
|
|
68
|
+
**Supported connection string formats:**
|
|
69
|
+
- `postgresql://host:port/dbname`
|
|
70
|
+
- `host:port/dbname`
|
|
71
|
+
|
|
40
72
|
### Usage with Claude Desktop
|
|
41
73
|
|
|
42
74
|
To use this server with the Claude Desktop app, add the following configuration to the "mcpServers" section of your `claude_desktop_config.json`:
|
|
43
75
|
|
|
44
76
|
### Docker
|
|
45
77
|
|
|
46
|
-
*
|
|
47
|
-
*
|
|
78
|
+
* When running Docker on macOS, use `host.docker.internal` if the PostgreSQL server is running on the host network (e.g., localhost)
|
|
79
|
+
* Credentials are passed via environment variables `PG_USER` and `PG_PASSWORD`
|
|
48
80
|
|
|
49
81
|
```json
|
|
50
82
|
{
|
|
@@ -54,9 +86,12 @@ To use this server with the Claude Desktop app, add the following configuration
|
|
|
54
86
|
"args": [
|
|
55
87
|
"run",
|
|
56
88
|
"-i",
|
|
57
|
-
"--rm",
|
|
89
|
+
"--rm",
|
|
90
|
+
"-e", "PG_USER=myuser",
|
|
91
|
+
"-e", "PG_PASSWORD=mypassword",
|
|
58
92
|
"mochoa/mcp-postgres",
|
|
59
|
-
"postgresql://host.docker.internal:5432/mydb"
|
|
93
|
+
"postgresql://host.docker.internal:5432/mydb"
|
|
94
|
+
]
|
|
60
95
|
}
|
|
61
96
|
}
|
|
62
97
|
}
|
|
@@ -72,8 +107,12 @@ To use this server with the Claude Desktop app, add the following configuration
|
|
|
72
107
|
"args": [
|
|
73
108
|
"-y",
|
|
74
109
|
"@marcelo-ochoa/server-postgres",
|
|
75
|
-
"postgresql://localhost/mydb"
|
|
76
|
-
]
|
|
110
|
+
"postgresql://localhost:5432/mydb"
|
|
111
|
+
],
|
|
112
|
+
"env": {
|
|
113
|
+
"PG_USER": "myuser",
|
|
114
|
+
"PG_PASSWORD": "mypassword"
|
|
115
|
+
}
|
|
77
116
|
}
|
|
78
117
|
}
|
|
79
118
|
}
|
|
@@ -81,6 +120,11 @@ To use this server with the Claude Desktop app, add the following configuration
|
|
|
81
120
|
|
|
82
121
|
Replace `/mydb` with your database name.
|
|
83
122
|
|
|
123
|
+
**Note**: Replace the following placeholders with your actual values:
|
|
124
|
+
- `myuser` and `mypassword` with your PostgreSQL credentials
|
|
125
|
+
- `localhost:5432` with your PostgreSQL server host and port
|
|
126
|
+
- `mydb` with your database name
|
|
127
|
+
|
|
84
128
|
### Usage with VS Code
|
|
85
129
|
|
|
86
130
|
For quick installation, use one of the one-click install buttons below...
|
|
@@ -106,7 +150,18 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
|
|
|
106
150
|
{
|
|
107
151
|
"type": "promptString",
|
|
108
152
|
"id": "pg_url",
|
|
109
|
-
"description": "PostgreSQL URL (e.g. postgresql://
|
|
153
|
+
"description": "PostgreSQL URL (e.g. postgresql://host.docker.internal:5432/mydb)"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"type": "promptString",
|
|
157
|
+
"id": "pg_user",
|
|
158
|
+
"description": "PostgreSQL username"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"type": "promptString",
|
|
162
|
+
"id": "pg_password",
|
|
163
|
+
"description": "PostgreSQL password",
|
|
164
|
+
"password": true
|
|
110
165
|
}
|
|
111
166
|
],
|
|
112
167
|
"servers": {
|
|
@@ -116,6 +171,8 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
|
|
|
116
171
|
"run",
|
|
117
172
|
"-i",
|
|
118
173
|
"--rm",
|
|
174
|
+
"-e", "PG_USER=${input:pg_user}",
|
|
175
|
+
"-e", "PG_PASSWORD=${input:pg_password}",
|
|
119
176
|
"mochoa/mcp-postgres",
|
|
120
177
|
"${input:pg_url}"
|
|
121
178
|
]
|
|
@@ -134,7 +191,18 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
|
|
|
134
191
|
{
|
|
135
192
|
"type": "promptString",
|
|
136
193
|
"id": "pg_url",
|
|
137
|
-
"description": "PostgreSQL URL (e.g. postgresql://
|
|
194
|
+
"description": "PostgreSQL URL (e.g. postgresql://localhost:5432/mydb)"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"type": "promptString",
|
|
198
|
+
"id": "pg_user",
|
|
199
|
+
"description": "PostgreSQL username"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"type": "promptString",
|
|
203
|
+
"id": "pg_password",
|
|
204
|
+
"description": "PostgreSQL password",
|
|
205
|
+
"password": true
|
|
138
206
|
}
|
|
139
207
|
],
|
|
140
208
|
"servers": {
|
|
@@ -144,7 +212,11 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
|
|
|
144
212
|
"-y",
|
|
145
213
|
"@marcelo-ochoa/server-postgres",
|
|
146
214
|
"${input:pg_url}"
|
|
147
|
-
]
|
|
215
|
+
],
|
|
216
|
+
"env": {
|
|
217
|
+
"PG_USER": "${input:pg_user}",
|
|
218
|
+
"PG_PASSWORD": "${input:pg_password}"
|
|
219
|
+
}
|
|
148
220
|
}
|
|
149
221
|
}
|
|
150
222
|
}
|
|
@@ -159,6 +231,10 @@ Docker:
|
|
|
159
231
|
docker build -t mochoa/mcp-postgres -f src/postgres/Dockerfile .
|
|
160
232
|
```
|
|
161
233
|
|
|
234
|
+
## Sources
|
|
235
|
+
|
|
236
|
+
As usual the code of this extension is at [GitHub](https://github.com/marcelo-ochoa/servers), feel free to suggest changes and make contributions, note that I am a beginner developer of React and TypeScript so contributions to make this UI better are welcome.
|
|
237
|
+
|
|
162
238
|
## License
|
|
163
239
|
|
|
164
240
|
This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
|
package/dist/db.js
CHANGED
|
@@ -2,15 +2,52 @@ import pg from "pg";
|
|
|
2
2
|
let pool = undefined;
|
|
3
3
|
let resourceBaseUrl = undefined;
|
|
4
4
|
export async function initializePool(connectionString) {
|
|
5
|
+
const dbUser = process.env.PG_USER;
|
|
6
|
+
const dbPassword = process.env.PG_PASSWORD;
|
|
7
|
+
if (!dbUser || !dbPassword) {
|
|
8
|
+
console.error("Error: Environment variables PG_USER and PG_PASSWORD must be set.");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
// Parse the connection string to extract host, port, and database
|
|
12
|
+
// Expected format: postgresql://host:port/dbname or host:port/dbname
|
|
13
|
+
let host;
|
|
14
|
+
let port;
|
|
15
|
+
let database;
|
|
16
|
+
try {
|
|
17
|
+
// Try parsing as URL first
|
|
18
|
+
if (connectionString.startsWith('postgresql://') || connectionString.startsWith('postgres://')) {
|
|
19
|
+
const url = new URL(connectionString);
|
|
20
|
+
host = url.hostname;
|
|
21
|
+
port = url.port ? parseInt(url.port) : 5432;
|
|
22
|
+
database = url.pathname.slice(1); // Remove leading '/'
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Parse format: host:port/dbname
|
|
26
|
+
const match = connectionString.match(/^([^:]+):(\d+)\/(.+)$/);
|
|
27
|
+
if (!match) {
|
|
28
|
+
throw new Error("Invalid connection string format. Expected: host:port/dbname or postgresql://host:port/dbname");
|
|
29
|
+
}
|
|
30
|
+
host = match[1];
|
|
31
|
+
port = parseInt(match[2]);
|
|
32
|
+
database = match[3];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
console.error("Error parsing connection string:", err);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
5
39
|
pool = new pg.Pool({
|
|
6
|
-
|
|
40
|
+
user: dbUser,
|
|
41
|
+
password: dbPassword,
|
|
42
|
+
host,
|
|
43
|
+
port,
|
|
44
|
+
database,
|
|
7
45
|
});
|
|
8
46
|
// Test connection
|
|
9
47
|
const client = await pool.connect();
|
|
10
48
|
client.release();
|
|
11
|
-
|
|
12
|
-
url
|
|
13
|
-
url.password = "";
|
|
49
|
+
// Build resource base URL without credentials
|
|
50
|
+
const url = new URL(`postgresql://${host}:${port}/${database}`);
|
|
14
51
|
resourceBaseUrl = url;
|
|
15
52
|
}
|
|
16
53
|
export function getPool() {
|
package/dist/server.js
CHANGED
package/dist/tools/connect.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { initializePool, closePool } from "../db.js";
|
|
2
2
|
export const connectHandler = async (request) => {
|
|
3
|
-
const
|
|
4
|
-
|
|
3
|
+
const newConnectionString = request.params.arguments?.connectionString;
|
|
4
|
+
const newUser = request.params.arguments?.user;
|
|
5
|
+
const newPassword = request.params.arguments?.password;
|
|
6
|
+
if (typeof newConnectionString !== "string" || !newConnectionString ||
|
|
7
|
+
typeof newUser !== "string" || !newUser ||
|
|
8
|
+
typeof newPassword !== "string" || !newPassword) {
|
|
5
9
|
return {
|
|
6
|
-
content: [{ type: "text", text: "Missing or invalid connectionString argument." }],
|
|
10
|
+
content: [{ type: "text", text: "Missing or invalid connectionString, user, or password argument." }],
|
|
7
11
|
isError: true,
|
|
8
12
|
};
|
|
9
13
|
}
|
|
10
14
|
try {
|
|
11
15
|
await closePool();
|
|
12
|
-
|
|
16
|
+
// Override env vars for this session
|
|
17
|
+
process.env.PG_USER = newUser;
|
|
18
|
+
process.env.PG_PASSWORD = newPassword;
|
|
19
|
+
await initializePool(newConnectionString);
|
|
13
20
|
return {
|
|
14
|
-
content: [{ type: "text", text: `Successfully connected to Postgres DB: ${
|
|
21
|
+
content: [{ type: "text", text: `Successfully connected to Postgres DB: ${newConnectionString} as user ${newUser}` }],
|
|
15
22
|
isError: false,
|
|
16
23
|
};
|
|
17
24
|
}
|
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const tools = [
|
|
2
2
|
{
|
|
3
3
|
name: "pg-query",
|
|
4
|
-
description: "
|
|
4
|
+
description: "This tool executes SQL queries in a READ ONLY session connected to a PostgreSQL database. If no active connection exists, it uses MCP server registration argument and environment variables PG_USER and PG_PASSWORD.\n\nYou should:\n\n\tExecute the provided SQL query.\n\n\tReturn the results in Toon format.\n\nArgs:\n\n\tsql: The SQL query to execute.\n\n\nThe `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information.\nThe `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.\n\nReturns:\n\n\tJson-formatted query results.\nFor every SQL query you generate, please include a comment at the beginning of the SELECT statement (or other main SQL command) that identifies the LLM model name and version you are using. Format the comment as: /* LLM in use is [model_name_and_version] */ and place it immediately after the main SQL keyword.\nFor example:\n\nSELECT /* LLM in use is claude-sonnet-4 */ column1, column2 FROM table_name;\n\nPlease apply this format consistently to all SQL queries you generate, using your actual model name and version in the comment\n",
|
|
5
5
|
inputSchema: {
|
|
6
6
|
type: "object",
|
|
7
7
|
properties: {
|
|
@@ -25,7 +25,7 @@ export const tools = [
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
name: "pg-stats",
|
|
28
|
-
description: "Get statistics for a specific table",
|
|
28
|
+
description: "Get comprehensive statistics for a specific PostgreSQL table. This tool retrieves detailed information including row counts, table size, index information, column statistics, and other metadata that can help optimize queries and understand data distribution.\n\nArgs:\n\n\tname: The name of the table to get statistics for.\n\n\nThe `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information.\nThe `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.\n\nReturns:\n\n\tJson-formatted table statistics including row counts, size information, indexes, and column details.\n",
|
|
29
29
|
inputSchema: {
|
|
30
30
|
type: "object",
|
|
31
31
|
properties: {
|
|
@@ -49,7 +49,7 @@ export const tools = [
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: "pg-explain",
|
|
52
|
-
description: "
|
|
52
|
+
description: "Generate and display the execution plan for a given SQL query using PostgreSQL's EXPLAIN command. This tool helps you understand how PostgreSQL will execute your query, including information about table scans, joins, indexes used, and estimated costs.\n\nArgs:\n\n\tsql: The SQL query to explain.\n\n\nThe `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information.\nThe `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.\n\nReturns:\n\n\tDetailed execution plan showing how PostgreSQL will process the query, including costs, row estimates, and access methods.\n",
|
|
53
53
|
inputSchema: {
|
|
54
54
|
type: "object",
|
|
55
55
|
properties: {
|
|
@@ -73,13 +73,21 @@ export const tools = [
|
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
name: "pg-connect",
|
|
76
|
-
description: "
|
|
76
|
+
description: "Provides an interface to connect to a specified PostgreSQL database. If a database connection is already active, the tool will close the existing connection before establishing a new one.\n\nThis tool accepts three required parameters:\n\n\tconnectionString: The PostgreSQL connection string without embedded credentials (e.g., postgresql://host:port/dbname or host:port/dbname)\n\tuser: The PostgreSQL username\n\tpassword: The PostgreSQL password\n\nThe credentials are stored in environment variables PG_USER and PG_PASSWORD for the session.\n\nThe `model` argument should only be used to specify the name and version of the LLM (Large Language Model) you are using, with no additional information.\nThe `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.\n",
|
|
77
77
|
inputSchema: {
|
|
78
78
|
type: "object",
|
|
79
79
|
properties: {
|
|
80
80
|
connectionString: {
|
|
81
81
|
type: "string",
|
|
82
|
-
description: "The PostgreSQL connection string (e.g. postgresql://
|
|
82
|
+
description: "The PostgreSQL connection string (e.g. postgresql://host:port/dbname or host:port/dbname)"
|
|
83
|
+
},
|
|
84
|
+
user: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description: "The PostgreSQL user (e.g. postgres)"
|
|
87
|
+
},
|
|
88
|
+
password: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "The PostgreSQL password"
|
|
83
91
|
},
|
|
84
92
|
mcp_client: {
|
|
85
93
|
"type": "string",
|
|
@@ -92,7 +100,7 @@ export const tools = [
|
|
|
92
100
|
"default": "UNKNOWN-LLM"
|
|
93
101
|
}
|
|
94
102
|
},
|
|
95
|
-
required: ["connectionString"]
|
|
103
|
+
required: ["connectionString", "user", "password"]
|
|
96
104
|
},
|
|
97
105
|
},
|
|
98
106
|
{
|