MCPg — Progress Tracker
Resume here. A new session should read
PLAN.mdthen this file, then start the task under Next action. Update this file and commit before ending any session.
Current state
- Phase: post-v0.6.10. Every Batch (A–G) from the original
shortlist plus the 0.6.x waves have shipped — security (IP
allowlist, TLS/mTLS, cloud secrets backends), observability
(slow-call logging + OpenTelemetry), staged migrations + history,
pgvector analytics, BM25/
pg_search,pg_turboquant, the RAG efficiency suite, PG 19 readiness (SQL/PGQ,REPACK, skip-scan,WAIT FOR LSN, data-checksum/logical-rep toggles, partition merge/split), WarehousePG (MPP) coverage, Redis FDW,pg_prewarm, the 22-provider NL→SQL fleet, the generated-doc-table drift guard, and the first-party SQL-safety kernel (18.1 de-vendor complete — no vendored runtime code remains). - Last updated: 2026-07-09
- Branch:
main - Tool count: 252 (source of truth:
tests/contract/tool_surface.snapshot.json) - Released: v0.6.10 (2026-07-09)
Note on this log. The dated session log below is a historical record that trails off at 2026-05-26 (~90 tools). The nine 0.6.x releases and ~160 tools shipped since are not re-logged here —
CHANGELOG.mdand thedocs/release-notes-0.6.*.mdfiles are the authoritative history for that period, anddocs/feature-shortlist.mdis the live roadmap.
Next action
Trunk is at 0.6.10. The feature roadmap (
docs/feature-shortlist.md§1–18) is fully shipped. The next concrete item is the 0.6.11 per-request-tenancy fix for the HTTP/SSE transports (theX-MCPG-Role/ OIDC override is pinned to a session’s first request; see the known-limitation note indocs/security-hardening.md). Beyond that, pick from any newly-surfaced rows indocs/feature-shortlist.md.
Phase 0 — Spike & foundation ✅ COMPLETE
- 0.1 Evaluate
crystaldba/postgres-mcp(code, tests, license, activity) → ADR-0001 (hard-fork) - 0.2 Confirm/record stack → ADR-0002 (Python 3.12 + psycopg3 + mcp SDK)
- 0.3 Vendor
sql/subpackage (MIT,NOTICE+_vendor/README.md); scaffolduvproject - 0.4 Configure
ruff,mypy --strict,pytest,pytest-cov, coverage gate (inpyproject.toml) - 0.5 GitHub Actions CI (
.github/workflows/ci.yml: ruff + mypy + pytest) - 0.6
CONTRIBUTING.md, pre-commit hooks (local hooks), issue/PR templates - 0.7 First green CI run — run #1 on commit
a20a757, conclusion: success
Phase 0 notes
- Vendored kernel lives in
src/mcpg/_vendor/sql/; 75 upstream tests ported and passing (tests/vendor/).test_db_conn_poolandtest_readonly_enforcementwere NOT ported — they couple to upstreamserver.py; re-derive under TDD in Phase 1/3. uv sync+uv run pytest tests/vendor+ruff+mypy src/mcpgall green locally.- CI runs ruff + mypy + pytest. The coverage gate (
fail_under = 90) and the PG 14–17 service-container matrix are intentionally deferred: they are wired in during Phase 1 (authored code exists) and Phase 2 (integration tests exist) respectively, to avoid dead/failing config now.
Phase 1 — Core server skeleton ✅ COMPLETE
- 1.1 Typed env-driven config/settings loader (
mcpg/config.py, TDD, 100% cov) - 1.2 Connection-pool lifecycle wrapper (
mcpg/database.py, TDD, 100% cov) - 1.3 MCP server bootstrap (
mcpg/server.py, TDD, 100% cov); no global state - 1.4
get_server_infotool — first end-to-end vertical slice (mcpg/tools.py, TDD) - 1.5
mcpgCLI entry point (mcpg/__main__.py, TDD) - 1.6 Coverage gate (
--cov,fail_under = 90) wired into CI
Phase 2 — Schema introspection & safe reads ✅ COMPLETE
- 2.1 Integration-test harness (
tests/integration/) + PG 14–17 CI service matrix - 2.2 Introspection tools:
list_schemas,list_tables,describe_table,list_indexes,list_extensions(mcpg/introspection.py, TDD) - 2.3
run_select— read-only-enforced query execution via vendoredSafeSqlDriver(mcpg/query.py, TDD) - 2.4
explain_querytool (mcpg/query.py, TDD) - 2.5 Result shaping —
max_rowscap +truncatedflag onQueryResult(TDD)
Phase 3 — Security hardening & access control ✅ COMPLETE
- 3.1 Access-mode policy engine — gate tool registration by
Settings.access_mode(mcpg/policy.py, TDD) - 3.2 SQL-safety regression suite — adversarial tests for the SQL-injection CVE class (
tests/unit/test_sql_safety.py) - 3.3 Audit logging of tool invocations (
mcpg/audit.py, TDD) - 3.4 Threat model + security documentation (
docs/security.md)
Phase 4 — Write & DDL tools ✅ COMPLETE
- 4.1
run_write— gated DML (INSERT/UPDATE/DELETE), unrestricted mode only (mcpg/write.py, TDD) - 4.2
run_ddl— gated DDL, unrestricted mode +MCPG_ALLOW_DDLopt-in (mcpg/write.py, TDD) - 4.3 Phase 4 verification — write tool calls audited end-to-end
Phase 4 decisions
- DDL requires a second opt-in beyond unrestricted mode (
MCPG_ALLOW_DDL), per user direction — DDL has the highest blast radius. - No dry-run/preview: writes execute directly (user direction — avoid the runtime cost of a rolled-back preview transaction).
- Per-write auditing is already provided by
AuditedFastMCP(every tool call is audited); Task 4.3 verifies it for write tools rather than adding code.
Phase 5 — Ops, health & tuning ✅ COMPLETE
Authored fresh under TDD — the upstream
database_health/,index/,top_queries/modules were not vendored (ADR-0001 narrowed scope tosql/).
- 5.1
check_database_health— connections, cache hit ratio, vacuum/dead tuples, invalid indexes (mcpg/health.py, TDD) - 5.2
analyze_workload— slow queries viapg_stat_statements(mcpg/workload.py, TDD) - 5.3
recommend_indexes— missing-index heuristics (mcpg/indexing.py, TDD) - 5.4
analyze_query_plan— structuredEXPLAINplan analysis (mcpg/query.py, TDD)
Phase 6 — Scalability & multi-tenancy
- 6.1 Configurable connection-pool sizing (
MCPG_POOL_MIN_SIZE/MAX_SIZE, vendoredDbConnPoolpatched per ADR-0003) - 6.2 Multi-tenancy & RLS awareness — document-only for v0.1.0
(
docs/security.md); per-request-role mechanism deferred post-1.0 - 6.3 Scaling characteristics (
docs/scaling.md) + benchmark harness (benchmarks/bench.py) - 6.4 (optional, deferred post-1.0) server-side cursors; read-replica routing
Phase 7 — Docs, packaging & release ✅ COMPLETE (pending release sign-off)
- 7.1 Usage docs + tool reference (
docs/tools.md); the usage guide was later split intodocs/installation.md+docs/user-guide.md - 7.2 Packaging —
Dockerfile,.dockerignore, install instructions - 7.3 v0.1.0 release prep — version bumped to 0.1.0, CHANGELOG finalised. Tagging/publishing awaits explicit user sign-off.
v0.1.0 merged to
mainvia PR #1. Post-1.0 work continues below.
Phase 8 — Index intelligence & extension management ✅ COMPLETE
- 8.1
list_indexesreports the index access method (btree/gin/gist/…) - 8.2
list_available_extensionstool — installed vs available - 8.3
enable_extensiontool — gated DDL, known-extension allowlist - 8.4 Index-type-aware
recommend_indexes— GIN forjsonb/arrays, trigram GIN for text columns
Phase 9 — Text search & fuzzy matching ✅ COMPLETE
- 9.1 Trigram fuzzy/similarity search tool over
pg_trgm(mcpg/textsearch.py, TDD) - 9.2 Full-text search tool over
tsvector/tsquery(mcpg/textsearch.py, TDD)
Phase 10 — Vector search (pgvector) ✅ COMPLETE
- 10.1
vectorcolumn awareness —describe_tablereports vector dimension (TDD) - 10.2 k-NN vector similarity search tool (
<->/<=>/<#>) (mcpg/textsearch.py, TDD) - 10.3 HNSW/IVFFlat index awareness —
list_indexesreports the access method; confirmed by an integration test (method == "hnsw").
Phase 11 — Geospatial (PostGIS) ✅ COMPLETE
- 11.1
geo_searchtool — k-NN by PostGIS distance to a lon/lat point; CI builds a pgvector + PostGIS image so it is integration-tested. - Geometry column types and GiST spatial indexes were already surfaced by
describe_tableandlist_indexes.
Phases 8–11 cover PostgreSQL extension and advanced-feature support; see
PLAN.md§7a for the capability inventory and per-extension priorities.
Phase 12 — Deeper schema introspection
- 12.1
list_constraints— PK, FK, unique, check, exclusion (mcpg/introspection.py, TDD) - 12.2
list_views(+ view definitions) (mcpg/introspection.py, TDD) - 12.3
list_functions— functions and procedures (mcpg/introspection.py, TDD) - 12.4
list_triggers(mcpg/introspection.py, TDD) - 12.5
list_sequences(mcpg/introspection.py, TDD)
Phase 13 — Partitioning
- 13.1
list_partitions— strategy, bounds, parent↔partition links (mcpg/introspection.py, TDD) - 13.2 Flag partitioned tables / partitions in
list_tables(mcpg/introspection.py, TDD) - 13.3 Partition-aware
list_indexesandrecommend_indexes(TDD)
Phase 14 — Access-control introspection
- 14.1
list_policies— Row-Level-Security policies on a table (mcpg/introspection.py, TDD) - 14.2
list_roles(mcpg/introspection.py, TDD) - 14.3
list_grants— table/object privileges (mcpg/introspection.py, TDD)
Phase 15 — Live ops & maintenance
- 15.1
list_active_queries+ lock / blocking inspection (mcpg/liveops.py, TDD) - 15.2 Replication-lag and bloat health checks (
mcpg/health.py, TDD) - 15.3 Gated
run_maintenance(VACUUM/ANALYZE) (mcpg/maintenance.py, TDD) - 15.4 Gated
cancel_query/terminate_backend(mcpg/liveops.py, TDD)
Phases 12–15 cover deeper introspection and live ops; see
PLAN.md§7b for the capability gap analysis behind them.
Decisions log
| ID | Decision | Status | Date |
|---|---|---|---|
| — | Scope: broad (ops + data access, gated by access mode) | accepted | 2026-05-20 |
| ADR-0001 | Approach: hard-fork crystaldba/postgres-mcp (MIT); TDD-hybrid (strict TDD for new code, characterization tests for inherited kernel) |
accepted | 2026-05-20 |
| ADR-0002 | Stack: Python 3.12 + psycopg3 + mcp SDK + pglast; mypy --strict + coverage gate for new code |
accepted | 2026-05-20 |
| — | Phase 4: DDL gated behind a second opt-in (MCPG_ALLOW_DDL); no dry-run (direct execution) |
accepted | 2026-05-20 |
| — | Extension support (Phases 8–11) lands after the v0.1.0 release (Phase 7) | accepted | 2026-05-20 |
| — | Index intelligence (Phase 8) is the first extension area implemented | accepted | 2026-05-20 |
| ADR-0003 | Configurable pool sizing via a minimal behaviour-preserving patch to the vendored DbConnPool |
accepted | 2026-05-20 |
| — | Multi-tenancy/RLS: document-only for v0.1.0 (one instance per tenant); per-request SET ROLE deferred post-1.0 |
accepted | 2026-05-20 |
Open questions
All resolved as of 0.6.9:
Remote HTTP transport auth model (Phase 1/3).Shipped: static bearer token + OIDC/JWT validation (mcpg.http_runtime,mcpg.oidc).Whether tuning tools need opt-in beyondResolved: reads need no opt-in; only DDL/shell/listen/migrate carry the per-featureunrestricted(Phase 5).MCPG_ALLOW_*gates (seepolicy.py).Observability scope (Phase 6).Shipped: Prometheus metrics + OpenTelemetry tracing (mcpg.observability,mcpg.otel_tracing).
Session log
- 2026-05-20 — Researched ecosystem, created
PLAN.md+ this tracker. Official MCP Postgres server confirmed deprecated/archived;crystaldba/postgres-mcpidentified as strongest base. Plan committed; Phase 0 ready to start. - 2026-05-20 — Task 0.1/0.2: hands-on eval of
crystaldba/postgres-mcp(commit07eb329, MIT, ~7.3k src / ~6.4k test LOC, real-Postgres tests). Decided hard-fork with TDD-hybrid strategy. Wrote ADR-0001 + ADR-0002. - 2026-05-20 — Task 0.3/0.4: narrowed vendoring scope to the self-contained
sql/subpackage only (import-graph verified). Vendored 6 files + 75 tests, scaffolded theuvproject (pyproject.toml, tooling config,NOTICE,CHANGELOG.md). All tests/lint/types green locally. - 2026-05-20 — Task 0.5: added GitHub Actions CI (
ci.yml) running ruff, ruff-format, mypy, and pytest. Coverage gate + PG matrix deferred (see notes). - 2026-05-20 — Task 0.6/0.7: added
CONTRIBUTING.md, local pre-commit hooks, issue/PR templates. Setforce-excludeso ruff skips vendored code under pre-commit. CI run #1 green. Phase 0 complete. - 2026-05-20 — Task 1.1: TDD’d the env-driven config loader (
mcpg/config.py):Settings,AccessMode,Transport,load_settings,ConfigError. 16 tests, 100% coverage of authored code; repr redacts credentials. - 2026-05-20 — Task 1.2: TDD’d the
Databaselifecycle wrapper (mcpg/database.py) around the vendoredDbConnPool— connect/close, async context manager, typedDatabaseError. Switched pytest toasyncio_mode = auto. 99 tests, 100% coverage. - 2026-05-20 — Task 1.3: TDD’d the server bootstrap (
mcpg/server.py):create_server,make_lifespan,AppContext,run. No global state — shared state lives in the lifespan.rundispatches all three transports, so Task 1.5 is reduced to the CLI entry point. 104 tests, 100% coverage. Installed thepre-commitgit hook locally. - 2026-05-20 — Task 1.4: TDD’d the first tool (
mcpg/tools.py):ServerInfo,build_server_info,register_tools+ theget_server_infotool. MovedAppContexttomcpg/context.pyto break a server/tools import cycle. Verified the tool end-to-end via an in-memory MCP client. 108 tests, 100% cov. - 2026-05-20 — Task 1.5/1.6: TDD’d the
mcpgCLI entry point (mcpg/__main__.py) and restored the[project.scripts]entry; wired the coverage gate into CI (pytest --cov). 110 tests, 100% coverage. Phase 1 complete. - 2026-05-20 — Task 2.1: integration-test harness (
tests/integration/):database_url/connected_databasefixtures gated onMCPG_TEST_DATABASE_URL, auto-integrationmarker, 3 real-DB tests for theDatabaselifecycle. CItestjob is now a PG 14–17 service-container matrix. Verified locally against PostgreSQL 16. 113 tests, 100% coverage. - 2026-05-20 — Task 2.2: TDD’d schema introspection (
mcpg/introspection.py):list_schemas,list_tables,describe_table,list_indexes,list_extensions— typed results, parameterised catalog queries — plus their MCP tools. AddedFakeDriver/FakeDatabasedoubles and real-DB integration tests. 126 tests, 100% coverage. - 2026-05-20 — Task 2.3: TDD’d
run_select(mcpg/query.py) — runs agent-supplied SQL through the vendoredSafeSqlDriver(AST allowlist + forced read-only), returns a typedQueryResult, wraps rejections/failures inQueryError. Registered therun_selecttool. 136 tests, 100% coverage. - 2026-05-20 — Task 2.4: TDD’d
explain_query(mcpg/query.py) — wraps the query inEXPLAIN (FORMAT JSON), validated by the same allowlist, returns a typedExplainResult. Registered theexplain_querytool. 142 tests, 100% cov. - 2026-05-20 — Task 2.5: TDD’d result shaping for
run_select— amax_rowscap (default 1000) with atruncatedflag onQueryResult, exposed as a tool parameter. Cursor-style pagination is left to caller SQLLIMIT/OFFSET. 146 tests, 100% coverage. Phase 2 complete. - 2026-05-20 — Task 3.1: TDD’d the access-mode policy engine (
mcpg/policy.py):Capabilityenum + per-mode permission table.register_toolsnow takes the access mode and gates registration by capability (all current tools are reads; write gating bites in Phase 4). 157 tests, 100% coverage. - 2026-05-20 — Task 3.2: added an adversarial SQL-safety regression suite
(
tests/unit/test_sql_safety.py) — 21 hostile queries (statement stacking, comment escapes, transaction-control escapes, DDL/DML, COPY, DO blocks) all rejected before reaching the driver; 5 legitimate reads still accepted. 183 tests, 100% coverage. - 2026-05-20 — Task 3.3: TDD’d audit logging (
mcpg/audit.py):AuditEvent,redact_arguments(masks secret-named args, obfuscates embedded passwords),record.AuditedFastMCPoverridescall_toolso every tool invocation — success or error — is logged to themcpg.auditlogger. 192 tests, 100% cov. - 2026-05-20 — Task 3.4: wrote the threat model and security documentation
(
docs/security.md) — trust boundaries, threats T1–T5 with mitigations, operator responsibilities, scope. Linked docs from the README. Phase 3 complete. - 2026-05-20 — Task 4.1: TDD’d
run_write(mcpg/write.py) — parses withpglast, requires exactly one INSERT/UPDATE/DELETE (blocks statement stacking), executes read-write.register_toolsnow takesSettingsand gates therun_writetool to unrestricted mode. 209 tests, 100% coverage. - 2026-05-20 — Task 4.2: TDD’d
run_ddl(mcpg/write.py) — single-statement DDL allowlist. Added theMCPG_ALLOW_DDLconfig flag (Capability.DDL); therun_ddltool is registered only in unrestricted mode with the opt-in enabled. 224 tests, 100% coverage. - 2026-05-20 — Task 4.3: verified write tool calls are audited end-to-end
(
tests/unit/test_audit.py). 225 tests, 100% coverage. Phase 4 complete. - 2026-05-20 — Task 5.1: TDD’d database health checks (
mcpg/health.py):check_connections,check_cache_hit_ratio,check_dead_tuples,check_invalid_indexes, aggregated bycheck_database_healthand exposed as a tool. Added theFakeRoutingDrivertest double. 234 tests, 100% cov. - 2026-05-20 — Task 5.2: TDD’d
analyze_workload(mcpg/workload.py) — slowest queries viapg_stat_statements, degrading gracefully toavailable=Falsewhen the extension is absent. 239 tests, 100% coverage. - 2026-05-20 — Task 5.3: TDD’d
recommend_indexes(mcpg/indexing.py) — a table-level heuristic flagging large tables read mostly by sequential scan (column-level recommendations deferred to Phase 8). 244 tests, 100% coverage. - 2026-05-20 — Task 5.4: TDD’d
analyze_query_plan(mcpg/query.py) — walks theEXPLAIN (FORMAT JSON)tree into a structured summary (total cost, estimated rows, node types, sequential scans). 249 tests, 100% coverage. Phase 5 complete. - 2026-05-20 — Task 6.1: configurable connection-pool sizing. ADR-0003 chose a
minimal vendored
DbConnPoolpatch (min_size/max_sizeparams); addedMCPG_POOL_MIN_SIZE/MCPG_POOL_MAX_SIZEsettings flowing intoDatabase. 256 tests, 100% coverage. - 2026-05-20 — Task 6.2: multi-tenancy & RLS. Decided document-only for
v0.1.0 —
docs/security.mdgains a “Multi-tenancy and Row-Level Security” section (one instance per tenant with a tenant-specific role). The per-requestSET ROLEmechanism is deferred post-1.0. - 2026-05-20 — Task 6.3: added
benchmarks/bench.py(concurrentrun_selectthroughput/latency harness) anddocs/scaling.md(execution model, pool sizing, measured baseline ~2200 req/s p50 ~7ms, bottleneck guidance). Task 6.4 deferred post-1.0; Phase 6 effectively complete for v0.1.0. - 2026-05-20 — Task 7.1: wrote
docs/usage.md(install, configuration env-var table, access modes, running, MCP client config, troubleshooting) anddocs/tools.md(reference for all 14 tools). Linked from the README. - 2026-05-20 — Task 7.2: added a
uv-basedDockerfile(non-root, streamable-HTTP default) and.dockerignore; documented Docker usage and a README quick start. Not built locally (no Docker in this environment). - 2026-05-21 — Task 7.3: bumped the version to 0.1.0 (
pyproject.toml,mcpg.__version__,uv.lock), finalised the CHANGELOG with a[0.1.0]section. 256 tests green. Phase 7 complete — v0.1.0 release-ready, awaiting user sign-off to tag/publish. - 2026-05-20 — Planning: added PostgreSQL extension support to the roadmap
(
PLAN.md§7a + Phases 8–11): index-method intelligence (GIN/GiST/BRIN/…),pg_trgm/ full-text search,pgvector, PostGIS. Per-extension priority table recorded; ordering revisited before Phase 8 starts. - 2026-05-21 — v0.1.0 merged to
mainvia PR #1 (CI green, PG 14–17). Branch synced to mergedmain; post-1.0 extension work continues here. - 2026-05-21 — Task 8.1:
list_indexesnow reports each index’s access method (btree/gin/gist/brin/hash/spgist) via apg_amcatalog join;IndexInfogains amethodfield. 256 tests, 100% coverage. - 2026-05-21 — Task 8.2: added
list_available_extensions(pg_available_extensions) reporting every available extension with installed-vs-not status, exposed as an MCP tool. 258 tests, 100% coverage. - 2026-05-21 — Task 8.3: added
mcpg/extensions.py—enable_extensionrunsCREATE EXTENSION IF NOT EXISTSfor names on a curated allowlist (the injection guard, since the name is an identifier). Exposed as a DDL-gated MCP tool. 265 tests, 100% coverage. - 2026-05-21 — Task 8.4:
recommend_indexesis now index-type aware — a single join ofpg_stat_user_tables+information_schema.columnsyields per-columnIndexSuggestions (GIN forjsonb/arrays, trigram GIN for text). 268 tests, 100% coverage. Phase 8 complete. - 2026-05-21 — Task 9.1: added
mcpg/textsearch.py—fuzzy_searchranks a text column bypg_trgmtrigram similarity, degrading toavailable=Falsewhen the extension is absent. Identifiers are validated + quoted (the term is bound). Sharedextension_installedhelper moved tomcpg/extensions.py. 277 tests, 100% coverage. - 2026-05-21 — Task 9.2: added
full_text_search(mcpg/textsearch.py) — ranks documents via built-intsvector/websearch_to_tsquery/ts_rank(no extension needed); text-search config is identifier-validated. 285 tests, 100% coverage. Phase 9 complete. - 2026-05-21 — CI now runs the matrix on
pgvector/pgvector:pgNNimages so Phase 10 vector tests run for real. Task 10.1:describe_tablerewritten to apg_attributecatalog query;ColumnInfogainsvector_dimension, reported forvector(N)columns. 286 tests (1 pgvector test skips locally), 100% coverage. - 2026-05-21 — Docs: split
usage.mdinto livingdocs/installation.md(Installation Guide) anddocs/user-guide.md(User Guide), and addeddocs/architecture.md(Architecture Document). These are maintained alongside feature work (seeCONTRIBUTING.md). - 2026-05-21 — Task 10.2/10.3: added
vector_search(pgvector k-NN,mcpg/ textsearch.py); confirmed HNSW index awareness vialist_indexes. 291 tests (3 pgvector integration tests run in CI), 100% coverage. Phase 10 complete. Phases 0–10 done; 19 MCP tools. - 2026-05-21 — Phase 11: CI now builds a pgvector + PostGIS image
(
.github/ci-postgres.Dockerfile); addedgeo_search(PostGIS k-NN by distance to a lon/lat point) tomcpg/textsearch.py. 296 tests (4 extension integration tests run in CI), 100% coverage. Phase 11 complete — all eleven planned phases delivered; 20 MCP tools. - 2026-05-21 — Live-test of the real server surfaced a
fuzzy_searchUX gap; added aword/fullmode(defaultword). 306 tests. - 2026-05-21 — Capability gap analysis (
PLAN.md§7b): added Phases 12–15 to the roadmap — deeper schema introspection, partitioning, access-control introspection, and live ops & maintenance. - 2026-05-21 — Task 12.1: added
list_constraints— PK/FK/unique/check/ exclusion constraints on a table, viapg_constraint. 309 tests, 100% cov. - 2026-05-21 — PR #2 (v0.2.0 + Phase 12 start) merged to
main; branch re-synced. Task 12.2: addedlist_views— views and materialized views in a schema with definitions, viapg_class. 311 tests, 100% coverage. - 2026-05-21 — Task 12.3: added
list_functions— functions and procedures in a schema (kind, arguments, return type, language), viapg_proc. 313 tests, 100% coverage. - 2026-05-21 — Task 12.4: added
list_triggers— user-defined triggers on a table (function + definition), viapg_trigger. 315 tests, 100% coverage. - 2026-05-22 — Task 12.5: added
list_sequences— sequences in a schema (data type, range, increment, cycle, last value), viapg_sequences. Phase 12 complete. 318 tests, 100% coverage. - 2026-05-22 — Task 13.1: added
list_partitions— a table’s partitioning strategy and partitions with bound expressions, viapg_partitioned_tableandpg_inherits. 323 tests, 100% coverage. - 2026-05-22 — Task 13.2:
list_tablesnow readspg_classand flags each table withpartitionedandis_partition. 325 tests, 100% coverage. - 2026-05-22 — Task 13.3:
list_indexesflags partitioned-index templates;recommend_indexesrolls partition stats up to the partitioned parent. Phase 13 complete. 328 tests, 100% coverage. - 2026-05-22 — Task 14.1: added
list_policies— Row-Level-Security policies on a table (command, permissive, roles, predicates) plus the table’s RLS-enabled flag, viapg_policies. 334 tests, 100% coverage. - 2026-05-22 — Task 14.2: added
list_roles— database roles and their attributes (superuser, create-role/db, login, replication, bypass-RLS, connection limit, membership), viapg_rolesandpg_auth_members. 340 tests, 100% coverage. - 2026-05-22 — Task 14.3: added
list_grants— privileges granted on a table (grantee, privilege, grantable, grantor), viainformation_schema.table_privileges. Phase 14 complete. 342 tests, 100% coverage. - 2026-05-22 — Task 15.1: added
list_active_queries(newmcpg/liveopsmodule) — in-flight queries with wait events, duration, and blocking PIDs, viapg_stat_activityandpg_blocking_pids. 346 tests, 100% coverage. - 2026-05-22 — Task 15.2:
check_database_healthgainsreplication_lag(viapg_stat_replication) andtable_bloat(catalog-only size estimate) checks. 349 tests, 100% coverage. - 2026-05-22 — Task 15.3: added gated
run_maintenance(newmcpg/maintenancemodule) — VACUUM/ANALYZE on one table via a new autocommitDatabase.run_unmanagedpath. 357 tests, 100% coverage. - 2026-05-22 — Task 15.4: added gated
cancel_queryandterminate_backend— signal a backend PID viapg_cancel_backend/pg_terminate_backend. Phases 12–15 complete. 365 tests, 100% coverage. - 2026-05-23 — Post-Phase-15 roadmap (
PLAN.md§11) captured: Phases 16–27 grouped into six batches (catalog completeness, advisors, extension wrappers, data movement, replication/events, migrations). - 2026-05-23 — Task 16.1: added
list_enums,list_domains,list_composite_types— user-defined types viapg_type/pg_enum/pg_constraintandpg_attribute. Composite types filter onrelkind='c'to exclude table row-types. 251 unit tests. - 2026-05-23 — Task 16.2: added
list_foreign_data_wrappers,list_foreign_servers,list_foreign_tables,list_user_mappings— postgres_fdw and other wrappers viapg_foreign_data_wrapper,pg_foreign_server,pg_foreign_table,pg_user_mappings. Text[] options parsed into typed dicts. 255 unit tests. - 2026-05-23 — Task 16.3: added
list_publicationsandlist_subscriptions— read-only logical-replication catalog viapg_publication/pg_publication_tablesandpg_subscription. Phase 16 complete (42 MCP tools total). 257 unit tests, 100% coverage. - 2026-05-23 — PR #4 merged to
main(Phase 16); branch re-synced. - 2026-05-23 — Phase 17: added
list_foreign_keys(structured FK introspection viapg_constraint/pg_attributealigned by ordinal) andgenerate_schema_diagram(newmcpg.diagramsmodule) — a Mermaid ER renderer with PK/FK column markers, parent→child edges, cross-schema edge filtering, and aninclude_partitionsknob. Phase 17 complete (44 MCP tools total). 396 tests, 100% coverage. - 2026-05-23 —
PLAN.md§11 gained Batch G (ORM bridges): Phase 28generate_prisma_schemaflagged as a deliberate USP. Sibling tools for Drizzle, SQLAlchemy, sqlc may follow; scope deliberately narrow (catalog → DSL only, no DSL→DDL parsing, noprisma migratedriving). - 2026-05-23 — PR #5 merged to
main(Phase 17); branch re-synced. - 2026-05-23 — Phase 18: added
compare_schemas(newmcpg.schema_diffmodule) — structural diff between two schemas reporting tables / columns / indexes / constraints / foreign keys as added, removed, or changed. Identity is by name (renames = paired add + remove). Column changes carry afields_changedlist of differingColumnInfofields. Built on a small generic name-keyed helper_diff_by_name[T, C]shared across the four per-table object kinds. Batch A complete (catalog completeness → visualisation → diff). Phase 18 complete (45 MCP tools total). 409 tests, 100% coverage.FakeParamRoutingDrivertest fake added so the diff can be exercised in unit tests with two distinct fake schemas. - 2026-05-23 — v0.3.0 cut. Version bumped (pyproject +
__init__); CHANGELOG[Unreleased]→[0.3.0]. README refreshed (tool count 45, capability summary, PG 14–17 matrix).docs/tools.mdgained sections for the 12 Phase-16/17/18 tools and a new “Visualisation & diff (read)” group. Tech-debt audit: the “every introspection tool is callable” wiring check moved from unit (fakes-only) to integration (real-PG smoke across the matrix) — closes the one trust gap a fake driver couldn’t reach. PROGRESS tool counts corrected (Phases 16/17/18 were drifting low). - 2026-05-23 — PR #7 merged to
main(v0.3.0 release); branch re-synced. Localv0.3.0tag created on1c74b04butgit pushto the sandboxed remote returned 403; GitHub release to be cut manually fromdocs/release-notes-0.3.0.md. - 2026-05-23 — Phase 22 (Batch C, first half): new
mcpg.cronmodule addslist_cron_jobs(read; returns[]when pg_cron absent),schedule_cron_jobandunschedule_cron_job(write-gated). Newmcpg.partmanmodule addspartman_create_parent,partman_run_maintenance(single parent or all), andpartman_drop_partition(time- or id-controlled retention). Both extensions added toENABLEABLE_EXTENSIONS. Tests: 24 new unit tests covering graceful degradation + tool wiring matrix; new integration tests gated on extension availability (CI image doesn’t ship either extension — skip path verified). Phase 22 complete (51 MCP tools total). 434 tests, 100% coverage. - 2026-05-23 — PR #8 review fix: Gemini flagged that partman tools
perform DDL (CREATE/DROP partitions) but were registered under
Capability.WRITE, bypassing the MCPG_ALLOW_DDL guardrail. Split
_register_schedulinginto_register_cron_write(WRITE, cron DML) and_register_partman(DDL, alongside run_ddl / enable_extension). New unit test pins the gate. - 2026-05-23 — PR #8 merged to
main; branch re-synced. - 2026-05-24 — Phase 23 (Batch C second half): new
mcpg.vector_tuningmodule addstune_vector_index— recommends ivfflat/hnsw parameters from row count (via pg_class.reltuples) and column dimension, emits a ready-to-run CREATE INDEX statement — andvector_recall_at_kwhich compares the ANN operator path (<->/<=>/<#>, index-using) against the brute-force function path (l2_distance/cosine_distance/inner_product, documented by pgvector as non-indexed) to report mean recall over a row sample. Both raise VectorTuningError when pgvector is absent. 21 new unit tests + 3 integration tests against a real pgvector hnsw index (seeded with well-separated vectors → recall ~= 1.0). Batch C complete. Phase 23 complete (53 MCP tools total). 456 tests, 100% coverage. - 2026-05-24 — PR #9 review fix: Sourcery + Gemini flagged identifier
injection across 6 SQL sites in vector_tuning.py plus an unbounded
sample_sizeDoS invector_recall_at_k. Added a local_quotedhelper (allowlist[A-Za-z_][A-Za-z0-9_]*+ double-quote) and a_MAX_SAMPLE_SIZE = 100cap. New tests pin the gates. - 2026-05-24 — PR #9 merged to
main; branch re-synced. Batch C closed. - 2026-05-24 — Phase 28 (Batch G first cut): new
mcpg.prismamodule exposesgenerate_prisma_schema— read a PG schema and emit a valid Prisma.prismaschema string. Mirrorsprisma db pullfor the most-used surface: tables → models with PK/FK/composite-PK/composite- unique/secondary indexes; enums → top-level Prisma enums; standard defaults (nextval(...)→autoincrement(),now()/CURRENT_ TIMESTAMP→now(),gen_random_uuid()→uuid(), literals) mapped; unmappable types (vectors, custom domains) fall back toUnsupported("..."). Identifiers must match[A-Za-z_][A-Za-z0-9_]*and the schema-qualified prefix is stripped for enum / scalar lookup. 19 new unit tests cover the type/default mapping, FK back-relations, composite-PK + composite-unique rendering, index deduplication, and the Unsupported fallback; 1 integration test end-to-ends a real schema with serial PKs, an enum-typed column, an FK, and a secondary index. First USP-tier tool — no other PG MCP server bridges to an ORM schema DSL. Phase 28 complete (54 MCP tools total). 482 tests, 100% coverage. - 2026-05-24 — PR #10 review fix: 12 Sourcery + Gemini comments
collapsing to FK-name validation, Unsupported() quote escaping, dead
fk_columns_to_relation,_prisma_typesimplification, FK-name vs column-name collision detection, and three test-gap fills. Resolved acrossf231bc9and11dcb9d. - 2026-05-24 — PR #10 merged to
main; branch re-synced. Batch G first cut closed. - 2026-05-24 — Phase 20 (Batch B first half): new
mcpg.advisorsmodule exposes one read-only tool,run_advisors, that runs four codified catalog-driven rules and aggregates findings:missing_primary_key,unindexed_foreign_key(leading-column heuristic viapg_constraint.conkey[1]vspg_index.indkey[0]),duplicate_indexes(matchingindkey+ samerelam, deduplicated viaindexrelidinequality), andnullable_timestamp_without_tz(catches the common TZ-coercion source). 9 unit tests cover each rule + aggregator; 1 integration test seeds one example violation per rule plus a clean control table against real PG. Phase 20 complete (55 MCP tools total). 500 tests, 100% coverage. - 2026-05-24 — PR #11 review fix: Gemini flagged
_duplicate_indexesignoringindisunique/indpred/indclass/indoption/indexprs, which would have produced false positives an agent could act on destructively. Tightened the join + new regression test pinning the unique-vs-plain and partial-vs-plain non-duplication. Sourcery’sindkey[0]“always NULL” claim was incorrect (int2vector is 0-based in SQL, unlike int2[]) — replied with the explanation. - 2026-05-24 — PR #11 merged to
main; branch re-synced. - 2026-05-24 — Phase 21 (closes Batch B) + CI matrix: new
mcpg.audit_trailmodule exposeslist_audit_events(read tool, newest-first, optional tool-name filter) backed by an idempotentmcpg_audit.eventstable. NewMCPG_AUDIT_PERSISTenv var (default false) toggles per-call persistence inrun_write/run_ddl; arguments are credential-redacted before storage.run_ddlgains optionalschema/tablehints — when both supplied, the call snapshots the table’s columns before and after the DDL and attaches aSchemaDiffSnapshotto the result (and to the audit row). Audit- persistence failures are swallowed so they never mask real write outcomes. PG 18 added to the CI matrix (was 14-17; now 14-18). 11 new audit-trail unit tests + 5 new write-tests + 2 integration tests cover persistence happy path, error path, schema-diff capture, no-schema-no-capture, redaction, and the read tool’s empty/filled paths. Phase 21 complete (56 MCP tools total). 519 tests, 100% coverage. - 2026-05-24 — PR #12 review fix: Gemini caught two security-critical
issues (shallow
_redactleft credentials nested inresultunmasked;resultpayload was never run through_redactat all) and one performance issue (ensure_audit_tableran two CREATE round-trips per audited write). Recursive_redact,resultredaction at the record_audit call site, and a per-driverid(driver)-keyed ensure cache fix all three; 4 new tests pin them. - 2026-05-24 — PR #12 merged to
main; branch re-synced. Batch B closed, PG 18 live in the matrix on every PR. - 2026-05-24 — ADR-0004 (subprocess execution policy for Batch D),
ADR-0005 (LISTEN/NOTIFY delivery model for Batch E), and ADR-0006
(migration shadow-workflow strategy for Batch F) drafted and
accepted. Each picks a specific implementation path and pins the
policy / gates / failure surface up front so the implementation
PRs can focus on code rather than re-litigation. Highlights:
ADR-0004 puts subprocess behind a new
Capability.SHELL+MCPG_ALLOW_SHELLopt-in alongside the existingMCPG_ALLOW_DDLgate, with an allowlisted binary set, argv-only invocation, hard timeout, output cap, and credential-env-var passing (never on the command line). ADR-0005 picks the tool-poll model (subscribe_channel+poll_notifications) over MCP-side notifications, owning subscription state in a newmcpg.listenmodule and gating writes behindMCPG_ALLOW_LISTEN. ADR-0006 picks the same-database shadow-schema strategy overCREATE DATABASE TEMPLATEso a 500 GB database doesn’t pay full-clone cost on every staged migration; uses Phase-18compare_schemasas the agent’s review surface and stores migration state in a newmcpg_migrations.stagedtable alongside the existingmcpg_audit.events. Batches D, E, F are no longer ADR-gated; implementation order is open. - 2026-05-24 — PR #13 (ADRs) merged to
main; branch re-synced. - 2026-05-24 — Phase 24a (Batch D first slice): new
mcpg.data_movementmodule exposesexport_query(runs SQL through the existingrun_selectsafety checks, serialises rows to CSV or JSON) andexport_table(SELECT * FROM schema.table with the identifier allowlist). Both are read-only, no subprocess, no new attack surface — ADR-0004’s subprocess gate isn’t needed yet.truncatedflag in the result lets agents paginate without silently losing rows. CSV writer quotes commas + stringifies non-scalar values (datetime / UUID / Decimal) so the output is always parseable; JSON serialiser passesdefault=strfor the same reason. 15 new unit tests cover the format helpers (_rows_to_csv/_rows_to_json), every error path (unsupported format, non-positive limit, non-SELECT SQL, invalid identifier), the truncation flag, and the MCP tool wiring. 3 integration tests build a real schema with a row containing a comma in its text value and assert the CSV/JSON round-trip. Phase 24a complete (58 MCP tools total). 541 tests, 100% coverage. - 2026-05-25 — PR #14 (Phase 24a) merged to
main; branch re-synced. Gemini’s CSV-correctness catch (None→ empty,dict/list→ JSON, not Python repr) and accompanying regression tests landed with the merge. - 2026-05-25 — Phase 24b (subprocess infrastructure + first shell
tool): new
mcpg.shellmodule is the only place in MCPg that invokes external binaries, enforcing the ADR-0004 policy in one place — allowlisted binary set (pg_dump/pg_restore/psql),asyncio.create_subprocess_exec(binary, *argv)invocation, hard timeout (kills + flagstimed_out), stdout cap (drops tail + flagsoutput_truncated), libpq env-var credentials filtered to an allowlist (PGHOST/PGPORT/PGUSER/PGPASSWORD/PGDATABASE/PGSSLMODE/…), andPGPASSWORDredacted in the result for audit. NewCapability.SHELLenum entry; new env varsMCPG_ALLOW_SHELL(default false),MCPG_SHELL_TIMEOUT_SEC(default 60),MCPG_SHELL_MAX_OUTPUT_BYTES(default 64 MiB). Newdump_databasetool inmcpg.data_movementis the first consumer: parses the configured database URL into the libpq env, invokespg_dumpthrough the shell runner, returns the dump as text (plain format) or base64 (custom/tar). 13 new shell unit tests + 14 newdump_databaseunit tests + 1 real-pg_dumpintegration test cover allowlist / env filtering / redaction / truncation / timeout / URL parsing / format selection / tool-wiring gate. Phase 24b complete (59 MCP tools total). 568 tests, 100% coverage. - 2026-05-25 — PR #15 review fix: PG 17/18 CI failed because the ubuntu-latest runner ships an older pg_dump that refuses to dump from a newer server. Workflow now installs the matching postgresql-client-N from the pgdg apt repo before each test job, so pg_dump always matches the matrix server version. PG 14-18 all green after the fix; PR #15 merged.
- 2026-05-25 — Phase 24c (restore half of Batch D dump/restore
symmetry): new
restore_databasetool pipes a dump back into the connected database —format='plain'through psql with--single-transaction --set=ON_ERROR_STOP=on,custom/tarthroughpg_restore --single-transaction --exit-on-error. Base64-decodes binary payloads; rejects malformed base64 with ShellError. Audit trail integration is identical to dump_database. Fixed a latentmcpg.shellbug:stdinwas written AFTERprocess.wait()returned, which would deadlock any consumer of stdin (no shipped tool exercised stdin yet so it didn’t bite, but it blocked restore_database from working). Now writes stdin concurrently with the stdout/stderr drain. 7 new unit tests cover plain → psql wiring, custom → pg_restore wiring + base64 decoding, unsupported format / invalid base64 / missing-database rejection, and the shell-gate tool-wiring matrix. 1 new integration test runs a real dump → drop schema → restore round-trip against every PG version in the CI matrix. Phase 24c complete (60 MCP tools total). 576 tests, 100% coverage. - 2026-05-25 — Phase 24e (bulk imports): two new write tools land
the import half of Batch D.
import_csvpipes raw CSV content intoCOPY "schema"."table" [(cols)] FROM STDIN WITH (FORMAT csv, HEADER ?, DELIMITER ?)— header / delimiter / explicit-columns all configurable, with the delimiter restricted to a single non-newline non-quote character so it cannot terminate the COPY options list.import_jsonparses a JSON array of objects, derives the column list from the first row’s keys (or an explicitcolumnsarg), and runsINSERT INTO ... VALUES (%s, ...)viaexecutemany; nested dict/list values are JSON-serialised so they survive into a jsonb column, missing keys bind as NULL. Both gated under unrestricted mode (WRITE capability) — no subprocess, noMCPG_ALLOW_SHELL. VendoredSqlDriverdoesn’t expose COPY or executemany, so two new helpers (Database.copy_from_stdin,Database.execute_many) wrap raw pool-connection access;FakeDatabasegrew matching recorders so unit tests don’t need a live server. 19 new unit tests cover SQL composition, identifier rejection, delimiter validation, empty-input no-op, error wrapping, negative-rowcount fallback, and the WRITE-gate tool wiring matrix. 2 new integration tests round-trip real CSV + JSON loads against every PG version in the CI matrix (including ajsonbcolumn on the JSON path). Phase 24e complete (62 MCP tools total). 599 tests, 98% coverage. - 2026-05-25 — Phase 24d (closes Batch D): new
copy_table_between_databasestool runspg_dump --format=custom --table=schema.tableagainst a caller- supplied source URL, captures the binary archive in memory, then pipes it throughpg_restore --format=custom --single-transaction --exit-on-error --no-owner --no-privilegesagainst the configured destination URL. Both legs go through the existingmcpg.shell.run_pg_binaryrunner with separate libpq env dicts so credentials never reach argv on either side. pg_restore needs--dbnameeven with PGDATABASE set (without-dit switches to script-output mode), so the argv carries--dbname=postgresql:///— an empty libpq URI that makes libpq fall back to PG* env for every connection parameter.include_schemaandinclude_dataare required (no defaults) per design feedback. A truncated dump raisesShellErrorBEFORE pg_restore runs (a partial custom- format archive cannot be safely restored); a non-zero dump exit short-circuits and returns the dump stderr_tail withrestore_exit_code=-1. 11 new unit tests cover the two-leg pipeline (separate envs, stdin handoff), schema-only / data-only argv composition, both-flags-off rejection, identifier rejection on each side, both-URL database-name requirement, truncation refusal, dump-failure short-circuit, restore-timeout flag surfacing, and theMCPG_ALLOW_SHELLtool-wiring gate. 1 new integration test spins up a fresh target database viarun_unmanaged, pre-creates the schema there (pg_dump –table doesn’t includeCREATE SCHEMA), copies the seeded widget table across, and verifies the rows arrived. Batch D closed — export, dump, restore, bulk import, and cross-DB copy are all shipped. Phase 24d complete (63 MCP tools total). 611 tests, 98% coverage. - 2026-05-25 — Phase 26 (Batch E first slice, LISTEN/NOTIFY bridge):
new
mcpg.listenmodule implements the ADR-0005 tool-poll model.ListenManagerowns server-lifetime subscription state behind an asyncio.Lock; subscriptions get individual boundedasyncio.Queues and overflow drops oldest while bumping a per-sub drop counter that surfaces in the next poll’s first message (then resets). A dedicated PG connection (lazy — opened only on first subscribe, separate from the request pool) holds every active LISTEN; a backgroundasyncio.Taskdrains psycopg’snotifies()generator. Discovery during integration testing: psycopg’s connection lock is held whilenotifies()waits on the socket, so atimeout=Noneiteration would deadlock concurrent UNLISTEN execute() calls. Fixed by iterating withtimeout=0.5and yielding between iterations so the lock is released periodically. Four new tools land:subscribe_channel,poll_notifications,unsubscribe_channel,list_notification_subscriptions. NewCapability.LISTEN+MCPG_ALLOW_LISTENopt-in (defence-in-depth: must be unrestricted AND opt-in). NewMCPG_LISTEN_QUEUE_MAXknob (default 1000).AppContextgrew alisten_managerfield;create_serveraccepts an injectablelisten_managerso unit tests can pass a fake connection factory. Server lifespan enters/exits the manager viaasync with, so subscriptions cannot outlive the server. 20 new unit tests cover subscribe / unsubscribe lifecycle, LISTEN/UNLISTEN reference counting per channel, queue overflow + dropped_count semantics, poll validation, channel-name allowlist, close idempotency, and the three-mode tool-wiring gate. 2 new integration tests round-trip a realSELECT pg_notify(...)from one connection to the listener and verify unsubscribe halts delivery. Phase 26 complete (67 MCP tools total). 635 tests, 97% coverage. - 2026-05-25 — Phase 27 (closes Batch F, staged-migration workflow):
new
mcpg.migrationsmodule implements ADR-0006’s same-database shadow strategy.prepare_migrationcreates a freshmcpg_shadow_<id>schema, replays the target schema’s structure into it via introspection (tables + columns, PK / UNIQUE / CHECK / FK constraints, indexes; intra-schema FKs are rewritten to point at the shadow, cross-schema FKs documented as remaining- pointed-at-original per ADR), applies the candidate SQL withSET LOCAL search_pathso unqualified identifiers resolve in the shadow, runscompare_schemas(target, shadow), and persists the staged row inmcpg_migrations.staged.complete_migrationruns the same candidate against the target schema (same SET LOCAL treatment) and drops the shadow;cancel_migrationdrops the shadow without applying (idempotent).list_pending_migrationssweeps expired prepared rows before listing. NewCapability.MIGRATEgates the four tools under unrestricted mode- the existing
MCPG_ALLOW_DDLopt-in (the underlying ops are DDL). Discovery during smoke testing: the vendoredSqlDrivergives a fresh pool connection perexecute_querycall, so a standaloneSET search_pathwould only affect that one call. Fix: a_execute_in_schemahelper reaches through the driver to the underlying pool, opens one connection, and runs SET LOCAL + the candidate SQL together in one transaction. Second discovery:TableInfo.typecomes frominformation_schemaasBASE TABLEnottable; the replay filter had to match. 16 new unit tests cover the pure helpers (identifier check, migration-id derivation, shadow naming, column clause builder, FK + index schema rewriting), input validation inprepare_migration, and the three-mode tool- wiring gate. 5 new integration tests round-trip a real prepare → complete (column landed on target, shadow gone), prepare → cancel (shadow gone, target untouched), bad SQL rolls back the shadow without orphaning it, the pending list reflects cancellations, and complete refuses unknown or already-completed ids. Batch F closed — all three roadmap- blocking ADRs (D / E / F) are now shipped. Phase 27 complete (71 MCP tools total). 656 tests, 97% coverage.
- the existing
- 2026-05-25 — Batch G follow-ons (Phase 28b/c/d): three new ORM
exporters sit alongside the existing
generate_prisma_schemaand close out the schema→DSL umbrella.mcpg.drizzleemits adrizzle-orm/pg-coreTypeScript schema with pgTable consts, PG-native helpers (integer / bigint / varchar with length / timestamp withwithTimezone: true/ jsonb / etc.),pgEnumconsts for enum columns,serial/bigserialdetected fromnextval()defaults, single-column FKs as column-level.references(() => target.col), composite PK/unique/index in the extras callback, and a stripped import line computed from what was actually emitted (chain methods like.primaryKey()are NOT picked up — only top-level helpers).mcpg.sqlalchemy_exportemits a 2.0-style declarative file withDeclarativeBase+Mapped[T]+mapped_column, PG types from both core and the PG dialect (jsonb),ForeignKey("schema.table.col")for single-column FKs,UniqueConstraintin__table_args__for composites, Pythonenum.Enumclasses for PG enums, andserver_default=text(...)/func.now()for defaults; the output compiles cleanly undercompile()so syntax errors can never reach the agent.mcpg.sqlcemits plain DDL ordered for replay against an empty database (CREATE SCHEMA → CREATE TYPE enums → CREATE TABLE columns-only → ALTER TABLE ADD CONSTRAINT in PK/unique/check/FK order → CREATE INDEX for non-constraint indexes). All three tools are read-only — no new capability or opt-in needed. 41 new unit tests across three test files cover helper composition (camelCase / PascalCase / type maps / default rendering / nextval detection / enum resolution including schema-qualified types / FK chain rendering) and tool registration. 6 new integration tests round-trip each exporter against a real PG schema with FKs + uniques + enum + jsonb; SQLAlchemy output is verified tocompile()cleanly, and the sqlc output is verified to order PK before FK so the file replays clean. Batches A–G are all closed. Phase 28b/c/d complete (74 MCP tools total). 698 tests, 96% coverage. - 2026-05-26 — PR #17 code-review fixes: 10 confirmed findings
fixed with 25 new regression tests (restore_database missing
--dbname, ListenManager dead-conn recovery, migration CHECK-literal corruption, sqlc apostrophe escape, SQLAlchemy enum-class fallback for non-identifier labels, Drizzle default escape ordering, shadow-name NAMEDATALEN cap, migrations refuses non-transactional candidates, shell_write_stdinclose in finally, ListenManager.close conn-close timeout). Test count 698 → 723; coverage 96%. PR #17 stays open for the user’s review; PR #16 (Phase 24c shell stdin hardening) landed on main. - 2026-05-26 — v0.4.0 release prep: pyproject.toml +
mcpg/__init__.pybumped 0.3.0 → 0.4.0; CHANGELOG[Unreleased]section converted to[0.4.0] - 2026-05-26with a release-overview blurb covering Batches D/E/F/G and the 10 review fixes; newdocs/release-notes-0.4.0.mdwith the full release summary, capability table, upgrade notes, and what’s-next; README capability surface refreshed (45 → 74 tools, PG 14-18 in CI, data movement + LISTEN/NOTIFY + staged migrations + ORM bridges highlighted). No code changes — release prep only. Tagging / publishing awaits explicit user sign-off. - 2026-05-26 — v0.4.0 tagged and released on GitHub
(https://github.com/devopam/MCPg/releases/tag/v0.4.0). PR #17
merged. Branch fast-forwarded to main (
77970f2). - 2026-05-26 — Post-0.4.0 Batch G follow-ons shipped: four more
catalog→DSL exporters alongside the existing Prisma / Drizzle /
SQLAlchemy 2.0 / sqlc ones.
mcpg.dieselemits Diesel ORM (Rust)schema.rswithtable!macros,Nullable<T>for nullable columns,joinable!for single-column intra-schema FKs, anallow_tables_to_appear_in_same_query!macro, and Text-backed wrapper enums in apg_enummodule so output works withoutdiesel_derive_enum.mcpg.jooqemits ajooq-codegenconfiguration XML pointing at the live database — unlike other exporters, jOOQ generates Java code itself at build time, so the artefact is the config file (with explicit<includes>regex,<excludes>for MCPg’s bookkeeping schemas, and<forcedType>entries for json / jsonb columns → org.jooq.JSON / .JSONB).mcpg.entemits Ent (Go) Schema struct files — one.goper table, withfield.X(...)calls,edge.To(...)for FKs, andfield.Enum().Values()for enum columns.mcpg.ectoemits Ecto (Elixir) schema modules — one.exper table, named after the singularised table (Phoenix convention), with@primary_keydeclared,fieldper column,belongs_tofor single-column FKs, andtimestamps()when bothinserted_atandupdated_atexist. Configurableapp_modulearg. All four tools are read-only — no new capability or opt-in. 49 new unit tests (helper functions, FK / enum handling, default mapping, tool registration) + 5 new integration tests round-trip each exporter against real PG. Tool surface 74 → 78. 772 tests pass / 9 skipped; coverage maintained. - 2026-05-26 — Documentation pass: refreshed
docs/tools.mdto cover all 78 tools (was at 45 from the v0.3.0 era) with a capability-gate matrix and a tool-index table at the top of the page, plus new sections for data movement (read / write / shell), LISTEN/NOTIFY bridge, staged migrations, audit trail, ORM-DSL exporters (including the four follow-ons), pg_cron, pg_partman. Newdocs/tour.md— a one-page tool-tour organised by what an agent typically wants to do (“what’s in this database?”, “move data in/out”, “react to events”, “generate code for my ORM”, etc.) for fast discovery without reading the source. Updateddocs/user-guide.mdwith post-0.3.0 sections (data movement, LISTEN/NOTIFY, staged migrations, ORM bridges, persistent audit)- extended troubleshooting (new opt-in env vars, CONCURRENTLY-in-migrations error). README capability surface refreshed to list all eight ORM exporters and link the new tour doc. No code changes.
- 2026-05-26 — Tier-A pgvector tools shipped (Phase 11.1 / 11.2 /
11.3 from
docs/feature-shortlist.md). Three new tools land inmcpg.textsearchalongside the existing pgvector family.hybrid_searchdoes reciprocal-rank fusion of vector k-NN and full-text ranking — the canonical fix for the “vector misses keywords / FTS misses synonyms” gap in agentic RAG; each match carries per-source rank + the fused score so the agent can see WHY a result surfaced.vector_range_searchis the threshold-rather-than-top-k counterpart tovector_search, useful for de-dup / similarity gating; still ordered by distance and capped atlimitso a too-loose threshold can’t blow up.recommend_vector_quantizationscans a schema forvector(N)columns whose storage could halve by switching to pgvector v0.7+’shalfvec(N); the catalog query joinspg_typeand filters ontypname IN ('vector','halfvec','sparsevec')so PG’s built-inbit(N)doesn’t false-positive. 26 new unit tests- 3 new integration tests pin the wiring, including a real-PG smoke test that creates 10001 768-dim rows and verifies the advisor fires. Tool surface 78 → 81. 806 tests pass / 3 skipped.
- 2026-05-26 — Tier-A composite tools shipped (Phase 5.2 / 8.2 /
10.1 from
docs/feature-shortlist.md). Three agent-UX tools that compose existing primitives so an agent doesn’t have to issue 4-5 round trips for common queries. Newmcpg.compositemodule holdssummarize_table(columns + constraints + FKs + indexes + storage / vacuum stats + optional sample, all in one) andwhy_is_this_slow(EXPLAIN + plan analysis + active-query + blocking-lock + cache-hit snapshot + categorised suggestions — safe by design because EXPLAIN does NOT execute the query).mcpg.advisorsgrewfind_unused_objects— scanspg_stat_user_tables/pg_stat_user_indexesfor tables with zero scans + zero writes and user indexes with zero scans (excluding PRIMARY KEY / UNIQUE indexes since PG needs them regardless). Documented as a SIGNAL not a verdict. 25 new unit tests + 4 new integration tests against real PG (creates a real schema with extra unused indexes and verifies the composite shapes). Tool surface 81 → 84. 831 tests pass / 3 skipped. - 2026-05-26 — Tier-A milestone closed — three picks from
docs/feature-shortlist.mdshipped in one branch. (1.1) HTTP transport bearer-token auth via a newmcpg.http_runtimeASGI middleware: whenMCPG_HTTP_AUTH_TOKENis set, every request to the streamable-http / sse transport needs `Authorization: Bearer` (constant-time compared via `hmac.compare_digest`). `/metrics`, `/healthz`, `/readyz` are exempted so a Prometheus scraper / load-balancer probe can hit them without holding the MCP token. (2.1) In-process Prometheus metrics — new `mcpg.observability` emits `mcpg_tool_calls_total{tool,status}` and `mcpg_tool_duration_seconds_*` (histogram + sum + count) via a zero-dep text-exposition renderer. `AuditedFastMCP.call_tool` records every invocation; the same payload is exposed as the `get_metrics_exposition` MCP tool for stdio transports. (4.2) TimescaleDB hypertable wrappers — new `mcpg.timescaledb` adds five tools (`list_hypertables`, `list_chunks`, `create_hypertable`, `add_compression_policy`, `add_retention_policy`); every interval / identifier is allowlisted before being inlined into SQL, and each tool degrades to `available=False` when the extension is missing. 33 new unit tests pin the wiring (`test_observability.py`, `test_http_runtime.py`, `test_timescaledb.py`). Tool surface 84 → 90.