pg-mcp-for-devs 1.0.0
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 +75 -0
- package/dist/index.js +124 -0
- package/examples/claude-code/mcp.json +12 -0
- package/examples/copilot/mcp.json +20 -0
- package/examples/cursor/mcp.json +11 -0
- package/examples/windsurf/mcp_config.json +11 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# pg-mcp-for-devs
|
|
2
|
+
|
|
3
|
+
Postgres MCP server for developers. **Unlike the official server, this allows arbitrary read/write SQL execution** — not just read-only queries.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
- `execute_sql` — run any SQL (SELECT / INSERT / UPDATE / DELETE / DDL)
|
|
8
|
+
- `list_tables` — list tables in `public`
|
|
9
|
+
- `describe_table` — columns, types, nullability, defaults
|
|
10
|
+
|
|
11
|
+
## Quick setup
|
|
12
|
+
|
|
13
|
+
Copy the example for your client from [`examples/`](./examples), set `DATABASE_URL`, and reload the MCP servers.
|
|
14
|
+
|
|
15
|
+
Requires Node 18+.
|
|
16
|
+
|
|
17
|
+
### Cursor
|
|
18
|
+
|
|
19
|
+
Copy [`examples/cursor/mcp.json`](./examples/cursor/mcp.json) to:
|
|
20
|
+
|
|
21
|
+
- Project: `.cursor/mcp.json`
|
|
22
|
+
- Global: `~/.cursor/mcp.json`
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"pg-mcp-for-devs": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "pg-mcp-for-devs"],
|
|
30
|
+
"env": {
|
|
31
|
+
"DATABASE_URL": "postgresql://user:password@localhost:5432/mydb"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Claude Code
|
|
39
|
+
|
|
40
|
+
Copy [`examples/claude-code/mcp.json`](./examples/claude-code/mcp.json) to project-root `.mcp.json` (or merge into `~/.claude.json`).
|
|
41
|
+
|
|
42
|
+
Set `DATABASE_URL` in your shell / environment — the example expands `${DATABASE_URL}`.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
export DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
claude mcp add --scope project --env DATABASE_URL="$DATABASE_URL" -- npx -y pg-mcp-for-devs
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### GitHub Copilot (VS Code)
|
|
55
|
+
|
|
56
|
+
Copy [`examples/copilot/mcp.json`](./examples/copilot/mcp.json) to `.vscode/mcp.json`.
|
|
57
|
+
|
|
58
|
+
Note: Copilot uses the top-level key **`servers`** (not `mcpServers`). On first start, VS Code prompts for `DATABASE_URL`.
|
|
59
|
+
|
|
60
|
+
### Windsurf
|
|
61
|
+
|
|
62
|
+
Merge [`examples/windsurf/mcp_config.json`](./examples/windsurf/mcp_config.json) into:
|
|
63
|
+
|
|
64
|
+
- macOS / Linux: `~/.codeium/windsurf/mcp_config.json`
|
|
65
|
+
- Windows: `%USERPROFILE%\.codeium\windsurf\mcp_config.json`
|
|
66
|
+
|
|
67
|
+
Then refresh MCP in Cascade → Manage MCPs.
|
|
68
|
+
|
|
69
|
+
## Security note
|
|
70
|
+
|
|
71
|
+
`execute_sql` can run any SQL, including writes and DDL. Use against databases you trust, preferably with a least-privilege DB user.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
ISC
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
7
|
+
const pg_1 = require("pg");
|
|
8
|
+
// 初始化数据库连接
|
|
9
|
+
const pool = new pg_1.Pool({
|
|
10
|
+
connectionString: process.env.DATABASE_URL,
|
|
11
|
+
});
|
|
12
|
+
const server = new index_js_1.Server({
|
|
13
|
+
name: "pg-mcp-for-devs",
|
|
14
|
+
version: "1.0.0",
|
|
15
|
+
}, {
|
|
16
|
+
capabilities: {
|
|
17
|
+
tools: {},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
// 注册 3 个核心工具:执行SQL、列出表、查看表结构
|
|
21
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
22
|
+
return {
|
|
23
|
+
tools: [
|
|
24
|
+
{
|
|
25
|
+
name: "execute_sql",
|
|
26
|
+
description: "Execute arbitrary read/write SQL queries against the local Postgres database. Supports DDL, DML, DQL.",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
query: { type: "string", description: "The SQL query to execute" },
|
|
31
|
+
params: {
|
|
32
|
+
type: "array",
|
|
33
|
+
description: "Optional query parameters",
|
|
34
|
+
items: {} // 使用空对象,在 JSON Schema 中代表允许任何类型
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
required: ["query"],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "list_tables",
|
|
42
|
+
description: "List all tables in the public schema of the database.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "describe_table",
|
|
50
|
+
description: "Get the schema (columns, data types, constraints) for a specific table.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
table_name: { type: "string", description: "The name of the table to describe" },
|
|
55
|
+
},
|
|
56
|
+
required: ["table_name"],
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
// 处理工具调用
|
|
63
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
64
|
+
const { name, arguments: args } = request.params;
|
|
65
|
+
try {
|
|
66
|
+
if (name === "execute_sql") {
|
|
67
|
+
const { query, params } = args;
|
|
68
|
+
const result = await pool.query(query, params || []);
|
|
69
|
+
return {
|
|
70
|
+
content: [{
|
|
71
|
+
type: "text",
|
|
72
|
+
text: JSON.stringify(result.rows.length ? result.rows : { success: true, rowCount: result.rowCount }, null, 2)
|
|
73
|
+
}],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (name === "list_tables") {
|
|
77
|
+
const query = `
|
|
78
|
+
SELECT table_name
|
|
79
|
+
FROM information_schema.tables
|
|
80
|
+
WHERE table_schema = 'public'
|
|
81
|
+
ORDER BY table_name;
|
|
82
|
+
`;
|
|
83
|
+
const result = await pool.query(query);
|
|
84
|
+
const tables = result.rows.map(r => r.table_name);
|
|
85
|
+
return {
|
|
86
|
+
content: [{ type: "text", text: JSON.stringify({ tables }, null, 2) }],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (name === "describe_table") {
|
|
90
|
+
const { table_name } = args;
|
|
91
|
+
const query = `
|
|
92
|
+
SELECT
|
|
93
|
+
column_name,
|
|
94
|
+
data_type,
|
|
95
|
+
is_nullable,
|
|
96
|
+
column_default,
|
|
97
|
+
character_maximum_length
|
|
98
|
+
FROM information_schema.columns
|
|
99
|
+
WHERE table_schema = 'public' AND table_name = $1
|
|
100
|
+
ORDER BY ordinal_position;
|
|
101
|
+
`;
|
|
102
|
+
const result = await pool.query(query, [table_name]);
|
|
103
|
+
if (result.rows.length === 0) {
|
|
104
|
+
return { content: [{ type: "text", text: `Table '${table_name}' not found or has no columns.` }] };
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
content: [{ type: "text", text: JSON.stringify(result.rows, null, 2) }],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
throw new Error(`Tool ${name} not found`);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
return {
|
|
114
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
115
|
+
isError: true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
async function main() {
|
|
120
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
121
|
+
await server.connect(transport);
|
|
122
|
+
console.error("Local Postgres MCP Server running with schema awareness...");
|
|
123
|
+
}
|
|
124
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputs": [
|
|
3
|
+
{
|
|
4
|
+
"type": "promptString",
|
|
5
|
+
"id": "database_url",
|
|
6
|
+
"description": "Postgres connection string (DATABASE_URL)",
|
|
7
|
+
"password": true
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"servers": {
|
|
11
|
+
"pg-mcp-for-devs": {
|
|
12
|
+
"type": "stdio",
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "pg-mcp-for-devs"],
|
|
15
|
+
"env": {
|
|
16
|
+
"DATABASE_URL": "${input:database_url}"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pg-mcp-for-devs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Postgres MCP server with full read/write SQL — list tables, describe schema, execute arbitrary queries",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"README.md",
|
|
9
|
+
"examples"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"pg-mcp-for-devs": "dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"type": "commonjs",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"mcp-server",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"postgres",
|
|
24
|
+
"postgresql",
|
|
25
|
+
"postgres-mcp",
|
|
26
|
+
"sql",
|
|
27
|
+
"cursor",
|
|
28
|
+
"read-write"
|
|
29
|
+
],
|
|
30
|
+
"author": "devandy1024",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
37
|
+
"pg": "^8.23.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^26.4.1",
|
|
41
|
+
"@types/pg": "^8.23.1",
|
|
42
|
+
"tsx": "^4.23.13",
|
|
43
|
+
"typescript": "^7.0.2"
|
|
44
|
+
}
|
|
45
|
+
}
|