Postgres MCP server — agent-first database workbench
Project description
Tabulus
Let your AI agent query your real Postgres — without leaking customer data to the LLM.
Tabulus is a Postgres MCP server that sits between your AI agent (Claude Code, Cursor, any MCP client) and your database. It scrubs emails, API keys, JWTs, credit cards, SSNs, phones, and IPs out of every result before the agent ever sees them — so you can point Claude at a production-shaped database without piping your customers' PII into someone else's model.
Same query, redactor off vs on — real output. Record the animated version yourself: demo/.
The problem
Connecting an AI agent to your database means every row it samples — every customer email, every Stripe key sitting in a config table, every JWT in a sessions row — gets shipped into the LLM's context window. To Anthropic. To OpenAI. To wherever the model runs. Most DB MCP servers solve "can the agent drop my tables." Tabulus solves what leaves the building.
Without redaction: {"email": "jane@acme.com", "api_key": "sk_live_4eC39Hq..."}
With Tabulus: {"email": "[REDACTED:email]", "api_key": "[REDACTED:stripe_key]"}
Turn it on with TABULUS_REDACT=on. The sentinel keeps enough structure for the
agent to reason ("Stripe call failed with [REDACTED:stripe_key]") without ever
seeing the secret.
Also in the box
- PII/secret redactor — emails, API keys (Anthropic/OpenAI/Stripe/GitHub/AWS/
Slack/Google), OAuth + bearer tokens, JWTs, PEM private keys, credit cards, SSNs,
international + US phones, IPv4/IPv6 — plus
key=valuesecrets and any value in a secret-named column (password,api_key, …). Conservative by design: false positives are cheap, false negatives leak. - Read-only, enforced three ways — keyword gate + Postgres read-only transaction + row cap. The agent can't drop your tables.
- Schema introspection tuned for context windows — compact JSON, foreign keys flattened, sample rows inline. Fits a 50-table schema in one prompt.
EXPLAINas a tool — the agent reasons about query plans before proposing optimizations.- Statement timeout + row cap server-side. No accidental DOS.
Status
v0.0.4 — alpha. Postgres only. Stdio MCP transport only. No GUI yet.
Install
pip install tabulus
Run
export DATABASE_URL=postgres://user:pass@host:5432/dbname
tabulus
Then point your MCP client at the tabulus command.
Claude Code (project-level)
Create .mcp.json in your project root:
{
"mcpServers": {
"tabulus": {
"command": "tabulus",
"args": [],
"env": {
"DATABASE_URL": "postgres://user:pass@host:5432/dbname"
}
}
}
}
Restart Claude Code in that directory and approve the trust prompt.
Claude Code (user-level via CLI)
claude mcp add tabulus "$(which tabulus)" --env DATABASE_URL=postgres://user:pass@host:5432/dbname
Cursor
Add to ~/.cursor/mcp_servers.json:
{
"mcpServers": {
"tabulus": {
"command": "tabulus",
"env": { "DATABASE_URL": "postgres://user:pass@host:5432/dbname" }
}
}
}
Tools
| Tool | Description |
|---|---|
list_tables |
All tables with row count estimates + sizes |
describe_schema |
Columns, PK, FKs, indexes, sample rows for a table |
sample_rows |
Random sample from a table |
safe_select |
Run a read-only SELECT (write keywords rejected) |
explain |
Get query plan (EXPLAIN FORMAT JSON) |
Configuration
| Variable | Default | Purpose |
|---|---|---|
DATABASE_URL |
— (required) | Postgres connection URL |
TABULUS_MAX_ROWS |
100 |
Hard cap on rows returned by any tool |
TABULUS_SAMPLE_SIZE |
3 |
Sample rows included in describe_schema |
TABULUS_STATEMENT_TIMEOUT_MS |
5000 |
Server-side query timeout |
TABULUS_REDACT |
off |
Set on to scrub PII (emails, API keys, JWTs, credit cards, phones, IPs) from sample_rows, safe_select, and describe_schema output before the agent sees it. Recommended for production. |
TABULUS_ALLOW_WRITES |
false |
Set true to disable the write block (NOT recommended) |
For teams
Tabulus core is free and MIT — and stays that way. If your organization is letting AI agents touch real, sensitive databases and you need audit logs, centrally enforced redaction policy, column-level masking, or SSO, we're exploring a self-hosted Team tier (your data never routes through us).
Roadmap
- v0.1 — Postgres parity, polished install
- v0.2 — SQLite adapter
- v0.3 — MySQL / MariaDB adapter
- v0.x — Tauri desktop GUI shell on top of the same core
- v1.0 — Stable, cross-platform, multi-DB
License
MIT. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tabulus-0.0.4.tar.gz.
File metadata
- Download URL: tabulus-0.0.4.tar.gz
- Upload date:
- Size: 18.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd7dabff50fc9ffd3088745c0f695092e5b41db6f57a404cafb7e3ad618984ba
|
|
| MD5 |
2bfae202aad8e9cefbe243d0e5feeb2e
|
|
| BLAKE2b-256 |
33aabd85c49a30bd6d513b61604f1efa9c114e559b9f20d73a847e6345cbda30
|
Provenance
The following attestation bundles were made for tabulus-0.0.4.tar.gz:
Publisher:
publish.yml on WalkingMountain/tabulus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tabulus-0.0.4.tar.gz -
Subject digest:
bd7dabff50fc9ffd3088745c0f695092e5b41db6f57a404cafb7e3ad618984ba - Sigstore transparency entry: 2017736937
- Sigstore integration time:
-
Permalink:
WalkingMountain/tabulus@45cc7feded225b37d1763c84d777ec193c1068bf -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/WalkingMountain
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@45cc7feded225b37d1763c84d777ec193c1068bf -
Trigger Event:
push
-
Statement type:
File details
Details for the file tabulus-0.0.4-py3-none-any.whl.
File metadata
- Download URL: tabulus-0.0.4-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa15f920b39e218678b1b7aa398cc7dd134018c4c69df36364f8d05dca33810f
|
|
| MD5 |
20a435e65734f4b74a65c9b469ba3864
|
|
| BLAKE2b-256 |
b64b7d34beb45813d76f17ba55c549313aa4d460f5c188c479f93c144038fde2
|
Provenance
The following attestation bundles were made for tabulus-0.0.4-py3-none-any.whl:
Publisher:
publish.yml on WalkingMountain/tabulus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tabulus-0.0.4-py3-none-any.whl -
Subject digest:
fa15f920b39e218678b1b7aa398cc7dd134018c4c69df36364f8d05dca33810f - Sigstore transparency entry: 2017737136
- Sigstore integration time:
-
Permalink:
WalkingMountain/tabulus@45cc7feded225b37d1763c84d777ec193c1068bf -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/WalkingMountain
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@45cc7feded225b37d1763c84d777ec193c1068bf -
Trigger Event:
push
-
Statement type: