MCP Server
Give Claude, Cursor, Windsurf, VS Code Copilot, and any MCP-compatible AI tool persistent long-term memory via CortexDB.
The CortexDB MCP server is a small bridge process that exposes CortexDB to any Model Context Protocol–compatible client — Claude Desktop, Claude Code, Cursor, Windsurf, VS Code Copilot.
Requires Python 3.10+. cortexdb-mcp doesn't install on Python 3.9 — pip refuses with
"Requires-Python >=3.10". macOS users on Apple's bundled Python 3.9 need a newer interpreter first:
brew install python@3.11 (then python3.11 -m pip install …), or use pipx / uv which manage
their own Python.
Installation
# pip (any Python 3.10+ venv)
pip install 'cortexdb-mcp>=0.7.5'
# pipx — recommended on macOS/Linux; auto-isolates the install
pipx install --python python3.11 'cortexdb-mcp>=0.7.5'
# uv — fastest; pulls its own Python if needed
uvx --python 3.11 cortexdb-mcp --helpThe PyPI package is cortexdb-mcp, not cortexdbai-mcp (which does not exist on PyPI). The
current release is listed in
Versioning and SDK compatibility; if you run an
older one, see Upgrading.
Verify it's on your PATH:
cortexdb-mcp --version # cortexdb-mcp 0.8.0
cortexdb-mcp --helpThe binary takes two options. --transport accepts only stdio (there is no HTTP/SSE transport), and
--tool-profile all|code selects the tool surface — see Tool profiles.
Windows: use the full .exe path
On Windows, use the full path to cortexdb-mcp.exe (e.g.
%LOCALAPPDATA%\Programs\Python\Python313\Scripts\cortexdb-mcp.exe) in the MCP config — Windows MCP
clients don't resolve bare command names through PATH reliably.
Setup
Every MCP client uses a JSON config file. The structure is the same everywhere — only the file path differs. There are three ways to set it up.
Option A — CortexDB Cloud
Create an API token on your dashboard, which also shows your actor and default scope, and give the server all four:
{
"mcpServers": {
"cortexdb": {
"command": "cortexdb-mcp",
"env": {
"CORTEXDB_URL": "https://api.cortexdb.ai",
"CORTEXDB_API_KEY": "<your API token>",
"CORTEXDB_ACTOR": "user:acct_42",
"CORTEXDB_SCOPE": "org:acct_42/user:acct_42"
}
}
}
}The token lasts 90 days; replace it with a new one from the dashboard. Every tool call counts against
your plan. With no CORTEXDB_API_KEY the server tries an anonymous
POST /v1/auth/signup against CORTEXDB_URL instead; CortexDB Cloud has signup off (its accounts come
from cortexdb.ai), and a self-hosted server only allows it with its dev minter on, so set the key.
Option B — Bring your own token (your own IdP)
Set three env vars so the server skips signup and uses the credentials you supply:
CORTEXDB_API_KEY— The bearer credential: a PASETO v4 token minted viaPOST /v1/auth/tokens(or by your IdP).CORTEXDB_ACTOR— The actor id; must match the token'ssubclaim. Sent asX-Cortex-Actoron every call.CORTEXDB_SCOPE— The default scope path tools use when one isn't passed explicitly. Optional when signup supplied one; otherwise required (a tool call without a scope fails withno scope configured; it does not fall back to the actor).
Option C — Self-hosted server
Point CORTEXDB_URL at your server and supply the server's key as the bearer. CORTEXDB_SCOPE is
required here (a self-hosted server normally has no signup to derive one from); a tool call without a
scope fails with no scope configured.
{
"mcpServers": {
"cortexdb": {
"command": "cortexdb-mcp",
"env": {
"CORTEXDB_URL": "http://localhost:3141",
"CORTEXDB_API_KEY": "<the server's CORTEX_API_KEY value>",
"CORTEXDB_ACTOR": "user:alice",
"CORTEXDB_SCOPE": "user:alice"
}
}
}
}On a server started with CORTEX_INSECURE_NO_AUTH=1, omit CORTEXDB_API_KEY (no Authorization
header is sent; the server serves each request as the X-Cortex-Actor the MCP server sends from
CORTEXDB_ACTOR, or user:local without one) but keep CORTEXDB_SCOPE. See
Self-hosting defaults and the
authorization note on presets.
Local state
The server stores its credentials (and only its credentials) under:
- macOS / Linux:
$XDG_CONFIG_HOME/cortexdb-mcp/state.json(default~/.config/cortexdb-mcp/state.json) - Windows:
%APPDATA%\cortexdb-mcp\state.json
The file is mode 0600 on POSIX. Contents: { "token", "actor", "scope", "expires_at" } — the values
POST /v1/auth/signup returned (user_id is stored as actor; expires_at when the mint reported
one, used to sign up again on expiry). No memories are stored locally. It is only read
when CORTEXDB_API_KEY is unset; an explicit env key always wins. Delete the file to force a re-signup on the next call.
This path and key set differ from the CLI's state file
The MCP server reads <APPDATA|XDG>/cortexdb-mcp/state.json, while the CLI and connectors use
~/.cortexdb/state.json — and the CLI writes the actor under user_id, not actor. Reusing one
anonymous identity across both tools means copying the file to the other tool's path and renaming
user_id ↔ actor — see CLI configuration.
Per-client configuration
The JSON blocks below show a token in the env block (Options A and B). For a self-hosted
server use the Option C env block instead.
Claude Desktop
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"cortexdb": {
"command": "cortexdb-mcp",
"env": {
"CORTEXDB_API_KEY": "v4.public.eyJpc3MiOi...",
"CORTEXDB_ACTOR": "user:u_019e2f...",
"CORTEXDB_SCOPE": "org:u_019e2f.../user:u_019e2f..."
}
}
}
}Claude Code (CLI)
claude mcp add --transport stdio \
-e CORTEXDB_URL=https://api-v1.cortexdb.ai \
-e CORTEXDB_API_KEY=v4.public... \
-e CORTEXDB_ACTOR=user:u_019e... \
-e CORTEXDB_SCOPE=org:u_019e.../user:u_019e... \
cortexdb -- cortexdb-mcpOptions go before the server name and -- separates Claude Code's flags from the server command.
Add --scope user to make the server available in every project, or --scope project to write it
to a shareable .mcp.json in the repository root. Without --scope, Claude Code stores the entry in
~/.claude.json (local scope, this project only); there is no ~/.claude/mcp.json. To edit by hand,
put the same mcpServers block into .mcp.json (project) or ~/.claude.json (user/local).
Cursor
Edit ~/.cursor/mcp.json:
{
"mcpServers": {
"cortexdb": {
"command": "cortexdb-mcp",
"env": {
"CORTEXDB_URL": "https://api-v1.cortexdb.ai",
"CORTEXDB_API_KEY": "v4.public...",
"CORTEXDB_ACTOR": "user:u_019e...",
"CORTEXDB_SCOPE": "org:u_019e.../user:u_019e..."
}
}
}
}Windsurf
Edit ~/.codeium/windsurf/mcp_config.json (same mcpServers block as Cursor).
VS Code (GitHub Copilot)
Add to .vscode/mcp.json (project) or ~/.vscode/mcp.json (global). Note the key is servers, not
mcpServers:
{
"servers": {
"cortexdb": {
"command": "cortexdb-mcp",
"env": {
"CORTEXDB_URL": "https://api-v1.cortexdb.ai",
"CORTEXDB_API_KEY": "v4.public...",
"CORTEXDB_ACTOR": "user:u_019e...",
"CORTEXDB_SCOPE": "org:u_019e.../user:u_019e..."
}
}
}
}Tools exposed
The server registers 27 tools, plus 3 resources (cortexdb://health,
cortexdb://episodes, cortexdb://insights) and 5 prompts.
Matched spans and code citations
memory_searchshows matched document spans. For a long (chunked) document the reply ends with--- N matched document span(s) ---: one line per chunk a retrieval channel matched, with the event id, the channel (bm25orvector) and the section path, for exampleevt_… [bm25] Handbook > VPN troubleshooting: …. Needs server capabilitymatched_fragments_v1; short memories, and servers without that capability, show nothing extra. When the server serves an excerpt of the document, the span line names the section but carries no span text.- Code tools describe citations as
repo:path@<snippet-hash>#Lstart-Lend(the hash covers the snippet, not a git commit) and label call-graph nodes by their qualified C++ name (buffered_file::close).
Every tool that takes a scope accepts it as
tenant_id (a legacy name — it is a v1 scope path) and falls back to CORTEXDB_SCOPE.
Memory
| MCP tool | v1 endpoint | Notes |
|---|---|---|
memory_store | POST /v1/experience | Wraps free-form text in a conversation envelope with a fresh idempotency_key; source / episode_type become source: / type: labels; namespace appends /ns:<name> to the scope. ttl_seconds is accepted but ignored (the reply says so). Returns captured immediately — it does not wait for indexing. |
memory_status | GET /v1/experience/status | Did a store land? Check by event_id or idempotency_key (keys are kept 24 h) after a timeout. |
memory_search | POST /v1/recall | view from CORTEXDB_VIEW (default holistic); diagnostics="none" so free-tier tokens succeed. Shows the first max_results memories from the pack's context_block, falling back to derived facts. |
get_context | POST /v1/recall | Same call, rendered as memories + facts + beliefs for "what should I know before I respond". include_graph only adds a hint line. |
advanced_search | POST /v1/recall | time_range_start / time_range_end become a temporal window; source / episode_type filter on labels; limit / offset page the results. |
memory_list | GET /v1/events | Scope-aware list of raw events; offset is sent as cursor; episode_type filters client-side on the type: label. |
memory_get | GET /v1/events/{id} | Single event by id (0.8.0 sends no ?scope= filter, so it reads any event the credential can see). |
Deleting
| MCP tool | v1 endpoint | Notes |
|---|---|---|
forget_preview | POST /v1/forget/preview | Dry run: per-layer estimated counts plus a fpvw_… preview id. Same selector rules as the delete tools. |
memory_forget | POST /v1/forget | query → selector.about_subject; no query → whole-scope confirm_all=true. Pass from_preview_id from forget_preview for the two-phase flow. Always cascade: derived_only. |
memory_bulk_delete | POST /v1/forget (+ /v1/forget/preview when dry_run=true) | Subject-targeted delete by query; dry_run previews instead. |
memory_delete | POST /v1/forget | Selector preset for one memory_ids=[…]. |
Knowledge graph and beliefs
| MCP tool | v1 endpoint | Notes |
|---|---|---|
entity_list | GET /v1/facts | Distinct fact subjects in the scope (synthetic subjects filtered out). |
entity_get | GET /v1/facts?subject= | Facts filtered to one subject (predicate -> object lines). |
entity_edges | GET /v1/facts?subject= | Same query, rendered as subject --[predicate]--> object. |
entity_link | POST /v1/experience | Records a "X relates to Y" sentence for the LLM extractor to turn into a fact. |
belief_declare | POST /v1/beliefs | Writes a belief record directly (statement, confidence, optional supports event/fact ids, subject, predicate). A newer belief on the same subject+predicate closes the previous one. |
list_conflicts | GET /v1/conflicts | Detected contradictions for a scope (status=open default, or all). |
resolve_conflict | POST /v1/conflicts/{id}/resolve | pick (needs winner) / split (boundary, earlier, later) / new_information (record) / dismiss. Wrong or missing fields are rejected client-side with the expected list. |
claim_history | GET /v1/claims/history | Full bi-temporal change-log of one subject+predicate claim, with any conflicts on it. |
Status, usage and helpers
| MCP tool | v1 endpoint | Notes |
|---|---|---|
health_check | GET /v1/auth/whoami | Auth + reachability in one call: caller, tenant, preset, capabilities. |
get_usage | GET /v1/auth/whoami | Same call plus the X-RateLimit-Limit and X-Cortex-Token-Expires-* response headers. |
get_insights | GET /v1/events, /v1/facts, /v1/beliefs (up to 500 each) | Heuristic pass over the scope — contradictions, low-confidence beliefs, key entities, activity spikes, new sources. No recall and no LLM involved. |
cortexdb_check_call | none (offline) | Validates a planned HTTP call or SDK snippet before you make it — catches POST /v1/memories, client.remember(...), a scope missing its type: prefix, a selector combined with confirm_all — and returns the correction. |
Code memory
Four read-only tools for the code memory plane; the server must run with
CORTEX_CODE_PLANE=1 or every call returns 503 CODE_PLANE_DISABLED. Repository registration is an
operator action through the API/CLI, not an MCP tool.
| MCP tool | v1 endpoint | Notes |
|---|---|---|
code_explore | POST /v1/code/context (one repo) or POST /v1/code/workspace/context (several) | Token-budgeted evidence envelope of cited snippets (repo:path@hash#Lx-Ly). |
code_impact | GET /v1/code/impact | Reverse dependency closure of a symbol, depth 1–6. |
code_inventory | POST /v1/code/symbol/search or POST /v1/code/inventory | kind is required: a symbol-prefix search, or a bounded structural inventory (stats, files, …). |
code_graph | POST /v1/code/graph/query | Bounded graph traversal from roots, with node/edge budgets. |
Code tools need the code plane
The four code_* tools answer 503 CODE_PLANE_DISABLED on a server without CORTEX_CODE_PLANE=1.
Entity/Facts tools need enrichment on self-host
entity_list / entity_get / entity_edges / list_conflicts / claim_history read the Facts
layer, which is empty on a content-only self-hosted instance — those layers need enrichment
configured. memory_store / memory_search / memory_list / belief_declare work regardless. See
Self-hosting defaults.
Resources and prompts
The server also registers three MCP resources — cortexdb://health (GET /v1/auth/whoami),
cortexdb://episodes (the scope's last 50 raw events via GET /v1/events) and cortexdb://insights
(the same heuristic pass as get_insights) — and five prompts: investigate_incident(topic),
summarize_knowledge(topic), deployment_review(service), onboard_to_codebase(repo) and
weekly_digest(tenant_id?). The prompts are plain instruction templates; they make no API calls
themselves.
Tool profiles
cortexdb-mcp --tool-profile code exposes only the four code_* tools (the memory tools are
removed from the listing and cannot be called). The default all exposes all 27. Resources and
prompts are registered under both profiles.
Configuration Reference
| Environment variable | Default | Notes |
|---|---|---|
CORTEXDB_URL | https://api-v1.cortexdb.ai | v1 endpoint. With no CORTEXDB_API_KEY, anonymous signup is attempted against this URL (any host). |
CORTEXDB_API_KEY | (none) | PASETO v4 bearer — see Auth — or, self-hosted, the server's CORTEX_API_KEY value. Unset → the cached state file, then anonymous signup. |
CORTEXDB_ACTOR | (none) | Sent as X-Cortex-Actor. Must match the token's sub claim; set automatically by signup. |
CORTEXDB_SCOPE | (none) | Default scope for tools that don't take an explicit one; set automatically by signup. Required otherwise. |
CORTEXDB_VIEW | holistic | Default recall reach for memory_search / get_context / advanced_search: holistic, descend (scope + all sub-scopes), or granular. |
CORTEXDB_TENANT_ID | (none) | Legacy tenant id (v0 callers only). |
CORTEXDB_TIMEOUT | 30.0 | HTTP request timeout (seconds). |
The wheel also carries a small FastAPI app (uvicorn cortexdb_mcp.api:app) that serves the insights
pass as GET /api/insights for a dashboard. It is not part of the MCP surface.
Architecture
Your Machine CortexDB
┌──────────┐ stdio ┌───────────┐ HTTPS ┌──────────┐
│ Cursor / │ ◄─────────► │ cortexdb- │ ◄─────────► │ v1 API │
│ Claude / │ MCP JSON │ mcp │ REST │ server │
│ VS Code │ │ (bridge) │ │ │
└──────────┘ └───────────┘ └──────────┘The bridge process holds the bearer token in memory, injects Authorization and X-Cortex-Actor
headers on every call, and translates MCP tool invocations into v1 HTTP requests. Nothing is stored
locally except the credentials.
Next steps
- Python SDK — programmatic access,
V1Client+AsyncV1Client. - TypeScript SDK — Node.js and browser apps,
V1Client.signup()one-liner. - Auth — how tokens, actors, and capabilities fit together.
- API Reference — endpoint-by-endpoint reference.