1. 项目概述与核心价值
最近在折腾AI应用开发,特别是想搞点能深度集成到工作流里的智能工具,发现一个挺有意思的项目:feralcarazp/project-memory-mcp。乍一看这名字,MCP(Model Context Protocol)和Memory(记忆)的组合,就让人感觉不简单。这玩意儿本质上是一个为AI Agent设计的“记忆系统”服务器,它能让那些基于MCP协议的AI助手(比如Claude Desktop、Cursor等)拥有长期、结构化、可查询的记忆能力。
简单来说,没有它之前,AI助手就像金鱼,每次对话都是新的开始,它不记得你上次说了什么,更别提你一周前、一个月前交代过的项目细节、个人偏好或者待办事项。而project-memory-mcp就是给AI装了个“外接大脑”,让它能记住关于你的一切上下文,并在需要时精准调取。这解决了AI应用领域一个核心痛点:上下文窗口有限与长期记忆需求之间的矛盾。无论你是想打造一个永远记得你喜好的个人助理,还是一个能持续跟进复杂项目的团队协作者,这个项目都提供了一个非常扎实、可扩展的基础设施。
它的核心用户,就是像我这样的AI应用开发者、热衷于个性化工作流自动化的极客,以及任何希望将AI从“一次性对话工具”升级为“长期合作伙伴”的人。接下来,我就结合自己搭建和使用的经验,把这个项目的里里外外、从原理到实操、从踩坑到优化,给大家彻底拆解清楚。
2. 核心架构与设计思路拆解
2.1 什么是MCP?为什么是MCP?
要理解这个项目,首先得搞懂MCP。MCP是由Anthropic提出的一套开放协议,旨在标准化AI应用与各种工具、数据源之间的通信方式。你可以把它想象成AI世界的“USB协议”或者“驱动模型”。在MCP架构下,AI助手(客户端)可以通过标准的JSON-RPC接口,去发现、调用由各种MCP服务器提供的工具(Tools)和资源(Resources)。
project-memory-mcp就是一个遵循MCP协议的服务器。它的高明之处在于,没有尝试去修改AI模型本身(那是模型提供商的事),而是通过标准化的协议,为AI提供了一个通用的记忆服务接口。这意味着,任何兼容MCP的AI客户端,无需任何特殊适配,就能立刻获得记忆能力。这种设计思路非常“Unix哲学”:做一件事,并把它做好。它专注于解决“记忆存储与检索”这个单一问题,并通过标准接口暴露给整个生态。
2.2 记忆系统的核心设计哲学
这个记忆服务器的设计,围绕几个关键目标展开:
- 持久化与向量化:记忆不能只存在内存里,必须持久化到数据库。同时,为了支持基于语义的模糊搜索(比如“我之前关于用户认证的想法”),文本记忆需要被转换成向量(Embedding),存储到向量数据库中。
- 结构化与关联性:记忆不是一堆杂乱的文本。项目支持为记忆打标签(Tags)、关联实体(Entities,如“人”、“项目”、“会议”),并建立记忆之间的链接(Links)。这模仿了人类大脑的联想记忆,使得检索不再是简单的关键词匹配,而是带有关系的图谱查询。
- 隐私与安全:所有记忆数据默认存储在本地。服务器运行在你自己的机器上,数据不进任何第三方云。这对于存储个人或敏感信息至关重要,也是自托管项目的最大吸引力之一。
- 可扩展性:它不绑定特定的向量数据库或关系数据库。虽然默认配置使用了SQLite(轻量)和ChromaDB(本地向量库),但架构上支持切换到PostgreSQL、Qdrant、Weaviate等,适应从个人到企业级的不同场景。
2.3 技术栈选型解析
项目主要采用Node.js生态,这是一个务实的选择:
- 运行时:Node.js。生态成熟,异步IO模型适合IO密集型的记忆检索和存储操作。
- Web框架:Fastify。相比Express,Fastify性能更高,对JSON-RPC协议的支持更原生、更友好,非常适合MCP服务器这种API密集型应用。
- 向量数据库:默认集成ChromaDB。它是一个开源嵌入向量数据库,易于本地运行,API简单。向量化模型默认使用
Xenova/all-MiniLM-L6-v2,这是一个轻量级且效果不错的句子转换模型,可以在本地运行,无需OpenAI API密钥,进一步保障了隐私和离线能力。 - 结构化存储:SQLite(默认)或PostgreSQL。用于存储记忆的元数据(ID、时间戳、标签、关联等)。SQLite适合个人单机使用,零配置;PostgreSQL则适合需要并发访问和高可靠性的场景。
- 协议:严格遵守MCP协议规范,使用JSON-RPC over stdio/SSE。这是与AI客户端通信的基石。
这个技术栈平衡了易用性、性能和隐私,让开发者能快速上手,同时也为深度定制留足了空间。
3. 环境准备与部署实操
3.1 基础环境搭建
首先,确保你的开发环境已经就绪。你需要:
- Node.js:版本18或以上。推荐使用nvm(Node Version Manager)来管理多个Node版本。
# 使用nvm安装最新LTS版本 nvm install --lts nvm use --lts - Git:用于克隆代码库。
- Python 3.8+(可选但推荐):因为ChromaDB底层依赖一些Python库,虽然项目通过
@chromadb/node客户端尝试提供纯Node支持,但准备Python环境可以避免一些潜在的本地依赖问题。
注意:如果你在Windows上开发,建议使用WSL2(Windows Subsystem for Linux)来获得与Linux/macOS一致的体验,能避开很多路径和依赖的坑。
3.2 获取与初始化项目
打开终端,开始操作:
# 1. 克隆项目仓库 git clone https://github.com/feralcarazp/project-memory-mcp.git cd project-memory-mcp # 2. 安装项目依赖 npm install # 这个过程可能会花费一些时间,因为它需要下载并编译一些本地依赖,比如ChromaDB的客户端。 # 3. 复制环境变量示例文件,并根据需要修改 cp .env.example .env现在,打开新创建的.env文件,你会看到一些核心配置:
# 数据库连接配置(默认使用SQLite) DATABASE_URL="file:./data/memory.db" # 如果你想用PostgreSQL,可以改成: # DATABASE_URL="postgresql://username:password@localhost:5432/memory_db" # 向量数据库配置(默认使用ChromaDB本地持久化) VECTOR_DB_TYPE="chroma" CHROMA_DB_PATH="./data/chroma_db" # 嵌入模型配置(默认使用本地Xenova模型) EMBEDDING_MODEL="Xenova/all-MiniLM-L6-v2" # 如果你想用OpenAI的模型(需要API Key),可以改成: # EMBEDDING_MODEL="openai" # OPENAI_API_KEY="sk-..." # 服务器监听配置 HOST="localhost" PORT=3000对于个人使用或初次体验,强烈建议保持默认配置。SQLite和本地ChromaDB的组合是零配置的,数据会保存在项目目录下的./data文件夹里,完全自包含。
3.3 数据库初始化与服务器启动
项目使用Prisma作为ORM(对象关系映射工具)来管理数据库结构。我们需要先初始化数据库:
# 生成Prisma客户端并执行迁移,创建数据库表 npx prisma db push执行成功后,会在./data目录下生成memory.db文件(SQLite数据库)。
接下来,就可以启动记忆MCP服务器了:
# 开发模式启动,带有热重载 npm run dev # 或者,生产模式构建后启动 npm run build npm start如果一切顺利,终端会输出类似信息,表明服务器已在http://localhost:3000启动,并准备好通过stdio接受MCP连接。
3.4 配置AI客户端(以Claude Desktop为例)
服务器跑起来了,但要让它发挥作用,需要配置你的AI客户端去连接它。这里以最流行的Claude Desktop为例:
- 找到Claude Desktop的配置文件夹。
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
- macOS:
- 编辑(或创建)
claude_desktop_config.json文件,添加MCP服务器配置。关键是要配置mcpServers对象。
{ "mcpServers": { "project-memory": { "command": "node", "args": [ "/ABSOLUTE/PATH/TO/YOUR/project-memory-mcp/build/index.js" ], "env": { "DATABASE_URL": "file:/ABSOLUTE/PATH/TO/YOUR/project-memory-mcp/data/memory.db", "CHROMA_DB_PATH": "/ABSOLUTE/PATH/TO/YOUR/project-memory-mcp/data/chroma_db" } } } }这里有几个至关重要的细节:
command: 必须是node,因为我们的服务器是Node.js应用。args: 必须指向构建后的入口文件index.js(在build目录下)。直接指向源码src/index.ts是无效的。env: 这里的环境变量会覆盖项目根目录下的.env文件。必须使用绝对路径,相对路径在Claude Desktop的上下文中可能会解析错误。- 请务必将
/ABSOLUTE/PATH/TO/YOUR替换成你电脑上project-memory-mcp文件夹的绝对真实路径。
- 保存配置文件,并完全重启Claude Desktop(不是关闭窗口,而是从任务栏/程序坞彻底退出再重新打开)。
重启后,当你新建一个对话,Claude的输入框旁边如果出现了一个“大脑”或“工具”图标,点击它,你应该能看到一个名为“project-memory”的服务器,以及它提供的工具列表(如create_memory,search_memories等)。恭喜,至此,你的AI助手已经成功接上了“外接大脑”!
4. 核心功能深度解析与使用指南
服务器配置好了,我们来看看它到底提供了哪些能力,以及如何高效地使用它们。
4.1 记忆的创建与结构化
核心工具是create_memory。这不仅仅是保存一段文本那么简单。
// 这是一个通过AI客户端调用create_memory的示例请求(底层JSON-RPC格式) { "method": "tools/call", "params": { "name": "create_memory", "arguments": { "content": "我们决定在下个季度的产品路线图中,优先开发基于用户行为分析的智能推荐模块。预计需要前端2人周,后端3人周。关键依赖是用户事件收集系统需在本月底前上线。", "tags": ["product-roadmap", "q3-planning", "backend", "frontend"], "entities": [ {"type": "project", "name": "智能推荐模块"}, {"type": "milestone", "name": "用户事件收集系统上线"} ] } } }参数解读与最佳实践:
content:记忆的核心内容。尽量清晰、完整。AI在将来检索时,会基于此内容的语义进行查找。tags:标签数组。这是最重要的组织方式。建议建立个人或团队的标签规范,例如:- 按领域:
devops,marketing,design-review - 按项目:
project-alpha,website-redesign - 按状态:
todo,waiting-for-feedback,archived - 按类型:
meeting-note,code-snippet,decision-log
- 按领域:
entities:实体数组。用于标识内容中提到的具体对象。这能帮助建立记忆之间的关联网络。例如,你可以把“人”、“公司”、“产品功能”、“代码仓库”都定义为实体类型。
实操心得:不要偷懒只写内容。花30秒打好标签和实体,未来检索的效率能提升200%。你可以训练你的AI助手,在帮你保存记忆时,主动询问:“这段内容需要打上什么标签吗?里面提到了哪些具体的项目或人名需要我标记为实体?”
4.2 记忆的检索:从关键词到语义搜索
记忆存进去,更要能高效地取出来。search_memories工具是核心。
// 搜索示例 { "method": "tools/call", "params": { "name": "search_memories", "arguments": { "query": "关于后端工作量的规划", "limit": 5, "tags": ["product-roadmap"], "search_type": "hybrid" // 可选:'semantic' (纯语义), 'fulltext' (纯全文), 'hybrid' (混合) } } }搜索策略详解:
- 语义搜索(
search_type: "semantic"):将查询词“关于后端工作量的规划”转换成向量,然后在向量数据库中寻找内容向量最相似的记忆。它能找到“预计需要前端2人周,后端3人周”这条记忆,即使原文没有出现“工作量规划”这几个字。这是处理模糊、概念性查询的利器。 - 全文搜索(
search_type: "fulltext"):在记忆的文本内容中进行传统的关键词匹配。对于精确的术语、错误码、特定ID等搜索非常快。 - 混合搜索(
search_type: "hybrid"):默认且推荐的方式。它同时执行语义和全文搜索,然后对结果进行加权和重排。兼顾了召回率(找到相关记忆)和精确度。
使用技巧:
- 结合
tags过滤可以极大缩小搜索范围,提升准确率。比如tags: ["q3-planning"]。 limit参数控制返回数量,避免信息过载。- 搜索结果会返回一个相关性分数
score,帮助你判断匹配度。
4.3 记忆的更新、关联与删除
记忆不是一成不变的。
update_memory:可以修改记忆的内容、标签或实体。比如会议结论改变了,或者给一个记忆增加了新的标签。link_memories:这是构建知识图谱的关键。你可以明确地建立两条记忆之间的联系,并定义关系类型。例如,将“项目启动会议纪要”与“产品需求文档”链接,关系为references;将“某人提出的创意”与“后续的任务分配”链接,关系为led_to。这些链接在复杂的知识追溯场景下非常有用。delete_memory:删除不再需要的记忆。谨慎操作,或者考虑使用archived标签来软删除。
4.4 高级查询与记忆管理
除了基本CRUD,服务器还提供了更强大的管理工具:
get_memory:通过唯一ID获取单条记忆的完整详情。list_memories:分页列出所有记忆,支持按时间、标签过滤。适合定期回顾和整理。get_related_memories:给定一条记忆ID,找出所有与它链接(linked)的其他记忆。这是探索知识关联网络的入口。
5. 实战场景:打造你的AI第二大脑
理论说再多,不如看实战。我来分享几个我深度使用后的场景。
5.1 场景一:项目管理与进度跟踪
我是一名独立开发者,同时维护着好几个开源项目。以前,每个项目的待办事项、会议记录、技术决策都散落在不同的笔记软件、Issue列表和聊天记录里。
现在,我养成了习惯,在任何关于项目的讨论或思考后,立即让Claude帮我存入记忆。
我的操作流:
- 在Claude对话中,我直接说:“帮我把这个记下来:
项目A的登录模块,决定采用JWT方案而非Session,因为需要支持无状态横向扩展。选型了jsonwebtoken库,密钥轮换策略待定。” - Claude会调用
create_memory工具,并主动问我:“这条记忆可以打上project-a、auth、technical-decision标签吗?需要标记JWT或jsonwebtoken为实体吗?” - 我确认后,记忆就被结构化保存了。
当一周后我需要回顾登录模块的设计时,我只需问Claude:“查一下我们之前关于项目A登录模块的技术决策。” Claude会调用search_memories,用query: "项目A 登录 模块 技术决策"和tags: ["project-a", "technical-decision"]进行混合搜索,瞬间把那条记忆找出来,并呈现在对话中。上下文无缝衔接。
5.2 场景二:学习与研究笔记
我在学习一门新课或研究一个新领域时,会阅读大量资料。我会将核心概念、精彩论点、参考文献摘要,通过AI助手存入记忆。
关键技巧:为每个学习主题创建专属标签,如learning-kubernetes、research-llm-agent。对于复杂概念,我会创建多条记忆,并用link_memories将它们关联起来,形成知识链。例如,“Kubernetes Pod概念”链接到“Pod生命周期管理”,再链接到“实际部署YAML示例”。
效果:当我在后续工作中遇到相关问题,比如“如何在Pod中处理配置文件”,我就可以让AI搜索tags: ["learning-kubernetes"]和query: "pod configmap"的相关记忆,快速调出之前的学习笔记,而不是重新去翻几百页的文档或杂乱的书签。
5.3 场景三:个性化助理与上下文延续
这是最酷的用法。我训练我的Claude,在每次对话开始时,自动搜索与我(用户)相关的近期记忆。
实现思路(通过自定义提示词或客户端配置):
- 在对话初始化时,自动执行一个搜索,查询
tags: ["user-preferences", "conversation-history"],并按时间倒序,获取最近几条。 - AI助手在开场白中就可以说:“嗨,看到你上周提到了对暗色主题的偏好,我已经记住了。另外,你昨天问到的关于API限流的问题,我找到了一些新的资料...” 这种体验是革命性的,它让每次对话都像是和老朋友继续聊天。
注意事项:自动注入记忆时要注意隐私和上下文长度。不要一次性注入太多条,避免耗尽AI模型的上下文窗口。可以设定一个时间范围(如最近3天)或数量限制(最近5条)。
6. 性能调优、问题排查与进阶配置
用了一段时间后,你可能会遇到一些性能问题或有更高级的需求。下面是一些实战经验。
6.1 向量搜索慢?数据库优化与模型选择
症状:search_memories调用响应慢,特别是记忆条数超过几千条时。
排查与解决:
- 检查向量索引:ChromaDB默认会在保存时创建向量索引。确保你没有禁用此功能。对于生产环境,可以考虑使用性能更好的向量数据库,如Qdrant或Weaviate。
project-memory-mcp的架构支持更换向量库,你需要实现对应的VectorDbService接口。- 切换到Qdrant:修改
.env,设置VECTOR_DB_TYPE=qdrant,并配置QDRANT_URL和QDRANT_API_KEY。Qdrant的HNSW索引对于大规模向量搜索效率更高。
- 切换到Qdrant:修改
- 审视嵌入模型:默认的
all-MiniLM-L6-v2模型平衡了速度和效果。如果追求极速,可以换用更小的模型(如Xenova/all-MiniLM-L6-v2的量化版),但可能会损失一些语义精度。如果追求极致精度,可以换用更大的模型(如thenlper/gte-base),但会消耗更多计算资源和时间。你可以在.env中更改EMBEDDING_MODEL,项目使用@xenova/transformers库,支持很多Hugging Face上的句子转换模型。 - 优化搜索参数:
search_memories的limit不要一次性设置太大(比如100),通常5-10条最相关的记忆就足够了。混合搜索(hybrid)虽然全面,但比单一搜索更耗资源,在明确知道关键词时,可以尝试只用fulltext。
6.2 记忆检索不准确?优化内容与标签策略
症状:明明记得存过,但就是搜不出来,或者搜出来的不相关。
解决:
- 优化存储内容:存入记忆时,
content字段尽量是完整、自包含的句子或段落,避免过于零碎或使用大量代词(它、这个、那个)。AI的语义理解基于你存入的文本。 - 善用标签系统:这是最有效的过滤手段。建立清晰、一致的标签层级。例如,可以用冒号表示层级:
project:alpha、project:beta、type:meeting、type:code。搜索时用tags: ["project:alpha", "type:meeting"]可以精准定位。 - 实体识别辅助:在
create_memory时,尽可能填写entities。未来可以结合实体进行关联检索(get_related_memories),即使语义上不直接匹配,也能通过实体网络找到相关信息。
6.3 客户端连接失败?配置与路径问题详解
这是新手最常遇到的问题,Claude Desktop显示服务器连接错误。
排查清单:
- 绝对路径:再次检查
claude_desktop_config.json中的args和env里的所有路径,必须是绝对路径。在终端里执行pwd命令可以获取当前目录的绝对路径。 - 构建产物:确保
args指向的是build/index.js,而不是src/index.ts。你必须先运行过npm run build。 - 环境变量覆盖:
claude_desktop_config.json中的env设置会覆盖项目根目录的.env文件。如果你在.env里配置了数据库路径,但在JSON里又配了一个不同的,会以JSON为准。确保两者一致或只在JSON中配置。 - 端口冲突:检查
.env中的PORT是否被其他程序占用。可以尝试改成另一个端口,如3001,但注意MCP over stdio不依赖HTTP端口,这个端口主要用于服务器自身的健康检查或未来扩展。 - 查看日志:在启动项目的终端里查看详细的错误日志。或者在Claude Desktop的开发者工具(如果有)中查看连接日志。最常见的错误信息会直接指出是路径错误、模块找不到还是权限问题。
6.4 数据备份与迁移
你的记忆数据非常宝贵,定期备份是必须的。
备份方案:
- 简单备份:直接复制整个
./data目录。里面包含了SQLite数据库文件(memory.db)和ChromaDB的向量数据目录(chroma_db/)。 - 自动化备份:写一个简单的Shell脚本或使用
cron任务,定期将./data目录打包压缩,上传到云存储或其他安全位置。 - 迁移到PostgreSQL:如果数据量增长,想从SQLite迁移到PostgreSQL:
- 修改
.env中的DATABASE_URL为PostgreSQL连接串。 - 确保PostgreSQL数据库已创建好(例如
createdb memory_db)。 - 运行
npx prisma db push。Prisma会自动在PostgreSQL中创建表结构。 - 数据迁移:这是一个需要谨慎操作的过程。你需要使用数据库迁移工具(如
pgloader或手动导出导入)将SQLite中的数据迁移到PostgreSQL。由于涉及向量数据关联,建议在测试环境充分验证后再进行生产迁移。
- 修改
7. 扩展开发与二次开发指南
project-memory-mcp是一个开源项目,如果你不满足于现有功能,完全可以对其进行扩展。
7.1 添加新的工具(Tools)
MCP服务器的能力通过“工具”暴露。假设你想添加一个summarize_project工具,用于自动总结某个标签下所有记忆的概览。
- 在
src/tools/目录下创建新文件,例如summarizeProjectTool.ts。 - 定义工具模式:遵循
zod库定义输入参数的模式。// src/tools/summarizeProjectTool.ts import { z } from 'zod'; import { MemoryService } from '../services/memoryService'; export const summarizeProjectTool = { name: 'summarize_project', description: 'Summarize all memories under a specific project tag.', inputSchema: z.object({ projectTag: z.string().describe('The project tag to summarize, e.g., project:alpha'), }), handler: async ({ projectTag }, { memoryService }: { memoryService: MemoryService }) => { // 1. 调用memoryService的方法,获取所有带有该标签的记忆 const memories = await memoryService.searchMemories({ tags: [projectTag], limit: 100, // 获取足够多的记忆 }); // 2. 提取关键信息,生成摘要(这里可以集成一个LLM进行智能摘要) const summary = `Project ${projectTag} has ${memories.length} related memories. Latest activity: ${memories[0]?.createdAt}. Key topics include: ...`; // 简化示例 // 3. 返回结果 return { content: [ { type: 'text', text: summary, }, ], }; }, }; - 注册工具:在
src/index.ts或专门的工具注册文件中,将新工具导入并添加到工具列表中。 - 重新构建并重启服务器:
npm run build。Claude Desktop会在下次连接时发现这个新工具。
7.2 集成外部数据源
记忆不一定非要手动创建。你可以编写一个“抓取器”,定期将外部数据同步到记忆库。
示例:同步GitHub Issues到记忆
- 创建一个新的服务类,例如
src/services/githubSyncService.ts。 - 使用Octokit(GitHub API客户端)获取指定仓库的Issues。
- 将每个Issue的标题、正文、标签、状态等信息,通过
memoryService.createMemory转化为一条记忆,并打上source:github、repo:your-repo-name等标签,将Issue编号和作者标记为实体。 - 设置一个定时任务(例如使用
node-cron),每天运行一次这个同步服务。
这样,你就可以直接问AI:“我们仓库里关于‘登录bug’的未解决Issue有哪些?” AI会通过搜索记忆来回答你。
7.3 自定义嵌入模型或向量数据库
如果你对默认的ChromaDB和MiniLM模型不满意,项目架构允许你替换它们。
- 实现
VectorDbService接口:在src/services/vectorDb/下创建一个新文件,例如qdrantVectorDbService.ts,实现upsert,search,delete等方法,内部调用Qdrant的客户端库。 - 实现
EmbeddingService接口:在src/services/embedding/下创建新文件,例如openAIEmbeddingService.ts,实现generateEmbedding方法,内部调用OpenAI的Embeddings API。 - 修改依赖注入:在
src/index.ts或应用启动文件中,使用你新创建的服务类实例,替换掉默认的服务实例。
这个过程需要对代码结构有一定了解,但项目本身的模块化设计使得这种替换相对清晰。
经过以上从部署到使用,从排查到扩展的完整梳理,feralcarazp/project-memory-mcp这个项目已经从一个陌生的仓库,变成了你手中一个强大的、可定制的AI记忆中枢。它不再是一个黑盒,而是一个你可以理解、掌控并融入自己工作流的核心组件。记住,工具的价值在于使用。现在就去给你的AI装上这个“外接大脑”,开始构建属于你自己的、持续进化的数字记忆体吧。