PostgreSQL MCP server
Last verified: 2026-09
Run SQL against a Postgres database.
Official reference Databases & data Needs a secret Claude Desktop, Cursor, Windsurf, Claude Code, VS Code
What it does
Runs SQL against a Postgres database you pass as a connection string. There is no extra permission layer: if the role can DROP TABLE, the model can too. Create a read-only user first.
It sits in Databases & data: A database MCP is SQL or an API with your credentials.
Good for
- Ask for a SELECT on a staging database with a read-only role.
- Explain a slow query by letting the model read EXPLAIN output.
- Generate a migration from schema the role can see — then you run it.
- Explore tables you do not have memorized, with LIMIT baked into the habit.
Tools
- query — Execute SQL and return rows.
Config (Claude Desktop / Cursor / Windsurf)
Paste the JSON below. Same mcpServers shape. Replace placeholder paths and secrets.
Windows paths look like C:\\Users\\you\\project, not /path/to.
Host-side steps →
Claude Desktop
| OS | Config file |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json
(usually C:\Users\<you>\AppData\Roaming\Claude\) |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Cursor
| Scope | macOS / Linux | Windows |
|---|---|---|
| This project | .cursor/mcp.json in the repo root | |
| This user | ~/.cursor/mcp.json |
%USERPROFILE%\.cursor\mcp.json |
Windsurf
| OS | Config file |
|---|---|
| macOS / Linux | ~/.codeium/windsurf/mcp_config.json |
| Windows | %USERPROFILE%\.codeium\windsurf\mcp_config.json |
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://mcp_ro:pass@localhost/db"
]
}
}
}
Windsurf remote MCP: use serverUrl instead of url if the block below is HTTP.
One-liner: npx -y @modelcontextprotocol/server-postgres postgresql://user:pass@localhost/db
Secrets it wants: DATABASE_URL in the connection string
How to get started
- CREATE USER mcp_ro with a SELECT-only GRANT on the schemas you mean.
- Put that URL in the args (not a superuser URL).
- Ask the model to list tables, then a narrow SELECT, before you let it write.
Access risk
SQL is the access model. A write-capable role is production access. Prompt injection via a webpage the model also has Fetch on can become a query.
When to skip it
Skip it for a local file DB (SQLite) or a hosted Neon/Supabase project that already has its own MCP. Never paste a production owner URL into a chat config.
Vs alternatives
| Server | Official? | Needs a secret? | Best for |
|---|---|---|---|
| PostgreSQL | Yes | Yes | Run SQL against a Postgres database. |
| SQLite | Yes | No | Query a local SQLite file. |
| Neon | No | Yes | Manage and query Neon Postgres. |
| Supabase | No | Yes | Talk to a Supabase project: tables, auth, edge functions. |
More in Databases & data
FAQ
Will it DROP TABLE?
If the role can, yes. There is no extra MCP permission layer. GRANT SELECT only on a copy or replica.
Connection string in mcp.json — is that OK?
It is a secret on disk. Use a least-privilege user, not the owner URL from your password manager.
Postgres or Neon/Supabase?
Postgres if you only need SQL. Vendor servers if you also need branches and project admin.
Does it support migrations?
It runs SQL. It does not own your migration tool. Review anything that writes.