project-memory-mcp
# project-memory-mcp
Coding agents forget everything between sessions. You explain a decision on Monday, and on Wednesday the agent re-derives it, differently. This is a small MCP server that gives agents a place to write things down and find them again — per project, across sessions, across tools.
It does three things and nothing else:
- **`memory_record`** — save a note, decision, requirement, or learning.
- **`memory_search`** — full-text search over what was saved for a project.
- **`project_status`** — see whether a project has any memory yet, counts by kind, and the last few entries.
Everything lives in one SQLite file on your machine. No cloud, no accounts, no native dependencies — it uses the `node:sqlite` module that ships with Node, so `pnpm install` pulls in only the MCP SDK and zod.
## How it works
Each tool call takes an absolute `project_root`. That path is the project's identity: the first time a memory is recorded for a root, a project row is created; after that every search and status call is scoped to it. Two projects can contain the same words and never see each other's memories.
Memory is append-only. Recording the same kind, title, and body twice stores it once and tells you `created: false`. There is no update or delete — to change a decision, record a new one with `supersedes` pointing at the old id; the old memory keeps its history but drops out of search results. That keeps the history honest and the tool surface tiny.
Search is deliberately boring: every word in your query must appear in a hit (title, body, or tags), ranked by SQLite's FTS5 with titles weighted highest, and the last word is a prefix match so `sqlite` finds `sqlite3`. Hits come back with a short excerpt, not the full body — pass `include_body: true` when you need the whole text. No query syntax to learn, no way to break it with punctuation.
## Getting started
Requires Node 26 and pnpm.
```sh
pnpm install
pnpm test
pnpm build
```
Then point your agent harness at the built server. For Claude Code, Codex, or anything else that reads an MCP config:
```json
{
"mcpServers": {
"project-memory": {
"command": "node",
"args": ["/absolute/path/to/project-memory-mcp/dist/server.js"]
}
}
}
```
The database is created on first use at `~/.local/share/project-memory/store.sqlite` (or under `$XDG_DATA_HOME` if set). To put it somewhere else, set `PROJECT_MEMORY_DB=/path/to/file.sqlite` in the server's environment.
## Teaching the agent to use it
Exposing tools is not the same as an agent knowing *when* to use them. `skills/project-memory/SKILL.md` is a short, harness-agnostic skill that tells the agent to resolve the project root once, check `project_status` before starting, search before re-deriving old decisions, and record requirements and decisions as they happen. Copy that folder into your harness's skills directory (for example `~/.claude/skills/` or `~/.codex/skills/`) and adjust the server path in its setup section.
## Kinds of memory
| kind | use it for |
|---|---|
| `requirement` | a constraint the work must satisfy |
| `decision` | a choice that was made, and why |
| `learning` | a non-obvious fact about the code or environment |
| `note` | anything else worth keeping |
## Project layout
```
src/server.ts stdio entry point
src/mcp.ts the three tool definitions
src/store.ts record / search / status against SQLite
src/db.ts schema, pragmas, database location
src/project-root.ts validates and canonicalizes project_root
test/ vitest: store behavior and MCP round-trips
skills/project-memory/SKILL.md
```
## License
MIT
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: recording, searching, and summarizing project memory. There is no overlap or ambiguity between them.
Names follow a predictable resource-prefixed pattern: memory_record, memory_search, project_status. The pattern is readable and consistent enough, though project_status is more of a noun phrase than an action-oriented name.
Three tools is well-scoped for a focused project-memory server. Each tool earns its place and the surface is small but not underwhelming.
Core memory workflows are covered: recording, searching, and checking status. A minor gap is the lack of a get-by-id or full-text retrieval tool, since search only returns excerpts; deletion is handled indirectly via supersede.