amnesic
You can use this MCP server to run safe read-only SQL queries while building and reusing persistent semantic knowledge about your database schema across sessions.
List configured database connections without exposing credentials.
List known tables and fetch schemas merged with saved annotations.
Execute read-only SELECT queries with row limits; write statements are blocked.
Search table and column knowledge using BM25-ranked full-text search.
Annotate tables/columns with descriptions, aliases, enum mappings, foreign keys, and example values.
Soft-deprecate or permanently forget annotations, with optional cascade for tables.
Detect drift between saved annotations and the live schema.
Discover and navigate foreign-key relationship graphs for JOIN planning.
Sync annotations between connections or environments.
Provides persistent semantic memory for PostgreSQL databases, enabling AI agents to remember schema, annotations, and relationships across sessions.
Provides persistent semantic memory for SQLite databases, enabling AI agents to remember schema, annotations, and relationships across sessions.
amnesic — the MCP server with the most ironic name in the registry
Your database's institutional memory, as an MCP server. The name is ironic — it remembers everything.
"The MCP server with the most ironic name in the registry. It's anything but amnesic — it remembers your database so your AI doesn't have to."
Most database MCP servers are query executors: they connect, introspect, run SQL, and forget. amnesic is a semantic memory — it accumulates what your schema means (what status = 3 is, which columns are really foreign keys, what that legacy table is for) and hands it to every future session automatically. Think data catalog, minus the platform, the ingestion pipeline, and the invoice. Where amnesic fits ↓
Works with Claude Code · Claude Desktop · Cursor · VS Code · Cline · Windsurf — any MCP-compatible client.
Available on Official MCP Registry · Claude Code plugin marketplace
👋 Using amnesic? Say hi in the adopters thread — download counts can't tell me what's actually being used, and it directly shapes what gets built next.
🔒 Read-only by design. amnesic refuses to execute
INSERT,UPDATE,DELETE,DROP,TRUNCATE,ALTER,CREATE,EXEC,MERGE,GRANT,REVOKE— and any write statement smuggled inside aWITHCTE. Two layers of defense: static SQL analysis rejects the statement before connecting, and every query runs inside a transaction that is immediately rolled back. Safe to point at prod. Details ↓
The problem
Every session with an AI starts cold. You spend the first few minutes re-explaining what tables exist, what a status column value of 3 means, which FK connects orders to users. Then the session ends, and you do it all over again tomorrow.
amnesic fixes this. It gives your AI a persistent SQLite knowledge store — one per database — that survives across sessions. Annotate a status enum once; every future session sees those labels automatically. Discover FK relationships once; every future JOIN query uses that graph.
The knowledge is also portable and outlives your access to the database. When you rotate off a project, amnesic export hands the next developer everything you taught it — years of "oh, that column actually means…" that would otherwise leave with you.
Related MCP server: subconscious-mcp
Where amnesic fits
The database MCP ecosystem splits into two camps, and amnesic is deliberately in neither.
Query executors — DBHub, Postgres MCP Pro, Google's MCP Toolbox, and the vendor servers (Supabase, Neon). They introspect live, run SQL, and some go deep on performance — Postgres MCP Pro does genuine index tuning and PgHero-style health checks. They are excellent at this. They are also stateless: every session re-learns your schema from scratch, and nothing they return can tell you what a column means, because the database doesn't know either.
Enterprise catalogs — DataHub, Atlan, Cube, AtScale. These do hold semantic context: glossaries, column descriptions, ownership, lineage. They're also a platform commitment — metadata ingestion, a service to run, usually a paid tier. Worth it at company scale; wildly disproportionate for one developer who needs to remember what six status codes mean in a legacy MSSQL database nobody will ever onboard to a catalog.
amnesic is the third thing: catalog-grade semantic memory at query-executor setup cost. pipx install, one TOML file, a local SQLite file per database. No platform, no ingestion, no server to run.
Honest comparison
amnesic | Query executors | Enterprise catalogs | |
Semantic context (what a value means) | ✅ persistent, yours | ❌ none | ✅ platform-managed |
Survives across sessions | ✅ | ❌ | ✅ |
Portable / outlives DB access | ✅ | ❌ | ⚠️ platform-bound |
Setup cost | one command | one command | ingestion pipeline |
Live schema freshness | ✅ cached, staleness reported | ✅ always live | ⚠️ ingestion lag |
Execution plans / index tuning | ❌ | ✅ (Postgres MCP Pro) | ❌ |
Lineage / ownership / governance | ❌ | ❌ | ✅ |
Works on legacy schemas with no FK constraints | ✅ annotate them yourself | ❌ nothing to introspect | ⚠️ needs ingestion |
Use a query executor instead of amnesic if you want execution plans, index recommendations, or database health diagnostics — that's not amnesic's job and adding it would make it a worse version of a tool that already exists.
Use amnesic alongside one. They compose: nothing stops you running both. amnesic holds the meaning; they hold the machinery.
The rows marked ⚠️ above are known gaps with open issues — see Roadmap ↓.
Quickstart (90 seconds)
pipx install amnesic # install the core
amnesic init # interactive wizard⚡ Try it without credentials. Run
amnesic init --demoinstead — it adds a self-contained SQLite sample DB (e-commerce schema: customers / products / orders with FKs and an enum column) so you can exercise every tool in under a minute. Great for a first look before pointing amnesic at a real database.
The wizard asks which database type you're connecting to and tells you the one command to run if its driver isn't installed yet — you never need to guess extras up front.
The wizard:
Asks for your database type, host, and credentials
Tests the connection before saving anything
Stores the password securely in
~/.config/amnesic/.env(chmod 600)Writes the connection block to
~/.config/amnesic/connections.toml
Then add amnesic to your AI client and restart.
Install pipx (one-time):
brew install pipx # macOS
sudo apt install pipx # Linux (Debian/Ubuntu)
python -m pip install --user pipx # Windows / genericOr use uv (single-binary alternative — fast, no Python required):
brew install uv # macOS
curl -LsSf https://astral.sh/uv/install.sh | sh # Linux / macOS
powershell -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
uv tool install amnesicOr plain pip (installs into your active Python env):
pip install amnesicWhichever you pick,
amnesic initasks which database you'll connect to and prints the one extra command to install that driver — no need to commit to extras up front.
After install, amnesic --help works from any terminal.
Where amnesic stores things
File | macOS / Linux | Windows |
Config |
|
|
Secrets |
|
|
Knowledge |
|
|
Set $AMNESIC_HOME (or $XDG_CONFIG_HOME on Linux) to override the location.
Adding more connections later
amnesic add # add another connection to existing config
amnesic test # verify all connections
amnesic test orders.prod # verify one connectionSetting and rotating passwords
amnesic init and amnesic add save your password automatically — for the typical setup flow, you never need to think about this section.
Use set-secret when you need to change a stored password later — IT rotated it, you mistyped it during setup, or you're hand-editing the config.
$ amnesic set-secret ORDERS_PROD_PASSWORD
Value: **** ← hidden input (your typing is invisible)
Confirm: ****
✓ Set ORDERS_PROD_PASSWORD in ~/.config/amnesic/.envWhat's the variable name? It's the env var your connections.toml references for that connection's password. The wizard auto-generates these as <CONNECTION_NAME_UPPERCASE_WITH_UNDERSCORES>_PASSWORD:
Connection name | Generated env var |
|
|
|
|
|
|
To see the exact name your config uses, check ~/.config/amnesic/connections.toml — anything inside ${...} is the variable to pass to set-secret.
Under the hood: writes (or replaces) the line in ~/.config/amnesic/.env, sets file permission to chmod 600 (only your user can read it), preserves all other entries.
Managing connections and knowledge
Knowledge accumulates per connection in a local SQLite file. These commands let you move it between machines and clean up:
# Hand off everything you've taught amnesic about a database (annotations +
# relationships, not the re-derivable schema cache) as portable JSON:
amnesic export orders.prod -o orders-knowledge.json
amnesic export orders.prod # or print to stdout to pipe/redirect
# Load that knowledge into another connection (e.g. promote staging → prod,
# or onboard a teammate). Unconditional upsert — existing entries are overwritten:
amnesic import orders.prod orders-knowledge.json
# Wipe stored knowledge for a connection but keep the config entry:
amnesic clear orders.staging
# Drop a connection from connections.toml entirely (knowledge file kept
# unless you pass --delete-knowledge):
amnesic remove old.connection
amnesic remove old.connection --delete-knowledgeexport/import/clear/remove operate purely on local files — they never connect to the database, so they work even if a connection's credentials aren't set. remove edits connections.toml with surgical string edits, leaving every other block's formatting and comments byte-for-byte intact.
Add to your AI client
Once amnesic is installed with the right driver extras (see Quickstart), the amnesic command is on your PATH. Use the same snippet across every MCP client:
Claude Code
One-line install (recommended — no JSON editing). Inside Claude Code:
/plugin marketplace add https://github.com/SurajKGoyal/amnesic-marketplace
/plugin install amnesic@amnesicThat wires amnesic as an MCP server automatically. Source: SurajKGoyal/amnesic-marketplace.
{
"mcpServers": {
"amnesic": {
"command": "amnesic"
}
}
}Claude Desktop
Add to your platform's Claude Desktop config:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"amnesic": {
"command": "amnesic"
}
}
}Cursor
One-click install — click the button below and Cursor wires it up for you:
Add to .cursor/mcp.json in your project (or ~/.cursor/mcp.json globally):
{
"mcpServers": {
"amnesic": {
"command": "amnesic"
}
}
}Without a global install (ephemeral)
If you'd rather not install amnesic on your system, use uvx or pipx to fetch it each time the MCP client starts. Note the driver extras must be passed explicitly:
// uvx — requires `uv` installed (see Install section for per-OS instructions)
{
"mcpServers": {
"amnesic": {
"command": "uvx",
"args": ["--from", "amnesic[mssql]", "amnesic"]
}
}
}
// pipx — usually pre-installed via Homebrew or system package manager
{
"mcpServers": {
"amnesic": {
"command": "pipx",
"args": ["run", "--spec", "amnesic[mssql]", "amnesic"]
}
}
}For multiple drivers, comma-separate inside the brackets — e.g. amnesic[postgres,mssql] or use amnesic[all] for everything.
VS Code (with MCP extension)
Add to .vscode/mcp.json:
{
"servers": {
"amnesic": {
"type": "stdio",
"command": "amnesic"
}
}
}Updating
amnesic ships often. Upgrade with the same tool you installed it with:
Installed via | Upgrade command |
|
|
|
|
|
|
| uvx caches builds — run |
Then restart your MCP client (Claude Code, Cursor, …) so it relaunches the amnesic server and picks up any new tools.
Upgrading is safe — you won't lose annotations. Your knowledge files auto-migrate to the new schema on first load; amnesic only ever adds columns, never drops your data.
To check the installed version: amnesic --version. Latest release: PyPI · Releases.
Tools
Tool | Description |
| List all configured connections (no secrets exposed) |
| All known tables with descriptions and column counts |
| BM25 search over table/column descriptions and aliases |
| Column schema merged with saved annotations |
| Execute a read-only SELECT query |
| Persist semantic annotations for tables/columns |
| Soft-retire a stale annotation — flagged (and warned) but kept, reversible |
| Audit annotations vs the live schema — find orphaned annotations + undocumented tables |
| Hard-delete an annotation (cascade opt-in) — permanent |
| Copy annotations between connections (e.g. staging → prod) |
| Discover all FK relationships from the live DB |
| Navigate the FK graph for JOIN planning |
| Propose enum values for low-cardinality columns (never writes) |
Searching the knowledge base
For large schemas, db_list_tables is impractical — you'd dump 500+ rows into Claude's context. Use db_search to find the relevant tables/columns by keyword instead:
"What table tracks customer payments?"
→ db_search("payments")
Top results:
- dbo.payments (table) "Customer payment records..."
- dbo.orders.payment_method (column) "Mode of payment..."db_search uses SQLite FTS5 with BM25 ranking — fast, local, no embeddings or external services. Search syntax supports:
Syntax | Effect |
| Match the word (with stemming — also matches "payments", "paying") |
| Exact phrase |
| Prefix match — "payment", "payable", etc. |
| Both terms required |
| Either term |
Results return ranked table/column rows with descriptions and highlighted snippets.
The knowledge layer
The core differentiator. Every annotation survives restarts, model updates, and new sessions.
Session 1 — you discover something
You: What does status=3 mean in the orders table?
AI: Let me check. [runs db_query: SELECT DISTINCT status FROM dbo.orders]
I see values 1, 2, 3, 4. Let me look at some examples...
Based on the data, 3 appears to be "cancelled".
You: Save that. And status=1 is "pending", 2 is "confirmed", 4 is "delivered".
AI: [calls db_annotate]
db_annotate(
table="dbo.orders",
column="status",
column_description="Order lifecycle status",
enum_values={"1": "pending", "2": "confirmed", "3": "cancelled", "4": "delivered"}
)
Saved. Future sessions will see these labels automatically.Session 2 — the knowledge is already there
You: How many cancelled orders are there this month?
AI: [calls db_get_schema("dbo.orders")]
Schema response includes:
column: "status"
description: "Order lifecycle status"
enum_values: {"1": "pending", "2": "confirmed", "3": "cancelled", "4": "delivered"}
[writes correct SQL immediately]
SELECT COUNT(*) FROM dbo.orders WHERE status = 3 AND ...No re-discovery. No wasted turns. The annotation persisted.
Relationship graph
Understand your schema's JOIN structure once, reuse it forever.
AI: [db_discover_relationships(connection="orders.prod")]
Discovered 47 foreign key relationships.
AI: [db_get_relationships(table="orders", depth=2)]
neighbors:
orders → users (via user_id → id)
orders → order_items (via id ← order_id)
paths:
orders -> users
orders -> order_items
order_items -> productsNow the AI knows exactly how to JOIN across your schema without guessing.
Sync between environments
Build up annotations in staging, then promote to prod:
db_sync_knowledge(from_connection="orders.staging", to_connection="orders.prod")Returns {synced: [...], skipped: [{table, reason}], warnings: [{table, column, reason}]}.
Tables missing from the target schema cache are skipped with a clear reason. Columns missing from target schema are warned but don't block the rest of the sync.
Advanced: hand-edit the TOML
If you prefer to manage the config file yourself, generate a blank template:
amnesic init --templateThis writes ~/.config/amnesic/connections.toml with commented examples and exits — no wizard. Edit the file directly:
# ~/.config/amnesic/connections.toml
# Nested style: [connections.product.env]
[connections.orders.prod]
driver = "mssql"
server = "localhost"
port = 11433
database = "OrdersDB"
user = "${ORDERS_USER}"
password = "${ORDERS_PROD_PASSWORD}"
tunnel_script = "~/.scripts/mssql-tunnel.sh" # macOS / Linux (bash)
# tunnel_script = "C:/scripts/mssql-tunnel.ps1" # Windows (PowerShell)
[connections.orders.staging]
driver = "mssql"
server = "localhost"
port = 11434
database = "OrdersDB_Staging"
user = "${ORDERS_USER}"
password = "${ORDERS_STAGING_PASSWORD}"
# Flat style: [connections.name]
[connections.analytics]
driver = "postgres"
server = "analytics.company.com"
port = 5432
database = "warehouse"
user = "${ANALYTICS_DB_USER}"
password = "${ANALYTICS_DB_PASSWORD}"
# SQLite — no credentials needed
[connections.local]
driver = "sqlite"
database = "/absolute/path/to/local.db" # macOS / Linux
# database = "C:/path/to/local.db" # Windows (use forward slashes)
# Optional, any connection: days before db_get_schema flags the cached
# schema as stale (0 disables the flag for that connection).
# schema_cache_ttl_days = 30The TTL defaults to AMNESIC_SCHEMA_TTL_DAYS (30) when the env var is set, and to 30 otherwise; a per-connection schema_cache_ttl_days overrides both. Set it to 0 to disable staleness flagging.
Use ${ENV_VAR} for credentials — never hardcode passwords.
Secrets are loaded from ~/.config/amnesic/.env automatically (format: KEY=VALUE, one per line, # for comments). For each ${VAR_NAME} referenced in your TOML, populate the matching .env entry with amnesic set-secret VAR_NAME (hidden input, chmod 600), or write .env yourself.
Canonical connection names use dot notation: orders.prod, orders.staging, analytics, local.
Supported databases
Database | Python driver | Installed by |
PostgreSQL |
| wizard nudge when you pick Postgres, or |
MySQL / MariaDB |
| wizard nudge when you pick MySQL, or |
Microsoft SQL Server |
| wizard nudge when you pick MSSQL, or |
SQLite | stdlib | always available — no extra |
Safety & read-only enforcement
amnesic is built to be safe to point at production databases.
Why your AI can't damage your data
Every query passes through two independent layers before reaching the database:
Static analysis (in
amnesic/readonly.py) — the SQL is tokenized and rejected if it contains any of:INSERT,UPDATE,DELETE,DROP,TRUNCATE,ALTER,CREATE,EXEC,EXECUTE,MERGE,BULK,GRANT,REVOKE,DENY. This includes write statements smuggled inside CTEs (WITH x AS (SELECT ...) UPDATE ...is caught and refused).Transaction rollback — even if a write statement somehow gets past the static check, the query runs inside
BEGIN TRANSACTION ... ROLLBACKso nothing is ever committed. Belt and suspenders.
Only SELECT and WITH ... SELECT reach the database. Comments are stripped before analysis so /* DELETE FROM users */ can't be used to hide an attack.
Other safety measures
No credentials in responses:
db_list_connectionsstrips passwords and usernames from its output. The AI can see which connections exist, never how to authenticate to them.Credentials via env vars only:
${ENV_VAR}expansion at config-load time — passwords never touchconnections.tomlon disk.Secure
.envstorage: on macOS/Linuxchmod 0o600(owner read/write only); on Windows the.envlives in%APPDATA%which is restricted to your user profile by Windows ACL.Identifier validation: table/schema/database names are checked against
[A-Za-z0-9_]+before any string interpolation into SQL.Tested: 40+ unit tests in
tests/test_readonly.pycover every write keyword, comment-stripping edge case, CTE-with-write attempts, semicolon-separated multi-statements, and identifier injection attempts.pytest tests/test_readonly.pyto verify on your machine.
Is this safe with my data?
amnesic is local-only and protocol-only. It doesn't introduce a new external trust boundary — the trust boundary is wherever your MCP client sends data, not amnesic itself. Choosing the AI client decides the policy that applies to your rows.
your DB → amnesic (local) → MCP client → your AI deployment
↑ trust boundary lives hereThe honest question to ask, whether you're indie or enterprise:
Do I trust my AI client with the data in this database?
If yes — and for most setups, the answer is yes — you're good. That covers:
Solo devs on Claude Pro / Cursor / Copilot using their own projects, dev DBs, or test data
Side projects querying personal SQLite or self-hosted Postgres
Open-source maintainers working with public schemas
Teams on enterprise AI with explicit isolation: AWS Bedrock (tenant + IAM), Azure OpenAI (region-pinned, your subscription), Anthropic Enterprise (zero data retention, training opt-out), Vertex AI (your GCP project), self-hosted (Ollama, vLLM, on-prem Claude/GPT — data never leaves the network)
Anyone on a paid AI plan with zero-retention guarantees and a DPA covering your use
Worth a closer look if
Your DB holds data belonging to other people (users, customers, patients) and you haven't verified your AI provider's terms cover that processing
You're on consumer-tier AI (free / personal Pro) AND working with regulated data — PHI (HIPAA covered entity), cardholder data (PCI-DSS), restricted PII under GDPR / India's DPDP Act
Your employer has an explicit policy restricting external AI tool use on prod DBs
You're under data-residency rules where rows can't leave a specific region
Data minimization is built in
A property of the design, not an afterthought: the annotation layer means the AI answers most schema questions from a local SQLite knowledge file — no db_query runs, no row data is sent anywhere.
"What does status=3 mean?" → resolves from your saved annotation
"How do orders join users?" → resolves from the FK graph
"Which tables have a
created_atcolumn?" → resolves from schema cache
For purely structural exploration, six tools never touch your data: db_list_tables, db_get_schema, db_search, db_annotate, db_discover_relationships, db_get_relationships. They return metadata only.
That's measurably less data movement than a "naked" SQL MCP — which has to run SELECT DISTINCT status FROM orders every time the AI is confused about an enum. amnesic answers it once from local annotations.
Disclaimer: amnesic is provided as-is under the MIT License (no warranty, no liability — see LICENSE). This section is not legal or compliance advice. Your use of amnesic, and the AI client you connect it to, is your responsibility. If you handle regulated data, consult your security / compliance team before pointing it at production.
Roadmap
Shipped so far: the knowledge layer (v0.1), BM25 search (v0.1.5), lifecycle management — deprecate / drift detection / forget (v0.2), and portable knowledge export/import (v0.2.2).
Next up (v0.3 — "Earn the memory"): knowledge that accumulates without anyone typing it — soft-FK inference for legacy schemas with no constraints, and JOIN-pattern learning. Plus the table-stakes work: a token budget on every response, indexes and primary keys in the schema fetch, and a smaller tool surface.
See ROADMAP.md for the full picture and the reasoning behind the ordering.
🙌 Contributions wanted
Every v0.3 item is filed as a GitHub issue with the design already thought through — the problem, the proposed shape, the files to touch, and how to test it. Several are tagged good first issue.
Pick one and open a PR — no need to ask first. Just comment on the issue so two people don't build the same thing.
New driver? Follow the structure in
amnesic/drivers.pyandamnesic/tools/schema.py.Tests live in
tests/. New tools need unit tests; runpytest tests/before opening the PR.
Have an idea that isn't listed? Open an issue. A use case beats a patch — it saves you rework.
Track usage
pypistats.org/packages/amnesic
License
MIT — see LICENSE.
MCP Registry
This server is registered on the official MCP Registry.
mcp-name: io.github.SurajKGoyal/amnesicAvailable Tools
12 toolsdb_annotateA
Persist semantic annotations for a table or column — survives across sessions.
This is the core of amnesic's persistent memory. Every annotation saved here
is automatically merged into future db_get_schema() responses, so the AI
never has to rediscover what a status code means or what a table is for.
Call this after discovering: what an enum value means, what a column represents,
how a table relates to another, or what a table is used for.
Args:
table: Table name, optionally schema-qualified to match your
DB — e.g. "users", "public.users" (Postgres),
"dbo.Orders" (MSSQL), "mydb.orders" (MySQL).
connection: Connection name. Defaults to first defined.
table_description: Human-readable description of the table's purpose.
table_aliases: Alternative names the table is known by.
column: Column to annotate (required for column-level args below).
column_description: What this column represents in the business domain.
enum_values: Dict mapping stored values to labels {"1": "active", "2": "inactive"}.
foreign_key: FK reference as "other_table.column_name".
example_values: Representative sample values from this column.
Returns:
{table, connection, updated: {table_knowledge?, column_knowledge?}}
Inputs: table (required), connection, table_description, table_aliases, +5 more.
db_deprecateA
Soft-retire a table or column annotation — flag it stale without deleting it.
Use when a table/column still exists but should no longer be relied on. The
deprecation flag is surfaced in db_get_schema so the AI is warned off it on
future calls. Reversible via undo=True. To remove an annotation entirely
(e.g. the column was dropped from the DB), use db_forget instead.
Args:
table: Table name, optionally schema-qualified (e.g. "users",
"public.users", "dbo.Orders", "mydb.orders").
connection: Connection name. Defaults to first defined.
column: Column to deprecate. Omit to deprecate the whole table.
reason: Why it's deprecated (e.g. "replaced by status_v2").
undo: Clear the deprecation flag instead of setting it.
Returns:
{table, connection, column, target, deprecated, reason}
Inputs: table (required), connection, column, reason, +1 more.
db_detect_driftA
Audit saved annotations against the live database schema (read-only).
Surfaces drift after the schema evolves:
- orphaned annotations — a table or column you annotated that no longer
exists in the DB. Remove with db_forget, or db_deprecate if pending.
- undocumented tables — live tables with no annotation yet (coverage gaps).
Changes nothing — purely a report. Run after schema changes, or periodically.
Args:
connection: Connection name. Defaults to first defined.
Returns:
{connection, orphaned_tables, orphaned_columns, undocumented_tables,
undocumented_truncated, summary}
Inputs: connection.
db_discover_relationshipsA
Discover all foreign key relationships in the database and save them to the graph.
Runs driver-specific FK introspection queries against the live database and
persists results to the local KnowledgeStore. Run once per database; re-run
after schema changes. After discovery, use db_get_relationships to navigate
the graph when planning complex JOIN queries.
Args:
connection: Connection name. Defaults to first defined.
Returns:
{connection, discovered: count, relationships: [{from_table, from_column, to_table, to_column}]}
Inputs: connection.
db_forgetA
Permanently delete a table or column annotation. Safe by default — NOT reversible.
Use to remove a wrong annotation, or to clean up after a table/column was
dropped from the DB (pairs with db_detect_drift). Unlike db_deprecate, this
hard-deletes. Cascade is opt-in so you can't nuke a table by accident:
- db_forget(table) -> ONLY the table's own annotation
- db_forget(table, column="x") -> ONLY that column's annotation
- db_forget(table, cascade=True) -> the table + all its column annotations
+ all relationships touching it
Only the local knowledge store is changed — never the live database.
Args:
table: Table name, optionally schema-qualified (e.g. "users",
"public.users", "dbo.Orders", "mydb.orders").
connection: Connection name. Defaults to first defined.
column: Column annotation to delete. Omit to target the table.
cascade: When targeting a table, also delete its columns +
relationships. Ignored when column is given.
Returns:
{table, connection, column, removed_table, removed_columns, removed_relationships}
Inputs: table (required), connection, column, cascade.
db_get_relationshipsA
Get the foreign key relationship graph for a table up to the given traversal depth.
Depth 1 returns direct neighbors (tables one JOIN away). Depth 2 returns
neighbors-of-neighbors. Returns both a flat neighbor list and formatted join
path strings to help plan multi-table queries. Requires db_discover_relationships
to have been run first.
Args:
table: Table name (e.g. "Orders").
connection: Connection name. Defaults to first defined.
depth: BFS traversal depth (default 1, recommended max 3).
Returns:
{table, connection, neighbors: [...], paths: ["TableA -> TableB -> TableC", ...]}
Inputs: table (required), connection, depth.
db_get_schemaA
Get column schema for a table, merged with any saved semantic annotations.
Checks the local cache first; fetches from the database on cache miss or
when force_refresh=True. Saves the result to cache for future calls.
Merges column descriptions, enum value mappings, and FK references from
previous db_annotate() calls into the response.
Args:
table: Table name, optionally schema-qualified. Use whatever your
DB uses — e.g. "users", "public.users" (Postgres),
"dbo.Orders" (MSSQL), "mydb.orders" (MySQL).
connection: Connection name. Defaults to first defined.
force_refresh: Bypass cache and fetch fresh schema from the database.
Returns:
{table, connection, columns (with annotations merged in), table_description, cached}
Inputs: table (required), connection, force_refresh.
db_list_connectionsA
List all configured database connections without exposing passwords or usernames.
Use this first to see what databases are available before calling other tools.
Returns connection names, drivers, databases, and server addresses.
Returns:
{connections: [{name, driver, database, server}]}
Inputs: no named parameters.
db_list_tablesA
List all known tables for a connection, with descriptions and column counts.
Tables appear once they have been fetched via db_get_schema or annotated via
db_annotate. Descriptions come from the knowledge store — richer than raw
INFORMATION_SCHEMA.
Args:
connection: Connection name. Defaults to first defined.
Returns:
{connection, database, tables: [{table_fqn, description, aliases, column_count}]}
Inputs: connection.
db_queryA
Execute a read-only SELECT query and return rows as a list of dicts.
All queries run inside an immediately-rolled-back transaction — write
statements are blocked both statically and at the transaction level.
Call db_get_schema first if you are unfamiliar with the table structure.
Args:
sql: SELECT query to execute. No INSERT/UPDATE/DELETE allowed.
connection: Connection name (e.g. "orders.prod"). Defaults to first defined.
max_rows: Maximum rows to return (default 500). Set lower for large tables.
Returns:
{rows, row_count, connection, database, truncated}
Inputs: sql (required), connection, max_rows.
db_searchA
Search the knowledge layer for tables/columns matching a query — BM25-ranked.
Use this BEFORE db_list_tables when you're looking for a specific concept
(e.g. "payments", "user email", "shipping address"). db_list_tables returns
every table; db_search returns just the relevant ones with descriptions and
highlighted snippets.
Searches across:
- Table names, descriptions, and aliases
- Column names, descriptions, and enum_values
Falls back gracefully to empty results if the query has invalid FTS5 syntax.
Args:
query: Search text. Supports FTS5 syntax: phrases ("foo bar"),
prefix matching (pay*), boolean operators (foo AND bar).
connection: Connection name. Defaults to first defined.
target: "tables", "columns", or "all" (default).
limit: Max results to return (default 10).
Returns:
{query, connection, target, result_count, results: [
{target_type, table_fqn, column_name, description, snippet, score}, ...
]}
Inputs: query (required), connection, target, limit.
db_sync_knowledgeA
Copy annotations from one connection's knowledge store to another.
Typical use: after confirming that staging and prod share the same schema,
sync all the semantic knowledge you've built up in staging to prod.
Only syncs tables and columns that exist in the target schema cache —
tables missing from target are reported in 'skipped', columns in 'warnings'.
Args:
from_connection: Source connection (e.g. "orders.staging").
to_connection: Target connection (e.g. "orders.prod").
tables: Optional list of specific table FQNs to sync. Defaults to all.
Returns:
{synced: [...], skipped: [{table, reason}], warnings: [{table, column, reason}]}
Inputs: from_connection (required), to_connection (required), tables.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 12 tools
Each tool has a clear, distinct purpose. There is no overlap: annotation management (annotate, deprecate, forget), schema retrieval (get_schema, list_tables), querying (query), searching (search), relationship discovery (discover_relationships, get_relationships), drift detection (detect_drift), and knowledge sync (sync_knowledge) are all separate concerns.
All tools follow the consistent pattern `db_<verb>_<noun>` using snake_case. The verbs are descriptive and indicate the action (e.g., annotate, query, list_tables). No mixing of conventions or vague names.
With 12 tools, the server is well-scoped for a database knowledge management system. Each tool serves a necessary function in the lifecycle of schema understanding, annotation, querying, and maintenance. Not overloaded nor sparse.
The tool set covers the core workflow: connection listing, table discovery, schema retrieval, querying, annotation CRUD (annotate, deprecate, forget), relationship discovery, drift detection, and knowledge sync. Missing a direct tool to view all annotations in isolation, but schema retrieval and search provide access.
Maintenance
Related MCP Connectors
Universal persistent memory and knowledge retrieval layer for AI agents and LLMs.
Shared memory for AI agents, as a graph in your own Postgres. Writes never call an LLM.
Hosted persistent memory with semantic search, importance and TTL for AI agents.
Mem0-compatible persistent memory for AI agents: write facts once, recall them semantically.
Related MCP Servers
- AlicenseAqualityCmaintenancePersistent semantic memory for AI agents. SQLite-backed, local-first, zero config. Semantic search via Ollama embeddings with keyword fallback. Tools: remember, recall, history, forget, stats.1737 npm1MIT
- AlicenseNot gradedqualityCmaintenanceLocal-first semantic memory layer for MCP agents. Recall, remember, forget, stats over stdio. ChromaDB plus sentence-transformers, all on-machine.46 PyPIMIT
- AlicenseNot gradedqualityDmaintenanceProvides persistent long-term memory for LLMs via local SQLite storage and semantic search, enabling recall across sessions without external APIs.23 npm5MIT
- AlicenseNot gradedqualityCmaintenanceProvides persistent local memory for AI assistants using SQLite and semantic search, enabling context-aware conversations.23 npmMIT