Read-only Postgres: drop-in for the archived server-postgres, with schema context.
MCPpedia last refreshed this data
io.github.contextflo/postgres-mcp is an MCP server that read-only Postgres: drop-in for the archived server-postgres, with schema context. Its tool list has not been published yet over stdio, sse and http, requires no API key, and scores 59/100 on MCPpedia's security, maintenance and efficiency rubric.
Config is the same across clients - only the file and path differ.
{
"mcpServers": {
"postgres": {
"env": {
"DATABASE_URL": "postgresql://mcp_readonly:change-me@db.example.com:5432/mydb"
},
"args": [
"-y",
"@contextflo/postgres-mcp",
"--context-file",
"/path/to/project/.contextflo/context.md"
],
"command": "npx"
}
}
}Are you the author?
Add this badge to your README to show your security score and help users find safe servers.
Read-only Postgres: drop-in for the archived server-postgres, with schema context.
This server supports HTTP transport. Be the first to test it - help the community know if it works.
Five weighted categories - click any category to see the underlying evidence.
No known CVEs.
Checked @contextflo/postgres-mcp against OSV.dev.
Be the first to review
Have you used this server?
Share your experience - it helps other developers decide.
Sign in to write a review.
Others in data
Token-efficient database MCP server for PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite
Manage Supabase projects — databases, auth, storage, and edge functions
A cross-platform desktop application for managing AI Agents and MCP Servers. 一款用于管理AI智能体与MCP服务器的跨平台桌面应用程序。
Extract data from any website with thousands of scrapers, crawlers, and automations on Apify Store ⚡
MCP Security Weekly
Get CVE alerts and security updates for io.github.contextflo/postgres-mcp and similar servers.
Start a conversation
Ask a question, share a tip, or report an issue.
Sign in to join the discussion.
The analytics MCP server for Postgres. Read-only by construction, with a context file you and the agent both write to, so the model answers the way your team would.
Built and maintained by Contextflo.
A drop-in replacement for the archived @modelcontextprotocol/server-postgres, which shipped with a
SQL injection vulnerability
that let COMMIT; DROP SCHEMA public CASCADE walk straight out of its read-only transaction.
Watch the 100-second demo: setup, the
agent working out that an events table is not what it looks like and saving that as a note, and a DROP the server
refuses.
npx @contextflo/postgres-mcp postgresql://localhost/mydb
Read-only that holds up. The archived server enforced read-only as a property of the SQL string. Here it is a property of the wire protocol, the connection, the Postgres parser, and the database role: four independent layers, each of which stops that payload on its own. The exploit is a test case in this repo.
Answers that make sense. A model that does not know fct_orders_v2 is the table your team actually uses, or that
revenue is gross rather than net, writes confident, wrong SQL. .contextflo/context.md is a markdown file you edit
and this server hands to the model, with nothing behind it but the file. The agent adds to it too: when it learns
something the schema does not say, add_table_context appends a note, which you review in a diff like any other change.
1. Create a read-only role. Run this as the database owner, in psql or your provider's SQL editor. Use your
database name and a real password, and repeat the schema lines for each schema the agent should see:
CREATE ROLE mcp_readonly LOGIN PASSWORD 'change-me';
GRANT CONNECT ON DATABASE mydb 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;
This makes read-only a property of the database, not just of this server's code.
2. Put that role's connection string in .env in your project folder:
DATABASE_URL='postgresql://mcp_readonly:change-me@db.example.com:5432/mydb'
Keep the quotes: hosted providers add ?sslmode=require&..., and the & needs them. The server reads DATABASE_URL
from .env in the directory it starts in, so the connection string never appears on a command line.
Point it at a read replica or a branch rather than your primary if you can. Read-only stops writes, not load: an agent
exploring your data can run a full-table scan or a heavy join, and on the primary that competes with your application.
Neon and Supabase can branch or replicate a database in a few clicks, and RDS, Cloud SQL, and most other hosts offer
read replicas. The statement timeout (30 seconds by default, --statement-timeout) and the row cap limit how long one
query runs and how much it returns; they do not make it cheap.
3. Generate the context file:
npx @contextflo/postgres-mcp init
That writes .contextflo/context.md, seeded from your COMMENT ON values. Edit it: the business definitions section
is where the value is.
4. Add it to your client. Claude Code starts servers in your project folder, so it finds .env and the context
file on its own:
claude mcp add postgres --scope project -- npx -y @contextflo/postgres-mcp
--scope project writes .mcp.json into the folder instead of your global config.
Other clients may start servers outside your project folder (Claude Desktop starts them in /), so give them the
connection string and t