Cursor's MCP integration lives inside Agent mode, and the friction points here are different from the terminal-first tools: Cursor's UI makes it easy to forget memory MCP is even connected, because tool calls happen inline in a chat panel next to your editor rather than in a visible terminal log. This topic covers the Cursor-specific config, the "teach it once" pattern that fits an IDE-centric workflow well, and the pruning discipline Cursor in particular needs.
Connecting Memory MCP to Cursor Agent Mode
Cursor reads MCP config from .cursor/mcp.json at the project root, or ~/.cursor/mcp.json for a global config available across all projects. The shape matches Claude Code and Gemini CLI's mcpServers format:
{
"mcpServers": {
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"],
"env": {
"MEMORY_FILE_PATH": "/Users/dat/agent-memory/english-grammar-platform.json"
}
}
}
}
After saving .cursor/mcp.json, open Cursor Settings → MCP and confirm the memory entry shows a green status with a tool count. Cursor doesn't auto-reload MCP config changes in every version — if the entry shows red or is missing after editing the file, use the toggle in that settings panel to disable and re-enable the server rather than assuming a restart of Cursor itself is required (though a full restart also works and is sometimes faster than hunting for the toggle).
Cursor's Agent mode needs the memory tools enabled in its tool-use permissions the same way any MCP tool needs enabling — check under Settings → Agent that memory isn't sitting in a disabled state, which is a common reason a freshly-connected server appears available but the agent never actually calls it.
Quick verification prompt inside Cursor Agent chat:
List the memory tools you have access to right now.
Expected: create_entities, create_relations, add_observations,
delete_entities, delete_observations, delete_relations, read_graph,
search_nodes, open_nodes
If that list comes back empty or the agent claims no memory tools exist, the config connected at the transport level but tool permissions are the actual blocker — go back to Settings → Agent before troubleshooting the .cursor/mcp.json file further.
Tips
-.cursor/mcp.jsonuses the samemcpServersshape as Claude Code and Gemini CLI — reuse those config blocks directly.
- A green status in Settings → MCP doesn't guarantee the agent can call the tools — check Settings → Agent for tool-use permissions separately.
- Ask the agent to list its available memory tools as a fast sanity check before troubleshooting the config file.
Teaching Cursor Your Architecture Decisions Once and Reusing Them
Cursor's workflow is IDE-native — you're usually looking at a specific file when you invoke Agent mode, which makes "teach it once, in context, right where the decision is visible" a natural pattern that terminal-first tools don't get for free in the same way.
With src/services/rate_limiter.py open in the editor:
Prompt: Store this file's design as a memory entity. entityType
"component", name "rate-limiter". Cover the algorithm choice and
why, referencing the file path so future sessions can find the
source without re-reading this whole file.
{
"type": "entity",
"name": "rate-limiter",
"entityType": "component",
"observations": [
"Implemented in src/services/rate_limiter.py",
"Uses token bucket algorithm, not sliding window",
"Sliding window was reverted (see commit a3f21c9) due to burst rejections under mobile app load-test traffic",
"Public entry point: RateLimiter.check(key: str) -> bool"
]
}
The "referencing the file path" instruction matters specifically in Cursor's context — the IDE already gives the agent cheap access to re-read the actual file, so the memory entity doesn't need to duplicate implementation detail. Its job is to hold the decision context the file itself can't express: why token bucket won over sliding window. That's a smaller, more durable entity than one trying to summarize the whole file, and it stays accurate even as the implementation is refactored, so long as the algorithm choice itself doesn't change.
Extend this into relations once you have a few components mapped:
Prompt: Add a relation — rate-limiter is used_by api-gateway.
{
"type": "relation",
"from": "api-gateway",
"to": "rate-limiter",
"relationType": "uses"
}
Now, weeks later, with src/gateway/router.py open instead:
Prompt: This file calls into the rate limiter. Any known gotchas
I should know about before modifying the call site?
→ search_nodes("rate limiter")
→ finds "rate-limiter" entity and, via the "uses" relation, confirms
api-gateway is a known caller
Agent: The rate limiter uses a token bucket algorithm — a prior
sliding-window implementation was reverted due to burst rejections.
If you're changing how api-gateway calls check(), keep the token
bucket semantics in mind rather than reintroducing windowed logic.
That's the compounding value of teaching decisions "once, in context" — a different file, a different session, a different week, and the relevant history surfaces without anyone having re-explained it.
Tips
- Store the decision and its reasoning, not a restatement of the code — Cursor can always re-read the actual file cheaply, so don't duplicate it in memory.
- Build relations between components as you touch them, not in one big upfront modeling session — it stays proportional to what you've actually worked on.
- When opening a file that calls into a component you've documented, search memory before modifying the call site, not just when working on the component directly.
Keeping Memory Fresh: Update, Prune, and Invalidate Stale Entries
Cursor sessions tend to be shorter and more frequent than a single long Claude Code terminal session — quick edits, quick agent invocations, many times a day. That cadence means stale memory accumulates faster here relatively speaking, because there are more opportunities across a week to add an observation and fewer natural "end of session, let's clean up" checkpoints than a single long session gives you.
Build pruning into the same prompts that make changes, rather than treating it as separate maintenance:
Prompt (after actually replacing the token bucket with something new):
We just replaced the rate limiter's token bucket with a
sliding-window-log approach, fixing the old burst-rejection issue
via a grace-window parameter. Update the "rate-limiter" memory
entity: remove the observation about using token bucket, remove
the note about the sliding-window revert (it's no longer relevant —
we fixed the original problem), and add the new algorithm and
grace-window detail.
Agent's tool calls:
delete_observations("rate-limiter", [
"Uses token bucket algorithm, not sliding window",
"Sliding window was reverted (see commit a3f21c9) due to burst
rejections under mobile app load-test traffic"
])
add_observations("rate-limiter", [
"Now uses sliding-window-log algorithm with a grace-window
parameter to prevent the previously-seen burst rejections",
"Replaced token bucket implementation on 2026-08-21"
])
This is the difference between memory that stays trustworthy and memory that quietly becomes wrong. Leaving the old "uses token bucket" observation in place after the algorithm changed doesn't just add noise — it actively misleads the next session into describing outdated behavior as current fact, with no signal that it's stale.
For entities that become fully obsolete (a deprecated service, a removed feature flag), delete rather than leave a "DEPRECATED" note buried in observations — a dangling stale entity that still surfaces in search_nodes results is worse than no entity at all, because it costs a moment of the agent's (and your) confidence in every result it appears in.
Periodic prune prompt, run every few weeks:
Read the full memory graph. Flag any entity whose observations
reference a file path, algorithm, or component name that no longer
matches the current codebase. List them for me to confirm before
deleting anything.
Note the "list them for me to confirm" instruction — don't let the agent auto-delete based on its own judgment of staleness without a human check. An agent's confidence about what's outdated is itself unverified inference, the same category of risk covered as context poisoning in this module's opening topic.
Tips
- Update memory in the same prompt/commit that makes the underlying change — don't defer it to a separate cleanup pass that may never happen.
- Delete fully obsolete entities outright rather than leaving a stale note in place — a dangling wrong entity actively misleads future searches.
- Run a periodic (every few weeks, not daily) audit prompt that flags candidates for deletion, but keep a human confirmation step before anything is actually removed.
Known Limitations and Workarounds for Memory MCP in Cursor
- No visible tool-call log by default in the compact chat view. Cursor can call
create_entitiesoradd_observationswithout it being obvious at a glance that a memory write happened, unlike a terminal session where every tool call scrolls past. Expand the tool-call details in the chat panel (usually a small collapsed row under the agent's response) to confirm what was actually written, especially the first several times you use a new prompt pattern. - Config reload isn't always automatic. As noted above, editing
.cursor/mcp.jsondoesn't guarantee the running agent session picks up the change without a manual toggle or restart — don't assume a config fix took effect just because you saved the file. - No per-project memory isolation enforced by Cursor itself. If your global
~/.cursor/mcp.jsonand a project's.cursor/mcp.jsonboth define amemoryserver, which one wins depends on Cursor's config precedence rules for that version — verify with the tool-listing prompt from the first section rather than assuming project-level always overrides global. - Same server-level limitations as everywhere else — no semantic search, no encryption,
read_graphreturns everything at once with no pagination. Cursor doesn't add or remove any of this; it's inherent to@modelcontextprotocol/server-memoryregardless of client.
Workaround for the invisibility problem specifically: adopt a habit of ending memory-writing prompts with "confirm what you stored" so the agent echoes the entity/observation back into the visible chat text, not just into a collapsed tool-call row.
Prompt: Store this decision in memory, then tell me exactly what
entity and observations you created so I can verify it's right.
Tips
- Expand collapsed tool-call rows in Cursor's chat panel, or ask the agent to echo back what it stored, until you trust it's writing what you expect.
- Don't assume a.cursor/mcp.jsonedit took effect without checking Settings → MCP or restarting — silent non-reload is a real failure mode here.
- Watch for global-vs-project config precedence ambiguity if you maintain both~/.cursor/mcp.jsonand a project-level file with the same server name.
Tips
Tips
- Confirm both connection (Settings → MCP) and tool-use permission (Settings → Agent) separately — a green connection status doesn't guarantee the agent can actually call memory tools.
- Store decisions and reasoning tied to the file you're looking at, not restatements of the code itself — Cursor can always re-read the file cheaply.
- Update or delete stale observations in the same prompt that makes the underlying change, rather than deferring cleanup indefinitely.
- Ask the agent to echo back exactly what it stored — Cursor's compact chat view makes memory writes easy to miss otherwise.