Skip to content

Give your agent memory — one command

nlqdb is analytical memory for AI agents: a real Postgres your agent connects to over MCP and queries in plain English — GROUP BY, JOIN, aggregate over what it remembered, not just the top-k a vector store recalls. One command connects it.

The hosted server lives at https://mcp.nlqdb.com/mcp (the protocol is at /mcp, not the bare domain). Follow the one step for your host — each host’s key names differ, so copy its own block, not a neighbour’s.

  1. Claude Code — run in your terminal:

    Terminal window
    claude mcp add --transport http nlqdb https://mcp.nlqdb.com/mcp
  2. Codex — add to ~/.codex/config.toml (remote HTTP servers are not addable via codex mcp add, which is stdio-only):

    [mcp_servers.nlqdb]
    url = "https://mcp.nlqdb.com/mcp"
  3. Claude Desktop — Settings → Connectors → Add custom connector, then paste the URL above. This is the one host whose documented remote path is a dialog, so it is the one step here a coding agent can’t run for you — take the headless route instead, which is a file it can write for you (you still quit and reopen the app).

  4. Windsurf — merge the nlqdb entry into mcpServers in ~/.codeium/windsurf/mcp_config.json, keeping any servers already there (a remote entry uses serverUrl, not url):

    { "mcpServers": { "nlqdb": { "serverUrl": "https://mcp.nlqdb.com/mcp" } } }
  5. Zed — merge the context_servers key into ~/.config/zed/settings.json (same path on macOS and Linux; zed: open settings file opens it). That file holds every Zed setting — theme, keymap, language servers — so add the key, don’t overwrite the file:

    { "context_servers": { "nlqdb": { "url": "https://mcp.nlqdb.com/mcp" } } }
  6. Cursor — merge the nlqdb entry into mcpServers in the project’s .cursor/mcp.json (or ~/.cursor/mcp.json to apply it everywhere), keeping any servers already there:

    { "mcpServers": { "nlqdb": { "url": "https://mcp.nlqdb.com/mcp" } } }
  7. VS Code — merge the nlqdb entry into .vscode/mcp.json, keeping any servers already there (the root key is servers, and a remote entry needs "type": "http"):

    { "servers": { "nlqdb": { "type": "http", "url": "https://mcp.nlqdb.com/mcp" } } }

Every file-based host above is machine-followable: a coding agent edits the config itself, no GUI click. Each block shows only the nlqdb entry — merge it in; overwriting the file drops the developer’s other servers and settings. On Cursor and VS Code the one-click deep-link buttons on nlqdb.com/integrations are a faster route for a human, not a requirement — the file works either way. Claude Desktop is the exception on this route: its connector dialog needs a human. The headless route below reaches it through a file instead, which an agent can write.

Every block above points at the hosted server, whose first tool call opens a browser page someone has to approve. If nobody is at a browser — an unattended agent, CI, a container — run the same five tools locally over stdio instead. npx fetches @nlqdb/mcp and it talks to the same production API; the credential is an sk_mcp_ MCP key in the host config, so no browser opens at any point.

Mint the key once at app.nlqdb.com/app/keys (that page needs a signed-in account — pick MCP key, and name the host and device it is for), then swap the nlqdb entry from your host’s Step 1 block for this one — same root key, only the server value changes. An MCP key is scoped to MCP: it can ask, list and describe your databases and read/write memory, but it cannot connect external databases or manage keys, and you can revoke that one host+device without touching anything else. It is still a live credential, so put it in the user-level config — ~/.cursor/mcp.json, ~/.codex/config.toml, or VS Code’s MCP: Open User Configuration rather than its workspace .vscode/mcp.json — never a file your repo commits. Revoke it at /app/keys if it leaks.

{ "command": "npx", "args": ["-y", "@nlqdb/mcp"], "env": { "NLQDB_API_KEY": "sk_mcp_REPLACE_ME" } }

That object is also the route into Claude Desktop, whose hosted path is the one dialog on this page: merge it into mcpServers in claude_desktop_config.json~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows, or Settings → Developer → Edit Config to open it — then fully quit and reopen the app.

VS Code additionally needs "type": "stdio" on that entry, in place of the "type": "http" its hosted block carries. Claude Code reads that same object too, but its JSON file is the repo-committed .mcp.json — so use the CLI, which writes the key to ~/.claude.json and nothing into your project:

Terminal window
claude mcp add --env NLQDB_API_KEY=sk_mcp_REPLACE_ME --transport stdio nlqdb -- npx -y @nlqdb/mcp

(the --transport stdio between --env and nlqdb is deliberate — the CLI reads a bare name straight after --env as another KEY=value pair and rejects it). Codex takes TOML, not JSON — its ~/.codex/config.toml table becomes:

[mcp_servers.nlqdb]
command = "npx"
args = ["-y", "@nlqdb/mcp"]
env = { NLQDB_API_KEY = "sk_mcp_REPLACE_ME" }

Steps 3–5 below apply to both routes.

Hosted route: on the first tool call, nlqdb opens an OAuth page in your browser. Approve it once; the host stores the token. There is no key to generate or paste, but it does need a human at a browser (as does Claude Desktop’s connector dialog in Step 1).

Headless route: already done — the sk_mcp_ key in the config above authenticates every call, and nothing opens a browser.

After connecting, the host lists these nlqdb tools:

  • nlqdb_query — ask your memory a question in English; returns rows plus the exact SQL it ran (in trace). The database materialises on first reference — there is no separate create step.
  • nlqdb_list_databases — list the memory databases scoped to your account.
  • nlqdb_describe — inspect one database’s shape (slug, engine, schema).
  • nlqdb_connect_database — attach an existing ClickHouse/Postgres so the agent can query it in English (no migration, no schema upload).
  • nlqdb_remember — write a typed memory row directly into an agent_memory_v1 preset database. See What’s live today — live for signed-in keys; set kind and tags on every fact (they become your GROUP BY columns), and fall back to nlqdb_query if it answers wrong_preset.

Store one fact, then read it back, both through nlqdb_query. The natural-language goal is the q argument; omit db and nlqdb targets your memory database — no database name to invent (a db slug that doesn’t exist yet returns db_not_found). The very first query has nothing to target yet, so nlqdb provisions the database from your goal on that call and returns db_created (the compiled schema rides in trace) — that is the “first reference”, and there is no separate create step to run. Every write after that goes through a render-before-commit gate: the write call returns requires_confirm: true plus a diff of what it will write, and you re-call with confirm: true to commit. Reads run straight through.

# First query provisions your memory DB from the goal (one-time) → db_created
Agent → nlqdb_query(q: "remember that the user prefers metric units")
→ db_created: true, dbId: "db_…" (+ the compiled schema in trace)
# Write — previews first, then commit
Agent → nlqdb_query(q: "remember that the user prefers metric units")
→ requires_confirm: true (+ a diff of the row it will insert)
Agent → nlqdb_query(q: "remember that the user prefers metric units", confirm: true)
→ committed (+ the SQL in trace)
# Read — no confirm needed
Agent → nlqdb_query(q: "what do you remember about the user?")
→ rows (+ the SQL in trace)

The read returning your fact — with the SQL visible in trace — confirms setup end to end: connected, authenticated, a database provisioned, and writing (through the confirm gate) and reading memory.

  • 404 / connection refused on first call (hosted route) — the config points at the bare domain. It must be the full https://mcp.nlqdb.com/mcp (the protocol is served at /mcp). The headless route carries no URL at all, so it cannot fail this way.
  • Auth loop / unauthorized (hosted route) — the browser OAuth was dismissed. Trigger any tool again and complete the approval.
  • Headless route: NLQDB_API_KEY is not set — the host didn’t pass env through. The binary exits before connecting, so the host reports the server as failed rather than showing a tool error; check the env block sits inside the nlqdb entry, and restart the host so it re-reads the file.
  • Headless route: unexpected prefix — the key was copied with a stray quote or whitespace, or it isn’t an account key.
  • nlqdb_connect_database answers connect_requires_account — expected on an sk_mcp_ key: attaching an external database is deliberately outside what an MCP key can do. Do it once from the dashboard (or with an sk_live_ account key); everything else on this page works on the MCP key.
  • Headless route: a tool call answers “This tool requires a user-scoped key” — the config reached the server and the server reached nlqdb, but the key isn’t valid. Mint a fresh one at app.nlqdb.com/app/keys and restart the host.
  • Host doesn’t show the tools — restart the host after editing its config, then re-list MCP servers. If they still don’t appear, check the root key: Cursor reads mcpServers from .cursor/mcp.json, VS Code reads servers from its mcp.json, each entry needing a "type""http" on the hosted route, "stdio" on the headless one. The wrong key parses as zero servers, with no error.
  • nlqdb_remember returns wrong_preset — the target database isn’t an agent_memory_v1 preset. Create one (db.create { preset: 'agent_memory_v1' } or the dashboard), or write through nlqdb_query instead (see below).

Want the coding agent you build with to wire this up once and use it forever? Drop a ready-made artifact into your project — the connect command in each is pinned by a test to the same source as this page, so the two can’t drift apart.

Claude Code: install the plugin — it bundles the MCP server and both skills, so this replaces Step 1 rather than following it. Run both lines inside Claude Code:

Terminal window
/plugin marketplace add nlqdb/nlqdb
/plugin install nlqdb-memory@nlqdb

The plugin is nlqdb’s published artifacts directory itself, so its skills are the same files listed below — never a copy that can drift. Authentication is the hosted route above: the first tool call opens the browser OAuth page once.

Any host (Claude Code, Cursor, Codex) — installs the skill alone with the skills CLI (public repo, no account):

Terminal window
npx skills add https://github.com/nlqdb/nlqdb/tree/main/apps/web/public/agent-artifacts/nlqdb-memory

It writes .agents/skills/nlqdb-memory/SKILL.md — the cross-agent skill directory Cursor and Codex read directly — plus a .claude/skills/ symlink to it (Claude Code documents only .claude/skills/) and a skills-lock.json. Verified against the live CLI 2026-07-25. It does not write a .cursor/rules/ file and does not edit AGENTS.md; if your host reads only AGENTS.md, append the snippet below by hand.

Or drop a file in by hand:

  • AGENTS.md (host-neutral — Claude Code, Codex, and any agent that reads it): append AGENTS.snippet.md.
  • Claude Code (skill): save SKILL.md as .claude/skills/nlqdb-memory/SKILL.md.
  • Cursor: save nlqdb-memory.mdc as .cursor/rules/nlqdb-memory.mdc.
  • Codex: merge codex-config.toml into ~/.codex/config.toml.

Index + drop locations: nlqdb.com/agent-artifacts/README.md.

A second skill points the same memory at the repo it lives in. It extracts the structure your docs already carry — decision ids and statuses, open questions with the dates they appeared, queues, trackers, and the references between them — so “which features have open questions older than 30 days” and “which decisions reference GLOBAL-013” become one query instead of an afternoon of grep. It ingests structure only, never prose paragraphs, and the sync is one-way: markdown stays the source of truth and nlqdb never writes it.

Terminal window
npx skills add https://github.com/nlqdb/nlqdb/tree/main/apps/web/public/agent-artifacts/nlqdb-docs-memory

Two paths, both live. The dedicated nlqdb_remember verb and the typed agent_memory_v1 schema (facts / episodes / entities, per-agent isolation, TTL) are live for signed-in keys as of 2026-07-29: create a memory database with the preset, then nlqdb_remember writes typed rows into it (a non-preset target rejects with wrong_preset). And nlqdb_query works everywhere, anonymous sessions included: your agent provisions a database on first reference and reads and writes memory through it in plain English, aggregating over what it stored. Everything on this page works through nlqdb_query regardless.