Project Memory MCP
by twenj
README.md
# Project Memory MCP
Project Memory MCP 是一个与模型无关的 MCP Server,用来实现 `Project Memory Protocol (PMP)` 的第一版能力。
这个项目的核心思路不是让每个 AI 工具各自维护一套 Memory,而是把项目共享记忆统一存放在项目目录下的 `.ai/` 中,保证它可读、可追踪、可复用。
## 项目定位
- `PMP` 是协议,也是目录约定。
- `Project Memory MCP` 是 `PMP` 的一种实现。
- 任何支持 MCP 的客户端,都可以读取和更新同一份项目记忆。
## MVP 能力
当前 MVP 提供 13 个核心工具:
- `run_project_open_workflow`
- `run_conversation_end_workflow`
- `suggest_memory_optimization`
- `apply_memory_optimization`
- `bootstrap_project_context`
- `get_project_context`
- `get_current_task`
- `update_current_task`
- `add_decision`
- `record_conversation_summary`
- `suggest_context_updates`
- `summarize_git_diff`
- `optimize_ai_memory`
## 目录结构
```text
.ai/
memory.yaml
.memory.lock
project.md
architecture.md
current-task.md
todo.md
decisions.md
coding-style.md
recent-changes.md
recent-changes.archive.md
conversation-summary.md
archive/
recent-2026-07.md
summary-2026-07.md
```
## 本地开发
```bash
pnpm install
pnpm build
pnpm dev
```
`pnpm dev` 会直接通过 `tsx` 启动 `src/index.ts`,适合本地联调和观察启动日志。
## 终端命令 与 MCP Tools 的区别
这个项目里有两类“能力入口”,使用方式不同:
### 1. 终端命令
这些命令在 shell / Terminal 中执行:
```bash
pnpm install
pnpm build
pnpm dev
node dist/index.js
```
它们的作用主要是:
- 安装依赖
- 编译项目
- 本地调试 MCP Server
- 手动观察启动日志和报错
### 2. MCP Tools
这些不是终端命令,而是 MCP 客户端连接到 `project-memory` 之后,由 AI 或客户端发起的 tool call。
例如:
- `bootstrap_project_context`
- `get_project_context`
- `record_conversation_summary`
- `summarize_git_diff`
- `optimize_ai_memory`
所以像 `optimize_ai_memory` 这样的能力:
- 不是在 Terminal 里直接输入
- 而是在 Trae、Cursor、Codex、Claude Code 等支持 MCP 的客户端里触发
## 运行状态与报错机制
当前开发态已经包含基础的运行状态输出和报错机制:
- 启动成功时会输出服务已监听、Memory 根目录和当前运行模式
- 遇到 `uncaughtException` 时会打印异常并以非零状态退出
- 遇到 `unhandledRejection` 时会打印异常并以非零状态退出
- 收到 `SIGINT` 或 `SIGTERM` 时会输出关闭日志
- 进程退出时会输出退出码
这意味着在 `pnpm dev` 运行过程中,如果启动失败、运行时抛错或进程被中断,终端里都会有明确反馈。
## MCP 配置示例
推荐把配置放在**每个业务项目**的 `.cursor/mcp.json`,用 `${workspaceFolder}` 绑定当前工作区。打开哪个仓库,Memory 就写到哪个仓库的 `.ai/`:
```json
{
"mcpServers": {
"project-memory": {
"command": "node",
"args": [
"/absolute/path/to/project_memory/dist/index.js"
],
"env": {
"PROJECT_MEMORY_ROOT": "${workspaceFolder}"
}
}
}
}
```
多项目时以项目级配置为准。全局 `~/.cursor/mcp.json` 里的 `${workspaceFolder}` 不如项目级可靠,也不要在全局配置里写死某个业务项目的绝对路径。
## 使用说明
- 默认情况下,MCP Server 会读取 `PROJECT_MEMORY_ROOT/.ai/`。
- 如果没有设置 `PROJECT_MEMORY_ROOT`(或值里仍含未展开的 `${...}`),则会先从当前工作目录开始自动向上查找项目根目录。
- 写入策略以追加或定向更新为主,便于审计和 Git 跟踪。
## 自动 Memory 整理
项目现在包含第一版自动 Memory 整理机制,目标是:
- 永远不要丢失用户记忆
- 安全性优先于压缩效率
- 优先归档,不直接删除历史
当前实现包含:
- 写入前文件大小检查
- `.ai/.memory.lock` 全局锁
- `suggest_memory_optimization` 的 dry run 方案
- `apply_memory_optimization` 的确认后执行
- `.ai/archive/` 月度归档目录
默认阈值配置写在:
```text
.ai/memory.yaml
```
默认内容:
```yaml
memory:
maxFileSizeKB: 256
```
当某次写入会让目标 Memory 文件超过阈值时,系统会:
1. 暂停这次写入
2. 返回优化建议
3. 等待用户或客户端调用 `apply_memory_optimization`
4. 优化完成后再重试原始写入
这意味着普通写入不会在超限时悄悄覆盖上下文,而是先走一次安全整理流程。
## 如何确认 `.ai/` 实际写到哪里
如果你发现客户端里没有看到 `.ai/`,最常见的原因不是工具没工作,而是 `project root` 和你以为的目录不一致。
当前项目根目录的判定逻辑是:
1. 优先使用已展开的 `PROJECT_MEMORY_ROOT`(推荐在项目 `.cursor/mcp.json` 里设为 `${workspaceFolder}`)
2. 如果没有设置,或值仍含未展开的 `${...}`,则从 `process.cwd()` 开始向上查找 `.ai/`
3. 如果没找到,再继续向上查找 `package.json`
4. 如果还没找到,再继续向上查找 `.git`
5. 只有全部没找到时,才回退到 `process.cwd()`
为了方便排查,项目现在提供:
- 启动日志会打印 `Effective project root`
- MCP tool `get_effective_project_root`
你可以直接调用:
```json
{
"name": "get_effective_project_root",
"arguments": {}
}
```
它会返回:
- `projectRoot`
- `memoryRoot`
- `projectRootSource`
如果 `projectRootSource` 是 `process.cwd()`,说明客户端既没有显式传入 `PROJECT_MEMORY_ROOT`,向上也没探测到 `.ai/`、`package.json` 或 `.git`,这时 `.ai/` 很可能不在你当前打开的业务项目目录里。
## 推荐自动工作流
如果客户端支持基于意图自动调用 MCP tools,推荐使用下面这条明确工作流:
1. 进入项目时自动调用 `bootstrap_project_context`
2. 每轮对话结束时自动调用 `suggest_context_updates`
3. 如果属于明确完成型对话,再自动调用 `record_conversation_summary`
4. 当 `.ai/` 变脏时,再触发 `suggest_memory_optimization`
为了更方便客户端接入,项目还提供了两个高层工作流封装:
- `run_project_open_workflow`
- `run_conversation_end_workflow`
如果你不想在客户端里手动编排多个 tool,也可以直接优先调用这两个工作流入口。
## 项目启动时的推荐流程
推荐在 AI 第一次进入项目时,优先调用 `bootstrap_project_context`。
它会返回两层信息:
- `coreContext`
- 完整读取 `project.md`
- 完整读取 `current-task.md`
- 完整读取 `architecture.md`
- 完整读取 `coding-style.md`
- `supplementalContext`
- 摘要化返回 `recent-changes.md`
- 摘要化返回 `decisions.md`
- 摘要化返回 `conversation-summary.md`
- 摘要化返回 `todo.md`
同时它还会返回:
- `recommendedNextFiles`
- `warnings`
其中 `warnings` 会提示哪些文件目前还像占位内容,适合后续继续完善。
如果你确实需要完整读取全部主要上下文,再调用 `get_project_context` 即可。
如果你希望直接走工作流封装,也可以调用 `run_project_open_workflow`。
## 对话结束后的更新流程
这个项目支持在每次对话结束后更新上下文文件。
推荐流程:
1. 对话结束后,由客户端调用 `record_conversation_summary`。
2. 工具会将一条带日期的摘要追加到 `.ai/conversation-summary.md`。
3. 如果这轮对话还影响了长期上下文,同一次调用也可以:
- 覆盖 `.ai/current-task.md`
- 追加到 `.ai/recent-changes.md`
- 追加一条或多条记录到 `.ai/decisions.md`
这样可以把“短期对话摘要”和“长期项目记忆”分开维护,减少上下文被频繁误改的风险。
如果你希望一步走完对话结束阶段的推荐逻辑,也可以直接调用 `run_conversation_end_workflow`。
它会:
- 始终生成 `suggest_context_updates` 等价结果
- 在 `completed=true` 时自动记录对话摘要
- 在 `.ai/` 需要整理时自动附带 `suggest_memory_optimization` 结果
## 建议模式
如果你希望采用“先建议,后确认”的流程,可以先调用 `suggest_context_updates`。
它会返回:
- 建议修改哪些 `.ai/` 文件
- 每项修改是 `append` 还是 `replace`
- 对应内容的预览
随后再由用户或客户端确认是否调用 `record_conversation_summary` 进行真正写入。
## Git Diff 摘要
可以调用 `summarize_git_diff` 来查看当前 Git 工作区变化。
- 如果当前目录是 Git 仓库,它会返回变更文件和 diff 统计。
- 如果当前目录不是 Git 仓库,它会返回安全的不可用结果,而不是直接报错。
- 如果 `writeToRecentChanges` 为 `true`,它还会把生成的摘要追加写入 `.ai/recent-changes.md`。
## 记忆整理流程
推荐使用两段式流程:
1. `suggest_memory_optimization`
2. `apply_memory_optimization`
这样可以先生成计划,再决定是否真正修改 `.ai/`。
当前会处理的内容包括:
- 初始化缺失的 `.ai/` 文件
- 识别明显的占位文案
- 去除 `decisions.md`、`recent-changes.md`、`conversation-summary.md`、`todo.md` 中的重复条目
- 整理多余空白行
- 将较早的 `recent-changes.md` 条目归档到 `recent-changes.archive.md`
当前版本仍以保守优化为主,不会自动重写高风险语义内容。
### 归档策略
`recent-changes.md` 用于保留最近的变更摘要。
当其中的条目变多时,整理流程会:
- 保留最近的 3 条在 `recent-changes.md`
- 将更早的条目追加归档到 `recent-changes.archive.md`
这样可以让“最近变更”保持短小,同时保留历史记录。
### 触发方式
如果你已经把 `project-memory` 配到 MCP 客户端里,通常可以直接对 AI 说:
- “先帮我看看项目记忆该怎么整理”
- “请生成一份 memory optimization plan”
- “确认后把这些记忆整理应用掉”
也可以把它理解成两次标准 tool call:
```json
{
"name": "suggest_memory_optimization",
"arguments": {}
}
```
确认后再执行:
```json
{
"name": "apply_memory_optimization",
"arguments": {}
}
```
`optimize_ai_memory` 仍然保留为兼容入口,但更推荐直接使用上面的两段式工具。
### 意图触发建议
推荐客户端或 AI 采用“意图触发”而不是“固定口令触发”。
也就是说,不要求用户必须说出完全一致的一句话,只要表达的语义接近“整理项目记忆”,就可以触发 `optimize_ai_memory` 或后续更高层的记忆整理流程。
例如下面这些说法,都可以视为同类意图:
- “整理一下项目记忆”
- “优化一下 `.ai`”
- “帮我清理项目上下文”
- “把共享记忆收一收”
- “同步整理一下 memory”
- “把 recent、todo、decision 整理一下”
推荐分工如下:
- 上层 AI 负责理解自然语言意图
- MCP tool 负责执行稳定、可预期的整理动作
这样可以避免把触发逻辑设计成只能匹配单一句式,实际体验会自然很多。
### 什么时候用
适合在这些场景手动触发:
- `.ai/` 文件积累了一段时间,想做一次整理
- 决策、最近变更或对话摘要里怀疑出现了重复内容
- 项目准备切换给另一个 AI 或另一个开发工具之前
- 想先把项目记忆整理干净,再继续沉淀新的上下文
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues