nlqdb
OfficialOne line: nlqdb gives an AI agent a natural-language database — it queries, remembers, inserts, and can attach your own Postgres/ClickHouse and run a DBA loop on it.
Ask in English (
nlqdb_query) — run NL questions as real SQL over structured memory (GROUP BY / JOIN / aggregates), returning rows plus the compiled SQL intrace; destructive plans return a diff and need a second call withconfirm: true.Read-only queries (
nlqdb_read) — same NL interface but guaranteed never to write, so it's safe to always-allow.Browse databases (
nlqdb_list_databases,nlqdb_describe) — list the memory DBs you can query and inspect one's slug, engine and schema.Remember things (
nlqdb_remember) — deterministic typed writes (facts, episodes, entities) with no LLM in the loop; auto-provisions anagent_memory_v1DB, supports TTL expiry, entity upserts, and thread/end-user scoping.Insert structured rows (
nlqdb_insert) — up to 1,000 rows per call, auto-creating unseen tables and columns with inferred types; passkeyto upsert instead of duplicate.Attach your own database (
nlqdb_connect_database) — connect an existing Postgres or ClickHouse by connection URL (stored sealed), then query it in English.Run the DBA loop (
nlqdb_list_proposals,nlqdb_apply_proposal,nlqdb_reject_proposal) — on attached Postgres: review index proposals with their inverse and measured p95 before/after, apply them (built CONCURRENTLY, auto-reverted on regression, idempotent), or reject with a reason the DBA learns from.
Provides a framework wrapper for Astro to easily embed nlqdb-powered components.
Plans to support ClickHouse as an additional analytical database engine.
Uses DuckDB as an embedded analytical database engine.
Provides GitHub OAuth as a sign-in method for users.
Provides Google OAuth as a sign-in method for users.
Provides a framework wrapper for Next.js to easily embed nlqdb-powered components.
Provides a framework wrapper for Nuxt to easily embed nlqdb-powered components.
Supports OpenAI's models as the LLM backend for natural-language to SQL conversion.
Provides a framework wrapper for React to easily embed nlqdb-powered components.
Uses Redis as a database engine for storing and querying data.
Provides a framework wrapper for Solid to easily embed nlqdb-powered components.
Handles billing and payment processing via Stripe webhooks.
Provides a framework wrapper for Svelte to easily embed nlqdb-powered components.
Provides a native Swift package for integrating nlqdb into iOS/macOS applications.
This server has a remotely hosted endpoint. Open its connector listing for connection details, authentication requirements, and setup instructions:
nlqdb — your autonomous DBA.
nlqdb attaches to the Postgres or Cloudflare D1 database you already run, proposes the changes it needs, applies the ones you approve, measures them, and reverts any that regress.
Why it exists: the mission — encapsulate the trial-and-error journey every company walks to a good database infrastructure.
Where it is going (docs/END_GOAL.md): paste a
connection string — on nlqdb.com, with the CLI, through the SDK, or from your
coding agent over MCP — and the first proposals arrive within minutes, each
with its expected effect, cost and inverse. Apply is one click; nlqdb then
measures p95 on the same queries and keeps the change or reverts it, never on
your app's request path. That loop is being built
(Roadmap); what is live today is the hosted product below.
No backend to build. You write HTML; each component asks for what it wants in plain English; nlqdb infers the schema, writes the SQL, runs it, and renders the result. There is no backend for you to build.
Two actions. That's the whole product:
Create a database — one word: a name (or a goal).
Talk to it in plain English.
<script src="https://elements.nlqdb.com/v1.js" type="module"></script>
<nlq-data
goal="the 5 newest orders, with customer and item"
api-key="pk_live_xxx"
template="table"
refresh="10s"
></nlq-data>That's the entire backend for a live order list — no API to write, no schema to define, no JSON to parse. Engine choice (Postgres / Mongo / Redis / DuckDB / pgvector / …), schema inference, indexing, backups, and auto-migration between engines based on your real workload are background concerns you never have to see.
Status — early, open
nlqdb is early and built in the open, but fully public — no gate, no
invite code. The marketing site, the /v1/ask pipeline, the <nlq-data> /
<nlq-action> elements, the chat app, the TypeScript SDK, the hosted MCP
server, and the nlq CLI are all live in some form (see the surface table
below). Natural-language → SQL accuracy is still climbing toward our public
bar (BIRD ≥ 0.65, Spider 2.0 ≥ 0.75 on the free model chain), so answers can
be wrong — every response carries a confidence signal and the SQL it ran.
Related MCP server: ogham-mcp
Use it
Connecting an agent over MCP? On Claude Code, one marketplace add wires the hosted server and both memory skills in a single step:
/plugin marketplace add nlqdb/nlqdb
/plugin install nlqdb-memory@nlqdbOn any other MCP host, connect your agent
with one browser-OAuth approval; headless hosts skip the browser with
npx -y @nlqdb/mcp and an sk_mcp_* MCP key
(MCP setup). @nlqdb/sdk and @nlqdb/mcp
are both published and importable from npm.
The 60-second walkthrough — plain HTML, CLI, and ten framework wrappers —
lives at docs.nlqdb.com. Start with the
HTML tutorial or the
CLI tutorial.
You don't generate an API key separately: describe your database at
nlqdb.com, and the chat hands you a
<nlq-data> snippet with the key already inlined.
Examples
examples/ — minimal scaffolds in plain HTML, Next.js,
Nuxt, SvelteKit, Astro, plus a CLI-only walkthrough. Each is the smallest
valid integration around one <nlq-data> element or one CLI session.
What makes it different
Four things every release has to move, none allowed to regress
(GLOBAL-025):
Engine quality — natural-language → SQL accuracy (measured continuously on BIRD + Spider 2.0 + an internal eval), plus the multi-engine layer that moves your data to the right engine for your workload.
Onboarding — landing to first answer in under a minute, no card, no config.
UX — see the diff before any write, see the SQL behind every answer, and on low confidence get a one-click clarify — a guided turn, never a dead-end, and never a silent guess.
Performance — sub-400 ms cached, sub-1.5 s cold.
The bet: get this right on free, open models and it only gets better on frontier ones — the scaffolding compounds with whatever model is underneath.
Models & plans
Free forever on the built-in open-model chain — queries, embeds, and the elements, no card required.
Bring your own LLM key (Anthropic / OpenAI / Gemini / Grok / OpenRouter) on any tier, at no markup.
Hosted premium models on paid plans, when you'd rather not manage a key of your own.
Self-host the source — the engine, CLI, MCP server, and SDKs are source-available under FSL-1.1-ALv2: free to self-host for any non-competing use, bring your own LLM key, no per-call fees. The license auto-converts to Apache 2.0 two years after each release.
The hosted-premium model lane went live 2026-08-14. The full model strategy is in
GLOBAL-026.
Surfaces at a glance
Surface | Status | Where |
HTTP API ( | ✓ shipped |
|
| ✓ shipped (v0.1) |
|
| ✓ shipped (incl. |
|
Framework wrappers (React / Next / Vue / Nuxt / Svelte / SvelteKit / Astro / Solid + Swift) | ~ built + CI-tested; npm / SPM publish pending |
|
Chat app | ✓ shipped |
|
Hosted MCP server | ✓ shipped (host auto-detect pending) |
|
Local stdio MCP server | ✓ shipped — |
|
Droppable agent artifacts (AGENTS.md · Claude Code skill + plugin · Cursor rules · Codex config) | ✓ shipped — |
|
| ✓ shipped (core verbs; device-login pending) |
|
Full integration matrix in docs/progress.md.
Packages on npm
Published to the public npm registry with build provenance
(SK-CIPERM-003). Version badges
are live from npm; the table itself is generated from the workspace by
scripts/sync-readme-packages.mjs, so it
lists exactly the packages that are un-gated ("private" removed) and nothing
that isn't.
Package | Version | What it is | Source |
Shim that installs the nlq CLI binary for the host platform. | |||
Analytical-memory MCP server for nlqdb — a real database your AI agent can GROUP BY / JOIN / aggregate over in natural language, not just recall. | |||
Typed HTTP client for the nlqdb /v1 API — works in browsers, Node, Bun, Workers. |
Roadmap
The section below is the live focus; the numbered phases after it are
the hosted product's roadmap, kept until the GLOBAL-043 deletion series. Canonical plan + exit gates:
docs/phase-plan.md. Legend:
✓ shipped · ~ in progress · ◯ planned.
This roadmap is yours to shape. Want something added, reprioritised, or dropped? Open a PR editing this section (and
docs/phase-plan.mdif it's engine-facing), or open an issue to float it first. Say why now — which of the four north-star pillars (engine quality, onboarding, UX, performance) it moves. New to the codebase? Point your coding agent at this repo and paste:Read README.md and docs/phase-plan.md, then propose a roadmap change: add/change "<your idea>" under the right section in one line, with a "why now" naming which north-star pillar it moves. Open a PR with just that edit — no code.Setup, branch naming, and the CLA are in CONTRIBUTING.md.
Now — attach to the database you already run (GLOBAL-043)
One loop — observe → propose → apply → verify → revert — on your Postgres
(Supabase, Neon, RDS) or Cloudflare D1. Plan, KPIs and exit gate:
GLOBAL-043.
~
/app/dbachange ledger — every change with its inverse, newest first; Apply / Reject on each proposal~ Attach product on synthetic databases — observer,
create_indexproposal, apply → verify → auto-revert, the four doors (the web door, paste a Postgres string at/app/connectthen Apply / Reject in/app/dba, the API door,POST /v1/attach/client.attach()withclient.applyProposal()/rejectProposal(), the CLI door,nlq attach/nlq proposals/nlq apply/nlq reject, and the MCP door,nlqdb_connect_database/nlqdb_list_proposals/nlqdb_apply_proposal/nlqdb_reject_proposal; the web, API, CLI and stdio MCP (@nlqdb/mcp0.4.0) doors are live; hostedmcp.nlqdb.comserves the MCP tools once its held deploy runs; verify runs on its own once an applied proposal's 72 h window has passed; on D1 the API door attaches, applies and rejects so far), tested in CI~ Postgres spike — one index proposed, applied and measured (before/after p95) on a real-traffic database (the spike DB attaches read-only in CI, first proposal in 2.7 s; no index applied yet)
◯ D1 attach on the real rateme12 — the dogfood
◯ The playbook — unused-index drops, bloat, retypes, partitioning, retention, placement
Phase 0 — Foundations ✓
Worker skeleton · KV + D1 + R2 bindings · Neon adapter + OTel · LLM router
(free chain) · Better Auth (GitHub + Google + magic link) · /v1/ask
end-to-end · events queue + drain · Stripe webhook · CI/CD + PR preview
environments.
Phase 1 — On-ramp
A stranger lands on nlqdb.com, creates a DB in plain English, embeds it,
and shares the link — in under 60 seconds, no card, no config.
✓ Marketing site (Astro, live at
nlqdb.com)✓
<nlq-data>+<nlq-action>elements (v0.1)✓ Sign-in — magic link + GitHub + Google
✓ Chat surface — streaming three-part response (answer / data / trace), anonymous mode
✓ Anonymous mode — 72h token, adopted onto your account on sign-in
✓ Hosted db.create pipeline (table-card embeddings stubbed pending the pgvector slice)
✓ API keys dashboard (
/app/keys)◯ Hello-world tutorial polish
Phase 1.5 — Trust + telemetry
✓ Diff preview on writes + visible SQL trace on every response
✓ Demand-signal telemetry on every "not yet" path
◯ Confidence floor (clarify-on-low-confidence — a guided turn, not a dead-end) — lands with quality-eval
Phase 2 — Distribution (agent + developer surfaces)
✓ Hosted MCP server (
mcp.nlqdb.com/mcp) — host auto-detect pending; local stdio@nlqdb/mcpis on npm, sonpx -y @nlqdb/mcpwith ansk_mcp_*key is a headless route in with no browser consent step (/agentsnow carries it; the per-host install panel is still OAuth-only). On Claude Code,/plugin marketplace add nlqdb/nlqdbinstalls the server + both memory skills in one step✓ CLI
nlq(Go) — core verbs + raw-SQL escape hatch; device-login + chat REPL pending✓
@nlqdb/sdk— basic methods +runSql+ cross-tenant grant + pack-import runner verbs; published and importable from the registry;insert()andrunSqlparamspublish in0.5.0~ Framework wrappers + native Swift package — built + CI-tested; npm / SPM publish pending
✓ Quality-eval harness (BIRD + Spider 2.0) — a CI regression alarm for the NL→SQL interface, not a KPI
~ Bring-your-own-LLM dispatch — HTTP lane live; remaining surfaces in progress
◯ CSV upload in chat
~ Docs-site reference completeness — SDK + framework-wrapper guides, an enumerable error-code reference, and a build-time
/llms.txtfor agents now live; tutorial polish remains◯ Custom domains for embeds
Phase 3 — Multi-engine engine (the moat)
◯ Workload analyzer → migration orchestrator
◯ ClickHouse / DuckDB / Redis as additional engines
◯ Dual-read verification
✓ Hosted-premium model lane (demand-gated) — live 2026-08-14 (
PREMIUM_METER_LIVEflipped)
Phase 4 — Beyond v1
~ Bring-your-own Postgres / ClickHouse — connect path live end-to-end (
POST /v1/db/connect+ web UI, CLI, SDK, query dispatch); prod-gated on theBYO_SECRET_KEKsecret. Supabase adds one-click OAuth connect over the read-only Management-API (no DSN to paste); prod-gated on theSUPABASE_OAUTH_CLIENT_ID/_SECRETsecrets, with a graceful fall-back to paste when unset◯ SSO (SAML / OIDC), audit-log export, per-org quotas
◯ EU data residency, VPC peering, SOC 2
Develop locally
git clone git@github.com:nlqdb/nlqdb.git && cd nlqdb
scripts/bootstrap-dev.sh # installs everything, pulls Ollama models, seeds .envrc
scripts/login-cloud.sh # signs you into cloud providers that have a CLI flowbootstrap-dev.sh stands up the whole toolchain in one shot — Bun, Node
20+, Go 1.25+, uv; Biome / gofumpt / golangci-lint / ruff; lefthook git
hooks; the cloud CLIs (wrangler, flyctl, stripe, gh); a local Ollama so the
LLM router works offline; and a .envrc with self-generated dev secrets.
Details in
docs/history/infrastructure-setup.md §8.
Day-to-day:
bun run fix # biome format + lint --write (most issues)
bun run check:all # biome + golangci-lint + ruff (what CI runs)
bun run hooks:run # run pre-commit hooks against staged filesEnd-to-end tests (manual trigger)
E2E coverage is persona-driven and manually triggered so cost stays
inside the free-tier envelope — one workflow_dispatch workflow per
surface:
gh workflow run e2e-opencheck.yml # web — live LLM, Neon branch, Workers preview
gh workflow run e2e-cli.yml # Go testscript, hermetic
gh workflow run e2e-sdk.yml # vitest + cassettes, hermetic
gh workflow run e2e-mcp.yml # InMemoryTransport protocol tests, hermetic
gh workflow run e2e-examples.yml # Playwright across HTML/Next/Astro/Nuxt/SvelteKit
gh workflow run e2e-examples.yml -f live=true # + staging for the curl + CLI shell smokesRun the hermetic surfaces locally without GitHub:
( cd tests/e2e/cli && go test ./... )
( cd tests/e2e/sdk && bun install && bun run test )
( cd tests/e2e/mcp && bun install && bun run test )
( cd tests/e2e/examples && bun install && bun run install:browsers && bun run test )Only execution is manual: tests/e2e/{sdk,mcp,examples} live outside the root
workspace, so CI's typecheck-e2e job tscs them on every PR — the free
backstop against a suite that compiles today and rots before the next dispatch.
Conventions, persona mapping, and cassette governance are in
docs/features/e2e-coverage/FEATURE.md.
Docs & reference
docs/architecture.md— system design (auth, pricing, the $0 stack, model selection, hosted db.create, hello-world).docs/phase-plan.md— canonical phase plan and exit gates.docs/decisions.md— cross-cuttingGLOBAL-NNNdecisions; per-feature records live underdocs/features/.docs/performance.md— SLOs, latency budgets, span/metric catalog.docs/competitors.md— competitive landscape.
Community & legal
CONTRIBUTING.md — dev setup, branch naming, commits, CLA flow.
CODE_OF_CONDUCT.md — Contributor Covenant 2.1. Reports to
conduct@nlqdb.com.SECURITY.md — vulnerability disclosure (
security@nlqdb.com). 90-day fix target.SUPPORT.md — where to ask questions and what we don't (yet) offer.
CLA.md — Contributor License Agreement, signed once via the bot on your first PR.
TRADEMARKS.md — what you can and can't do with the nlqdb name and logo.
SUBPROCESSORS.md — third-party services that may process personal data on our behalf.
IMPRESSUM.md — Swiss UWG-mandated operator disclosures.
Privacy policy and terms of service: nlqdb.com/privacy · nlqdb.com/terms.
License
FSL-1.1-ALv2 — Functional Source License, Apache 2.0 future license. Source-available for any non-competing use; auto-converts to Apache 2.0 two years after each release. (Pattern used by Sentry, Convex, and others.)
nlqdb™ is an unregistered trademark of the project's licensor. See
TRADEMARKS.md for usage guidelines.
Available Tools
10 toolsnlqdb_apply_proposalApply one of the DBA's proposalsAIdempotentInspect
Apply a proposal on the attached database: its DDL runs (an index built CONCURRENTLY), the ledger records this key as who decided, and verify measures the query it targets after the window — a regression is reverted automatically by the stored inverse. Applying the same id again is a no-op (replayed: true).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The proposal's `id` from nlqdb_list_proposals or nlqdb_connect_database. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond annotations: DDL runs, an index is built CONCURRENTLY, the ledger records the deciding key, verification measures the targeted query after the window, and a regression triggers automatic revert via the stored inverse. The idempotent no-op with replayed: true is also disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and packed with relevant behavior in two tight sentences. The parenthetical and em-dash clauses each carry distinct operational meaning, so nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the mutation complexity and no output schema, the description covers the important side effects and idempotency well. It only partially describes the return payload beyond replayed: true, leaving a minor gap for an agent that needs the full response shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the single id parameter is already documented well. The description adds the retry/no-op behavior for the same id, but does not add syntax or constraints beyond what the schema and annotations provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
State a specific verb and resource: 'Apply a proposal on the attached database.' It goes beyond a restatement by explaining the DDL execution, ledger recording, verification, and automatic rollback, and its contrast with the sibling reject_proposal is clear from the verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes when to use it: a proposal exists on the attached database and its id comes from nlqdb_list_proposals or nlqdb_connect_database. It also explains replay behavior, though it does not explicitly state when not to use it or name reject_proposal as the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_connect_databaseConnect an existing database so the agent can query it in EnglishAInspect
Connect (attach) an existing Postgres or ClickHouse database: the agent can query it in natural language with nlqdb_query, and on Postgres nlqdb's DBA starts watching it — no migration, no schema upload. Pass the engine and a connection URL; the credential is stored sealed server-side and never echoed back. Returns the new dbId, a preview of the discovered schema and, on Postgres, the DBA's first proposals to apply or reject.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional display name for the connection; defaults to the database/host name. | |
| engine | Yes | Which engine the existing database runs — 'clickhouse' or 'postgres'. | |
| connection_url | Yes | The full connection URL for the database, including credentials (e.g. postgres://user:pass@host:5432/db or https://host:8443?user=…). Stored sealed server-side and never echoed back. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare destructiveHint=false, so the description carries the real burden and does so well: it discloses the side effect (the DBA starts watching the database on Postgres), the credential handling guarantee (stored sealed server-side, never echoed back), and the return shape (dbId, schema preview, first proposal set). It stops short of idempotency on re-connect (duplicate dbId?) or auth/permission prerequisites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the verb and resource, then side effects, then return value. "No migration, no schema upload" is a worthwhile disambiguation rather than filler, though the credential-storage clause is stated twice within the same paragraph.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly compensates by enumerating what comes back (dbId, schema preview, Postgres proposals). Combined with the sealed-credential note and engine options, an agent has everything needed to call it correctly; only failure/duplicate-connection behavior is unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and all three parameters are already documented with an enum on engine and format examples on connection_url. The description only restates "pass the engine and a connection URL" and repeats the sealed-credential note already present in the schema, so it adds little beyond the structured data.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("connect (attach) an existing Postgres or ClickHouse database") and immediately ties it to its downstream consumer (nlqdb_query). The supported engine list is named inline, so an agent can rule the tool in or out without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context for when to use: onboarding an existing database so it can be queried in natural language, with the explicit reassurance "no migration, no schema upload" that rules out a migration-style interpretation. It does not name a when-not condition or point at siblings such as nlqdb_list_databases for checking whether a connection already exists.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_describeDescribe one memory databaseARead-onlyInspect
Inspect the shape of one of your agent's memory databases. Return schema metadata (slug, engine, schema name) for one database. Requires a user-scoped key (sk_live_ or sk_mcp_).
| Name | Required | Description | Default |
|---|---|---|---|
| db | Yes | Database id or slug to describe. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already indicates a safe read operation, and the description adds context by specifying the exact metadata returned and the required key type. This goes beyond the annotation without contradicting it, but does not disclose potential error or edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences, each with clear value: the operation, the return structure, and the auth prerequisite. No redundant or filler content is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no output schema, no nested objects), the description covers all necessary aspects: purpose, return value, and prerequisites. The description fully compensates for the lack of an output schema by explicitly listing the metadata fields returned.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The single 'db' parameter is described in the schema as 'Database id or slug to describe,' and the tool description does not add any additional parameter-specific detail beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Inspect the shape of one of your agent's memory databases') and specifies the return value ('schema metadata (slug, engine, schema name)'). This distinguishes it from siblings like list_databases and query, which handle listing and querying respectively.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly notes it operates on a single database, contrasting with list_databases. It also mentions the auth requirement ('Requires a user-scoped key'), though it does not explicitly name alternative tools or provide a 'when not to use' exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_insertInsert rows; unseen tables and fields are createdADestructiveInspect
Insert structured rows into a table with no data modelling: an unseen table or field is created in the same transaction, typed from the values, and the rows land exactly as sent — no model call. Pass key to upsert: a row whose key exists is updated instead of duplicated. Returns the stored rows (generated ids included) and, when the schema widened, the DDL it ran. Use it whenever you hold the exact values; use nlqdb_query to write something described in words.
| Name | Required | Description | Default |
|---|---|---|---|
| db | Yes | Database id to write to (from nlqdb_list_databases). | |
| key | No | Fields that identify a row, e.g. ["server_id", "user_id"]. When set, a row whose key already exists is updated (only the fields it names) instead of duplicated, so re-running an import is safe. Every row must carry every key field; the first keyed write adds a unique index on them. | |
| rows | Yes | Rows as JSON objects, up to 1 000 per call. Keys become lower_snake_case columns (serverId → server_id); a field the table hasn't seen is added, typed from the values (number → numeric, string → text, object/array → jsonb, boolean → boolean). A key a row omits takes the column default. No model call, so the values land exactly as sent — use this for structured writes, nlqdb_query for writes described in words. | |
| table | Yes | Table to insert into. It need not exist: an unseen table is created, and its name is snake_cased like the columns. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only flag destructiveHint=true; the description supplies the substance behind it — schema widening happens in the same transaction, column types are inferred from values, naming is snake_cased, and the DDL that ran is returned. It doesn't say that the created table/columns persist and cannot be undone if the write was a mistake, which is the one behavioural consequence of the destructive hint left implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and its no-modelling trait, then the upsert rule, then the return shape, then the sibling routing. It is dense but every clause carries information; slightly heavy punctuation and a couple of restated points (no model call appears twice) keep it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description steps in and explains the return values (stored rows with generated ids, plus the DDL when the schema widened). Combined with the disclosed write limits and upsert behaviour, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already spells out `key` upsert semantics, value→type mapping, and the 1000-row cap in detail. The description restates the same facts ('Pass `key` to upsert', 'typed from the values') without adding syntax, format, or edge-case meaning beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific verb and resource ('Insert structured rows into a table') and immediately names the distinctive trait — no data modelling, unseen tables/fields auto-created — that separates it from nlqdb_query. An agent can pick between this and its siblings without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection rule: 'Use it whenever you hold the exact values; use nlqdb_query to write something described in words.' It also states when to use the `key` parameter (upsert / safe re-import), so both tool choice and mode choice are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_list_databasesList your agent's memory databasesARead-onlyInspect
List the memory databases your agent can query, scoped to the authenticated user. Requires a user-scoped key (sk_live_ or sk_mcp_). Returns engine per row.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the read-only nature is known. The description adds the auth requirement (user-scoped key) and the return format ('engine per row'), which exceeds what annotations provide and helps set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences each carry distinct value: purpose, auth requirement, and return format. The description is front-loaded with the primary action and contains no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter listing tool, the description covers all essential aspects: what is listed, scope, authentication prerequisite, and return shape. No output schema exists, so the description appropriately compensates by mentioning 'engine per row'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so schema coverage is trivially 100%. Baseline 4 applies, and the description appropriately mentions the scope and auth context without needing to explain parameter syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and resource ('memory databases') with clear scoping ('scoped to the authenticated user'), making the operation unambiguous. It also distinguishes itself from siblings like query or remember, which perform different actions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides useful context: the tool lists databases the agent can query and requires a user-scoped key. It does not explicitly name alternatives or when-not-to-use, but the naming and description sufficiently imply the intended use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_list_proposalsList the DBA's proposals on an attached databaseARead-onlyInspect
List what nlqdb's DBA proposes for an attached Postgres — each an index with the statement that undoes it and the reason — plus the ones already decided, with verify's measured p95 before/after once the window has passed. Pass the dbId nlqdb_connect_database returned.
| Name | Required | Description | Default |
|---|---|---|---|
| db | Yes | Id of the attached database (the dbId nlqdb_connect_database returned). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true already covering safety, the description adds real substance: it enumerates what each proposal contains (undo statement, rationale) and notes that decided proposals carry verify's measured p95 before/after only once the observation window has passed. That timing caveat is the kind of context annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence that front-loads the core purpose before the payload details and the dbId instruction. It is information-rich with little waste, though the nested clauses make it slightly harder to parse than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description covers purpose, the parameter's provenance, and the shape of the returned items, including the conditional p95 data. Missing only explicit guidance on what to do with the results (apply/reject), which the sibling tools would cover.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Single parameter with 100% schema coverage, so the schema already documents `db` fully. The description's 'Pass the dbId nlqdb_connect_database returned' merely restates the schema's own text, adding no new syntax or format detail — baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List what nlqdb's DBA proposes for an attached Postgres') and spells out the payload — index, undo statement, reason, plus already-decided items with measured p95. This is clearly distinguishable from the sibling nlqdb_apply_proposal / nlqdb_reject_proposal, which act on those proposals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Establishes the prerequisite explicitly ('Pass the dbId nlqdb_connect_database returned'), which sequences the agent after connecting. It stops short of naming alternatives or exclusions — e.g. that this is the review step before nlqdb_apply_proposal / nlqdb_reject_proposal — so routing to siblings is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_queryQuery your agent's memory in natural languageADestructiveInspect
Query your agent's structured memory in natural language — a real database it can GROUP BY / JOIN / aggregate over, not just recall. Returns rows + the compiled SQL (in trace). The database is materialised on first reference — no separate create tool. Destructive plans return requires_confirm: true + a diff; re-call with confirm: true to commit.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | The natural-language goal. Example: 'top 5 customers by revenue this year'. Name tables explicitly when you know them; avoid pronouns. | |
| db | No | Target database id or slug. Optional: omit to let nlqdb pick — it auto-targets your only DB (or creates one from the goal when you have none), and on multiple DBs returns ambiguous_db with candidate ids to choose from. Ignored for pk_live_ keys (already scoped to one DB). | |
| model | No | Model preset: 'fast' pins the free built-in chain, 'best' requires a frontier model (errors model_unavailable unless the account stored a BYOLLM key or has a paid plan), omit/'auto' lets nlqdb pick. | |
| confirm | No | Destructive writes are two calls: the first (confirm absent) returns requires_confirm: true plus a diff preview; show the diff, then re-call with confirm: true to commit. Read-only queries ignore this. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses the two-step confirmation for destructive plans (requires_confirm + diff, then confirm: true), the auto-creation of the database on first reference, and the return of rows along with compiled SQL in trace. These details give the agent a clear understanding of side effects and expected output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each delivering unique value: purpose and capabilities, return values and auto-creation, and destructive confirmation. It is front-loaded and free of redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description adequately covers return behavior (rows + SQL trace) and critical side effects (auto-creation, destructive confirm flow). Parameter descriptions handle errors like ambiguous_db and model_unavailable. It could be slightly more explicit about result formatting, but given the tool's complexity, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% parameter descriptions, including examples, edge cases, and enumeration. The tool description adds no further parameter semantics beyond what the schema states; even the confirm behavior is repeated verbatim from the schema. Baseline 3 is appropriate as the schema handles parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool queries the agent's structured memory in natural language, emphasizing its capability for GROUP BY/JOIN/aggregate operations. It distinguishes itself from simple recall and the sibling tools by positioning itself as a real database query interface.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for structured queries involving joins or aggregations, contrasting with 'not just recall' which hints at nlqdb_remember. It also explains the confirmation flow for destructive plans, guiding when confirm is needed. However, it does not explicitly name alternatives for listing or connecting databases, so it lacks a fully explicit when/when-not structure.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_readRead your agent's memory in natural language (never writes)ARead-onlyInspect
Read-only natural-language query over your agent's memory — SELECT / aggregate / JOIN over existing data. Guaranteed never to write, create, or modify: a request whose plan would change data is refused (use nlqdb_query for that), so this tool is safe to mark 'always allow' in your host. Auto-targets your only database; pass db to pick one when you have several. Returns rows + the compiled SQL in trace.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | The natural-language question. Read-only: SELECT / aggregate / JOIN over existing data. Example: 'top 5 customers by revenue this year'. Name tables explicitly when you know them; avoid pronouns. | |
| db | No | Target database id or slug. Optional: omit to auto-target your only database. Unlike nlqdb_query, this tool never creates a database — with several databases and no `db` it returns ambiguous_db with candidate ids; with none it asks you to create one via nlqdb_query first. | |
| model | No | Model preset: 'fast' pins the free built-in chain, 'best' requires a frontier model (errors model_unavailable unless the account stored a BYOLLM key or has a paid plan), omit/'auto' lets nlqdb pick. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only mark readOnlyHint: true, but the description goes much further: it guarantees no write/create/modify, states that plan-to-change requests are refused, discloses auto-target behavior and the ambiguous_db edge case, and tells the agent it returns rows plus compiled SQL. This is rich, non-contradictory behavioral disclosure well beyond structured hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, all value-dense and front-loaded with the core purpose and safety guarantee. Each sentence delivers a distinct piece of actionable information — behavior, exception, db targeting, return format — without repetition. It is concise but not under-specified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is fully self-contained for a read-only natural-language query tool. It covers the safety contract, failure cases (ambiguous_db, no db, now database), model selection, and the exact return output (rows + compiled SQL). Given the lack of an output schema, this description effectively compensates by disclosing the return shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaningful semantic context: `db` can be omitted to auto-target the only database, but with several it returns candidate IDs; `model`'s 'best' presets require specific account conditions; 'unique' is the default for nlqdb to choose. This goes beyond the schema's basic parameter docs, clarifying real usage nuances.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource pattern: 'Read-only natural-language query over your agent's memory — SELECT / aggregate / JOIN over existing data.' It clearly distinguishes this from sibling nlqdb_query and from a generic list/connect tool by emphasizing it never writes. The tool's intent is immediately transparent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given: 'a request whose plan would change data is refused (use nlqdb_query for that), so this tool is safe to mark always allow.' It also explains when to pass `db` vs. auto-targeting and touches on ambiguous-database behavior. This leaves little ambiguity about when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_reject_proposalReject one of the DBA's proposalsAIdempotentInspect
Decline a proposal; nothing runs on the database and it is never proposed again. Give a one-sentence reason (e.g. 'this table is append-only') — the DBA learns from it.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The proposal's `id` from nlqdb_list_proposals or nlqdb_connect_database. | |
| reason | No | Why not, in a sentence — kept on the proposal for the DBA to learn from. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by stating the side-effect profile: nothing runs on the database and the proposal is 'never proposed again', which tells the agent the rejection is durable. Idempotence and non-destructiveness are already in annotations, so no credit is needed there. What is missing is what happens with an invalid or already-decided id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with the action and its consequence, then the parameter guidance. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation with no output schema, the description covers the essential behavioral fact (nothing executes) and the reason field. Only error/edge-case behavior on invalid ids is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are fully documented in the schema; the description only echoes the reason guidance with an example. Baseline 3 applies because the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Decline') and resource ('a proposal') and the goal is unmistakable, distinguishing it from nlqdb_apply_proposal by implication. It does not name the sibling explicitly, but the action is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied — you reject a proposal you don't want executed — but there is no explicit statement of when to reject versus apply or edit, and no prerequisites or error conditions mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nlqdb_rememberRemember something in your agent's memoryAInspect
Write a typed row into your agent's memory database — a fact to recall later, a conversation episode, or an entity (person/project/thing). Materialises directly into the agent_memory_v1 schema with no LLM in the loop, so it's deterministic. Omit db on first use and this tool will find (or provision) the agent_memory_v1 database for you and echo dbId (and db_created: true on a fresh provision) in the result — pin that id on subsequent calls. Query it back later with nlqdb_query (which can GROUP BY / aggregate over what you remembered). Set kind + tags on facts — they are the columns those aggregates group by.
| Name | Required | Description | Default |
|---|---|---|---|
| db | No | Optional. The agent_memory_v1 database id (db_agent_memory_v1_…). Omit on first use and this tool will find (or provision) your account's memory DB automatically and return the new dbId in the result — pass that on subsequent calls. A non-memory DB is rejected with wrong_preset and the recovery is the same: omit `db` to auto-provision. | |
| kind | Yes | Which memory table to write into. Prefer 'entity' for anything with a current state (a project, a person, a config) — an entity is the CURRENT SNAPSHOT and upserts on (agent+kind+name), so re-remembering refreshes it in place instead of accumulating stale rows. Use 'fact' for a statement whose truth is time-bound (a status update, an observation, an idea) — give it a ttlSeconds when it's transient. Use 'episode' for one conversation/tool turn (append-only log). | |
| payload | Yes | Kind-specific fields. fact: { content, kind?, tags?, source? }. episode: { role, content, tool_calls?, tokens? }. entity: { kind, canonical_name, properties? }. Write for the queries you'll ask later: fact kind + tags become GROUP BY columns — reuse a small lower_snake kind vocabulary (leaving every row on the default 'fact' makes categories unqueryable) and tag every id/topic the row touches. Entities are current snapshots: keep the state in `properties` (JSONB) and re-remember the entity to update it — an upsert on (agent, kind, canonical_name) replaces properties when provided, so re-send the whole object. Prefer updating an entity over accumulating facts about it. Supersede rather than accumulate: when a fact becomes wrong or outdated, write the corrected fact (same tags) rather than piling on — old facts fade via ttlSeconds; entities are refreshed in place. Make content one self-describing sentence, so a row reads correctly on its own in a result set. | |
| threadId | No | Optional thread/conversation scope (facts / episodes). | |
| endUserId | No | Optional end-user scope (facts / episodes). | |
| ttlSeconds | No | Optional TTL in seconds — sets expires_at on a fact. Expired facts stop appearing in queries (RLS filters them out) and are physically evicted opportunistically on subsequent writes, so memory forgets what it no longer needs. Set this on any fact whose relevance is time-bound (a status, an observation, a hypothesis) — a day for daily standups, a week for weekly plans, a month for quarterly context. Facts without a TTL live forever; entities never expire (update them in place instead). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide only destructiveHint=false, so the description must cover the write behavior. It explains that writing is deterministic, materializes directly into a schema, and describes auto-provisioning of the database on first use. It also hints that facts with a TTL expire and are filtered out, and entities are upserted in place. However, it does not explicitly state that writing is not read-only beyond the annotation's implication – a small gap but overall strong transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is packed with valuable details but is somewhat lengthy. Each sentence adds meaning, though some repetition occurs (e.g., the TTL concept appears in both `payload` and `ttlSeconds` descriptions). It is front-loaded with the core purpose, making the rest readable. A bit more brevity could improve it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 6 parameters (2 required) and no output schema, the description covers all key aspects: how to start, parameter semantics, expected results (dbId, db_created), and how to query later. It lacks an explicit note on error handling beyond the wrong_preset for `db`, but overall it is sufficient for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, yet the description adds significant value beyond the schema. For `kind`, it explains the semantics of each enum option (snapshot vs time-bound vs append-only). For `payload`, it provides detailed structure per kind and advice on query design. For `ttlSeconds`, it describes expiration behavior and usage patterns. The description transforms raw schema fields into actionable guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool writes a typed row into the agent's memory database, listing three use cases (fact, episode, entity) and distinguishes it from siblings like nlqdb_query by specifying this is the write side. It also explains the deterministic behavior without an LLM in the loop.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to omit `db` for first use, how to pin the returned `dbId`, references sibling tool nlqdb_query for reading back the data, and gives detailed instructions on choosing among kind values and whether to use entity vs fact. It also advises on superseding old facts rather than accumulating stale rows.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.27- Added
nlqdb_apply_proposal - Added
nlqdb_list_proposals - Added
nlqdb_reject_proposal
1 tool update
v0.1.23- Changed
nlqdb_insert1 field changed- added
Input schema / properties / keyAdded value: +{ + "description": "Fields that identify a row, e.g. [\"server_id\", \"user_id\"]. When set, a row whose key already exists is updated (only the fields it names) instead of duplicated, so re-running an import is safe. Every row must carry every key field; the first keyed write adds a unique index on them.", + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" +}
3 tool updates
v0.1.22- Added
nlqdb_insert - Added
nlqdb_read - Changed
nlqdb_remember5 fields changed- changed
Input schema / properties / db / descriptionPrevious value: -"The agent_memory_v1 database id (db_agent_memory_v1_…). Provision one with db.create { preset: 'agent_memory_v1' }; a non-memory DB is rejected with wrong_preset."New value: +"Optional. The agent_memory_v1 database id (db_agent_memory_v1_…). Omit on first use and this tool will find (or provision) your account's memory DB automatically and return the new dbId in the result — pass that on subsequent calls. A non-memory DB is rejected with wrong_preset and the recovery is the same: omit `db` to auto-provision." - changed
Input schema / properties / kind / descriptionPrevious value: -"Which memory table to write into: 'fact' (a durable statement to recall later), 'episode' (one conversation/tool turn), or 'entity' (a person/project/thing — upserts on agent+kind+name)."New value: +"Which memory table to write into. Prefer 'entity' for anything with a current state (a project, a person, a config) — an entity is the CURRENT SNAPSHOT and upserts on (agent+kind+name), so re-remembering refreshes it in place instead of accumulating stale rows. Use 'fact' for a statement whose truth is time-bound (a status update, an observation, an idea) — give it a ttlSeconds when it's transient. Use 'episode' for one conversation/tool turn (append-only log)." - changed
Input schema / properties / payload / descriptionPrevious value: -"Kind-specific fields. fact: { content, kind?, tags?, source? }. episode: { role, content, tool_calls?, tokens? }. entity: { kind, canonical_name, properties? }."New value: +"Kind-specific fields. fact: { content, kind?, tags?, source? }. episode: { role, content, tool_calls?, tokens? }. entity: { kind, canonical_name, properties? }. Write for the queries you'll ask later: fact kind + tags become GROUP BY columns — reuse a small lower_snake kind vocabulary (leaving every row on the default 'fact' makes categories unqueryable) and tag every id/topic the row touches. Entities are current snapshots: keep the state in `properties` (JSONB) and re-remember the entity to update it — an upsert on (agent, kind, canonical_name) replaces properties when provided, so re-send the whole object. Prefer updating an entity over accumulating facts about it. Supersede rather than accumulate: when a fact becomes wrong or outdated, write the corrected fact (same tags) rather than piling on — old facts fade via ttlSeconds; entities are refreshed in place. Make content one self-describing sentence, so a row reads correctly on its own in a result set." - changed
Input schema / properties / ttlSeconds / descriptionPrevious value: -"Optional TTL in seconds — sets expires_at on a fact so it can be swept later."New value: +"Optional TTL in seconds — sets expires_at on a fact. Expired facts stop appearing in queries (RLS filters them out) and are physically evicted opportunistically on subsequent writes, so memory forgets what it no longer needs. Set this on any fact whose relevance is time-bound (a status, an observation, a hypothesis) — a day for daily standups, a week for weekly plans, a month for quarterly context. Facts without a TTL live forever; entities never expire (update them in place instead)." - changed
Input schema / requiredPrevious value: -[ - "db", - "kind", - "payload" -]New value: +[ + "kind", + "payload" +]
5 tool updates
v0.1.0- First observed
nlqdb_connect_database - First observed
nlqdb_describe - First observed
nlqdb_list_databases - First observed
nlqdb_query - First observed
nlqdb_remember
TDQS
Scored across 10 tools
The descriptions do a good job of separating overlapping write paths: nlqdb_insert takes exact values, nlqdb_remember writes typed memory rows deterministically, and nlqdb_query is for writes described in words. The read/write split between nlqdb_read and nlqdb_query is also clearly stated, though four tools with query-like or write-like semantics (insert, remember, query, read) still require careful reading to pick correctly.
All tools use a uniform nlqdb_ snake_case prefix, which makes the set highly predictable. However, several names are bare verbs (describe, insert, query, read, remember) rather than verb_noun, so the pattern is mostly rather than fully consistent.
Ten tools is squarely in the well-scoped range, and each earns its place: database introspection, connection, three memory/insert write paths, read/query, and a coherent proposal lifecycle.
The surface covers listing, describing, connecting, reading, querying, inserting, remembering, and the full proposal apply/reject lifecycle, with destructive writes handled via confirm. Minor gaps remain: no disconnect/drop-database operation and no first-class delete/update row tool (upsert only via key on insert, deletes only via nlqdb_query's confirm flow).
Maintenance
Related MCP Connectors
Graph-native persistent memory for AI agents — 33 MCP tools, zero-LLM writes.
Shared cross-LLM long-term memory over MCP: semantic recall, sessions, and media (pgvector).
Persistent, inspectable memory for AI agents with lineage, correction, and a hosted MCP endpoint.
Versioned agent memory in your own Postgres: portable context, permissioned, audit trail.
Related MCP Servers
AlicenseNot gradedqualityBmaintenanceLets you use Claude Desktop, or any MCP Client, to use natural language to accomplish things with Neon.641 npm659MIT- AlicenseNot gradedqualityAmaintenancePersistent shared memory for AI agents. Hybrid search (pgvector + tsvector), knowledge graph, cognitive scoring, and 16-language temporal extraction. 97.2% Recall@10 on LongMemEval with one PostgreSQL query. Works across Claude Code, Cursor, Codex, OpenClaw, and any MCP client.116MIT
- AlicenseNot gradedqualityBmaintenancePersistent semantic memory for AI agents using PostgreSQL and vector embeddings, enabling cross-session continuity and semantic search.AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceProvides a standardized interface for interacting with Neon's tools and services through a unified API via the Model Context Protocol.1,485 PyPIMIT