Skip to main content
Glama
README.md
# Memory-MCP

**Shared, live team memory for Claude — a remote MCP server on Cloudflare Workers + D1.**

Everyone's Claude Code writes what it learns; everyone reads it. One live source, global at the edge. When one teammate figures something out, the whole team's Claude knows it.

---

## Why

A distributed team using Claude Code (or any MCP client) keeps re-learning the same things. Each person's assistant has its own local memory — decisions, gotchas, conventions — and none of it is shared. Memory-MCP is a tiny, self-hostable server that gives the whole team **one shared memory** their AI assistants can read and write through the [Model Context Protocol](https://modelcontextprotocol.io).

- **Index-first / lazy-body** — a session starts with lightweight titles only; full bodies are fetched on demand. Token-efficient.
- **Verified authorship** — the author of every note comes from the token, not the client. It can't be forged.
- **Accent/case-insensitive search** — full-text search folds diacritics and case (built with Turkish in mind, works for any Latin script).
- **History + soft-delete** — every change is archived; deletes are reversible.
- **Secret guard** — key/token/password-shaped content is rejected, so secrets never land in shared memory.

## Architecture

```
Each teammate's Claude Code ──(.mcp.json, personal Bearer token)──▶ Worker /mcp   ──▶ D1 (memories + FTS5 + history)
SessionStart hook (optional) ─(curl)──────────────────────────────▶ Worker /index ──▶ budgeted title list
```

- **Worker** — a single Cloudflare Worker. `/mcp` speaks MCP (streamable HTTP, via a Durable Object); `/index` is a plain REST endpoint for a lightweight title list.
- **D1** — SQLite at the edge. One `memories` table + an FTS5 search index + a `memory_history` audit table.

## Setup

Prerequisites: a [Cloudflare account](https://dash.cloudflare.com/sign-up), Node.js 18+, and [Wrangler](https://developers.cloudflare.com/workers/wrangler/) (`npx wrangler login`).

```bash
# 1. Install
git clone https://github.com/CedraInteractive/Memory-MCP.git
cd Memory-MCP
npm install

# 2. Create the D1 database, then paste the printed database_id into wrangler.jsonc
npx wrangler d1 create memory-mcp

# 3. Apply the schema (remote)
npm run db:init

# 4. Set the team token(s) — see "Identity" below
npx wrangler secret put AUTH_TOKENS       # {"tok_alice_...":"alice","tok_bob_...":"bob"}

# 5. Deploy
npm run deploy
```

Wrangler prints your worker URL, e.g. `https://memory-mcp.<your-subdomain>.workers.dev`.

### Identity

Give each teammate their own token. `AUTH_TOKENS` is a JSON map of token → author:

```json
{ "tok_alice_a1b2c3...": "alice", "tok_bob_d4e5f6...": "bob" }
```

Because the author is resolved server-side from the token, notes are attributed reliably and you can revoke one person by removing their entry and redeploying. (A single shared `AUTH_TOKEN` is also supported — author becomes `shared`.)

Generate a token however you like, e.g.:

```bash
node -e "console.log('tok_alice_'+require('crypto').randomBytes(16).toString('hex'))"
```

## Connect Claude Code

Copy `.mcp.example.json` to your project's `.mcp.json` (or your global config), fill in your subdomain, and set the `MEMORY_MCP_TOKEN` environment variable to your personal token:

```json
{
  "mcpServers": {
    "memory": {
      "type": "http",
      "url": "https://memory-mcp.<your-subdomain>.workers.dev/mcp",
      "headers": { "Authorization": "Bearer ${MEMORY_MCP_TOKEN}" }
    }
  }
}
```

Restart Claude Code — the `memory_*` tools are available. Just talk to it: *"search the team memory for the deploy steps"*, *"save this to team memory: …"*.

### Optional: auto-load on session start

To surface memory titles at the start of every session, add a SessionStart hook that curls the index:

```bash
curl -s -H "Authorization: Bearer $MEMORY_MCP_TOKEN" \
  https://memory-mcp.<your-subdomain>.workers.dev/index
```

This returns a lightweight, character-budgeted title list (no bodies) — cheap on tokens.

## MCP tools

| Tool | What it does |
|------|--------------|
| `memory_search(query, limit?)` | Full-text search (accent/case-insensitive); lightweight rows |
| `memory_get(name)` | Full body of one note (lazy) |
| `memory_upsert(name, description, body, type?, status?, project?)` | Write/update; `author` is automatic; secrets rejected; prior version archived |
| `memory_delete(name)` | Soft-delete (reversible; archived to history) |
| `memory_restore(name)` | Restore a soft-deleted note |
| `memory_history(name, limit?)` | Version history — who changed what, when |
| `memory_recent(since?, limit?)` | What changed mid-session |
| `GET /index` | REST title list (for the SessionStart hook) |

**Fields.** `status`: `preferred` (confirmed) · `tentative` (needs review) · `contested` (conflicting). `type`: `feedback` · `reference` · `project` · `shared`.

## Development

```bash
npm test          # pure-logic tests (fold, secret guard, index budget) — Node's built-in runner
npm run typecheck # tsc --noEmit
npm run dev       # wrangler dev (local)
```

The pure logic (`src/lib.ts`) is worker-independent and unit-tested; the worker/MCP wiring lives in `src/index.ts`.

## Security notes

- All requests require a Bearer token. For a stricter setup (e.g. a team on a private network), put the worker behind [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/policies/access/) so there is no public endpoint.
- The secret guard is defense-in-depth, not a vault — never rely on it to scrub real secrets. Keep credentials out of memory entirely.
- Deletes are soft (recoverable) and every change is auditable via `memory_history`.

## License

MIT — see [LICENSE](./LICENSE).