# Reported issues for sw-postgres-mcp

Pod holds 14 of 14 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [sw-postgres-mcp](/mcp/sw-postgres-mcp).

## Most discussed

### Submit to an MCP registry

Split — the human-only remainder (`npm publish`, demo recording, row-count verification) moved to #24. The seed/demo generator was already delivered in #10.

## What to build

Get the published package listed in the official [MCP Registry](https://registry.modelcontextprotocol.io) so clients can discover and install it.

The current submission flow is a **CLI**, not a GitHub PR. The agent-doable parts, all committed to the repo:

- **Ownership-verification marker.** For an npm package that is th

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/12) · 2026-08-12 · closed · 2 comments

### Spike: how the current MCP spec handles human-in-the-loop approval

## What to build

Answer, in writing, how the current MCP specification handles human-in-the-loop confirmation, so the approval flow is built on a sanctioned pattern rather than an invented one.

Elicitation and sampling have been moving fast. If the spec now has a first-class way for a server to ask a human for confirmation mid-tool-call, the approval flow should use it — that alignment is itself a selling point in the README. If it doesn't, the out-of-band localhost approval page is the design

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/1) · 2026-08-12 · closed · 2 comments

### Silent empty config on startup: write allowlist defaults to deny with no log trace

## Summary

When the server starts without finding a config file, `loadConfig()` (src/config.ts) silently treats the missing file as `{}`. Because connection strings commonly come from env vars (`DATABASE_URL_READONLY`/`DATABASE_URL_WRITER`), the server appears healthy: reads work (empty read allowlist = allow all), but the **empty write allowlist is default-deny**, so every write is refused with `TABLE_NOT_WRITABLE` and nothing in the logs explains why.

The config is also read exactly once at 

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/30) · 2026-08-14 · closed · 0 comments

### Fix failing tests and server.json version drift

## What to build

Two problems surfaced when running the test suite on main:

1. **Flaky approval-UI audit assertion.** `tests/approvalUi.test.ts` AC3 asserts the audit sequence after a second idempotent reject, but the core approval server sends its HTTP response *before* awaiting the `onDecision` audit hook, so the last decision's `mcp_audit.log` row can still be in flight when the test queries — the assertion fails nondeterministically under parallel-suite load.

2. **Manifest/package version

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/28) · 2026-08-14 · closed · 0 comments

### Refactor to consume safe-write-mcp-core

**Goal:** Prove the extracted core generalizes by having the original server consume it.

**Scope:** Replace src/writeCore.ts and src/approvalServer.ts with imports from safe-write-mcp-core; adapt the Postgres preview/execute callbacks to the core's preview/execute seam; keep the full existing test suite green (unit + integration + safetyCase + approvalUi); add a DECISIONS.md note recording the extraction.

**Done-when:** npm test && npm run test:integration green with the package imported; dele

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/26) · 2026-08-13 · closed · 0 comments

### Safety-case integration suite

## What to build

A test suite that demonstrates the safety layer holds as a whole, not tool by tool.

Individual tickets carry their own tests. This one covers the cross-cutting matrix — every guard against every write tool, against the seeded database, on a throwaway Postgres in Docker. **The safety cases are the tests that matter.** A green suite here is the evidence behind every claim the README makes.

The matrix:

- Threshold trip — above `approval_required_above_rows` returns `awaiting_ap

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/11) · 2026-08-12 · closed · 0 comments

### Seeded demo database generator

## What to build

Anyone who clones the repo can run one command and get the same database the demo runs against.

A committed generator script seeds a synthetic e-commerce database — roughly 200k rows across `customers`, `orders`, `order_items` and `products`, with realistic-enough distributions that query plans and row counts behave like a real database rather than a toy.

The data has to support the demo beats specifically, so these are requirements rather than incidental:

- Around **40,000 

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/10) · 2026-08-12 · closed · 0 comments

### run_migration: DDL that always requires approval

## What to build

The agent can change the schema, and a human always signs off.

`run_migration` puts DDL through the same two-phase machinery: preview, token, execute. It differs from the data tools in one way — **it always requires approval, regardless of the row threshold.** A migration touching zero rows can still be the most destructive thing the server does, so row count is the wrong gate and is not consulted.

Where DDL cannot be meaningfully previewed the way a `DELETE` can, the preview

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/9) · 2026-08-12 · closed · 0 comments

## Most recent

### insert_rows and update_rows through the two-phase core

## What to build

The agent can add and change rows, not just remove them — with the same preview-then-execute discipline `delete_rows` already has.

- **`insert_rows`** — previews what would be inserted, returns a token, executes on replay.
- **`update_rows`** — same, and shares the no-`WHERE` guard: an `UPDATE` with no `WHERE` is refused unless `confirm_full_table: true` is passed explicitly.

Both are cheap now that the core exists. That is the point of having built the core first: these tool

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/8) · 2026-08-12 · closed · 0 comments

### Approval threshold, hard row cap, and awaiting_approval

## What to build

Scope decides what happens next. The same tool call behaves in three different ways depending on how many rows it would touch:

- **Under `approval_required_above_rows`** (default 100) — the preview comes back with a usable token; the agent can proceed on its own.
- **Above it** — the tool returns `status: "awaiting_approval"` along with the plan token and the sample rows. The token exists but will not execute until a human approves it. The agent is told this plainly enough to 

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/6) · 2026-08-12 · closed · 0 comments

### Append-only audit log with insert-only grants

## What to build

Every path through the server leaves a trace that the server itself cannot erase. After any sequence of previews, executions, rejections and failures, the operator can query one table and reconstruct exactly what the agent tried, what it said it was doing, and what actually happened.

A separate `mcp_audit` schema holds one append-only table:

```
id, ts, tool, reason, statement, params_redacted,
preview_rows, actual_rows, plan_token, approved_by,
status (previewed|approved|exe

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/5) · 2026-08-12 · closed · 0 comments

### Two-phase write core: preview, plan token, execute_plan, delete_rows

## What to build

The heart of the project: **the agent must commit to a preview before it can execute.**

The agent calls `delete_rows`. The server runs the statement inside a transaction, captures the *exact* affected row count and a sample of the affected rows via `RETURNING`, then **rolls back**. It returns that preview plus a server-issued `plan_token`. Nothing has changed in the database.

The agent then calls `execute_plan(plan_token)`. The server replays the identical statement and commi

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/4) · 2026-08-12 · closed · 0 comments

### query and explain_plan read tools

## What to build

The agent can read data and reason about cost before proposing a change. Two tools:

- **`query`** — runs a SELECT and returns rows. Read-only because it runs on the `readonly` role, not because anything inspected the SQL.
- **`explain_plan`** — returns cost and estimated row count for a candidate statement, so the agent can reject an obviously expensive idea before anyone runs it.

`explain_plan` gives the planner's *estimate*, which is exactly why it is not the safety mechani

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/3) · 2026-08-12 · closed · 0 comments

### Scaffold the server with dual-role pools and describe_schema

## What to build

A user installs the server, points it at a Postgres database, restarts Claude Desktop, and can ask "what's in this database?" — getting back tables, columns, types, foreign keys, and row-count estimates for exactly the schemas and tables the config allows.

This is the skeleton every later slice hangs off, so it carries three things beyond the one tool:

- **Two connection pools with distinct Postgres roles** — a `readonly` role and a `writer` role. Read-only is enforced by the

[Read the thread](https://github.com/jpka/sw-postgres-mcp/issues/2) · 2026-08-12 · closed · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/jpka/sw-postgres-mcp/issues).
