A Model Context Protocol (MCP) server that gives AI assistants (Claude Desktop, Claude Code, Cursor, Cline, OpenCode, Zed) a persistent memory for your codebase. As you work, the AI can save architectural decisions, conventions, gotchas, and notes — and later recall them with semantic search when working on related tasks.
Think of it as a "second brain" for each project, shared between you and the AI.
Every codebase accumulates implicit knowledge: "we don't use ORMs because of the 2022 incident", "auth tokens must be HMAC-signed", "the payment retry has a subtle off-by-one in the 30-day window", "we settled on Fastify over Express because…".
This context lives in commit messages, Slack threads, your head — and vanishes the moment a new AI session starts. Claude Desktop, Cursor, and others see a fresh conversation every time.
This MCP server fixes that:
- You say, in chat: "Save this: we always validate webhook signatures with
timingSafeEqualbecause of an incident in March. Never use===." - AI calls
remember()— the memory is embedded and stored locally with categoryconvention, tags[security, webhooks] - Three weeks later, you ask: "Add a Stripe webhook handler"
- AI calls
recall("webhook signature handling")— your old note surfaces, AI writes correct code on the first try
- MCP-native — works with any MCP-compatible client (Claude Desktop, Claude Code, Cursor, Cline, OpenCode, Zed)
- Stdio transport — zero networking, local-only, no setup beyond installing
- Per-project namespacing — each project gets its own memory store automatically (detected from git root or
PROJECT_ROOTenv) - Semantic search — memories embedded with OpenAI
text-embedding-3-small(1536-dim) and recalled by cosine similarity - Categorisation —
decision/convention/gotcha/note/todo/bug-fix - Tagging + file linking — memories can reference specific files and lines
- Local SQLite — single-file database at
~/.codebase-memory/memories.db - Resources for browsing — AI clients can read
memory://current/decisionsetc. as live context - Guided prompts — built-in MCP prompts like
/remember-decisionwalk the AI through proper ADR-style entries - CLI inspector —
npm run inspectto browse, search, and export memories
- TypeScript on Node.js 20+
- @modelcontextprotocol/sdk v1+ — MCP protocol
- better-sqlite3 — local persistence
- openai SDK — embeddings (
text-embedding-3-smallby default; swappable) - Zod — schema validation for tool arguments
- Pino — structured logging to stderr (stdout is reserved for MCP protocol)
AI Client (Claude / Cursor / Cline)
│
│ MCP protocol (JSON-RPC over stdio)
▼
This MCP Server
│
├──▶ Tools (remember, recall, list_memories, get, update, forget, stats)
├──▶ Resources (memory://current/recent, /decisions, /conventions, /gotchas)
└──▶ Prompts (/remember-decision, /remember-convention, /recall-context)
│
▼
Memory Engine
│
├──▶ OpenAI Embedding API (only on write + on recall query)
│
└──▶ SQLite (~/.codebase-memory/memories.db)
│
├──▶ memories table (id, project, category, content, tags, files, timestamps)
└──▶ embeddings (id, vector_json) — loaded into RAM at startup
Cosine similarity is computed in JavaScript over the in-memory vector cache. This scales comfortably to ~50k memories per machine; beyond that, the roadmap upgrades to sqlite-vec.
All tools accept an optional project argument. If omitted, the server uses (in order): PROJECT_ROOT env var → git root of cwd → "default".
Save a new memory.
{
"content": "We never use === on tokens. Use crypto.timingSafeEqual with equal-length buffers. Reason: timing attack incident in March 2025.",
"category": "convention",
"tags": ["security", "auth"],
"files": ["src/auth/verify.ts"]
}Returns: { id: 42, ... }
Semantic search across all memories in the current project.
{
"query": "how should I handle webhook signatures",
"limit": 5,
"category": "convention"
}Returns: array of { id, content, similarity, category, tags, files, created_at }.
Paginated listing with filters.
{
"category": "decision",
"tags": ["database"],
"since": "2026-01-01",
"limit": 20
}Fetch a single memory by id.
Modify content, tags, category, or files of an existing memory. Re-embeds if content changes.
Delete a memory. Requires confirm: true to prevent accidents.
{ "project": "my-app" }Returns counts: total, by category, recent activity (last 7 / 30 days), total tokens stored.
AI clients can read these as live context without invoking a tool:
| URI | Returns |
|---|---|
memory://current/recent |
Last 20 memories in the current project (JSON) |
memory://current/decisions |
All architectural decisions |
memory://current/conventions |
All coding / process conventions |
memory://current/gotchas |
All pitfalls / "be careful here" notes |
These appear as slash commands inside MCP-aware clients and walk the AI through a structured workflow.
| Prompt | Purpose |
|---|---|
/remember-decision |
Guides through an ADR-style architectural decision (context, decision, consequences) |
/remember-convention |
Captures a coding/process convention with rationale |
/recall-context |
Pulls relevant memories for a task description before writing code |
cd "Codebase Memory MCP Server"
npm install
npm run buildCreate a .env file (or set as system env):
OPENAI_API_KEY=sk-...
The OpenAI key is only used for embeddings. Estimated cost: ~$0.02 per 1M tokens — typical use is under $0.10/month per developer.
Edit claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"codebase-memory": {
"command": "node",
"args": ["C:\\path\\to\\Codebase Memory MCP Server\\dist\\index.js"],
"env": {
"OPENAI_API_KEY": "sk-...",
"PROJECT_ROOT": "C:\\path\\to\\my-project"
}
}
}
}Restart Claude Desktop.
Edit ~/.cursor/mcp.json (or use the Settings → MCP UI):
{
"mcpServers": {
"codebase-memory": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": {
"OPENAI_API_KEY": "sk-...",
"PROJECT_ROOT": "${workspaceFolder}"
}
}
}
}Add to .claude/mcp.json in your repo (so each project gets its own scoped memory):
{
"mcpServers": {
"codebase-memory": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": {
"OPENAI_API_KEY": "sk-..."
}
}
}
}PROJECT_ROOT defaults to the git root of the workspace.
Inside your AI client, ask: "What tools do you have from the codebase-memory MCP server?"
The AI should list remember, recall, list_memories, etc.
# Show all memories
npm run inspect -- list
# Show memories for a specific project
npm run inspect -- list --project my-app
# Search by query (uses semantic search)
npm run inspect -- search "webhook validation"
# Show one memory in detail
npm run inspect -- get 42
# Export project memories to markdown
npm run inspect -- export --project my-app --out memories.md
# Database stats
npm run inspect -- statsYou: "Let's go with Fastify for the new service. Express has lifecycle bugs with our streaming SSE responses."
AI: "Got it. I'll also save that decision so future conversations remember it." [calls
remember]Memory stored:
{ "category": "decision", "content": "Use Fastify, not Express, for HTTP services. Reason: Express has lifecycle bugs with streaming SSE responses observed in [date].", "tags": ["http", "framework"] }
You (3 weeks later): "Add a new SSE endpoint for the dashboard."
AI: [silently calls
recall("SSE endpoint server framework")] — finds the Fastify decision.AI: "I'll add it to the existing Fastify app. Last month we decided against Express for SSE — I'll keep us consistent with that."
You: "Remember that the Stripe webhook can fire twice for
payment_intent.succeededdue to their retry logic. Always checkprocessed_eventstable first."AI: [calls
rememberwith categorygotcha, tags[stripe, webhooks, idempotency]]
By default: ~/.codebase-memory/memories.db
Override with MEMORY_DB_PATH=/path/to/db.sqlite env var.
The directory and file are created automatically on first run.
- MCP server with stdio transport
- 7 tools, 4 resources, 3 prompts
- OpenAI embeddings with cosine similarity
- Per-project namespacing (auto-detected from git)
- CLI inspector (list, search, get, export, stats)
-
sqlite-vecintegration for 100k+ memory scale - Swappable embedding providers (Voyage AI, Cohere, local transformers.js)
- Auto-promotion: AI suggests "save this?" when it detects a noteworthy decision
- HTTP/SSE transport for shared team memory
- Markdown sync (
memories/*.mdin the repo, two-way sync) - Memory expiry and decay scoring (oldest memories get pruned)
- Memory linking (one memory references another by id)
- Cross-project search ("show me all auth conventions across all projects")
codebase-memory-mcp-server/
├── README.md
├── package.json
├── tsconfig.json
├── .env.example
├── .gitignore
├── src/
│ ├── index.ts # MCP server entry, stdio transport
│ ├── config.ts # Env loading + Zod validation
│ ├── logger.ts # Pino → stderr (stdout is MCP protocol)
│ ├── util/
│ │ ├── project.ts # Project root detection (git → cwd → default)
│ │ └── similarity.ts # Cosine similarity in JS
│ ├── storage/
│ │ ├── db.ts # SQLite init
│ │ └── memories.ts # Memory CRUD + vector cache
│ ├── ai/
│ │ └── embed.ts # OpenAI embedding client (swappable)
│ ├── tools/
│ │ └── index.ts # All 7 MCP tools
│ ├── resources.ts # 4 MCP resources
│ └── prompts.ts # 3 MCP prompts
├── scripts/
│ ├── setup-db.ts # Initialize DB schema
│ └── inspect.ts # CLI: list/search/get/export/stats
├── examples/
│ ├── claude-desktop-config.json
│ ├── cursor-config.json
│ └── example-memories.json
└── data/ # SQLite DB lives here by default
MIT.