基于 MCP 连接 Omi 数据:DSPy、OpenAI Agents SDK 与 LangChain 实战示例解析
【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend
本篇技术指南聚焦 Friend 仓库中 mcp/examples 目录下的官方示例应用,讲解如何通过 Model Context Protocol(MCP)以自然语言方式访问、检索与操作 Omi 智能眼镜采集到的 Memories(记忆)与 Conversations(对话)数据。你将掌握环境搭建、三种主流 Agent 框架(DSPy、OpenAI Agents SDK、LangChain)的接入写法,以及基于 Streamlit 的交互式聊天界面的运行方式,并深入了解底层mcp-server-omi服务器暴露的 8 个 MCP 工具及其后端实现原理。
背景:为什么用 MCP 连接 Omi 数据
Omi 是"看得见屏幕、听得见对话、告诉你该做什么"的 AI 设备,其核心资产是持续沉淀的个人记忆(Memories)和会话记录(Conversations)。要让任意 LLM Agent 以统一、标准化的方式消费这些数据,Friend 仓库采用了 MCP(Model Context Protocol)作为连接协议,并在 mcp 目录下提供了完整的服务端与示例客户端:
- 服务端:mcp/src/mcp_server_omi/server.py 实现了一个本地 stdio 模式的 MCP 服务器,将 Omi 后端能力封装为一个个可被 LLM 直接调用的工具(Tool);
- 客户端示例:mcp/examples 提供了三个框架示例与一个 Streamlit 交互应用,演示不同 Agent 编排方式下如何挂载这些 MCP 工具。
从 mcp/maintain.README.md 可以确认,这些 MCP 工具并非独立实现,而是"直接包装 backend/routers/mcp.py 路由"——即与 App 端、Web 端共用同一套后端数据接口,保证了数据访问语义的一致性。
前置条件与环境准备
示例 README 明确了运行示例所需的四项前置条件,结合仓库实际情况整理如下:
| 前置条件 | 说明 | 获取方式 |
|---|---|---|
| Python 3.8+ | 所有示例脚本均为 Python | 官方 Python 安装包或系统包管理器 |
uvx命令行工具 | MCP 服务器通过uvx mcp-server-omi方式拉起,无需预先 pip 安装服务端 | pip install uvx(或安装 uv 工具链后自带uvx) |
| OpenAI API Key | 示例默认使用 OpenAI 的o4-mini/o3等推理模型作为 Agent 的 LLM 后端 | OpenAI 开发者平台 |
| Omi UID | 用户在 Omi 体系中的唯一标识,用于定位其 Memories 与 Conversations 数据 | Omi 应用内获取 |
需要特别强调的是uvx的地位:所有示例都以uvx mcp-server-omi作为 MCP 服务器的启动方式,uvx会在运行时自动从 PyPI 下载并执行已发布的mcp-server-omi包(当前仓库版本为0.1.9,见 mcp/src/mcp_server_omi/about.py),因此客户端侧无需手动安装该包。
安装依赖
按原文档步骤执行:
python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate pip install -r requirements.txtrequirements.txt 是一份经过uv pip compile解析的完整锁定清单,核心依赖包括:
- MCP 协议层:
mcp==1.28.1、openai-agents==0.17.3; - 三个框架示例:
dspy==3.2.1、langchain-mcp-adapters==0.2.2、langchain-openai==1.2.1、langgraph==1.2.0、langgraph-prebuilt==1.1.0; - 交互应用:
streamlit==1.57.0; - 环境配置与底层:
python-dotenv、openai==2.37.0、httpx、pydantic==2.13.4等。
配置环境变量
在项目根目录创建.env文件,写入两项核心变量:
OPENAI_API_KEY=your_openai_api_key OMI_UID=your_omi_uid各示例脚本顶部均调用load_dotenv()(例如 dspy_ex.py、openai_agents_sdk_ex.py),启动时会自动加载该文件。
值得注意的是,原文档中的.env只覆盖了 LLM 调用与 UID 定位。若要让 MCP 服务器实际访问数据,还需要通过OMI_API_KEY提供 MCP 专用 API 密钥(见下文"API 密钥机制"一节),该变量同样可写入.env或通过环境变量注入。另外,server.py 读取OMI_API_BASE_URL作为后端地址,自托管后端时可用它覆盖默认的https://api.omi.me/v1/mcp/。
三个框架示例:同一条 MCP 数据管道,三种 Agent 编排
原文档给出了三个示例脚本的启动命令,其核心价值在于展示"同一份 Omi 数据、同一套 MCP 工具,在不同 Agent 框架中的接入姿势"。三个示例运行的是同一个演示任务——"查看我的 Memories,了解我是什么样的人,然后检索最近 5 次对话并总结":
python dspy_ex.py python openai_agents_sdk_ex.py python langchain_ex.pyDSPy 示例:以 Signature 声明式定义 Agent 任务
dspy_ex.py 展示了 DSPy 风格的接入方式,其特点是用Signature(签名)声明输入输出,用ReAct编排工具调用:
- 建立 MCP 会话:通过
mcp.ClientSession与stdio_client建立 stdio 连接,StdioServerParameters(command="uvx", args=["mcp-server-omi"])指定服务器启动方式; - 初始化并列出工具:
await session.initialize()完成 MCP 握手,await session.list_tools()获取服务器声明的工具清单; - 工具转换:用
dspy.Tool.from_mcp_tool(session, tool)把 MCP 工具逐一包装为 DSPy 可调用的工具对象; - 构建 Agent:定义
DSPyOmiAgent签名(输入user_request、user_uid,输出response),以dspy.ReAct(DSPyOmiAgent, tools=dspy_tools)构建 ReAct Agent; - 配置语言模型:
dspy.configure(lm=dspy.LM("openai/o4-mini", temperature=1, max_tokens=24000)),采用 OpenAI o4-mini 推理模型,max_tokens=24000为长文本总结预留充足输出空间。
server_params = StdioServerParameters(command="uvx", args=["mcp-server-omi"], env=None) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() dspy_tools = [dspy.Tool.from_mcp_tool(session, tool) for tool in tools.tools] react = dspy.ReAct(DSPyOmiAgent, tools=dspy_tools) result = await react.acall(user_request=user_request, user_uid=os.getenv("OMI_UID")) print(result.response)该示例演示了 DSPy 的核心思想:无需手写复杂的 prompt 与工具调用循环,任务语义由 Signature 声明,工具选择与调用顺序由 ReAct 自动推理完成。
OpenAI Agents SDK 示例:MCP Server 作为一等公民挂载
openai_agents_sdk_ex.py 展示了 OpenAI Agents SDK 的接入方式,这也是Streamlit 应用底层使用的同一套 API:
- 创建 MCP 服务器句柄:
MCPServerStdio(cache_tools_list=False, params={"command": "uvx", "args": ["mcp-server-omi"]}),cache_tools_list=False意味着每次会话都重新拉取工具列表,避免工具更新后缓存不刷新; - 挂载到 Agent:
Agent(name="Omi Agent", instructions=f"...user UID is {uid}", mcp_servers=[mcp_server], model="o4-mini"),MCP 服务器通过mcp_servers参数直接注入,工具无需手动枚举; - 启用推理:
ModelSettings(reasoning=Reasoning(effort="high", generate_summary="auto"))开启高强度的推理模式; - 执行:
Runner.run(starting_agent=agent, input=message)驱动 Agent 完成任务。
async with MCPServerStdio( cache_tools_list=False, params={"command": "uvx", "args": ["mcp-server-omi"]}, ) as server: agent = Agent( name="Omi Agent", instructions=f"You are a helpful assistant that answers questions based on the user's OMI data, the user UID is {uid}.", mcp_servers=[server], model="o4-mini", model_settings=ModelSettings(reasoning=Reasoning(effort="high", generate_summary="auto")), ) result = await Runner.run(starting_agent=agent, input=message) print(result.final_output)脚本启动时会校验uvx是否可用:if not shutil.which("uvx"): raise RuntimeError(...),这是原文档 Troubleshooting 中"uvx 未安装"错误的直接来源。
LangChain / LangGraph 示例:MultiServerMCPClient 桥接
langchain_ex.py 展示了 LangChain 生态(LangGraph + langchain-mcp-adapters)的接入方式:
- 模型初始化:
ChatOpenAI(model="o4-mini-2025-04-16")使用指定版本的 o4-mini; - 多服务器客户端:
MultiServerMCPClient({"omi": {"command": "uvx", "args": ["mcp-server-omi", "-v"], "transport": "stdio"}})以字典形式声明 MCP 服务器(该结构天然支持同时挂载多个 MCP 服务器); - 工具获取:
client.get_tools()将 MCP 工具桥接为 LangChain 工具; - Agent 构建:
create_react_agent(model, client.get_tools())基于 LangGraph Prebuilt 快速构建 ReAct Agent,await agent.ainvoke(...)执行。
async with MultiServerMCPClient( {"omi": {"command": "uvx", "args": ["mcp-server-omi", "-v"], "transport": "stdio"}} ) as client: agent = create_react_agent(model, client.get_tools()) response = await agent.ainvoke({"messages": prompt}) print(response["messages"][-1].content)注意此处命令行参数多了-v(verbose 模式),与 Streamlit 应用及 maintain.README.md 中推荐的调试启动方式一致,便于在 Agent 运行过程中观察 MCP 服务器日志。
三种接入方式的对比
| 维度 | DSPy | OpenAI Agents SDK | LangChain / LangGraph |
|---|---|---|---|
| 任务定义 | Signature 声明 + ReAct 编排 | Agent + instructions + mcp_servers | create_react_agent + 工具列表 |
| MCP 客户端 | mcp.ClientSession+stdio_client | MCPServerStdio(一等公民) | MultiServerMCPClient |
| 工具接入 | dspy.Tool.from_mcp_tool逐个转换 | mcp_servers参数自动注入 | client.get_tools()批量桥接 |
| 代表模型 | openai/o4-mini | o4-mini | o4-mini-2025-04-16 |
| 适用场景 | 希望用声明式 Signatures 约束任务 | 追求 MCP 原生集成与官方 Agent 运行时 | 已深度使用 LangChain/LangGraph 生态 |
Streamlit 交互式聊天应用:零代码接入 Omi 数据
app.py 是示例集的主应用——一个基于 Streamlit 的聊天界面,运行命令:
streamlit run app.py启动后浏览器会自动打开应用。使用前需在侧边栏 Settings中输入 OMI UID,否则界面会提示 "Please enter your OMI UID in the sidebar settings to start chatting" 并停止。
从源码看,该应用有几个值得关注的设计细节:
- 前置校验:启动时通过
shutil.which("uvx")检查uvx是否在 PATH 中,缺失则直接st.error(...)并st.stop(),这与 openai_agents_sdk_ex.py 的校验逻辑互为印证; - 事件循环管理:
run_async_task函数为每个请求新建独立事件循环(asyncio.new_event_loop()),避免 Streamlit 环境中已有事件循环导致的冲突,这是 Streamlit + asyncio 集成的经典实践; - Agent 配置:底层与 OpenAI Agents SDK 示例同构——
MCPServerStdio(cache_tools_list=False, params={"command": "uvx", "args": ["mcp-server-omi", "-v"]}),Agent 使用model="o3"(源码中注释保留了litellm/anthropic/claude-3-7-sonnet-20250219作为可选模型),并配置ModelSettings(reasoning=Reasoning(effort="high")); - 多轮对话:将完整会话历史(含最新用户消息)传给
Runner.run,Agent 基于 Omi 数据连续作答;每次响应的new_items(推理过程与工具调用详情)被记录,可在 "View Reasoning/Tool Calls" 折叠面板中查看; - 追踪能力:
with trace(workflow_name="Stramlit Omi MCP Example"):为整个执行流程打上可观测性标记。
async with MCPServerStdio( cache_tools_list=False, params={"command": "uvx", "args": ["mcp-server-omi", "-v"]}, ) as server: omi_agent = Agent( name="Omi Agent", instructions=f"You are a helpful assistant that answers questions based on my Omi data, my UID is {uid}. ...", mcp_servers=[server], model="o3", model_settings=ModelSettings(reasoning=Reasoning(effort="high")), ) with trace(workflow_name="Stramlit Omi MCP Example"): run_output = await Runner.run(starting_agent=omi_agent, input=agent_input_messages)底层工具集:mcp-server-omi 暴露的 8 个 MCP 工具
三个示例和 Streamlit 应用共享同一个 MCP 服务器。要理解 Agent 能"做什么",需要看服务器实际声明的工具集。根据 server.py 的_get_tools()实现,服务器共暴露8 个工具,覆盖 Memories 与 Conversations 两类数据的读、搜、写操作:
| 工具名 | 类别 | 核心参数(默认值) | 底层接口 |
|---|---|---|---|
get_memories | 记忆 | limit(100)、offset(0)、categories | GET /memories |
search_memories | 记忆 | query(必填)、limit(10) | GET /memories/search |
create_memory | 记忆 | content(必填)、category(必填) | POST /memories |
edit_memory | 记忆 | memory_id(必填)、content(必填) | PATCH /memories/{id} |
delete_memory | 记忆 | memory_id(必填) | DELETE /memories/{id} |
get_conversations | 对话 | start_date、end_date、categories、limit(100)、offset(0) | GET /conversations |
get_conversation_by_id | 对话 | conversation_id(必填) | GET /conversations/{id} |
search_conversations | 对话 | query(必填)、limit(10)、start_date、end_date | GET /conversations/search |
几个值得展开的实现细节:
- 分类枚举:记忆分类(
MemoryCategory)包含core、hobbies、lifestyle、interests、habits、work、skills、learnings、other;对话分类(ConversationCategory)多达 33 项,覆盖personal、finance、health、sports、politics、technology等领域。分类过滤通过逗号拼接多值实现,例如params["categories"] = ",".join([c.value for c in categories]); - 日期语义:
get_conversations对end_date做了"当日 23:59:59"的收尾处理——(datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1) - timedelta(seconds=1)).isoformat(),确保结束日期整天都被包含; - 鉴权方式:每个工具都带可选
api_key参数(_API_KEY_FIELD),调用时优先取参数值,否则回退到OMI_API_KEY环境变量;两者皆无则抛出ValueError。日志输出时 api_key 会被掩码为***(见_execute_tool的log_args),避免密钥泄漏; - 错误处理:
_response_json统一调用raise_for_status(),HTTP 失败时抛出不含查询串与响应体的安全错误信息; - 结果序列化:所有工具返回
TextContent(type="text", text=json.dumps(result, indent=2)),即返回格式化的 JSON 文本,方便 LLM 直接阅读与再加工。
这些工具在仓库测试中也有直接覆盖:test_server.py 验证了get_memories的 limit 截断与分类过滤、get_conversations的include_discarded与 limit 行为;test_parse_categories.py、test_search_conversations.py、test_http_status.py 则分别覆盖分类解析、对话搜索与 HTTP 状态处理。
API 密钥机制与后端实现
MCP 服务器的鉴权与后端路由是理解整个链路的关键。根据 mcp/README.md:
- 在 Omi macOS 应用中,于 "Use omi memory anywhere" 下选择基于 key 的目标,展开 "Manual installation" 复制生成的密钥;跨平台应用中,则在
Settings > Developer Settings的MCP Server区块的API Keys列表中创建; - 生成的完整
omi_mcp_...值即为OMI_API_KEY; - 密钥可随每次工具调用传入,也可省略以使用
OMI_API_KEY环境变量(本地 stdio 包采用手动密钥路径;托管的 Omi MCP 端点对注册云客户端额外支持 OAuth)。
在 backend/routers/mcp.py(765 行)中,可以看到这些工具对应的后端能力:依赖注入get_uid_from_mcp_api_key完成 API Key 到用户 UID 的解析,工具数据分别来自database.memories、database.conversations、database.vector_db(向量语义搜索)等模块;对话列表还会经redact_conversations_for_list、populate_speaker_names等工具做脱敏与说话人姓名填充。也就是说,MCP 工具层只是协议适配层,真正的数据读写、语义搜索与隐私处理全部复用主后端既有能力,这保证了本地 MCP 客户端与 App/Web 端看到的数据口径一致。
调试与故障排查
常见错误与解决办法
原文档的 Troubleshooting 部分可直接作为排查清单:
uvx缺失错误:报错信息通常为RuntimeError: uvx is not installed. Please install it with 'pip install uvx'(见 openai_agents_sdk_ex.py),或在 Streamlit 应用中显示 "Critical Error:uvxcommand not found"。解决方式:pip install uvx,并确认其已加入 PATH;- 环境变量未设置:检查
.env中OPENAI_API_KEY与OMI_UID是否填写正确,以及文件是否位于启动命令的工作目录下; - 依赖未安装:重新执行
pip install -r requirements.txt; - MCP 服务器鉴权失败:确认
OMI_API_KEY(omi_mcp_...密钥)已配置——这是原文档.env清单之外但实际运行必需的变量; - 自托管后端地址不对:通过
OMI_API_BASE_URL指定后端地址(见下文)。
使用 MCP Inspector 调试
开发调试时可借助 MCP 官方 Inspector 工具直观查看工具声明与调用结果:
# 针对通过 uvx 发布的服务器 npx @modelcontextprotocol/inspector uvx mcp-server-omi # 本地开发(uv run 指向本地源码) npx @modelcontextprotocol/inspector uv run mcp-server-omimaintain.README.md 还给出两条本地开发提示:
- 在 Inspector 中测试时,启动命令可设为
uv+run mcp-server-omi -v;如果改用uvx+mcp-server-omi,则会指向已发布到 PyPI 的包而非本地改动; uv run之外,也可用python -m mcp_server_omi直接以模块方式启动。
查看 Claude Desktop 日志
将 MCP 服务器接入 Claude Desktop 后(配置方法见 mcp/README.md 的 uvx / docker / pip 三种方案),可通过以下命令跟踪其日志:
# macOS tail -n 20 -f ~/Library/Logs/Claude/mcp-server-omi.log# Windows PowerShell Get-Content "$env:APPDATA\Claude\logs\mcp-server-omi.log" -Tail 20 -Wait自托管后端
如果自行部署 Omi 后端,可覆盖 MCP 服务器的 API 基地址:
export OMI_API_BASE_URL="https://your-backend-url.com"该变量在 server.py 启动时读取,默认值为https://api.omi.me/v1/mcp/,为空时会抛出Exception("Base URL not found")。
从示例到自研应用:三步接入路径
综合以上内容,将 Omi 数据接入自有 Agent 应用只需三步:
- 准备运行环境:安装 Python 3.8+ 与
uvx,配置OPENAI_API_KEY、OMI_UID、OMI_API_KEY三个关键变量; - 选择接入方式:按团队技术栈在三种模式中选择——DSPy 的声明式签名、OpenAI Agents SDK 的 MCP 原生集成、LangChain/LangGraph 的生态复用,或直接以
uvx mcp-server-omi为起点,用任意支持 MCP 的客户端消费这 8 个工具; - 调试与验证:用
python -v观察服务器日志,用 MCP Inspector 验证工具声明与返回,用 Claude Desktop 日志确认真实环境下的调用链路。
这套示例组合覆盖了当前主流的 Agent 编排框架,既可作为 Omi 二次开发的起点,也是一份"同一 MCP 服务多框架复用"的可直接迁移的参考范式。
【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考