ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MCP基础学习四:MCP在AI应用中的集成(MCP在AI应用中的完整架构图)

MCP基础学习四:MCP在AI应用中的集成(MCP在AI应用中的完整架构图) 1. 从一次工具调用失败说起MCP 在 AI 应用中的集成到底难在哪如果你正在给自研的 AI 应用接 MCP大概率遇到过这种场景Server 明明在本地跑起来了日志也打印了list_tools返回了三个工具可客户端发出去的tools/call就是没反应或者返回一个reading choices的报错。问题往往不在模型而在 Host、Client、Server 这三层之间的链路没对齐。MCP 在 AI 应用中的集成本质是把「模型想调工具」这件事拆成三段可观测的通信Host 负责编排对话与工具循环Client 负责按协议把请求发给 ServerServer 负责真正执行工具并把结果回传。很多教程只讲怎么在 Cursor 里填一个 JSON却不讲这三层各自持有什么状态、谁负责重试、谁负责鉴权于是换个客户端就翻车。这篇面向正在搭建 MCP 客户端的开发者把三层结构、传输模式、可复制的配置片段和一次完整的工具调用验证流程串起来。你会看到 Host 如何决定把哪些工具暴露给模型、Client 如何用 STDIO 或 SSE 建立会话、Server 如何声明工具 schema以及当请求失败时该从哪一层开始排查。适合已经读过 MCP 基础概念、准备把 MCP 接进自己 AI 应用的人。2. TaoToken 前置给 MCP 客户端准备一个稳定的模型出口MCP 的 Host 层最终还是要调用大模型来决定「要不要调工具、调哪个工具、参数怎么填」。所以在你调试 MCP 集成之前先把模型出口配好能省掉一半「到底是 MCP 链路问题还是模型没返回 tool_calls」的扯皮。我一般用 TaoToken 作为模型接入层原因是它同时提供 OpenAI 兼容接口和 Anthropic 兼容接口MCP 客户端里常见的两种 SDK 都能直接指过去不用为了换模型改 Host 代码。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意 API 地址不带 UTM 参数配置里填这个就行。具体要准备三样东西也就是后面所有配置片段里都会出现的「三件套」Base URLhttps://taotoken.net/apiOpenAI 兼容路径通常再拼/v1Anthropic 兼容路径按 SDK 要求拼。 API Key在控制台的 API Keys 页面生成形如sk-开头的一串。生成入口在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 建议给 MCP 调试单独建一个 Key方便按项目撤销。 Model ID比如claude-sonnet-4-5或gpt-4o这类具体以模型对话页面列出的为准页面在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你打算长期跑编码类 Agent或者 MCP Server 里挂的是代码检索、文件操作这类工具可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 它更适合高频工具调用的场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到路径拼接问题先翻这里。注意MCP 的 Server 本身不负责模型调用模型出口是 Host 的事。所以 TaoToken 的 Key 要配在 Host 或客户端侧不要塞进 MCP Server 的配置里否则 Server 会多出一层不该有的鉴权逻辑。3. 可复制配置MCP Server 声明与客户端接入片段这一节给的是能直接抄的配置。先看 MCP Server 侧怎么声明工具再看客户端侧怎么把 Server 挂上去最后看 Host 侧模型出口怎么配。三件套Base URL Key Model ID在每个环节都要对齐。3.1 MCP Server 的工具声明Python 示例下面是一个最小可用的 MCP Server用官方 Python SDK 的FastMCP声明两个工具一个查天气一个算加法。重点看mcp.tool()装饰器如何把函数签名转成 JSON Schema这是 Client 能正确填参数的前提。# server.py from mcp.server.fastmcp import FastMCP mcp FastMCP(demo-server) mcp.tool() def get_weather(city: str) - str: 查询指定城市的天气。city 为城市名例如 Beijing。 fake {Beijing: 晴 24C, Shanghai: 多云 27C} return fake.get(city, f{city} 暂无数据) mcp.tool() def add(a: int, b: int) - int: 计算两个整数之和。 return a b if __name__ __main__: mcp.run(transportstdio)transportstdio表示走标准输入输出适合本地进程被客户端拉起。如果你要跨机器部署把这里换成transportsse并指定 host 和 port客户端侧就要用 SSE 的 URL 去连。3.2 客户端接入STDIO 与 SSE 两种写法以常见的 MCP 客户端配置格式为例STDIO 模式下客户端会自己拉起 Server 进程所以配置里写的是命令和参数而不是 URL。{ mcpServers: { demo-stdio: { command: python, args: [/absolute/path/to/server.py], env: { PYTHONUNBUFFERED: 1 } }, demo-sse: { url: http://127.0.0.1:8000/sse, headers: { Authorization: Bearer 你的MCP_SERVER_TOKEN } } } }这里有个容易混的点demo-sse里的Authorization是 MCP Server 自己的鉴权跟模型出口的 TaoToken Key 是两回事。别把sk-开头的模型 Key 填到这里否则 Server 会拿它去校验 MCP 会话必然 401。3.3 Host 侧模型出口配置三件套齐全Host 侧如果用 OpenAI 兼容 SDK配置大致如下。注意base_url指向 TaoToken 的 API 地址api_key用控制台生成的 Keymodel填模型对话页面里列出的 Model ID。# host_llm.py from openai import OpenAI client OpenAI( base_urlhttps://taotoken.net/api/v1, api_keysk-你的TaoTokenKey, ) resp client.chat.completions.create( modelclaude-sonnet-4-5, messages[{role: user, content: 北京天气怎么样}], tools[...], # 这里填入从 MCP Client 拿到的工具 schema ) print(resp.choices[0].message)如果你用的是 Anthropic 兼容 SDKBase URL 和 Key 不变只是 SDK 初始化参数名不同具体路径以接入文档为准。三件套里最容易错的是 Model ID填错会直接报模型不存在而不是工具调用失败所以先单独跑一次纯对话确认模型通了再叠 MCP。4. 验证请求跑通一次完整的工具调用链路配置写完不算完要能看到「模型决定调工具 → Client 转发 → Server 执行 → 结果回灌模型 → 模型给出自然语言回答」这一整条链路。下面按顺序验证。第一步单独验证 MCP Server 能被拉起并列出工具。用官方提供的 inspector 或者自己写个最小 Client# client_check.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params StdioServerParameters(commandpython, args[server.py]) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() for t in tools.tools: print(t.name, t.inputSchema) asyncio.run(main())正常输出会打印get_weather和add两个工具名以及各自的 JSON Schema。如果这里就报错说明 Server 侧有问题先别往下走。第二步手动调一次工具确认 Server 执行逻辑没问题result await session.call_tool(add, {a: 3, b: 4}) print(result.content)预期看到7。这一步过了说明 Client 到 Server 的链路是通的。第三步把工具 schema 喂给 Host 的模型观察模型是否返回tool_calls。用第 3.3 节的 Host 代码把tools参数填成从list_tools拿到的 schema 转换后的格式。发一句「3 加 4 等于几」正常情况模型不会直接回答 7而是返回一个tool_calls里面name是addarguments是{a:3,b:4}。第四步把工具执行结果作为role: tool的消息回灌再请求一次模型这次模型会基于结果生成自然语言回答。到这里一次完整的 MCP 工具调用就闭环了。实测下来最容易卡住的是第三步模型不返回tool_calls。常见原因是工具 schema 没按 OpenAI 的{type:function,function:{...}}格式包装或者tool_choice没设成auto。先确认 schema 格式再确认模型本身支持 function calling。5. 本篇常见错排查401、local proxy failed 与 reading choices集成 MCP 时报错信息往往指向不明这里按真实遇到的顺序列几个高频的对照着查。401 Unauthorized先分清是哪一层的 401。如果是 Host 调模型时报 401检查 TaoToken Key 是否填对、是否带了多余空格、Base URL 是否拼了/v1。如果是 Client 连 MCP Server 时报 401检查 Server 侧鉴权配置和 Client 配置里的Authorization是否一致。两层的 Key 不能混用。local proxy failed或连接被拒多见于 SSE 模式。先确认 Server 真的在监听那个端口用curl http://127.0.0.1:8000/sse看有没有响应。如果 Server 在容器里注意端口映射和0.0.0.0绑定。STDIO 模式下出现类似错误通常是command路径不对客户端拉不起进程把args里的脚本路径改成绝对路径再试。Cannot read properties of undefined (reading choices)这个报错基本出在 Host 侧解析模型响应时。原因通常是模型返回的不是标准 chat completion 结构比如你用了 Anthropic 兼容 SDK 却按 OpenAI 的resp.choices[0]去取。检查 SDK 类型和响应结构是否匹配Anthropic 的响应在content数组里不在choices。OAuth相关报错如果 MCP Server 配了 OAuthClient 侧要完成授权码流程才能拿到 token。调试阶段建议先用静态 Bearer Token把 OAuth 流程单独跑通再合进来。报invalid_grant多半是回调地址或 client_id 不匹配。工具调用返回空结果检查 Server 函数的返回类型。MCP 要求返回可序列化内容返回None或自定义对象容易导致 Client 解析失败。统一返回字符串或标准 content 结构。排查顺序建议固定为先单独验证 Server 的list_tools和call_tool再验证 Host 的纯对话最后合起来验证工具调用。每层单独通了合起来出问题就只可能是 schema 转换或消息拼接的锅。6. 把 MCP 接进你的 AI 应用从架构图到可运行代码回到开头那张三层结构Host 持有对话状态和模型出口Client 持有 MCP 会话和工具列表Server 持有具体执行逻辑。集成的关键不是把三层写在一个文件里而是让每层的职责边界清晰这样出问题时能快速定位是哪一层。如果你准备继续往下做建议按这个顺序推进先用第 3.1 节的 Server 跑通list_tools再用第 3.2 节的配置把 Client 挂上然后用第 3.3 节的三件套确认模型出口最后用第 4 节的四步验证闭环。每一步都有独立的成功标志不要跳步。模型出口这块TaoToken 的 API 地址是 https://taotoken.net/api Key 在 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 生成模型列表在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 看。接入细节翻 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。长期跑 Agent 的话Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后一个实用技巧在 Host 侧把每次tool_calls的原始请求和 Server 返回都打到日志里格式化成 JSON 一行。这样当模型突然不调工具、或者参数填错时你能直接看到是模型没返回、还是 Client 转发丢了字段、还是 Server 执行抛了异常。MCP 的调试成本八成花在「不知道断在哪一层」日志一打这个问题就没了。
返回列表