Skip to main content
Glama
README.md
# memos-mcp-server

A small Python MCP server that bridges any MCP-compatible IDE (VS Code, Cursor, Claude Code) to a local [MemOS](https://github.com/MemTensor/MemOS) instance, so notes you take in your editor land in the same knowledge base your AI agents read from.

Designed for the Animus Systems / Paperclip stack, where MemOS is already running in Docker and serving as the shared knowledge layer for ~50 Paperclip agents. Until now, knowledge written in human IDE sessions and knowledge written by agents lived in different worlds. This server closes that loop with one config line.

## Why

Sequence of events from a real Paperclip session:

1. You tell Claude/Copilot in VS Code: *"the accounts rename routine uses spaces around all dashes and 3-letter currency codes"*
2. That fact is captured nowhere persistent — when the session ends, it's gone
3. Two days later your bookkeeping agent runs the routine, doesn't know the convention, gets it wrong, and you have to type the same explanation into a Paperclip issue description

With this MCP server, step 1 stores the fact into MemOS via `memos_remember`. The Paperclip agent-memory plugin's pre-run hook auto-injects the same MemOS scope into every agent run. The bookkeeping agent picks up the convention on its next heartbeat, no plugin changes required.

## Tools

| Tool | What it does |
|---|---|
| `memos_remember(content, category, project, tags)` | Store a memory. Auto-redacts credentials before sending. |
| `memos_search(query, top_k, only_human)` | Search MemOS, return ranked results with metadata. |
| `memos_recent(hours, source)` | Recent memories (default last 24 h), optional source filter. |

A startup health check pings MemOS once and logs the result; tool errors are returned cleanly when MemOS is unreachable rather than crashing the server.

## How it integrates with Paperclip

The default config writes to MemOS scope `user_id = kb-{companyId}` — the **same scope** the Paperclip agent-memory plugin uses for its KB entries. This is the scope the OpenRouter adapter's pre-run hook queries when it builds the *"## RELEVANT CONTEXT FROM PREVIOUS RUNS"* block injected into every agent run.

So a memory you write from VS Code is, with zero plugin changes, automatically available to every Paperclip agent's next run. Bidirectional human ↔ agent memory.

If you don't want this — e.g. you want personal notes that Paperclip agents can't see — change `MEMOS_USER_ID` in the env block to something like `seth-personal`.

## Install (macOS)

```bash
git clone https://github.com/mchosc/memos-mcp-server.git ~/Documents/GitHub/animusystems/memos-mcp-server
cd ~/Documents/GitHub/animusystems/memos-mcp-server
bash install.sh
```

Then open `~/Library/Application Support/Code/User/mcp.json` and add the entry from `vscode-mcp.snippet.json` under the `servers` object. Reload VS Code (`Cmd+Shift+P → "Developer: Reload Window"`).

The server will auto-start the next time you open the Chat panel and use any MCP tool. Verify it's connected by asking: *"What MCP tools do you have?"*

## Configuration

All config is read from environment variables, which you set in the VS Code mcp.json `env` block:

| Env var | Default | Purpose |
|---|---|---|
| `MEMOS_URL` | `http://localhost:8000` | MemOS HTTP base URL |
| `MEMOS_CUBE_ID` | Animus Group UUID | Paperclip companyId — used as MemOS cube |
| `MEMOS_USER_ID` | `kb-${MEMOS_CUBE_ID}` | MemOS user_id scope (default: shared with agent KB) |
| `MEMOS_AUTHOR` | `human` | Author tag stamped on every entry |
| `MEMOS_ORIGIN` | `vscode` | Origin tag (e.g. `vscode`, `cursor`, `claude-code`) |
| `MEMOS_TIMEOUT_SEC` | `15` | HTTP request timeout |

## A note on MemOS consolidation

MemOS stores raw entries via `/product/add` but its internal pipeline runs an LLM (Mistral Small 3.2 in the Animus deployment) to consolidate raw entries into "evolving knowledge objects" — paraphrased, deduplicated versions of related memories. Searches return **both** the raw entries and the consolidated ones, and the consolidated ones often outrank the raw because they're cleaner.

Practical implication: the inline `[source: human]` / `[author: seth]` / `[category: note]` tags this MCP server adds to your content **may not survive consolidation**. The semantic content is preserved (your decisions, conventions, and notes still appear in search results), but the structured metadata block can be paraphrased away.

When that happens, search results display `(consolidated)` instead of the raw tag values. The `only_human=True` filter in `memos_search` only works for entries that still carry the raw tags — useful when you've just stored something, less useful weeks later when consolidation has run.

If you want guaranteed verbatim recall of personal notes, set `MEMOS_USER_ID` to a separate scope (e.g. `seth-personal-raw`) and skip the shared KB scope. That trade-off costs you the bidirectional human↔agent visibility.

## Sanitizer

`memos_remember` runs the content through a regex sanitizer (`sanitizer.py`) before storing. Patterns currently covered:

- Credit card numbers (Visa / MC / Amex / Discover)
- IBAN
- US SSN
- PEM private keys
- AWS access keys / secret keys
- Generic API keys (`sk-`, `sk-or-v1-`, `sk-ant-`, GitHub PATs `ghp_*`/`gho_*`, GitLab `glpat-`, Slack `xox[bps]-`)
- Bearer tokens
- Connection strings with embedded creds (postgres / mysql / mongodb / redis / amqp / smtp)
- JWT tokens
- Password / token assignments (`password=...`, `api_key: ...`, etc.)

These are ported from [`paperclip-plugin-agent-memory/src/worker/sanitizer.ts`](https://github.com/mchosc/paperclip-plugin-agent-memory/blob/master/src/worker/sanitizer.ts). If new patterns get added there, port them here too — the README documents what's covered.

When something is redacted, the tool's response includes a note like *"sanitized: 1x api_key"* so you know it happened.

## Usage examples

From any MCP client connected to this server, just ask:

> *"Remember that we set autoDecompose to false on the Animus Group task-triage plugin to stop routine fires from being decomposed into stuck-blocked subtasks."*

The model calls `memos_remember(content="...", category="decision", project="paperclip", tags=["task-triage", "routines"])`. Done.

A week later from a fresh session:

> *"Why did we disable autoDecompose on task-triage?"*

The model calls `memos_search(query="autoDecompose task-triage")` and gets the original decision back, verbatim, with the date and reason.

## Troubleshooting

**`MemOS unreachable at http://localhost:8000`**
Docker stack isn't running. `cd ~/Documents/paperclip-data && ./restart.sh` or `docker compose up -d memos`.

**Tools don't appear in VS Code chat**
1. Check the mcp.json was saved with valid JSON (`jq < ~/Library/Application\ Support/Code/User/mcp.json`)
2. Reload VS Code (`Cmd+Shift+P → "Developer: Reload Window"`)
3. Open the Chat panel → MCP servers panel; you should see `memos` listed
4. If it shows as failed, run the server manually to see the error: `/Users/seth/Documents/GitHub/animusystems/memos-mcp-server/.venv/bin/python3 /Users/seth/Documents/GitHub/animusystems/memos-mcp-server/server.py` (it will block on stdin — that's fine, you just want to see startup logs on stderr)

**Memories aren't showing up in agent runs**
The shared `kb-{companyId}` scope is only auto-injected by the Paperclip agent-memory plugin's pre-run hook. Check:
1. The plugin is loaded: `docker logs paperclip-data-server-1 2>&1 | grep agent-memory`
2. Your memory has the right `cube_id` (matches the agent's companyId)
3. The relevance ranking — MemOS is semantic, so unrelated queries won't surface your note. Try a `memos_search` with a similar query first to confirm it's findable.

**I want personal notes that agents can't see**
Change `MEMOS_USER_ID` in your mcp.json env block from `kb-...` to something like `seth-personal`. The server will use that scope instead, and agent runs (which still query `kb-...`) won't see those entries.

## License

MIT

TDQS

A4.3/5.0

Scored across 3 tools

Disambiguation5/5

Each tool serves a clear, distinct purpose: storing memories, retrieving recent ones, and searching by query. No overlap exists between the three operations.

Naming Consistency5/5

All tools follow a consistent 'memos_<verb>' pattern (remember, recent, search), making the naming predictable and easy to understand.

Tool Count4/5

With 3 tools, the count is slightly on the low side but appropriate for a focused memory server. It covers the core operations without unnecessary bloat.

Completeness3/5

The tool set lacks update and delete operations, which are notable gaps for a complete memory management system. However, the retrieval and creation tools are well-implemented.

Maintenance

ActivityInactive
ResponsivenessNo issues