FOR CURSOR

Connect Kireo memory MCP to Cursor

Add the Kireo memory MCP server to Cursor by creating ~/.cursor/mcp.json with one mcpServers.kireo entry that runs npx -y -p @kireo/mcp-server kireo-mcp and passes your ki_sk_ API key. Cursor's Agent then gets eight memory tools. Point Claude Code at the same key and both editors read and write one store.

Before you paste anything

Three prerequisites, and none of them are Cursor settings. You need Node.js 20 or newer on PATH — the package declares "node": ">=20.0.0" in its engines field, so npx can fetch and run it. You need a Kireo API key shaped like ki_sk_… from the API Keys page. And you need to know which of the two config files you want — Cursor documents ~/.cursor/mcp.json in your home directory for tools available everywhere, and <workspace>/.cursor/mcp.json for project-specific ones.

There is no separate install step. The npx invocation in the config is the install: Cursor spawns it, npm resolves @kireo/mcp-server, and the process talks JSON-RPC over stdio.

Sources on this page are split deliberately. Numbers about the server process were measured on a real machine. Statements about Cursor's own behaviour are cited from Cursor's documentation, checked 2026-08-03 — we could not run Cursor on the machine used for the measurements, so nothing here claims a Cursor end-to-end test.

The mcp.json block

Create the file if it does not exist, paste this, save. Same shape either way — put it in ~/.cursor/mcp.json to have Kireo everywhere, or in .cursor/mcp.json at a repo root to scope it to that project.

~/.cursor/mcp.json
json
{ "mcpServers": { "kireo": { "type": "stdio", "command": "npx", "args": ["-y", "--package=@kireo/mcp-server", "kireo-mcp"], "env": { "KIREO_API_KEY": "ki_sk_live_..." } } } }

The -p flag is not optional and not cosmetic. The npm package publishes two binaries — kireo-mcp (the MCP server) and kireo (a CLI) — and neither is named mcp-server, so npx cannot infer which one to run from the package name alone. Running npx -y @kireo/mcp-server exits 1 with npm error could not determine executable to run (measured 2026-08-03, npm 11.11.1). Older copies of this snippet that omit -p were still in circulation when this page was written — including in the package README shipped with 0.2.1. They do not work.

Keeping the key out of a file you might commit

A per-repo .cursor/mcp.json lives inside your repository, and an env block puts a live ki_sk_ key on a path somebody eventually commits. Cursor documents an envFile option for exactly this, and it is available to Kireo because Kireo is a STDIO server: “The envFile option is only available for STDIO servers. Remote servers (HTTP/SSE) do not support envFile” (cursor.com/docs/context/mcp, checked 2026-08-03).

~/.cursor/mcp.json (envFile variant)
json
{ "mcpServers": { "kireo": { "type": "stdio", "command": "npx", "args": ["-y", "--package=@kireo/mcp-server", "kireo-mcp"], "envFile": "/Users/you/.kireo/cursor.env" } } }

The referenced file holds one line: KIREO_API_KEY=ki_sk_live_.... An absolute path is used above on purpose — Cursor's documentation does not specify how a relative envFile path is resolved, so pinning it removes the question.

Verify it works

Start with the half that does not involve Cursor at all. If the package cannot start in a terminal, it will not start under Cursor either, and the terminal shows you why.

terminal
bash
npx -y -p @kireo/mcp-server kireo --version # 0.2.1 (exit 0, measured 2026-08-03)

Then open Cursor's Settings → MCP and look for the kireo entry with its eight tools. Cursor's docs do not state whether mcp.json is hot-reloaded after an edit, so we will not claim it either way — if the entry is not there, that screen is the first place to look.

The end-to-end check is to ask the Agent for a health probe. It calls a real tool and reports both halves of the connection at once:

in Cursor
text
> Check the Kireo memory server. ↳ memory_health {} ✓ local: { server_version, node_version, platform } ✓ remote: { status: "ok" }
How long the spawn takes. With the npx cache already warm, five runs of that exact server command completed the MCP initialize + tools/list handshake in 791–1,106 ms (median 812 ms), returning 8 tools every time — macOS 26.2 arm64, Node v25.8.2, npm 11.11.1, @kireo/mcp-server 0.2.1, measured 2026-08-03. A first run with a cold cache has to download the package first and will be slower; that case was not measured, so no number is given for it.

What Cursor's Agent gets 8 tools

These are the eight tools the server registers, in registration order, with the argument limits that actually bite when an agent calls them unattended. Names and constraints are read from packages/mcp-server/src/tools/*.ts and confirmed against a live tools/list handshake with the published build (@kireo/mcp-server 0.2.1, 2026-08-03).

  • memory_saveWrites one typed record. Required field: content.content 1–8,000 chars · type is one of fact, decision, preference, event, goal, insight, relationship, other (default fact) · returns { id, created_at, schema_version, embedding_status }, not the full record
  • memory_searchHybrid semantic + keyword retrieval. Required field: query.query 1–2,000 chars · limit defaults to 10, max 50 · namespace is optional — omitting it widens the query to every bucket on the account
  • memory_recallReplays a namespace with no query — the “what were we doing” call.limit defaults to 20, max 50 · order is recency (default) or importance · namespace defaults to "default"
  • memory_getFetches one record when the agent already holds the id.id must match ^mem_[A-Za-z0-9]+$ — the same pattern as update and delete
  • memory_updatePATCH semantics: only the fields you pass are changed.sending id alone is rejected with “Provide at least one field besides id”
  • memory_deleteRemoves a record. Always a soft delete.recoverable for 30 days, then purged automatically · the hard flag is accepted for compatibility and has no effect
  • memory_list_namespacesEnumerates the buckets on your account.no arguments · returns { name, created_at } per namespace — no per-namespace counts
  • memory_healthProbes local process and remote API in one call.no arguments · returns local { server_version, node_version, platform } and remote { status }

One rule applies to all eight: every input schema is strict (additionalProperties: false). An extra field an agent invents is rejected with InvalidParams — it is not silently ignored. The same strictness applies to values: namespace must match ^[a-z0-9_-]{1,32}$ (no uppercase, no dots, no slashes), tags must match ^[a-z0-9_-]+$, and metadata must serialise to 2,048 bytes or less.

Two behaviours are worth knowing before you tune anything. min_score on memory_search is not an API parameter — it is applied client-side inside the MCP server, afterlimit has already been enforced server-side, so a threshold returns fewer rows than limit rather than digging deeper for replacements. And memory_recall with order: "importance" pages through at most the 1,000 most recent rows and sorts those locally, always returning next_cursor: null — it is a recency-weighted importance ranking, not a ranking of your whole history.

One store, two editors

Most people reading this do not only use Cursor. That is the interesting part, and it is worth being precise about why it works, because the mechanism is not a Kireo feature.

The Model Context Protocol is an open standard for connecting AI applications to external systems, and its own specification says it “takes some inspiration from the Language Server Protocol, which standardizes how to add support for programming languages across a whole ecosystem of development tools” (modelcontextprotocol.io/specification/latest, checked 2026-08-03). Cursor and Claude Code are both MCP hosts. So “works in more than one editor” is a structural consequence of the protocol — one server implementation, any compliant host — and not something any single vendor invented.

What ties your two clients to one store is the API key. Every request the server makes carries Authorization: Bearer <key>, and stored rows carry a user_id column. Two client entries holding the same ki_sk_ key are the same account, so a decision Cursor's Agent saves is literally the row Claude Code's memory_search returns.

The unit of sharing is the namespace, not the client. Nothing in a record says which editor wrote it, and nothing needs to:

the same bucket, from either side
text
# in Cursor ↳ memory_save { content: "...", type: "decision", namespace: "acme-api" } # later, in Claude Code ↳ memory_recall { namespace: "acme-api", order: "recency" }

That symmetry is also why namespace is optional on memory_search: when you work across two editors, the bucket a decision landed in often depends on which one happened to be open at the time, and dropping the argument widens the query to every bucket on the account.

The other half of the pair is one command. Note the long --package= form rather than -p: a bare short flag after -- confuses claude mcp add's own option parser (measured on claude 2.1.220, 2026-08-03). A JSON file never goes through that parser, which is why the Cursor block above can keep the short -p.

terminal (the Claude Code half)
bash
claude mcp add kireo --scope user \ --env KIREO_API_KEY=ki_sk_live_... \ -- npx -y --package=@kireo/mcp-server kireo-mcp

The full Claude Code walkthrough, including its own scope and approval quirks, is on the Claude Code page.

Where the honest comparison lands

Cross-client memory over MCP is not exclusive to Kireo, and other implementations beat it on real axes. mem0's OpenMemory MCP is “a private, local-first memory server that creates a shared, persistent memory layer for your MCP-compatible tools”, and it is explicit that “All memory is stored on your machine. Nothing goes to the cloud”, listing Cursor, Claude Desktop, Windsurf and Cline as compatible (mem0.ai/blog/introducing-openmemory-mcp, checked 2026-08-03). If “nothing leaves this laptop” is your requirement, that is the stronger fit and you should use it. Graphiti, the Apache-2.0 temporal knowledge-graph engine behind Zep, also ships its own MCP server (github.com/getzep/graphiti, checked 2026-08-03) and models entities, relationships and their validity over time — something plain vector retrieval does not give you.

Kireo's trade is the opposite one: a hosted store you do not run, patch or back up, with a web UI for reading and deleting what your agents wrote. That is a real trade, not a strict improvement — you are choosing “someone else operates it” over “it never leaves my machine”.

Three things specific to Cursor

1. Write "type": "stdio" even though the docs' example omits it

Cursor's MCP documentation is internally inconsistent here: its STDIO field table marks type as required, while the example JSON further down the same page leaves it out (cursor.com/docs/context/mcp, checked 2026-08-03). The config at the top of this page includes it, because every real config we could inspect carries it — the entries already present in this machine's ~/.cursor/mcp.json have the field names type, command, args, and Claude Code writes "type": "stdio" into the .mcp.json it generates. Most copies of the Kireo snippet in circulation predate this and omit type. Adding it costs nothing and removes a variable.

2. envFile exists here and does not exist in Claude Code

This is the one place the two configs genuinely diverge rather than just looking different. Cursor gives STDIO servers an envFile option; Claude Code instead expands ${VAR} references inside .mcp.json. If you are keeping a per-repo config, use the envFile variant shown above rather than porting the Claude Code pattern across — ${VAR} has no meaning to Cursor, and an unexpanded literal fails the server's key check (^ki_sk_[A-Za-z0-9_-]+$) at startup.

Both key failures are loud in the right place and invisible in the wrong one. Missing key: [kireo-mcp] fatal: Error: Invalid Kireo configuration: KIREO_API_KEY (apiKey): Required. Wrong shape (an sk-… key pasted by habit, say): KIREO_API_KEY must look like ki_sk_xxx. Both were reproduced on 2026-08-03; both go to stderr and exit 1, which is why the host usually only shows you “failed to connect”.

3. A broken Kireo entry fails quietly, by design

Cursor “isolates server failures to prevent one server from affecting others” (cursor.com/docs/context/mcp, checked 2026-08-03). That is the right behaviour and it has a cost: when the kireo entry dies, your other MCP servers keep working and the failure reads as “the memory tools just aren't there”. A server you toggled off in settings — Cursor supports toggling servers on and off without removing them — produces the identical symptom.

Log files are rotated, so the obvious filename does not exist. Logs land in ~/.kireo/logs/ on macOS, Linux and Windows alike, but the files on disk are mcp-server.log.1, .log.2, .log.3 — there is no plain mcp-server.log, so the command everyone types first returns “no such file” (checked on this machine, 2026-08-03). Turning the level up with KIREO_LOG_LEVEL=debug is safe over stdio: logs go to those rotating files plus stderr and never to stdout, so they cannot corrupt the JSON-RPC stream.

FAQ

Should the Kireo entry go in ~/.cursor/mcp.json or the project’s .cursor/mcp.json?

Cursor documents both: ~/.cursor/mcp.json in your home directory for tools available everywhere, and .cursor/mcp.json inside a project for project-specific tools (cursor.com/docs/context/mcp, checked 2026-08-03). The Kireo memory MCP server keeps no per-project state — the namespace argument is what separates projects — so the global file is usually enough. Use the per-repo file when a client project needs its own API key.

Will Cursor and Claude Code really see the same memories?

Yes, when both client entries carry the same ki_sk_ key. Every request the server makes sends Authorization: Bearer <key>, and stored rows carry a user_id, so two entries holding one key are one account. Save from Cursor into namespace "acme-api" and memory_recall with that namespace from Claude Code returns it. memory_search with namespace omitted searches every namespace on the account.

Cursor shows no Kireo tools and no error. What do I check?

Cursor isolates server failures so that one server cannot affect the others (cursor.com/docs/context/mcp, checked 2026-08-03), which is exactly why a broken entry reads as silence rather than an error. Check the kireo entry under Settings → MCP and confirm it is not toggled off, then read ~/.kireo/logs/. The files are rotated — mcp-server.log.1, .log.2, .log.3 — there is no plain mcp-server.log. A missing or malformed key kills the process at startup with a fatal line on stderr naming KIREO_API_KEY.

Where does memory text go, and is it sent to a third-party AI provider?

Kireo’s privacy page states: "Your memory content and its embeddings stay on our own infrastructure (Hetzner compute); account metadata lives in Neon Postgres; encrypted off-site backups go to Cloudflare R2. Your memory text is never sent to a third-party AI or embedding provider." The server sends Authorization, Accept-Language, X-Client and X-Request-Id on every request, plus X-Device-Id only while telemetry is on — set KIREO_TELEMETRY=0 to drop it. Local log files redact authorization headers, API keys, tokens and passwords.

Is sharing memory across editors unique to the Kireo memory MCP server?

No, and it would be dishonest to claim it. It is a property of MCP itself, which the specification describes as an open standard inspired by the Language Server Protocol — implement a server once, connect any compliant host (modelcontextprotocol.io/specification/latest, checked 2026-08-03). Other memory servers do it too: mem0’s OpenMemory MCP is local-first and keeps everything on your own machine across Cursor, Claude Desktop, Windsurf and Cline (mem0.ai/blog/introducing-openmemory-mcp, checked 2026-08-03), and Graphiti, the Apache-2.0 temporal knowledge-graph engine behind Zep, ships an MCP server of its own (github.com/getzep/graphiti, checked 2026-08-03). Kireo’s trade is the opposite one: a hosted store you do not operate, with a web UI for reading and deleting what was written.

Facts on this page were checked on 2026-08-03 against @kireo/mcp-server 0.2.1 and the linked sources. Next: Quickstart