
PostgreSQL Performance (read-only)
io.github.gouranshulv0.1.0更新於 Oct 10, 2026
Read-only PostgreSQL performance diagnostics: slow queries, EXPLAIN, index advice, locks, functions
概覽
唯讀的 PostgreSQL 效能診斷:慢查詢、EXPLAIN 計畫、索引建議、資料表健康、鎖定與函式。
- 功能
- 透過一個受限的唯讀介面,讓助理從 pg_stat_statements、EXPLAIN 和 PostgreSQL 系統目錄取得真實數據。工具包括 top_slow_queries、explain_query、suggest_indexes、unused_indexes、table_health、blocking_sessions、slow_functions 和 explain_function,另有 schema 資源與引導式 diagnose_slow_database 提示。它只建議索引,從不建立索引,也不會取消或終止連線。
- 適用情境
- 當資料庫變慢,希望助理查看真實執行計畫、資料表大小、現有索引和查詢負載,而不是憑空猜測時使用。適合在副本或預備環境資料庫上診斷慢查詢、索引候選、資料表膨脹和鎖定競爭。
- 執行需求
- 執行已發布映像需要 Docker,從原始碼建置需要 Java 25。需要一個 PostgreSQL 資料庫,在 shared_preload_libraries 中啟用 pg_stat_statements,並有一個具備 pg_read_all_stats 和 pg_monitor 的唯讀角色。需設定 PGPERF_DB_URL、PGPERF_DB_USER、PGPERF_DB_PASSWORD 和 MCP_API_KEY;用戶端以 Authorization bearer 標頭傳送該金鑰。函式相關工具還需啟用 track_functions 和 auto_explain。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 PostgreSQL Performance (read-only),將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
pg-perf-mcp
[CI] [License: MIT] [Java 25] [Spring Boot 4.1]
An MCP server that lets AI assistants diagnose PostgreSQL performance problems safely: slow queries, EXPLAIN plans, index suggestions, table health and lock contention. It is read-only by design.
A real Claude Code session against the demo shop, sped up. First it finds which database functions are slow and why. Then it explains a slow catalog query and estimates the fix with a hypothetical index. Asked to create the index, it says it can't: every tool is read-only.
Why
When a page is slow, developers paste a query into a chat and ask "why is this slow?". The assistant then guesses, because it cannot see the plan, the table sizes, the existing indexes or which queries actually dominate the load.
pg-perf-mcp gives the assistant real numbers from pg_stat_statements, EXPLAIN and the
catalogs, through a narrow, audited, read-only interface. It cannot change data, cannot run DDL,
and never creates the indexes it recommends.
Demo
A condensed, illustrative session against the demo shop (docker compose up, then
./demo/workload.sh). Exact numbers vary from run to run:
Architecture
Tools
Resources: pg://schema/overview (tables, row estimates, sizes, indexes) and
pg://schema/{table} (columns, indexes with scan counts, foreign keys flagged when unindexed).
Prompt: diagnose_slow_database, a guided workflow: slow queries, then explain, suggest
indexes, table health, functions, then a prioritized summary.
Why a separate tool for database functions
EXPLAIN shows a function call as one opaque expression, and charges its time to whichever plan
node evaluates it. On the demo catalog page (20 products, each calling shop.product_rating),
explain_query blames the index scan on products (184 ms self time) and finds nothing else
serious. explain_function on the same query, against the full demo data:
How it works (ADR 0006): the query runs once
with auto_explain enabled for that transaction only, so the plan of each nested statement comes
back as a notice; per-function time comes from pg_stat_xact_user_functions and per-statement
calls from pg_stat_statements, both as before/after differences.
Security model
Five independent layers stand between the assistant and a write (details in ADR 0001):
- SQL guard: exactly one plain
SELECT. It is checked by a PostgreSQL-faithful lexer and JSqlParser, and both must agree. Blocks DML/DDL, multiple statements, data-modifying CTEs,SELECT INTO,FOR UPDATE/SHARE,COPY,DO, and dangerous functions (pg_sleep*,*_file,lo_*,dblink*,set_config,pg_terminate_backend,query_to_xml, ...). It fails closed. - Read-only role:
mcp_readonlyhasSELECTpluspg_read_all_stats/pg_monitor, withdefault_transaction_read_only = onandstatement_timeout = 5sset on the role. - Read-only connections: Hikari
readOnly=trueand a read-only session default. - One rolled-back read-only transaction per call:
statement_timeout/lock_timeoutset locally,standard_conforming_stringsforced on, always rolled back. - Row cap: every result is capped (default 200 rows).
Around those layers: a bearer API key (constant-time comparison; only /actuator/health is
open), a JSON audit line per call (SQL stored as a SHA-256 hash plus an 80-character preview),
error messages with no stack traces or connection details, and metrics mcp.tool.duration and
mcp.guard.rejections.
Quickstart
Requirements: Docker. There are two ways to start:
- Use it on your database: pull the published image. No clone or build.
- Try the demo shop: clone the repo and get a seeded database with realistic problems to diagnose.
Either way, finish with connecting your AI client.
Use it on your database
1. Pull the image (public on GHCR, built for amd64 and arm64):
2. Prepare the database (once). Create a read-only role like mcp_readonly (see
docker/init.sql) and make sure pg_stat_statements is in
shared_preload_libraries. Prefer a replica or staging database: analyze=true and
explain_function execute the query. For the function tools, also
enable function tracking.
3. Run it. Put the settings in a file so secrets stay out of your shell history:
host.docker.internal reaches a database on your machine (Docker Desktop; on Linux add
--add-host=host.docker.internal:host-gateway). The MCP endpoint is now
http://localhost:8080/mcp.
4. Connect your AI client: see below.
Try the demo shop
To build and test from source you also need Java 25.
Generate some slow-query statistics (optional, but makes top_slow_queries interesting):
Connect from Claude Code
In PowerShell, set the key first, or the header goes out empty and the server answers 401:
Then ask: "Use pg-perf to find out why the shop database is slow", or run the
diagnose_slow_database prompt.
Connect from Claude Desktop
Claude Desktop launches stdio servers, so use the mcp-remote bridge
(claude_desktop_config.json):
Connect from Cursor
~/.cursor/mcp.json (or .cursor/mcp.json in a project):
Connect from VS Code (Copilot agent mode)
.vscode/mcp.json. VS Code prompts for the key once and stores it securely:
Enable the function tools (optional)
slow_functions and explain_function need two extra settings on your own database. The demo
shop already has them, and every other tool works without them:
Without these, explain_function still reports what it can and says in notes what is missing.
Configuration
Properties can also be set as environment variables (PGPERF_QUERY_STATEMENT_TIMEOUT=3s, ...).
Metrics are at /actuator/prometheus (requires the API key).
Build and test
This runs unit tests, Testcontainers integration tests against PostgreSQL 18 (same image, init
scripts and read-only role as compose; needs Docker), an end-to-end test with the MCP Java SDK
client over HTTP, and a JaCoCo gate (80% lines on the guard and analysis packages).
Design decisions
- 0001: Read-only by design, enforced in depth
- 0002: Streamable HTTP transport
- 0003: Summarized plans instead of raw EXPLAIN
- 0004: Suggest indexes, never execute them
- 0005: Platform versions and API differences
- 0006: Looking inside database functions
Roadmap
- OAuth 2.1 resource server per the MCP authorization spec (per-user identity instead of a shared key)
- Multiple named database targets, with read replicas preferred
- Workload-level index advice (weigh candidates across all top queries, not one at a time)
auto_explainlog /pg_stat_kcacheingestion for plans of queries that already ran in production- Optional raw-plan output and per-tool rate limits
- MCP elicitation to confirm
analyze=trueon expensive queries
License
MIT © 2026 Anshul Gour
來源:README.md,提交 2b97e2b
工具
0版本歷史
1- v0.1.0最新Oct 10, 2026


