基于MCP协议与向量数据库构建AI助手本地记忆中枢

基于MCP协议与向量数据库构建AI助手本地记忆中枢 1. 项目概述为AI助手构建一个本地记忆中枢如果你和我一样每天都要和Claude、Cursor这类AI编程助手打交道肯定会遇到一个头疼的问题对话没有记忆。昨天刚和它讨论完项目的架构设计今天打开新会话它又得从头问起“这个项目是做什么的”。更麻烦的是那些在调试中踩过的坑、总结的最佳实践每次都得手动复制粘贴到新对话里效率极低。这个痛点催生了local-memory-mcp项目。简单说它是一个完全运行在你本地的记忆服务端遵循新兴的MCP协议。你可以把它理解成AI助手的“外接大脑”或“第二记忆体”。它的核心使命是让AI助手能记住跨会话的重要信息——比如你定下的代码规范、某个API的诡异返回值、上次部署失败的教训——并在后续对话中当AI助手需要相关背景时能主动、智能地“回忆”起来。我选择本地化方案核心考量是隐私、可控和离线可用。所有记忆数据、向量计算都在你的机器上完成不依赖任何外部云服务。技术栈上它用Bun作为运行时用轻量级的Zvec作为嵌入式向量数据库来存储和检索记忆并通过本地的Ollama服务使用embeddinggemma模型将文本转化为机器能理解的向量。整个系统通过一组定义清晰的工具memory.save,memory.search等暴露给AI助手让后者能像调用函数一样“存储”和“读取”记忆。这个项目特别适合软件开发者、技术写作者或任何需要与AI进行复杂、长期协作的人。无论是维护一个大型代码库还是撰写系列技术文档你都可以通过它建立一个持续进化的“项目知识库”极大提升人机协作的连贯性和深度。2. 核心设计思路与架构解析2.1 为什么是MCP协议驱动的可扩展性MCP全称Model Context Protocol是由Anthropic提出的一套开放协议。它的目标很明确为AI模型尤其是大语言模型定义一个标准化的方式来发现、调用外部工具和资源。你可以把它想象成AI世界的“USB协议”或“插件系统”。在local-memory-mcp中我们实现了一个MCP服务器。这意味着任何兼容MCP的客户端如Claude Desktop、Cursor、Windsurf等都能无缝接入我们的记忆服务而不需要为每个客户端单独开发适配器。这种协议优先的设计带来了巨大的灵活性未来如果出现了新的、更优秀的AI客户端只要它支持MCP我们的记忆服务就能立即为其所用。注意MCP服务器通常通过stdio标准输入输出与客户端通信。这是一种轻量级、跨平台的进程间通信方式。我们的服务器启动后就静静地等待客户端比如VS Code里的Copilot通过标准输入发送JSON格式的请求处理后再通过标准输出返回JSON结果。这种设计避免了复杂的网络端口管理和防火墙问题。2.2 记忆的存储与检索向量数据库的实战选型记忆的核心是“存”和“取”。存要把一段文本比如“用户偏好使用async/await而非Promise.then”变成计算机能高效处理的形式取则要在海量记忆中快速找到与当前问题最相关的那几条。1. 向量化从文字到数学这是实现语义搜索的基石。我们使用Ollama本地运行的embeddinggemma模型。当你调用memory.save存储一段文本时服务器会悄悄做一件事将这段文本发送给Ollama的/api/embed接口。该接口返回一个Float32Array通常是一个768维的向量具体维度由EMBEDDING_DIM环境变量定义必须与模型匹配。这个向量就是这段文本在高维空间中的“数学指纹”。语义相近的文本其向量在空间中的距离通常用余弦相似度衡量也会很近。2. 存储与检索为什么是Zvec得到向量后我们需要一个地方存储它并支持高效的近似最近邻搜索。这就是向量数据库的职责。市面上选择很多Pinecone, Weaviate, Qdrant等但我们选择了Zvec原因有三极致轻量与嵌入式Zvec是一个纯TypeScript库无需单独部署数据库服务。它直接在你的应用进程中运行将数据存储在单个文件中默认是./data/memory.zvec。这简化了部署也减少了运维负担。零外部依赖整个搜索逻辑在内存中完成检索速度极快尤其适合我们这种单用户、数据量在万级以内的场景。足够的查询能力Zvec支持带元数据过滤的KNN查询。这意味着我们不仅能根据向量相似度搜索还能加上条件比如“只搜索workspaceKey为my-react-project且type为bug的记忆”。这在实际应用中非常有用。在数据库设计上我们使用一个Zvec集合Collection每条记忆记录包含两个部分稠密向量字段存储由Ollama生成的embedding向量。标量元数字段存储id,workspaceKey,type,summary,text,tags,importance,createdAt,supersededAt等。这些字段用于过滤、管理和展示。3. 检索流程详解当AI助手需要背景信息时会调用memory.search并传入一个查询字符串例如“我们之前是怎么处理用户认证的”。服务器会将查询字符串同样通过Ollama转化为查询向量。在Zvec数据库中执行一次KNN查询寻找与查询向量最相似的向量集合。在查询时自动附加一个过滤器supersededAt字段必须为null即未被标记为过时。同时如果调用时指定了workspaceKey或type也会将这些作为过滤条件。最后根据相似度分数通常经过标准化处理返回排名前topK条的记忆记录包括它们的元数据和原始文本。2.3 记忆的生命周期管理增删改查的哲学一个健康的记忆系统不能只存不删否则会堆积大量无效、过时信息污染检索结果。local-memory-mcp设计了完整的记忆生命周期管理工具memory.save创建新记忆。这是最基础的操作。除了必填的text强烈建议提供清晰的summary和tags。summary是记忆的“标题”用于快速浏览tags是“关键词”便于后期按主题过滤。importance字段0.0到1.0可以手动标记记忆的重要性未来可用于加权搜索。memory.supersede标记过时。这是比删除更优雅的方式。软件在迭代决策会更新。当你有了新的、更准确的记忆例如“改用JWT替代Session认证”你可以用它supersede旧的那条。旧记忆的supersededAt字段会被打上时间戳从此在默认搜索中“隐身”但历史记录得以保留。这在需要追溯决策变更时非常有用。memory.delete永久删除。用于清除完全错误或无用的信息。memory.search智能检索。是整个系统的价值出口。memory.ping健康检查。用于验证服务器是否正常运行并返回版本等基础信息。工作空间隔离WORKSPACE_KEY的妙用这是一个关键设计。通过WORKSPACE_KEY环境变量通常设置为项目文件夹名我们可以将记忆按项目隔离。这样你在“React电商项目”中存储的关于UI组件的记忆不会在“Go后端微服务”项目中被检索出来避免了无关信息的干扰。同时所有记忆又存储在同一个物理数据库文件中便于备份和管理。3. 从零开始环境搭建与项目部署实操3.1 基础环境准备Bun与Ollama我们的技术栈依赖于两个核心运行时Bun和Ollama。下面是在macOS/Linux系统下的详细安装步骤Windows用户建议使用WSL2以获得最佳体验。1. 安装BunBun是一个现代化的JavaScript运行时速度很快内置了包管理器和测试运行器。安装一条命令搞定# 使用官方安装脚本 curl -fsSL https://bun.sh/install | bash安装完成后重启你的终端运行bun --version验证是否安装成功。2. 安装并配置OllamaOllama让你能在本地轻松运行大型语言模型。我们需要它来提供文本嵌入服务。# macOS 和 Linux 安装 curl -fsSL https://ollama.ai/install.sh | sh安装后Ollama服务会自动启动。你可以通过ollama serve来手动启动服务它默认监听在http://localhost:11434。接下来我们需要拉取专门用于生成文本向量的模型embeddinggemmaollama pull embeddinggemma这个模型大小约2GB下载时间取决于你的网络。你可以通过ollama list查看已下载的模型。实操心得首次运行ollama pull如果遇到网络问题可以尝试设置镜像源。但更常见的问题是内存不足。embeddinggemma运行需要一定内存确保你的机器可用内存大于4GB。可以通过ollama run embeddinggemma并输入一段文本来简单测试模型是否正常工作。3.2 获取与初始化项目假设你已经将basst85/local-memory-mcp项目克隆到本地。# 克隆项目 git clone https://github.com/basst85/local-memory-mcp.git cd local-memory-mcp # 使用Bun安装项目依赖 bun installbun install会读取package.json安装所有必要的依赖主要是zvec/zvec和modelcontextprotocol/sdk等。关键目录结构说明local-memory-mcp/ ├── src/ │ ├── index.ts # MCP服务器主入口处理协议通信 │ ├── memory-db.ts # 记忆数据库的核心逻辑增删改查 │ └── embed.ts # 封装与Ollama嵌入API的交互 ├── tests/ # 测试文件 ├── data/ # 默认的Zvec数据库文件存放目录需确保可写 ├── .vscode/mcp.json # VS Code工作区MCP配置示例 ├── .mcp.json # Claude Code项目级MCP配置示例 └── CLAUDE.md # 指导AI如何使用此记忆的提示词3.3 配置详解与环境变量调优项目的行为由一系列环境变量控制。理解它们对于正确使用和调试至关重要。环境变量默认值说明MEMORY_DB_PATH./data/memory.zvecZvec数据库文件路径。建议设置为绝对路径尤其是在多工作空间共享时避免路径混乱。OLLAMA_BASE_URLhttp://localhost:11434Ollama服务的URL。如果你的Ollama运行在其他机器或端口需要修改此变量。OLLAMA_EMBED_MODELembeddinggemma用于生成嵌入向量的模型名称。必须与通过ollama pull下载的模型名一致。EMBEDDING_DIM768嵌入向量的维度。必须与你使用的嵌入模型的实际维度严格匹配。embeddinggemma模型是768维。如果维度不匹配向量搜索将完全失效。WORKSPACE_KEYdefault工作空间键。用于隔离不同项目的记忆。最佳实践是将其设置为项目根目录的名称如${workspaceFolderBasename}或${PWD##*/}。配置建议开发/测试时可以在项目根目录创建一个.env文件需自行安装dotenv包或在代码中加载方便管理变量。生产/长期使用时通过启动命令或IDE配置传入环境变量更为可靠。例如在VS Code的mcp.json或启动脚本中设置。3.4 运行与测试验证你的安装一切就绪后让我们启动服务器并进行测试。1. 启动MCP服务器在项目根目录下运行bun run start如果一切正常终端不会有太多输出程序会挂起等待通过stdio接收MCP客户端请求。这意味着服务器已成功启动。2. 运行单元测试项目包含了重要的单元测试运行它们能验证核心功能是否正常尤其是与Ollama的连通性。bun run test你应该会看到类似以下的输出表明测试通过test tests/embed.test.ts ✓ parses successful Ollama embed response ✓ handles Ollama embed error test tests/memory-db.test.ts ✓ saves and searches memories ✓ supersedes memories ✓ deletes memories如果测试失败请重点关注embed.test.ts失败通常意味着Ollama服务未启动或OLLAMA_BASE_URL配置错误。请检查Ollama进程(ollama serve)和网络连通性(curl http://localhost:11434/api/tags)。memory-db.test.ts失败可能涉及文件写入权限检查data/目录或Zvec库的兼容性问题。4. 与你的开发环境深度集成让记忆服务在后台运行只是第一步关键是让它与你日常使用的AI助手无缝对接。下面以VS Code GitHub Copilot Chat 和 Claude Code 为例展示如何深度集成。4.1 集成到VS Code与GitHub Copilot ChatVS Code通过MCP支持可以让你在Copilot Chat中直接使用我们构建的记忆工具。方法一项目级配置推荐用于特定项目项目已经预置了.vscode/mcp.json文件。你只需要根据你的环境稍作调整{ servers: { local-memory-mcp: { type: stdio, command: bun, args: [run, start], env: { MEMORY_DB_PATH: /ABSOLUTE/PATH/TO/your/local-memory-mcp/data/memory.zvec, OLLAMA_BASE_URL: http://localhost:11434, OLLAMA_EMBED_MODEL: embeddinggemma, EMBEDDING_DIM: 768, WORKSPACE_KEY: ${workspaceFolderBasename} } } } }关键修改点将/ABSOLUTE/PATH/TO/your/local-memory-mcp替换为你电脑上项目的绝对路径。这是确保VS Code在任何位置都能正确启动服务器的关键。WORKSPACE_KEY: 使用${workspaceFolderBasename}这个VS Code变量它会自动取当前打开的工作区文件夹名作为键值完美实现项目间记忆隔离。配置好后打开VS Code的设置 (Ctrl,)搜索chat.mcp.autoStart确保这个实验性设置被启用。这样当你打开Copilot Chat时VS Code会自动启动配置好的MCP服务器。方法二用户级配置全局可用如果你希望在所有VS Code项目中都能使用这个记忆服务需要将其添加到用户全局配置。在VS Code中按下CtrlShiftP(或CmdShiftP)打开命令面板。输入并选择MCP: Open User Configuration。这会打开一个JSON配置文件。在其中添加上述服务器配置同样注意使用绝对路径。踩坑记录我最初使用相对路径MEMORY_DB_PATH: ./data/memory.zvec结果发现不同项目启动服务器时当前工作目录不同导致每个项目都创建了独立的数据库文件记忆完全无法共享。务必使用绝对路径来指向同一个数据库文件这是实现跨项目记忆共享同时依靠WORKSPACE_KEY隔离的前提。4.2 集成到Claude CodeClaude Code是Anthropic官方的代码编辑器对MCP的支持非常原生。项目级集成配置共享给协作者在项目根目录你可以使用Claude Code CLI工具快速添加claude mcp add --transport stdio --scope project \ --env MEMORY_DB_PATH./data/memory.zvec \ --env OLLAMA_BASE_URLhttp://localhost:11434 \ --env OLLAMA_EMBED_MODELembeddinggemma \ --env EMBEDDING_DIM768 \ --env WORKSPACE_KEY${PWD##*/} \ local-memory-mcp -- bun run start这条命令会在项目根目录生成一个.mcp.json文件内容与VS Code的类似。该文件可以提交到代码库这样所有使用此项目的团队成员只要本地有Ollama和Bun环境就能一键启用记忆功能。用户级集成仅自己使用如果你希望在任何使用Claude Code的项目中都能调用记忆可以添加到用户配置claude mcp add --transport stdio --scope user \ --env MEMORY_DB_PATH/ABSOLUTE/PATH/TO/local-memory-mcp/data/memory.zvec \ ...其他环境变量... local-memory-mcp -- bun --cwd /ABSOLUTE/PATH/TO/local-memory-mcp run start这里有两个关键点MEMORY_DB_PATH必须用绝对路径。命令中使用了bun --cwd /path/to/project run start这确保了Bun在正确的项目目录下启动服务器能正确找到node_modules和tsconfig.json等文件。管理你的MCP服务器添加后你可以随时查看和管理# 列出所有已配置的MCP服务器 claude mcp list # 查看某个服务器的详细配置 claude mcp get local-memory-mcp # 移除一个服务器 claude mcp remove local-memory-mcp4.3 实战工作流让AI助手真正“记住”配置完成后激动人心的时刻到了让你的AI助手开始利用记忆。以下是一个典型的工作流模拟初次会话存储决策你在开发一个React项目与AI助手讨论了状态管理方案。你“我们决定在这个项目中使用Zustand而不是Redux Toolkit因为它的样板代码更少对TypeScript支持也很好。”你手动或通过指令触发让AI助手调用memory.save工具。AI助手调用工具{ tool: memory.save, arguments: { workspaceKey: my-react-app, type: architecture_decision, summary: 选用Zustand作为状态管理库, text: 项目决定使用Zustand替代Redux Toolkit进行状态管理。主要考量1) API更简洁样板代码极少。2) 与TypeScript集成度极高类型推断友好。3) 基于Context和Hooks学习曲线平缓。后续所有全局状态都应通过创建的store来管理。, tags: [react, state-management, zustand, decision], importance: 0.9 } }后续会话智能回忆几天后你在同一个项目中处理一个复杂的组件忘记了状态该如何共享。你“这个组件的状态需要被多个地方访问该怎么处理”AI助手自动触发它意识到这是一个关于状态管理的问题会先调用memory.search查询相关记忆。AI助手调用工具{ tool: memory.search, arguments: { query: 如何管理需要跨组件共享的全局状态, topK: 3, workspaceKey: my-react-app } }服务器返回之前存储的关于Zustand的记忆因为语义高度相关会被检索出来。AI助手综合回答“根据项目之前的架构决策已从记忆库中检索我们统一使用Zustand来管理全局状态。我建议你在这里创建一个新的store...结合当前代码上下文给出具体建议”更新与修正后来团队决定升级到Zustand的新版本API有变动。你可以让AI助手memory.supersede旧的那条记忆并memory.save一条新的、描述最新实践的记忆。这样旧记忆被归档新记忆生效知识库得以更新。这个工作流的核心在于AI助手从被动的、失忆的问答机器变成了一个能主动查阅“项目笔记”、拥有持续上下文的学习型伙伴。5. 高级使用技巧、问题排查与性能优化5.1 提升记忆质量存储与检索的最佳实践记忆系统的效果很大程度上取决于你如何“喂养”它。以下是一些提升记忆检索准确性的实战技巧1. 精心构思summary和tagssummary应像一条清晰的推特用一句话概括核心。避免“关于XX的讨论”而是“决定使用Y方法解决X问题因为Z”。tags是重要的检索过滤器。使用具体、一致的标签如[“auth”, “bug”, “api-design”, “performance”]。可以建立一个小型的标签规范。2. 分拆记忆而非长篇大论一条记忆存储一个独立的概念或决策。不要将一整个会议纪要存为一条记忆。而是将其拆分为多条例如记忆1:summary: “选用PostgreSQL而非MySQL” tags: [“database”, “decision”]记忆2:summary: “用户表增加avatar_url字段” tags: [“schema”, “user”, “migration”]这样检索时粒度更细准确率更高。3. 利用type字段进行分类项目预定义了type字段你可以扩展它来对记忆进行粗粒度分类。例如architecture_decision: 架构决策code_convention: 代码规范known_bug: 已知缺陷lesson_learned: 经验教训api_spec: API约定 在搜索时可以指定type来缩小范围。4. 定期维护清理与更新每隔一段时间可以搜索importance较低的记忆或者用memory.search查询一些通用词如“TODO”、“maybe”看看是否有模糊、无效的记忆需要删除或通过supersede更新。5.2 常见问题排查指南即使按照步骤操作也可能会遇到问题。下面是一个快速排查清单现象可能原因解决方案服务器启动失败提示Cannot find module依赖未安装或Bun缓存问题。1. 在项目根目录运行bun install。2. 清理Bun缓存bun pm cache rm然后重装依赖。memory.search返回空数组但确定已存储记忆1.WORKSPACE_KEY不匹配。2. Ollama嵌入服务异常。3. 向量维度不匹配。1. 检查存储和搜索时使用的workspaceKey是否一致。2. 运行curl http://localhost:11434/api/embed -d {model:embeddinggemma, prompt:test}看Ollama是否正常响应。3.重点检查确认EMBEDDING_DIM环境变量是否与embeddinggemma模型维度768一致。测试bun run test时embed.test.ts失败Ollama服务未运行或网络不通。1. 终端运行ollama serve确保服务在后台运行。2. 检查OLLAMA_BASE_URL环境变量是否正确默认http://localhost:11434。3. 检查防火墙或代理设置是否阻止了本地连接。VS Code/Claude Code中无法调用记忆工具MCP服务器未成功连接或配置错误。1. 在终端手动运行bun run start看服务器是否能独立启动。2. 检查IDE的MCP配置.vscode/mcp.json或.mcp.json特别是命令和绝对路径是否正确。3. 查看IDE的日志输出如VS Code的“MCP”输出面板常有详细错误信息。存储或检索速度很慢1. 首次运行需初始化Zvec文件。2. Ollama生成嵌入向量是主要耗时操作。1. 首次慢是正常的。2. 确保Ollama使用的是GPU如果可用可大幅提升嵌入速度。检查Ollama日志确认。3. 对于批量操作可以考虑异步处理或缓存常用查询。5.3 性能考量与扩展方向性能瓶颈分析当前架构下主要性能开销在两点嵌入向量生成每次memory.save和memory.search都需要调用Ollama的嵌入接口存在网络延迟和模型计算时间。这是最大的延迟来源。向量检索Zvec作为内存数据库检索速度很快但当记忆条数超过10万级时纯内存搜索可能成为瓶颈。优化建议嵌入缓存对于完全相同的文本可以实现在内存或磁盘中的简单缓存避免重复调用Ollama。可以在src/embed.ts中增加一个基于文本哈希的缓存层。批量操作如果需要导入大量历史记忆如文档可以编写脚本批量读取、生成嵌入向量后一次性存入数据库避免频繁的请求-响应循环。异步处理对于memory.save操作可以考虑改为“快速存储文本元数据后台异步生成向量并更新”的模式让用户操作得到即时响应。数据库升级如果数据量极大可以考虑将Zvec替换为支持持久化索引、性能更高的嵌入式向量库如hnswlib-node但会引入C依赖增加部署复杂度。扩展可能性这个项目是一个强大的基础你可以基于它进行扩展自动记忆捕获编写IDE插件或Git钩子在代码注释中出现// MEMORY:或提交信息中有特定标签时自动提取文本并调用memory.save。记忆关联与图谱不仅存储孤立记忆还可以存储记忆之间的关系例如记忆A“推翻”了记忆B记忆C“引用”了记忆D构建知识图谱。多模态记忆扩展支持存储图片、音频的嵌入向量需要多模态嵌入模型让AI能记住“那个蓝色按钮的截图”或“错误告警音”。记忆快照与分享将某个WORKSPACE_KEY下的所有记忆导出为文件方便在不同机器间同步或与团队成员分享项目上下文。构建一个属于AI助手的本地记忆系统本质上是在构建一个外挂的、可进化的工作大脑。它不会取代你的思考而是将你从重复的背景交代中解放出来让你与AI的对话能站在更高的起点上持续深入。从配置环境到集成使用整个过程就像为你的数字工作台安装了一个强大的新工具。