基于MCP协议与向量数据库构建AI编程助手私有记忆系统
1. 项目概述:为你的AI编程助手打造一个“记忆宫殿”
如果你和我一样,重度依赖Cursor这类AI编程助手,那你肯定遇到过这个痛点:昨天刚和它深入讨论过一个复杂的业务逻辑实现,今天想参考一下,却发现在浩如烟海的聊天记录里翻找,比大海捞针还难。Cursor的聊天记录是线性的、扁平的,缺乏有效的组织和检索能力。我们和AI助手共同创造的“对话资产”,就这么白白浪费了。
这正是我动手开发Cursor History MCP的初衷。简单来说,它就是一个为你和Cursor(或其他兼容MCP协议的AI助手)的对话历史,构建的一个私有化、智能化的“记忆宫殿”。它不是一个简单的聊天记录导出工具,而是一个完整的自托管API服务,核心能力是基于语义的向量化搜索。你可以把它理解为你个人知识库的“私有化Google”,只不过索引的内容是你和AI助手的所有技术讨论、代码片段和解决方案。
这个项目的核心价值在于“Agentic Workflow”(智能体工作流)。它让AI助手从一个“健忘的临时工”,变成了一个“有持续记忆和上下文关联能力的资深搭档”。通过这个MCP服务器,你的AI助手可以主动查询过去的对话,将历史经验融入当下的问题解决中,实现真正连贯、积累式的协作。无论是回顾一周前讨论的架构设计,还是查找半年前解决过的某个特定错误,都变得轻而易举。
2. 核心架构与工具选型解析
为什么选择这样一套技术栈?这背后是经过深思熟虑的权衡,目标是在本地化、性能、易用性和功能强大之间找到最佳平衡点。
2.1 为什么是MCP服务器?
MCP(Model Context Protocol)可以看作是AI助手世界的“USB标准”。它定义了一套标准协议,允许像Cursor、Claude Desktop这样的AI客户端,安全、标准化地连接和使用外部工具、数据源和服务。将我们的历史搜索功能封装成MCP服务器,意味着:
- 无缝集成:Cursor等客户端可以原生发现并调用这个服务,用户无需复杂的配置。
- 标准化访问:提供了统一的、结构化的接口(工具列表、调用方式),AI助手知道如何与之交互。
- 上下文安全:MCP协议设计上注重安全,服务运行在用户指定的环境(通常是本地),数据不会泄露到第三方。
这比让AI去模拟点击、解析网页来“回忆”历史要可靠和高效得多。我们不是在改造客户端,而是在为它扩展一个标准化的“记忆”外设。
2.2 向量数据库:LanceDB的胜出理由
实现语义搜索,核心是将文本转换为向量(嵌入),并高效地进行相似度匹配。这就需要一个向量数据库。我选择了LanceDB,而不是更知名的Pinecone(云服务)或Chroma(本地)。
- 性能与本地优先:LanceDB是用Rust编写的,其列式存储格式(Lance)为机器学习工作负载做了极致优化,查询速度极快。它完美支持本地运行,数据文件就是普通的目录,备份、迁移异常简单。
- 零管理开销:与需要单独服务进程的Chroma不同,LanceDB可以作为一个Python库直接嵌入到你的应用中,无需启动和维护另一个数据库服务,极大简化了部署。
- 出色的开发者体验:其API设计非常Pythonic,几行代码就能完成建表、插入向量和搜索的全过程,降低了开发门槛。
对于这个自托管、追求轻量和高性能的项目,LanceDB几乎是无可争议的选择。它把复杂度留给了库作者,把简洁和速度留给了我们开发者。
2.3 嵌入模型与LLM:拥抱本地化的Ollama
项目的另一个关键决策是全面拥抱Ollama。Ollama使得在本地运行各种大型语言模型变得像ollama run llama3一样简单。
- 嵌入模型:我们使用Ollama来运行
nomic-embed-text这类轻量级嵌入模型。所有文本向量化的过程都在你的本地机器上完成,对话内容无需上传至任何第三方API(如OpenAI),彻底保障了隐私和安全。 - 检索增强生成:这是项目的进阶玩法。当搜索到相关的历史对话后,我们可以将这段历史作为上下文,连同当前问题,再次提交给Ollama中运行的LLM(如Llama 3、Mistral),让它进行总结、关联或续写,实现真正的“温故知新”。
这种架构意味着,从数据存储、处理到智能生成,整个流水线都可以在断网环境下运行,完全自主可控。
2.4 API框架:FastAPI为何是必然
作为连接MCP协议、业务逻辑和前端(如果需要)的桥梁,API框架需要快、现代且易于开发。FastAPI是不二之选:
- 异步优先:原生支持
async/await,非常适合处理IO密集型的AI模型调用和数据库查询,能轻松支撑高并发请求。 - 自动API文档:基于OpenAPI标准,自动生成交互式API文档(就是我们常看到的
/docs页面),前后端协作和调试效率倍增。 - 数据验证:使用Pydantic进行请求/响应数据的声明式验证,代码简洁且安全。
基于这些考量,最终的架构图(概念上)非常清晰:Cursor客户端通过MCP协议调用我们本地运行的FastAPI服务;该服务利用Ollama生成嵌入向量,存储并查询LanceDB向量数据库,最后将结构化的历史记录返回给Cursor,呈现在用户面前。
3. 从零开始:详细部署与配置指南
理论讲完,我们进入实战环节。假设你在一台全新的Linux或macOS开发机上,如何一步步让这个“记忆宫殿”运转起来?以下是经过实测的完整流程。
3.1 基础环境准备
首先,确保你的系统已经安装了必要的基石软件。
安装Docker与Docker Compose:这是简化部署的关键。通过包管理器安装即可。
# Ubuntu/Debian sudo apt-get update && sudo apt-get install docker.io docker-compose # macOS (使用Homebrew) brew install docker docker-compose安装后,记得将你的用户加入
docker组,避免每次都用sudo:sudo usermod -aG docker $USER,然后退出终端重新登录生效。安装Ollama:这是我们的AI引擎。
# 一行命令安装 curl -fsSL https://ollama.com/install.sh | sh # 启动Ollama服务 ollama serve & # 拉取我们需要的嵌入模型和一个小型LLM(以nomic-embed-text和llama3:8b为例) ollama pull nomic-embed-text ollama pull llama3:8b注意:
nomic-embed-text模型约300MB,llama3:8b约4.7GB,请确保你的磁盘空间和网络环境。如果只是先测试搜索功能,可以只拉取嵌入模型。
3.2 获取与配置Cursor History MCP
项目代码托管在GitHub,我们通过Git来获取。
# 克隆仓库 git clone https://github.com/Nossim/Cursor-history-MCP.git cd Cursor-history-MCP接下来是关键一步:配置Cursor的聊天历史路径。服务需要知道去哪里读取你的原始聊天数据。
找到你的Cursor历史文件:
- macOS:
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb - Windows:
%APPDATA%\Cursor\User\globalStorage\state.vscdb - Linux:
~/.config/Cursor/User/globalStorage/state.vscdb这个SQLite数据库文件包含了Cursor的所有状态信息,其中就有聊天记录。
- macOS:
配置服务:在项目根目录,你应该会找到一个示例环境文件,如
.env.example。复制它并创建你自己的.env文件。cp .env.example .env编辑
.env文件,设置正确的路径:# 将以下路径替换为你实际的 state.vscdb 路径 CURSOR_STATE_DB_PATH=/Users/你的用户名/Library/Application Support/Cursor/User/globalStorage/state.vscdb # LanceDB数据库存储目录,默认在项目内即可 LANCEDB_DATA_PATH=./lancedb_data # Ollama服务地址,默认本地 OLLAMA_BASE_URL=http://host.docker.internal:11434 # Docker容器内访问宿主机的地址 # 使用的嵌入模型名称 EMBEDDING_MODEL=nomic-embed-text重要提示(Docker网络):在Docker容器内,要访问宿主机的服务(Ollama),不能使用
localhost,而需要使用特殊的域名host.docker.internal(macOS/Windows)或宿主机的IP(Linux)。上述配置适用于macOS/Windows。Linux环境下可能需要配置为http://172.17.0.1:11434(宿主机在Docker网桥的IP)并确保宿主机防火墙放行端口。
3.3 使用Docker Compose一键启动
这是最推荐的部署方式,它通过一个docker-compose.yml文件定义了服务、网络和卷,管理起来非常方便。
检查并启动:确保在项目根目录,然后运行:
# 构建并启动所有服务(在后台运行) docker-compose up -d这条命令会做以下几件事:
- 构建一个包含Python、FastAPI和项目代码的Docker镜像。
- 创建一个持久化卷,用于存储LanceDB的数据文件,这样即使容器重启,你的向量索引也不会丢失。
- 将容器的8000端口映射到宿主机的8000端口。
- 以守护进程模式运行。
查看日志与状态:
# 查看所有服务的实时日志 docker-compose logs -f # 查看服务状态 docker-compose ps如果一切顺利,你应该能在日志中看到FastAPI服务在
http://0.0.0.0:8000启动成功的消息。验证API服务:打开你的浏览器,访问
http://localhost:8000/docs。你应该能看到自动生成的、漂亮的FastAPI交互式文档页面。这里列出了所有可用的API端点,如/search和/history,并且可以直接在页面上进行测试调用。
3.4 首次运行:数据初始化与向量化
服务启动后,数据库还是空的。我们需要触发它读取Cursor的原始历史并创建向量索引。
触发初始化:通过调用一个初始化端点(通常设计为
/initialize或首次搜索时自动触发)来加载数据。你可以在API文档页面找到对应端点,或者直接使用curl命令:curl -X POST "http://localhost:8000/initialize" -H "Content-Type: application/json"理解初始化过程:这个过程在后台会:
- 连接到你配置的
CURSOR_STATE_DB_PATH,解析SQLite数据库。 - 提取出所有的聊天会话和消息。
- 为每一条消息调用Ollama的嵌入模型API,将其文本内容转换为一个768维(以nomic-embed-text为例)的向量。
- 将这些向量连同原始文本、时间戳、会话ID等信息,批量写入LanceDB表中。
- 这个过程耗时取决于你的聊天记录数量。几千条消息可能需要几分钟。你可以在服务日志中看到进度。
- 连接到你配置的
进行首次搜索测试:初始化完成后,尝试搜索一下。
curl -X POST "http://localhost:8000/search" -H "Content-Type: application/json" -d '{"query": "如何用Python连接MySQL数据库", "limit": 5}'如果返回了与你历史对话相关的JSON结果,那么恭喜你,核心服务已经部署成功!
4. 深度集成:在Cursor中配置MCP服务器
让服务跑起来只是第一步,接下来要让Cursor AI助手能够“看见”并使用它。这需要通过Cursor的MCP配置来实现。
4.1 配置Cursor以连接本地MCP服务器
Cursor的MCP配置通常位于用户配置目录下的一个JSON文件中。你需要手动创建或编辑这个文件。
定位配置文件:
- macOS:
~/Library/Application Support/Cursor/User/globalStorage/mcp.json - Windows:
%APPDATA%\Cursor\User\globalStorage\mcp.json - Linux:
~/.config/Cursor/User/globalStorage/mcp.json如果文件或目录不存在,就创建它。
- macOS:
编辑mcp.json:用文本编辑器打开(或创建)这个文件,添加以下配置:
{ "mcpServers": { "cursor-history": { "command": "docker", "args": [ "run", "--rm", "-i", "--network=host", "cursor-history-mcp:latest" ], "env": { "OLLAMA_HOST": "http://localhost:11434" } } } }配置解析:
"command": "docker":告诉Cursor使用Docker命令来启动这个MCP服务器。"args":这是传递给docker run的参数。--rm:容器退出后自动清理,避免积累停止的容器。-i:保持标准输入打开,这是MCP协议通信所必需的。--network=host:让容器使用宿主机的网络栈。这是最关键的一步,它使得容器内的服务可以直接通过localhost:8000访问我们之前启动的FastAPI服务,也方便容器内访问宿主机的Ollama(如果Ollama在宿主机运行)。这比复杂的端口映射更简单直接。
"env":为容器设置环境变量,这里指明了Ollama的地址。
重要提示:这种
--network=host模式在Linux上工作完美,在macOS和Windows的Docker Desktop上也可用,但有时可能需要额外权限。如果遇到问题,可以回退到显式的端口映射模式,但需要确保容器内能正确解析宿主机地址。
4.2 在Cursor中验证与使用
保存mcp.json配置文件后,你需要完全重启Cursor。重启后,Cursor会在启动时读取配置,并尝试连接我们定义的MCP服务器。
- 验证连接:打开Cursor,新建一个聊天窗口。在输入框里,你可以尝试输入一些自然语言指令来测试,例如:“搜索一下我之前问过的关于Docker Compose的问题”。如果配置成功,Cursor的AI助手(通常是Claude)会理解你的意图,并在后台调用我们的MCP工具,最终将搜索结果整理后呈现给你。
- 理解交互模式:你不需要记忆具体的命令。就像平时和AI聊天一样,用自然语言表达你想“回忆”或“查找”的内容即可。例如:
- “帮我找找上个月我们讨论过的用户认证方案。”
- “我记得之前解决过一个Redis连接超时错误,把当时的对话找出来看看。”
- “搜索所有包含‘性能优化’关键词的对话。” AI助手会将这些请求翻译成对
/search端点的调用,并将返回的结构化数据组织成易于阅读的格式回复给你。
5. 进阶使用与运维技巧
项目运行起来后,如何维护和发挥其最大效用?这里有一些从实战中总结的经验。
5.1 数据更新与增量同步
Cursor的聊天记录在不断增长,我们的向量数据库也需要更新。有几种策略:
定时任务同步:最可靠的方式是设置一个定时任务(如Cron job),每隔一段时间(例如每小时)运行一次数据同步脚本。这个脚本可以:
- 检查
state.vscdb文件的最后修改时间。 - 只处理上次同步之后新增的聊天消息,为其生成嵌入向量并插入数据库。
- 这需要对项目代码进行小幅改造,增加一个增量同步的端点或脚本。
- 检查
手动触发同步:在API中提供一个
/sync端点,当你觉得需要更新时,手动调用或在Cursor中让AI助手帮你调用。文件监听同步(高级):使用像
watchdog这样的Python库,监听state.vscdb文件的变化事件,实时触发增量处理。这种方式更“实时”,但对系统有一定开销,且需要处理数据库文件被Cursor锁定时写入冲突的问题。
实操建议:对于个人开发,采用“定时任务+手动触发”的组合最为稳妥。可以写一个简单的Python脚本,用crontab每天在空闲时间(如凌晨)运行一次全量/增量同步。
5.2 搜索优化与技巧
默认的语义搜索已经很强,但通过一些技巧可以让你搜得更准。
关键词与语义结合:在查询时,可以尝试在自然语言问题中加入更具体的关键词。例如,与其问“之前的错误”,不如问“之前遇到的
ModuleNotFoundError: No module named 'lance'这个错误是怎么解决的”。后者能为嵌入模型提供更丰富的上下文线索。利用元数据过滤:理想的搜索应该支持按时间范围、会话ID等过滤。你可以修改
/search端点,接受额外的过滤参数,并在LanceDB查询时使用where子句。例如,请求体可以设计为:{ "query": "Python异步编程", "start_date": "2024-01-01", "end_date": "2024-03-31" }这样就能精准定位到今年第一季度的相关讨论。
调整相似度阈值:向量搜索返回的结果会有一个相似度分数(如余弦相似度)。在后台,可以设置一个阈值(例如0.7),低于此分数的结果不返回,以避免无关信息干扰。
5.3 常见问题排查实录
在部署和使用过程中,你可能会遇到以下问题。这里是我的排查笔记:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
访问localhost:8000/docs失败 | Docker容器未启动或端口映射错误 | 1.docker-compose ps查看容器状态。2. docker-compose logs查看错误日志。3. 检查 docker-compose.yml中端口映射是否为"8000:8000"。 |
| Cursor无法连接MCP服务器,提示超时或错误 | 1.mcp.json配置错误。2. Docker网络问题。 3. FastAPI服务未运行。 | 1. 检查mcp.json的语法和路径是否正确。2.重点:在终端直接运行 docker run --rm -it --network=host cursor-history-mcp:latest,看容器能否独立启动并输出日志。3. 在容器内尝试 curl http://localhost:8000/health测试API是否可达。4. 尝试将 --network=host改为显式映射-p 8001:8000,并将配置中的连接地址改为http://host.docker.internal:8001。 |
| 搜索返回空结果或错误 | 1. 数据未初始化。 2. Ollama嵌入模型未加载或调用失败。 3. LanceDB表不存在。 | 1. 调用/initialize端点,并观察日志。2. 检查Ollama服务是否运行: curl http://localhost:11434/api/tags。3. 检查模型是否已拉取: ollama list。4. 进入项目数据目录,检查 lancedb_data文件夹下是否有.lance后缀的数据文件。 |
| 初始化或搜索速度极慢 | 1. 首次初始化数据量大。 2. 机器性能不足(特别是CPU)。 3. Ollama模型加载到内存慢。 | 1. 首次初始化耐心等待,可在日志中观察进度。 2. 考虑使用更轻量的嵌入模型,如 all-minilm。3. 确保Ollama有足够的内存。对于大量历史记录,分批处理(如每次处理100条)比单条处理更高效。 |
| Docker构建失败,提示Python包缺失 | requirements.txt文件不全或网络问题。 | 1. 检查项目根目录的requirements.txt是否包含fastapi,lancedb,httpx,sqlite3等核心依赖。2. 尝试在Dockerfile中使用国内PyPI镜像源加速下载。 |
5.4 安全与备份建议
这是一个自托管服务,数据安全完全由你负责。
- 数据备份:核心数据是
lancedb_data目录下的文件。定期将这个目录压缩备份到其他位置(如云存储)。由于LanceDB是文件形式,备份非常简单。 - 网络隔离:虽然服务运行在本地(
localhost),但如果你在局域网内开放了端口,需注意防火墙设置。切勿将-p 8000:8000映射到0.0.0.0并暴露在公网,除非你完全理解其风险并添加了认证(如API Key)。本项目默认不包含认证层,适用于纯粹的本地环境。 - 环境变量管理:不要将包含路径或潜在敏感信息的
.env文件提交到Git。确保它在.gitignore列表中。
6. 扩展思路:超越简单的历史搜索
当基础功能稳定后,这个平台可以扩展出更多强大的应用场景,真正赋能你的AI工作流。
实现真正的RAG工作流:目前的搜索是“检索”,我们可以增加“生成”。添加一个新的MCP工具,例如叫
search_and_summarize。当用户提问时,这个工具会先进行向量搜索,找到最相关的K条历史对话,然后将这些历史作为“参考文档”,连同用户的新问题,一起发送给Ollama中的LLM,要求它“基于我们过去的讨论,回答当前问题”。这就实现了完整的本地化RAG。知识图谱与主题聚类:定期对所有聊天历史进行主题聚类分析(可以使用Ollama的LLM进行摘要和分类),自动生成标签。你不仅可以搜索,还可以浏览按“前端优化”、“后端架构”、“数据库设计”、“Bug排查”等主题归类好的历史对话集,形成结构化的个人知识库。
多客户端支持:MCP是开放协议。除了Cursor,理论上任何支持MCP的AI桌面应用(如Claude Desktop)都可以通过类似的配置连接到你这个历史服务,实现跨AI助手的统一记忆。
集成其他数据源:这个框架的潜力不止于Cursor。你可以编写新的数据加载器,将你的代码库文档、笔记(如Obsidian、Logseq)、甚至邮件和会议纪要向量化,并接入同一个服务。最终,你拥有的是一个私有的、覆盖所有数字工作记忆的通用语义搜索中心。
这个项目的魅力在于,它从一个具体的痛点(找不到聊天记录)出发,搭建了一个具有通用价值的本地AI基础设施。它把控制权和数据所有权完全交还给你,同时通过开源和模块化设计,留下了巨大的扩展空间。我自己的使用体验是,自从部署了它,我和Cursor的对话不再是“一次性快消品”,而变成了可沉淀、可复用的宝贵资产,工作效率和连续性提升了一个维度。如果你也厌倦了在AI对话中重复造轮子,不妨亲手搭建这个属于你自己的“记忆宫殿”,开启一段更高效的AI协作之旅。
