PostgreSQL MCP Server (Local Database)
Connect Claude or Cursor to a local PostgreSQL database via @modelcontextprotocol/server-postgres for read-only schema and query access.
Detailed Explanation
PostgreSQL Server: Read-Only SQL
The Postgres server lets the model inspect your schema (pg_catalog.pg_tables) and run SELECT queries. By design it does not allow INSERT, UPDATE, DELETE, or DDL — the convention is to point it at a read-only role.
Config
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://readonly:secret@localhost:5432/myapp"
]
}
}
}
Creating a read-only role
The connection string passes credentials in the URI, so create a dedicated role rather than reusing your superuser. In psql:
CREATE ROLE mcp_readonly WITH LOGIN PASSWORD 'secret';
GRANT CONNECT ON DATABASE myapp TO mcp_readonly;
GRANT USAGE ON SCHEMA public TO mcp_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;
That last line ensures any tables you add later automatically grant SELECT to the role — otherwise new tables will appear missing in the model's schema dump.
Connection string anatomy
postgresql://USER:PASSWORD@HOST:PORT/DATABASE — the URI scheme. The Postgres server passes this verbatim to libpq, so any standard option (?sslmode=require, ?application_name=claude-mcp) works as a query string suffix.
Safety notes
The connection string is a secret. The generator detects it and surfaces the secret-warning banner — don't commit claude_desktop_config.json to git. For more on rotating credentials, see PostgreSQL read-only setup.
Use Case
Letting the model answer 'how many users signed up in the last week?' or 'show me the schema of the orders table' against a real database during local development, without it being able to drop a table by mistake.