首页/新闻资讯/正文详情

[Ai Agent] 11 MCP进阶:手写客户端,让MCP连接万物(Client)——TaoToken 统一 Key 接入 Stdio 与 Streamable HTTP

发布时间:2026/9/26 16:53:22 来源:云帆数科 栏目:资讯中心
[Ai Agent] 11 MCP进阶:手写客户端,让MCP连接万物(Client)——TaoToken 统一 Key 接入 Stdio 与 Streamable HTTP
1. 为什么我要手写 MCP Client而不是一直用 GUI上一章我们用 FastMCP 造了个天气服务CherryStudio 点几下就连上了看起来一切都很美好。但真实工程里Agent 往往跑在 Linux 服务器上的 Python 脚本里没有图形界面或者需要同时连接本地的高德地图和远程的天气服务还要统一调度。这时候 GUI 就不够用了必须自己写 MCP Client。MCPModel Context Protocol能做什么简单说它让智能体用统一协议调用任意语言写的工具。适合谁适合已经会写 Python、想让 Agent 真正接入外部工具的人。我试过用封装库快速搭起来但只有亲手写过连接管理和协议适配你才会真正理解uvx到底怎么启动子进程JSON-RPC 消息怎么在管道里流转Streamable HTTP 到底比 SSE 强在哪这篇就带你从零手写一个支持 Stdio 与 Streamable HTTP 双模传输的 MCP Client并用 TaoToken 统一 Key 接入模型通道最后给出可复制的配置骨架和连通性验证动作。全程代码可跟做踩过的坑我也会标出来。2. TaoToken 前置统一 Key 与 API 通道在写客户端之前先把模型通道准备好。MCP Client 本身只负责连接工具但 Agent 的“大脑”还是 LLM所以我们需要一个稳定的 API 入口。TaoToken 提供统一 Key兼容 OpenAI 风格的接口接入文档在 https://taotoken.net/api 官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。你需要先拿到 API Key然后配置到环境变量里。我习惯用config.py集中管理避免 Key 散落在代码各处# config.py import os OPENAI_API_KEY os.getenv(TAOTOKEN_API_KEY, sk-你的Key) OPENAI_BASE_URL https://taotoken.net/api AMAP_MAPS_API_KEY os.getenv(AMAP_MAPS_API_KEY, 你的高德Key)注意不要把 Key 硬编码进提交到 Git 的文件里用环境变量或.env加载。TaoToken 的 Key 管理页面在 https://taotoken.net/api-keys 可以随时轮换。如果你只是验证模型对话是否通可以直接用模型对话页面 https://taotoken.net/models 试一条消息如果打算长期跑编码类 Agent建议看 Coding Plan https://taotoken.net/coding-plan 额度更划算。3. 可复制配置Stdio 与 Streamable HTTP 双模骨架MCP 定义了多种 Transport当前主流是 Stdio 和 Streamable HTTPSSE 已逐步淘汰。Stdio 面向本地开发本质是父子进程间的匿名管道通信Streamable HTTP 面向远程协作把工具变成可远程调用的 Web 服务。3.1 Stdio 模式配置Stdio 的启动靠npxNode.js 生态或uvxPython 生态临时执行即用即走不污染全局环境。下面是一个settings.json风格的配置骨架很多 MCP 宿主都认这个格式{ mcpServers: { 高德地图: { transport: stdio, command: npx, args: [-y, amap/amap-maps-mcp-server], env: { AMAP_MAPS_API_KEY: 你的高德Key } }, 本地天气: { transport: stdio, command: python, args: [-m, m10_mcp_basics.stdio_server], env: null } } }如果你更喜欢 TOMLconfig.toml可以这样写[[mcp_servers]] name 高德地图 transport stdio command npx args [-y, amap/amap-maps-mcp-server] [mcp_servers.env] AMAP_MAPS_API_KEY 你的高德Key3.2 Streamable HTTP 模式配置HTTP 模式下MCP Server 必须提前启动并长期运行客户端只消费服务不管理生命周期。配置里换成url即可{ mcpServers: { 高德地图远程: { transport: streamable_http, url: https://mcp.amap.com/mcp?key你的高德Key }, 本地天气服务: { transport: streamable_http, url: http://127.0.0.1:8001/mcp } } }注意测试本地 HTTP 服务前必须先运行对应的服务器文件比如streamable_http_server.py否则连接会直接失败。3.3 用适配器快速加载工具有了配置用langchain-mcp-adapters可以快速把两种传输统一成工具列表import os from langchain_mcp_adapters.client import MultiServerMCPClient from config import AMAP_MAPS_API_KEY MCP_SERVERS { 高德地图: { transport: stdio, command: npx, args: [-y, amap/amap-maps-mcp-server], env: {**os.environ, AMAP_MAPS_API_KEY: AMAP_MAPS_API_KEY} }, 高德地图远程: { transport: streamable_http, url: fhttps://mcp.amap.com/mcp?key{AMAP_MAPS_API_KEY} } } async def load_tools(): client MultiServerMCPClient(MCP_SERVERS) tools await client.get_tools() print(已加载工具:, [t.name for t in tools]) return toolsget_tools()会向所有注册的 MCP 服务发送list_tools请求Stdio 服务启动子进程读工具声明HTTP 服务发 POST 到/mcp拿元数据最终返回统一的 Tool 列表。4. 验证请求从 JSON-RPC 到成功结果配置写好了怎么确认真的连通最直接的办法是看 JSON-RPC 消息。Stdio 下请求写进 stdin响应从 stdout 读出来{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: search_poi, arguments: {keyword: 西湖} } }响应长这样{ jsonrpc: 2.0, id: 1, result: { content: [{type: text, text: 找到西湖附近 10 个 POI}] } }HTTP 模式下响应格式要自动识别。自研 FastMCP 服务通常返回text/event-stream第三方服务可能直接返回application/json。所以客户端不能盲目response.json()import json import httpx async def call_http_mcp(url, payload): async with httpx.AsyncClient() as client: resp await client.post(url, jsonpayload) content_type resp.headers.get(content-type, ) if text/event-stream in content_type: for line in resp.text.splitlines(): if line.startswith(data:): return json.loads(line[5:]) return resp.json()跑通后控制台会打印出工具名和调用结果。我实测下来四种组合Stdio/HTTP × 自研/高德全部能通说明这套骨架的通用性没问题。5. 本篇常见错排查报错一npx找不到或子进程启动失败。先确认 Node.js 已安装npx --version能输出版本。如果是在无 Node 环境的服务器上改用uvx跑 Python 版 MCP Server或者直接走 Streamable HTTP 模式。报错二HTTP 连接返回 404 或连接被拒。检查服务是否已启动端口是否对得上。本地服务用127.0.0.1而不是localhost避免 DNS 解析问题。远程服务确认 URL 里的key参数没写错。报错三工具列表为空。多半是env没传对比如高德的AMAP_MAPS_API_KEY没注入。Stdio 模式下子进程继承的是你显式传入的env不是父进程的全部环境变量所以要用{**os.environ, AMAP_MAPS_API_KEY: ...}合并。报错四程序退出后留下僵尸进程。这是没管好子进程生命周期。用AsyncExitStack把子进程、管道、会话都注册进去退出时按后进先出顺序自动清理from contextlib import AsyncExitStack class StdioMCPTransport: def __init__(self): self.exit_stack AsyncExitStack() async def connect(self): transport await self.exit_stack.enter_async_context(stdio_client(self.params)) self.session await self.exit_stack.enter_async_context( ClientSession(transport[0], transport[1]) ) async def cleanup(self): await self.exit_stack.aclose()报错五多工具时所有调用都指向最后一个工具。这是 Python 闭包延迟绑定的经典坑。循环里创建函数时用默认参数立即锁定变量值async def _dynamic_tool_func(tool_nametool_info[name], **kwargs): return await self.client.call_tool(tool_name, kwargs)报错六流式输出一坨一坨蹦。print默认有缓存加flushTrue才能一个字一个字出来。配合astream_events(versionv2)监听on_chat_model_stream和on_tool_start就能看到 Agent 思考、调工具、再总结的全过程。6. 下一步把 Key 和客户端接起来到这里你已经有了一个能同时连 Stdio 和 Streamable HTTP 的 MCP Client 骨架。接下来要做的是把模型通道接上让 Agent 真正跑起来。模型侧用 TaoToken 统一 Key接入文档在 https://taotoken.net/api Key 在 https://taotoken.net/api-keys 管理。如果你要长期跑编码或 Agent 任务Coding Plan https://taotoken.net/coding-plan 会更省心只想先验证模型对话直接去 https://taotoken.net/models 发一条消息就行。把config.py里的OPENAI_BASE_URL指向 TaoTokenOPENAI_API_KEY填你的 Key然后运行主程序async def main(): async with AsyncExitStack() as stack: tools await LangChainMCPAdapter.load_mcp_tools(stack, MCP_SERVER_CONFIGS) app build_graph(available_toolstools) await run_agent_with_streaming(app, 帮我查一下杭州西湖附近的酒店) if __name__ __main__: asyncio.run(main())控制台会依次打印工具加载、工具调用、流式回复。改MCP_SERVER_CONFIGS就能接入数据库、文件系统、地图服务Agent 的能力边界由你决定。

相关推荐

SpringBoot+Vue3相亲网站全栈项目实战:数据库设计、匹配算法与部署避坑指南
SpringBoot+Vue3相亲网站全栈项目实战:数据库设计、匹配算法与部署避坑指南

最近有个相亲网站的源码项目收尾了,前后端分离,Java SpringBootVue3MyBatisMySQL这套组合,从零搭到能跑通核心业务,整个过程踩坑无数,但也把很多网上讲得含糊的地方彻底搞明白了。今天不聊虚的,直接把这套系… · 2026/9/26 16:53:16

SpringBoot+MyBatis+JSP图书管理系统实战:避坑与进阶技巧
SpringBoot+MyBatis+JSP图书管理系统实战:避坑与进阶技巧

简介:这是一套基于SpringBoot、MyBatis与JSP构建的图书管理系统完整项目源码,面向具备Java Web基础、希望深入理解企业级开发流程的开发者与在校学生。系统覆盖图书增删改查、分类管理、借阅归还、分页查询等核心业务,采用MVC架构&#xff0c… · 2026/9/26 16:53:16

腾讯TokenHub上线之后:大厂验证聚合分发赛道,开发者如何选平台
腾讯TokenHub上线之后:大厂验证聚合分发赛道,开发者如何选平台

2026年5月,腾讯云TokenHub的上线在圈内引发热议:用一个API Key聚合自研混元与DeepSeek、Kimi、MiniMax、智谱GLM等第三方模型,大厂亲自下场做Token聚合分发生意。这对开发者意味着什么?第三方聚合平台还有多少空间?本文展开聊聊,并把第一个推荐的第三方平台给到词元之河(Toke… · 2026/9/26 16:53:16

MiniMax H3视频生成实战:从设计思维到本地部署配置全解析
MiniMax H3视频生成实战:从设计思维到本地部署配置全解析

从上周开始,我的消息列表里陆续有人在发 MiniMax H3 的测试片段。这里说的是做 AI 视频生成的那个 H3,不是硬件。坦白讲,这两年视频生成模型出了一个又一个,我早就免疫了,但 H3 是目前少数几个让我愿意坐下来把前两秒反… · 2026/9/26 17:24:21

WorkBuddy实战:从零搭建AI自动化工作流的完整指南
WorkBuddy实战:从零搭建AI自动化工作流的完整指南

先声明一下,我不是上来就甩教程链接的类型。这些年我翻过不少AI工具的教学视频,大多数情况是看了开头就关掉,因为很多所谓“教程”要么念说明书,要么把简单的东西讲得神乎其神。但WorkBuddy这套工具链不一样,它解决的是… · 2026/9/26 17:24:21

MySQL慢SQL排查指南:索引建了为何还慢?优化实战与EXPLAIN诊断
MySQL慢SQL排查指南:索引建了为何还慢?优化实战与EXPLAIN诊断

1. 先别急着怪索引:慢SQL到底慢在哪一步 我一直觉得MySQL里有个特别有意思的现象——越是刚接触索引的人,越容易陷入一个思维定式: "SQL慢?我已经建索引了啊,为什么还这么慢?" 这个问题的答案… · 2026/9/26 17:24:21

PVE 装 Arch Linux:体验 KDE 桌面
PVE 装 Arch Linux:体验 KDE 桌面

前面我已经在 PVE 上安装过 Ubuntu Server、Windows 11,以及 Debian 13.7 GNOME Desktop。 这次继续换一个很有代表性的 Linux 发行版: Arch Linux KDE Plasma。 一方面,我一直想实际体验一下 Arch;另一方面,前面的… · 2026/9/26 17:24:21

从零复刻《超级动物自走棋》游戏(4):没报错 ≠ 通过了
从零复刻《超级动物自走棋》游戏(4):没报错 ≠ 通过了

摘要:本文记录了一次自动化测试踩坑经历:测试脚本崩溃后不会打印结果行,导致统计总数悄悄变少而毫无察觉。作者总结了四个隐蔽问题——崩溃脚本从统计中消失、断言函数签名过窄导致框架自身崩溃、写死的期望值造成假失败、以及"没输出&q… · 2026/9/26 17:24:21

边缘计算控制器如何破解工业数据采集的三笔账
边缘计算控制器如何破解工业数据采集的三笔账

工业现场做自动化改造,绕不开一个越来越尖锐的矛盾:产线上跑着十几二十台设备,每台都在产生数据,但真正能把这些数据用起来的工厂少之又少。我这些年跑过不少车间,从注塑、冲压到包装、装配,发现一个特别普… · 2026/9/26 17:24:15

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码