modelcontextprotocol / modelcontextprotocol/servers

memory: safer persistence defaults, atomic writes, quotas, redaction, and destructive-operation guardrails

Open
#4,117 20 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
90.5k
Forks
11.7k
Avg merge
2d 2h
Merged PRs (30d)
5

Description

Summary

While auditing and hardening local MCP server usage, I reviewed @modelcontextprotocol/server-memory and built a local hardened wrapper for our environment. I am opening this issue to share findings and possible upstream improvements.

This is not a report about a known data loss incident in the upstream package. It is a defense-in-depth report about persistence defaults and operational safety for a memory tool exposed to autonomous agents.

Package/runtime reviewed

  • Package: @modelcontextprotocol/server-memory@2026.1.26
  • License observed: MIT
  • Author observed: Anthropic, PBC
  • Upstream repo/issue tracker: modelcontextprotocol/servers
  • npm maintainers observed from registry during local review: jspahrsummers, pcarleton, thedsp, ashwin-ant, ochafik

Findings

  1. Default persistence path can land inside the package directory.
    Local source evidence showed a default path based on path.dirname(fileURLToPath(import.meta.url)), with memory.jsonl under the package dist directory when MEMORY_FILE_PATH is not configured. This creates operational fragility:

    • package reinstall/update can remove or overwrite memory state
    • global/package directories are not intuitive user data locations
    • backup/sync behavior is unclear
  2. Writes appear to be whole-file writes without explicit atomic replace and lock discipline.
    For agent memory, interrupted writes or concurrent host usage can corrupt or lose state. This is especially relevant when the same memory server is configured across multiple MCP hosts.

  3. No obvious mutation journal or backup trail.
    Debugging accidental writes or deletes is hard without append-only audit entries or backup snapshots.

  4. Destructive tools are available by default.
    delete_entities, delete_observations, and delete_relations are useful, but high-impact. In an agent context, accidental deletion should require explicit operator opt-in or confirmation mode.

  5. No obvious quotas/caps.
    Large observations or graphs can become a memory/latency issue. Whole-graph reads and writes are also sensitive to unbounded growth.

  6. No obvious secret redaction before persistence.
    Memory can become a persistent prompt-injection and secret-retention surface if fetched web content, logs, stack traces, or credentials are persisted without sanitization.

  7. No namespace isolation by default.
    A single global memory file shared across workspace/host contexts can mix unrelated operational memories unless the user manually configures paths.

Local hardening behavior that worked well

For our local wrapper, we preserved the upstream-compatible 9 tool names:

create_entities, create_relations, add_observations, delete_entities,
delete_observations, delete_relations, read_graph, search_nodes, open_nodes

We added:

  • explicit persistence outside node_modules, defaulting to a user data path
  • refusal to persist under node_modules
  • namespace support for workspace separation
  • cross-process lock with stale-lock cleanup
  • temp-write plus rename, with backup file
  • append-only mutation audit journal
  • quotas for entity/relation counts and observation sizes
  • secret redaction before writes
  • destructive tools disabled unless LCV_MCP_MEMORY_ALLOW_DESTRUCTIVE=1

Validation from local wrapper

Smoke output from the hardened local wrapper:

memory tools: add_observations,create_entities,create_relations,delete_entities,delete_observations,delete_relations,open_nodes,read_graph,search_nodes
memory read_graph entities=0 relations=0

A redaction/destructive-operation check also behaved as intended in local testing:

create {"entities":[{"name":"redaction-proof","entityType":"test","observations":["token [REDACTED]"]}]}
delete [{"type":"text","text":"delete_entities is disabled by default. Set LCV_MCP_MEMORY_ALLOW_DESTRUCTIVE=1 to enable destructive memory mutations."}]

Suggested upstream changes

  • Default persistence to an OS/user data directory instead of the installed package directory.
  • Refuse or strongly warn when MEMORY_FILE_PATH resolves inside node_modules or another package-managed path.
  • Use atomic write/replace and cross-process locking.
  • Add backup and append-only mutation audit journal options.
  • Add quotas for graph size, entity count, relation count, and observation length.
  • Redact common secret patterns before persistence.
  • Add namespace support or document recommended per-workspace file paths.
  • Gate destructive tools behind an explicit environment flag or confirmation mechanism.

Compatibility note

Most of these can be additive and opt-in, except the safer default persistence path. If changing the default is too disruptive, a migration warning plus documented MEMORY_FILE_PATH recommendation would still help users avoid package-dir persistence.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No source file or test is named. Begin by locating the @modelcontextprotocol/server-memory persistence implementation and the handlers for the nine listed tools, then review existing tests and smoke checks. The work is complete only when the selected safety changes have separately defined acceptance checks for persistence, mutation protection, quotas, redaction, and namespace behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
backend, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.