个人MCP助手
这个项目是一个包含许多辅助工具(邮件、日历、PDF阅读、网页搜索、披萨订购和开放式问答)的FastAPI服务器。每个请求首先会经过一个隐私过滤器,该过滤器决定请求是留在您的机器上还是可以发送到OpenAI(仅当设置了API密钥且文本看起来安全时,才会使用OpenAI)。
高级流程
- 环境设置从(某处)读取
.env(由...加载python-dotenv或者通过你的shell(命令行界面)。 mcp_server.py启动FastAPI,构建一个共享(实例/服务)LocalModel,并将其分发给每个连接器。- 每个HTTP端点要么调用正确的连接器,要么询问
LocalModel帮忙。 LocalModel使用简单模式检查文本。私有文本保持本地并发送至LLaMA。如果存在API密钥,公共文本可以发送至OpenAI。- 在发送任何数据之前,会对结果进行清理,以隐藏敏感数据。
组件
local_model.py— 处理所有大型语言模型(LLM)调用。它可以与Ollama、llama.cpp、transformers或OpenAI进行交互。它还能识别私有数据,将其隐藏,并将自然文本转化为操作。mcp_server.py— 一个FastAPI应用程序,声明每个端点并插入连接器。connectors/— 实际技能:
- emailer.py 发送Gmail邮件。 - scheduler.py 创建Google日历事件。 - pdf_processor.py 使用PyPDF2读取PDF文件并隐藏私有文本。 - web_searcher.py 尝试使用Google自定义搜索、Serper.dev、Google网页抓取,然后是DuckDuckGo。 - pizza_orderer.py 通过与Domino's(达美乐披萨)的交流 pizzapi.
frontend/— 使用FastAPI提供的简单网页用户界面,用于快速测试。scripts/assistant_cli.py— 一个命令行辅助工具,用于发布到/assistant/command.test_endpoints.py和test_dependencies.py— 基本脚本,用于测试API并检查导入内容。
详细的数据流
整体生命周期(适用于CLI、前端或任何HTTP客户端)
- 用户输入请求(例如,“明天下午4点与Alex预约会议”)。
- 客户端向FastAPI服务器发送请求。命令行界面(CLI)和前端使用
/assistant/command; curl 可以调用任何端点。 mcp_server.py接收JSON。一个共享的LocalModel并且所有连接器均已装载完毕。- 服务器选择合适的处理程序。
/assistant/command使用下面更长的流程。像这样的简单路线:/email或者/search在快速进行隐私检查后,给他们联系人打电话。 - 每个处理器返回一个Python字典。
sanitize_data在响应离开服务器之前,隐藏或移除任何私人细节。 - FastAPI 将清理后的 JSON 返回给调用者。
/assistant/command 一步一步地
- 提示已发送至
LocalModel.interpret_instruction。 - 正则表达式用于查找私密标记,如密码、令牌、电子邮件、卡片信息和出生日期。
- 如果出现私有标记,提示信息将直接发送到本地的LLaMA运行程序。如果没有出现私有标记,则明显的标识符将被占位符替换(例如
[EMAIL_0]并再次检查。 - 安全提示来自OpenAI(当
OPENAI_API_KEY(已设置)。私有提示保留在本地模型中。两个模型都必须返回描述所请求工作的有效JSON。 - JSON被展平成一个列表
{action, payload}条目加上任何澄清问题。 - 每个动作依次执行:
- Emailer.send for send_email - Scheduler.schedule_meeting for schedule_meeting - WebSearcher.search for search_web - PDFProcessor.process 结合;与……一起 LocalModel.answer_from_documents for pdf_question - PizzaOrderer.place_order for order_pizza - LocalModel.complete 或者 answer_from_documents for answer_question
- 连接器可以呼叫
LocalModel再次说明,如果他们需要在保持数据本地化的同时(例如,PDF问答形式)获得另一个答案。 - 缺少的细节(如未填写收件人、未指定开始时间等)会导致需要澄清的问题,而非错误。
- 结果和澄清贯穿始终
sanitize_data该功能隐藏电子邮件、支付信息、PDF文本及类似字段。 - 最终清理后的JSON被返回给调用者。
直接任务端点
/ask使用LocalModel.complete对于简单的问题和转换到answer_from_documents当提供上下文时。/email并且/email/send打电话Emailer.send编辑完消息正文后。/meeting并且/meeting/schedule将时间转换为datetime对象,验证范围,并将请求转发至Scheduler.schedule_meeting。/pdf接受一个Base64字符串,对其进行解码,并提取文本PDFProcessor,编辑文本,并返回安全版本。/pdf/query从磁盘读取文件,提取文本,询问LocalModel.answer_from_documents并编辑回复。/assistant/pdf_question上传PDF文件,提取文本,并运行相同的问答辅助工具。/web/search并且/search对查询进行隐私检查,然后调用WebSearcher它依次尝试使用Google自定义搜索、Serper.dev、网页抓取和DuckDuckGo。/pizza并且/pizza/order在本地验证Domino's订单数据,清理特殊说明,并在启用实时模式时提交订单。/health回报;收益{"status": "ok"}不接触大型语言模型(LLM)。
本地计算与OpenAI计算
LocalModel 查找以下环境变量以初始化本地模型:
LLAMA2_PROVIDER—ollama,llama_cpp或者transformers。LLAMA2_MODEL— Ollama的模型名称。LLAMA2_MODEL_PATH,LLAMA_CPP_MODEL_PATH或者TRANSFORMERS_MODEL_PATH— 本地模型权重的路径。LLAMA_CPP_CTX— 可选的上下文窗口大小用于llama.cpp。
如果提示或文档看起来包含私密信息(如密码、令牌、社会保险号、卡号等), LocalModel 始终使用本地后端,从不将其发送给OpenAI。公开文本在以下情况下可以发送给OpenAI: OPENAI_API_KEY 已设置。可选的OpenAI设置:
OPENAI_API_KEYOPENAI_PROJECTOPENAI_ORG或者OPENAI_ORGANIZATIONOPENAI_MODEL(默认为gpt-3.5-turbo)
连接器凭据
存储秘密于 .env (从不提交生产环境的值)
- Gmail和Google日历:
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REFRESH_TOKEN,可选地GOOGLE_CALENDAR_SCOPES. - Google自定义搜索:
SEARCH_API_KEY,SEARCH_CX。 - Serper.dev:
SERPER_API_KEY。 - 点披萨:
PIZZA_LIVE_MODE,PIZZA_CARD_NUMBER,PIZZA_CARD_EXPIRATION,PIZZA_CARD_CVV,PIZZA_BILLING_POSTAL_CODE。
get_google_refresh_token.py 启动本地OAuth流程以刷新Google令牌。所有脚本均期望 python-dotenv 以便 .env 文件自动读取。
运行服务器
pip install -r requirements.txt
uvicorn mcp_server:app --reload当服务器启动时,它会读取 .env构建每个连接器,并在以下位置公开API http://localhost:8000静态前端托管于 / 如果 frontend/ 文件夹存在。
在本地使用Ollama
- 安装Ollama并下载你想要的模型(例如
ollama run llama2)。 - (可选但建议)在您的虚拟环境中安装Python客户端:
pip install ollama。 - 放置
LLAMA2_PROVIDER=ollama,LLAMA2_MODEL=llama2,和OLLAMA_HOST翻译成中文是:进入你的.env。 - 启动 Ollama 守护进程
ollama serve在运行 FastAPI 之前,如果 FastAPI 是在 Docker 或 WSL 中运行的,请将 Ollama 绑定到容器可以访问的地址,并指向该地址OLLAMA_HOST到那个地址。 - 如果守护进程已停止,您将在API回复和前端横幅中看到“无法初始化本地LLaMA2运行时…”。
- 打电话
POST /admin/local_model/initialize预热模型并确认其已准备好。
使用命令行界面(CLI)
python scripts/assistant_cli.py "schedule a meeting with alice@example.com tomorrow at 3pm"旗帜:
--search称呼为/search终端点。--pdf-question带有一个或多个--pdf文件要击中(或处理)/assistant/pdf_question.--pretty对JSON响应进行格式化打印。
测试与诊断
python test_dependencies.py导入所有所需的包,并打印出检测到的版本。python test_endpoints.py假设FastAPI服务器在本地运行,并对主要的端点进行测试。除非(特定条件满足),否则跳过披萨测试PIZZA_LIVE_MODE是真的。python -m compileall .这是一种快速确认所有模块都能编译的方法。
实施说明
- PDF提取功能现已防范返回的页面
None来自extract_text()。 - 在从端点和连接器返回之前,敏感字符串会始终被屏蔽处理。
- 该代码库避免使用内联注释,而是采用清晰的函数和变量名称,因此代码本身即可保持可读性,无需额外注释。
- 如果前端显示“本地模型状态:离线 — 未找到Ollama Python客户端…”,请安装
ollamaPython包(或确保OLLAMA_HOST(可以访问)并重启服务器。
