triage-mcp
Provides read-only access to a PostgreSQL database, allowing agents to run validated SELECT queries with timeouts and PII masking.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@triage-mcpInvestigate the bug in ticket #301: query recent failed payments for that account."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
triage-mcp
A read-only Postgres MCP server and a Claude-powered triage agent, from the tutorial "Build a Read-Only Postgres MCP Server for Automated Bug Triage".
sql/01_schema.sql: fictional SaaS billing schema, seed data, and a planted bugsql/02_readonly_role.sql: the least-privilegetriage_agentrolesrc/triage_mcp/sql_guard.py: parser-based SELECT validation (sqlglot)src/triage_mcp/db.py: read-only, time-boxed query execution (psycopg)src/triage_mcp/masking.py: PII scrubbing for every returned valuesrc/triage_mcp/server.py: the MCP server (streamable HTTP, bearer auth, audit log)src/triage_mcp/agent.py: the triage agent (Claude tool runner + MCP client)examples/ticket.json: a Microsoft List item as returned by Microsoft Graph
Requirements
Python 3.12 and uv 0.12
No Postgres install needed for local development:
pgserverships Postgres 16 binariesNode.js 22.19+ only if you want to use MCP Inspector
An Anthropic API key only to run the agent against the real API (tests don't need one)
Pinned versions: mcp 2.2.0, anthropic 1.6.0, psycopg 3.3.5, sqlglot 30.18.0,
uvicorn 0.53.0, pgserver 0.1.4 (PostgreSQL 16.2), pytest 9.1.1.
Related MCP server: Argos-MCP
Run the Tests
uv sync
uv run pytestThe tests start a throwaway Postgres, load the schema and role, run the MCP server under uvicorn, and call it over HTTP with the MCP Python client. The agent test replaces the Claude API with a scripted fake, so no API key is needed.
Run Locally
# 1. Start a local Postgres 16 with the demo data (prints connection strings)
uv run python scripts/local_db.py
# 2. Start the MCP server as the read-only role
export TRIAGE_DB_URL='postgresql://triage_agent:change-me@/billing?host=<socket dir printed above>'
export TRIAGE_MCP_TOKEN='local-dev-token'
uv run uvicorn triage_mcp.server:app --host 127.0.0.1 --port 8000
# 3. In another terminal, call a tool with MCP Inspector
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:8000/mcp --transport http \
--header "Authorization: Bearer local-dev-token" --method tools/list
# 4. Triage the example ticket (needs ANTHROPIC_API_KEY)
export TRIAGE_MCP_URL='http://127.0.0.1:8000/mcp'
uv run triage-agent examples/ticket.json
# Stop the local database when you're done
uv run python scripts/local_db.py --stopConfiguration
Variable | Used by | Purpose |
| server | Connection string for the |
| server, agent | Shared bearer token (replace with IdP-issued JWTs in production) |
| server | The URL clients use to reach |
| server | Comma-separated |
| server | Per-query timeout (default 5000) |
| agent | Where the agent reaches the MCP server |
| agent | Claude API credentials |
The seed data, customer names, and schema are fictional.
Deployment Checklist (AWS)
Run
sql/01_schema.sql(your real schema, views, and functions) andsql/02_readonly_role.sqlon the primary; roles and grants replicate to RDS read replicas. Keep the role password in AWS Secrets Manager.Point
TRIAGE_DB_URLat the read replica endpoint withsslmode=verify-fulland the RDS CA bundle.Run the server on EC2 in a private subnet:
uvicorn triage_mcp.server:app --host 0.0.0.0 --port 8000. Allow port 8000 only from the agent's security group, and 5432 on the replica only from the server.Terminate TLS at an internal load balancer and run uvicorn with
--proxy-headers --forwarded-allow-ips=<lb address>. SetTRIAGE_MCP_PUBLIC_URLandTRIAGE_MCP_ALLOWED_HOSTSto the internal hostname.Replace
StaticTokenVerifierwith JWT validation against your identity provider (check audience and expiry).Ship stderr (JSON audit lines prefixed with
audit) to CloudWatch Logs and alert onrejectedandtimeoutentries.Monitor the replica's
ReplicaLagmetric; results can trail the primary.Under load, replace per-call connections with
psycopg_pool, sized below the role'sCONNECTION LIMIT 10.
Troubleshooting
No module named 'mcp.server.fastmcp':mcp2.x renamedFastMCPtoMCPServer(from mcp.server import MCPServer).421 Misdirected Request: the request'sHostheader is not inTRIAGE_MCP_ALLOWED_HOSTS.401 Unauthorized: theAuthorization: Bearer <token>header is missing or doesn't matchTRIAGE_MCP_TOKEN.Timestamps in a non-UTC offset: make sure the role has
timezone = 'UTC'(set in02_readonly_role.sql).Audit lines wrapped across several lines:
mcp[cli]pulls inrich, whose log handler wraps long messages. The audit logger uses its ownStreamHandlerwithpropagate = Falseto keep one JSON line per query.Query timed outfromrun_select: add filters (user_id, acreated_atrange) or aggregate; the default timeout is 5 seconds (TRIAGE_STATEMENT_TIMEOUT_MS).
This server cannot be deployed
Maintenance
Related MCP Connectors
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Related MCP Servers
- FlicenseAqualityCmaintenanceEnables read-only exploration of a Postgres database using natural language, with multiple safety layers to prevent any modifications.5-
- AlicenseNot gradedqualityAmaintenanceEnables Claude Code to securely interact with PostgreSQL, MySQL, SQLite, and SQL Server databases, featuring read-only mode, query validation, SSH tunneling, and field redaction for production-safe data access.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables an AI assistant to run guarded, read-only SQL queries against a Postgres database with enforced limits and validation.MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to query a Postgres data warehouse through a governed, read-only SQL interface with policy enforcement, row limits, schema-level PII isolation, and a full audit trail.1-