느린 쿼리, 인덱스 상태, 테이블 블로트(bloat), 잠금(lock), 복제 지연 등을 분석하기 위한 읽기 전용 PostgreSQL 진단 기능을 제공합니다.
다른 이름 pascalallen/pgmcp
- 스타
- 0
- Tools
- 9
- 다운로드, 30일
- —
- 최신 버전
- 1.1.0
- 마지막 커밋
- 2026년 11월 4일
- 라이선스
- MIT
pgmcp MCP란?
pgmcp은(는) MCP server입니다. 느린 쿼리, 인덱스 상태, 테이블 블로트(bloat), 잠금(lock), 복제 지연 등을 분석하기 위한 읽기 전용 PostgreSQL 진단 기능을 제공합니다. 9개 도구를 제공합니다. 예: top_queries, explain, index_health.
프로젝트 README에서 생성된 요약
pgmcp MCP server 정보
pgmcp는 DBA와 개발자가 AI 클라이언트 내부에서 PostgreSQL 성능 및 데이터베이스 상태를 분석할 수 있도록 지원합니다. 느린 쿼리 조사, 불필요한 인덱스 식별, 테이블 블로트 모니터링, 복제 지연 추적을 위한 전문 진단 도구 모음을 제공합니다. 이 MCP server는 쓰기 권한이 없는 전용 데이터베이스 역할, 문장 타임아웃이 적용된 필수 읽기 전용 트랜잭션, 변경 명령을 거부하는 SQL 파서 등 세 가지 독립적인 보호 계층을 통해 읽기 전용으로 설계되었습니다.
사용자는 Claude Desktop 또는 Claude Code와 함께 로컬에서 사용하기 위해 stdio를 통해 배포하거나, 정적 API 키 또는 JWT 인증을 사용하는 공유 배포를 위해 HTTP를 통해 배포할 수 있습니다. PostgreSQL 13 이상을 지원하며 버전 16에 대해 특정 테스트를 거쳤습니다. 보안을 극대화하려면 관리자가 --disable-query 플래그를 사용하여 임시 SQL 실행 기능을 완전히 제거하고, 검사 가능한 8가지 핵심 진단 도구만 남겨둘 수 있습니다.
활용 사례
- 1느린 데이터베이스 문장 조사AI에게 어떤 쿼리가 서버 시간을 가장 많이 소비하는지 찾고 실행 계획을 설명하도록 요청합니다.
- 2인덱스 및 테이블 상태 최적화사용되지 않거나 비대해진 인덱스를 식별하고 autovacuum이 데드 튜플(dead tuples)을 적절히 처리하고 있는지 확인합니다.
- 3데이터베이스 잠금 경합 해결현재 잠금 대기 그래프를 조사하여 특정 쿼리가 중단되는 원인을 파악합니다.
- 4복제 및 연결 모니터링기본 서버와 스탠바이 서버 간의 지연을 확인하거나 현재 연결 상태를 모니터링합니다.
프로젝트의 README를 바탕으로 작성되었습니다. 모든 활용 사례는 해당 내용의 인용문과 대조하여 확인합니다.
pgmcp MCP 설치 방법
형식 확인: 2026년 11월 10일Cursor에 추가Goose에 추가Claude Code에 pgmcp MCP 설치
$ claude mcp add --env 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' pgmcp -- docker run -i --rm ghcr.io/pascalallen/pgmcp:1.1.0Cursor에 pgmcp MCP 설치
~/.cursor/mcp.json
{
"mcpServers": {
"pgmcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/pascalallen/pgmcp:1.1.0"
],
"env": {
"PGMCP_DATABASE_URL": "<YOUR_PGMCP_DATABASE_URL>"
}
}
}
}VS Code에 pgmcp MCP 설치
.vscode/mcp.json
{
"servers": {
"pgmcp": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/pascalallen/pgmcp:1.1.0"
],
"env": {
"PGMCP_DATABASE_URL": "<YOUR_PGMCP_DATABASE_URL>"
}
}
}
}VS Code CLI에 pgmcp MCP 설치
$ code --add-mcp '{"name":"pgmcp","type":"stdio","command":"docker","args":["run","-i","--rm","ghcr.io/pascalallen/pgmcp:1.1.0"],"env":{"PGMCP_DATABASE_URL":"<YOUR_PGMCP_DATABASE_URL>"}}'Claude Desktop에 pgmcp MCP 설치
claude_desktop_config.json
{
"mcpServers": {
"pgmcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/pascalallen/pgmcp:1.1.0"
],
"env": {
"PGMCP_DATABASE_URL": "<YOUR_PGMCP_DATABASE_URL>"
}
}
}
}Codex에 pgmcp MCP 설치
$ codex mcp add pgmcp --env 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' --env 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' -- docker run -i --rm ghcr.io/pascalallen/pgmcp:1.1.0Codex config.toml에 pgmcp MCP 설치
~/.codex/config.toml
[mcp_servers.pgmcp] command = "docker" args = ["run", "-i", "--rm", "ghcr.io/pascalallen/pgmcp:1.1.0"] [mcp_servers.pgmcp.env] PGMCP_DATABASE_URL = "<YOUR_PGMCP_DATABASE_URL>"
Gemini CLI에 pgmcp MCP 설치
$ gemini mcp add -s user -e 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' -e 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' pgmcp docker -- run -i --rm ghcr.io/pascalallen/pgmcp:1.1.0Gemini settings.json에 pgmcp MCP 설치
~/.gemini/settings.json
{
"mcpServers": {
"pgmcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/pascalallen/pgmcp:1.1.0"
],
"env": {
"PGMCP_DATABASE_URL": "<YOUR_PGMCP_DATABASE_URL>"
}
}
}
}pgmcp MCP 도구 9
README에서 감지됨top_queriesexplainindex_healthtable_healthlock_waitsconnectionsreplicationconfig_checkquery
| top_queries | — | |
| explain | — | |
| index_health | — | |
| table_health | — | |
| lock_waits | — | |
| connections | — | |
| replication | — | |
| config_check | — | |
| query | — |
구성
PGMCP_DATABASE_URL필수비밀Postgres connection string (read-only role recommended)
PGMCP_DATABASE_URL필수비밀Postgres connection string (read-only role recommended)
PGMCP_API_KEYSPGMCP_AUTH_MODEPGMCP_TEST_DSN
| 이름 | 설명 | 유형 |
|---|---|---|
| PGMCP_DATABASE_URL | Postgres connection string (read-only role recommended) | 필수비밀 |
| PGMCP_DATABASE_URL | Postgres connection string (read-only role recommended) | 필수비밀 |
| PGMCP_API_KEYS | — | |
| PGMCP_AUTH_MODE | — | |
| PGMCP_TEST_DSN | — |
자동 검사
2026년 11월 13일에 실행됨전체 보고서 →자동 검사를 통과했습니다. 이는 보안 감사가 아닙니다. 코드를 직접 읽고 서버에 필요한 최소한의 권한만 부여하십시오. 검사 방식
- 소스 저장소 연결 및 접근 가능통과
- 오픈 소스 라이선스 (OSI)통과
- 최근 1년 내 커밋 또는 릴리스통과
- 패키지 이름이 인기 패키지와 유사하지 않음검사되지 않음
- 원격 엔드포인트가 HTTPS 사용검사되지 않음
- 파괴적인 도구에 라벨 표시됨통과
- 모델에 대한 숨겨진 지침 없음통과
- 패키지 및 해당 종속성에 중요한 보안 권고 없음검사되지 않음
README
GitHub에서 보기pgmcp
pgmcp is a read-only PostgreSQL ops/DBA server for the Model Context Protocol, built on the official modelcontextprotocol/go-sdk. It answers the questions a DBA asks during an incident — which statements are slow, why this plan is slow, which indexes are dead weight, which tables autovacuum has fallen behind on, who is blocking whom, how far the standby is lagging — and it is read-only by construction rather than by convention: a dedicated database role that holds no write privilege, a BEGIN READ ONLY transaction with a statement timeout around every single statement, and a SQL parser guard that rejects anything that is not one SELECT/EXPLAIN/SHOW and every function that could mutate state from inside a read-only transaction. Tested against PostgreSQL 16; requires 13 or later.
Installation
Claude Desktop, one click: download pgmcp_<version>.mcpb from Releases and open it. Claude Desktop asks for a Postgres connection string, keeps it in the OS keychain, and launches the bundled binary itself — nothing on PATH, no config file to edit. One bundle covers macOS (universal) and Windows (x64).
Otherwise download a binary for your platform from Releases — darwin, linux and windows, amd64 and arm64, with checksums.
Or build from source with the Go CLI tool go:
go install github.com/pascalallen/pgmcp/cmd/pgmcp@latest
Or run the released image, which is distroless, non-root and multi-arch:
docker run --rm -i -e PGMCP_DATABASE_URL='postgres://…' ghcr.io/pascalallen/pgmcp
pgmcp is listed in the MCP Registry as io.github.pascalallen/pgmcp.
Before you point it at anything, create the read-only role — see Database role. It is the layer that still holds if the other two have a bug.
Usage
One MCP surface, two transports. Which one you run is configuration, not a different build.
Claude Code, stdio — the client launches the binary and talks over stdin/stdout:
claude mcp add pgmcp --transport stdio \
--env PGMCP_DATABASE_URL='postgres://pgmcp:…@db.internal:5432/app?sslmode=require' \
-- pgmcp
Claude Desktop, stdio — install the .mcpb bundle from Releases (see Installation), or write the same thing into claude_desktop_config.json by hand:
{
"mcpServers": {
"pgmcp": {
"command": "pgmcp",
"env": {
"PGMCP_DATABASE_URL": "postgres://pgmcp:…@db.internal:5432/app?sslmode=require"
}
}
}
}
HTTP — Streamable HTTP behind a static bearer key, for a shared deployment. pgmcp speaks plain HTTP and never terminates TLS itself; run it on loopback behind a reverse proxy.
PGMCP_DATABASE_URL='postgres://pgmcp:…@db.internal:5432/app?sslmode=require' \
PGMCP_AUTH_MODE=static \
PGMCP_API_KEYS="$(openssl rand -hex 32)" \
pgmcp --transport http --listen 127.0.0.1:8080
claude mcp add pgmcp --transport http https://pgmcp.example.com/mcp \
--header "Authorization: Bearer <key>"
TLS termination, the proxy settings the streaming transport needs, JWT auth against an identity provider, and wiring pgmcp up as a claude.ai custom connector are all in docs/DEPLOYING.md.
Tools
| Tool | The question it answers |
|---|---|
top_queries |
Which statements are slow or expensive server-wide? Ranks pg_stat_statements by total time, mean time, calls, rows or blocks read. |
explain |
Why is this statement slow? Plan tree, the nodes burning the most self time, plan warnings, and a stable plan_hash to diff against a later run. |
index_health |
Which indexes can I drop, and which are missing their job? Never-scanned, duplicate, invalid and bloated indexes. |
table_health |
Where is autovacuum falling behind? Dead-tuple ratio, last vacuum/analyze, sequential versus index scans and estimated bloat, per table. |
lock_waits |
Why is this query hanging? The current lock wait graph — who is blocked, who blocks them, and any cycle that amounts to a deadlock. |
connections |
What is the server doing right now, and how close is it to max_connections? Backends grouped by state, wait event, application, user or database, including idle-in-transaction sessions. |
replication |
How far behind is the standby, and which slot is retaining WAL? Primary/standby role, per-standby lag in bytes and milliseconds, slots and the current WAL rate. |
config_check |
Is this server tuned sanely? pg_settings against memory, autovacuum, WAL and connection heuristics, with an ok/review/warn verdict and a note per setting. |
query |
Everything the other eight do not cover. One read-only SELECT/EXPLAIN/SHOW in a READ ONLY transaction, bounded by a row cap and a statement timeout, with $1..$n bind parameters. |
Every tool is annotated readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, and returns a typed output schema.
query is the only tool that carries free-form SQL, and it is optional. --disable-query drops it from the catalogue entirely — a deployment that only needs the eight diagnostics tools can run without any ad hoc SQL surface at all. --query-schemas=public,app restricts it to named schemas instead — and bounds explain with it, since analyze=true executes the statement; read what that does and does not stop in docs/SECURITY.md.
Resources & prompt
| Resource | Contents |
|---|---|
pgmcp://overview |
The server snapshot to start from: version, uptime, recovery state, installed extensions, per-database sizes, cache hit ratio, and connections against max_connections. Cacheable for 30s. |
pgmcp://settings |
The raw pg_settings rows. Cacheable for 5m. |
| Prompt | Arguments | Purpose |
|---|---|---|
diagnose_slow_query |
sql (required) |
A four-step investigation: explain the statement, check index_health/table_health on every schema in the plan's hot nodes, look for it in top_queries, then summarize root cause, evidence and a recommended index or rewrite — written out as text only, never run. |
Configuration
Every setting has a --flag and a PGMCP_<KEY> environment variable. Flags win over the environment, which wins over the default. Configuration errors exit 2 with every offending key named in one message; runtime failures exit 1.
| Flag | Env | Default | Meaning |
|---|---|---|---|
--database-url |
PGMCP_DATABASE_URL |
— (required) | Postgres connection string |
--transport |
PGMCP_TRANSPORT |
stdio |
stdio or http |
--listen |
PGMCP_LISTEN |
127.0.0.1:8080 |
HTTP listen address |
--resource-url |
PGMCP_RESOURCE_URL |
— | Public origin this server is reachable at, for OAuth resource metadata |
--auth-mode |
PGMCP_AUTH_MODE |
none |
none, static or jwt (HTTP only) |
--api-keys |
PGMCP_API_KEYS |
— | Comma-separated static API keys, required for static |
--jwks-url |
PGMCP_JWKS_URL |
— | JWK set URL, required for jwt |
--jwt-issuer |
PGMCP_JWT_ISSUER |
— | Required iss claim, required for jwt |
--jwt-audience |
PGMCP_JWT_AUDIENCE |
— | Required aud claim, required for jwt |
--auth-servers |
PGMCP_AUTH_SERVERS |
— | Comma-separated OAuth authorization servers to advertise via RFC 9728 |
--disable-query |
PGMCP_DISABLE_QUERY |
false |
Drop the ad hoc query tool entirely |
--query-schemas |
PGMCP_QUERY_SCHEMAS |
— | Comma-separated schemas the query and explain tools may read; unset disables the allowlist |
--max-conns |
PGMCP_MAX_CONNS |
4 |
Maximum Postgres connections |
--call-timeout |
PGMCP_CALL_TIMEOUT |
60s |
Per-tool-call timeout |
--rate-limit |
PGMCP_RATE_LIMIT |
60 |
Tool calls per principal per minute (HTTP only) |
--max-output-bytes |
PGMCP_MAX_OUTPUT_BYTES |
1048576 |
Cap on a tool call's structured content |
--log-level |
PGMCP_LOG_LEVEL |
info |
debug, info, warn or error |
--log-format |
PGMCP_LOG_FORMAT |
text |
text or json |
--insecure-no-auth |
PGMCP_INSECURE_NO_AUTH |
false |
Allow auth-mode=none on a non-loopback listen address |
--version |
— | — | Print the version and exit |
The auth block applies to the HTTP transport only. Over stdio the operating system decides who the caller is: the parent process that launched the binary, and nobody else.
Security model
- Read-only three independent ways. A dedicated role with no write privilege (
pg_monitorplusSELECT, and deliberately notpg_signal_backend);BEGIN READ ONLYwithSET LOCAL statement_timeoutandlock_timeout = '2s'around every statement the adapter runs, always rolled back; and a parser-level guard, because a read-only transaction alone does not stoppg_terminate_backend,pg_read_file,pg_sleeporsetval. - The SQL guard is allow-list first. One top-level statement, and it must be a
SELECT,EXPLAINorSHOW; no nested write statement anywhere in the tree; noFOR UPDATE/FOR SHARElocking clause; noSELECT INTO; and no call to a denied function — file access, backup and WAL control, replication slots, advisory locks,dblink, sequence mutation, stats resets. - The schema allowlist is a guardrail, not a boundary.
--query-schemasmatches the schemas qualifying table references in the parsed statement, case-insensitively, and it bounds both tools that carry caller-supplied SQL —queryandexplain, soexplainwithanalyze=truecannot execute against a schema you excluded. A view, a set-returning function, or aSECURITY DEFINERfunction inside an allowed schema can still read outside it. Database privileges are the boundary; the allowlist just narrows the obvious path. - Authenticated, fail-closed, over HTTP. Static keys are compared in constant time against every stored hash without an early exit; JWTs are validated against a JWK set with asymmetric algorithms only (no
alg=none, no HMAC confusion) and a requirediss,audandexp, and the verifier holds no keys until the JWKS arrives, so it starts closed rather than open. RFC 9728 protected resource metadata advertises where to get a token. The server refuses to start on a non-loopback address with auth off. - Bounded. Per-principal rate limiting, a per-call timeout, a statement timeout and lock timeout inside the transaction, a row cap on the
querytool, a cap on a result's structured content, and a 1 MiB request body limit. - Nothing sensitive is logged. A tool call logs its name, duration, outcome and the caller's user id — never arguments, SQL text, result rows or error text. Parse failures come back as a fixed phrase rather than echoing the statement, and the DSN is redacted from connection errors.
The threat model, the full enumeration of the layers, and the limitations each one does not cover are in docs/SECURITY.md.
Testing
Run the test suite with the race detector and coverage:
go test -race -cover ./...
Integration tests need a Postgres database and are skipped when PGMCP_TEST_DSN is unset. To run them against a scratch Postgres with pg_stat_statements preloaded:
docker run -d --rm --name pg -e POSTGRES_PASSWORD=postgres -p 5544:5432 postgres:16 \
-c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all
docker exec pg psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements"
PGMCP_TEST_DSN="postgres://postgres:postgres@localhost:5544/postgres?sslmode=disable" go test -race -cover ./...
Create and view a coverage profile:
go test -covermode=count -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Drive a running server through the official MCP conformance suite, or smoke it with the Inspector:
npx -y @modelcontextprotocol/conformance server --url http://127.0.0.1:8080/mcp \
--expected-failures .github/conformance-expected-failures.yaml
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:8080/mcp --transport http --method tools/list
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
License
pgmcp MCP 질문
pgmcp MCP를 Claude Code에 추가하려면 어떻게 하나요?
터미널에서 claude mcp add --env 'PGMCP_DATABASE_URL=<YOUR_PGMCP_DATABASE_URL>' pgmcp -- docker run -i --rm ghcr.io/pascalallen/pgmcp:1.1.0를 실행합니다. 모든 프로젝트에서 사용할 수 있게 하려면 --scope user를 추가합니다.
pgmcp MCP를 Cursor에 추가하려면 어떻게 하나요?
~/.cursor/mcp.json를 열고 mcpServers 아래에 서버를 추가합니다. 위 설치 섹션에 표시된 Cursor 구성을 사용합니다.
pgmcp MCP는 어떤 도구를 제공하나요?
9개 도구를 제공합니다. 예: top_queries, explain, index_health, table_health, lock_waits.
운영 중인 데이터베이스에서 사용해도 안전한가요?
네, 쓰기 권한이 없는 전용 데이터베이스 역할 사용, 읽기 전용 트랜잭션, SQL 파서 가드 등 세 가지 보호 계층을 통해 읽기 전용으로 설계되었습니다.
어떤 PostgreSQL 버전을 지원하나요?
PostgreSQL 13 이상이 필요하며, PostgreSQL 16에서 테스트를 완료했습니다.
SQL 쿼리를 특정 스키마로 제한할 수 있나요?
네, --query-schemas 플래그를 사용하여 쿼리 및 explain 도구가 특정 이름의 스키마만 대상으로 하도록 제한할 수 있습니다.
Claude Desktop에 어떻게 설치하나요?
Releases 페이지에서 .mcpb 번들을 다운로드하여 실행하면 연결 문자열 입력 프롬프트가 나타나며 자동으로 설정이 진행됩니다.