ARTICLE DETAIL

资讯详情

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

【MCP】从 function call 到 MCP:stdio/sse 两种接入方式与 Python SDK 配置骨架

【MCP】从 function call 到 MCP:stdio/sse 两种接入方式与 Python SDK 配置骨架 1. 从 function call 到 MCP我踩过的边界与升级路径如果你已经用 OpenAI 的tools参数写过 function call大概率经历过这样的场景为了让模型查一次天气你得手写tools的 JSON Schema、解析tool_calls、把结果塞回messages、再发一次请求。单工具还能忍一旦工具数量涨到五六个脚本里的胶水代码就开始失控。MCPModel Context Protocol要解决的正是这个“胶水层”问题——它把外部工具的注册、发现、调用抽象成一套统一协议让 AI 客户端Host通过标准配置就能挂载任意 Server而不用为每个模型 SDK 重写一遍调用逻辑。这篇内容面向已经写过 function call、想升级到 MCP 的 Python 开发者。我会先讲清楚两者的边界差异再给出 Python SDK 下 stdio 与 sse 两种接入方式的 config 骨架配合 TaoToken 统一 Key/API 通道的settings.json示例最后跑一次可复现的连通性验证。判断标准很简单工具数量少、逻辑固定function call 够用工具要跨客户端复用、要动态增删MCP 才值得上。2. function call 与 MCP 的边界差异2.1 function call 的本质一次性的参数生成function call 的核心是“模型生成参数你的脚本执行函数”。看下面这段最小可运行代码它把tools定义、请求、解析、二次请求全串起来import openai import json def get_weather(city): return {Celsius: 27, type: sunny} client openai.OpenAI(api_keysk-xxx, base_urlhttps://taotoken.net/api) tools [{ type: function, function: { name: get_weather, description: 获取指定城市的天气, parameters: { type: object, properties: {city: {type: string, description: 城市名}}, required: [city] } } }] messages [ {role: system, content: 你是一个天气查询助手}, {role: user, content: 帮我查询上海的天气} ] res client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, tool_choiceauto ) tool_call res.choices[0].message.tool_calls[0] args json.loads(tool_call.function.arguments) messages.append(res.choices[0].message.to_dict()) messages.append({ role: tool, content: get_weather(args[city]), tool_call_id: tool_call.id }) res2 client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools ) print(res2.choices[0].message.content)跑通后你会发现两个硬伤第一tool_call_id必须严格对应上下文维护全靠手写第二换一个 Agent SDK比如 Qwen-Agent 或别的框架同一套工具要重新适配。工具越多这两点越痛。2.2 MCP 的本质把工具变成可挂载的服务MCP 采用 C/S 架构HostAI 客户端通过 Client 连接 ServerServer 用统一协议暴露 tools、prompts、resources。你写一次 Server任何支持 MCP 的 Host 都能挂载。它和 function call 不是替代关系——很多 Host 内部依然用 function call 来触发 MCP 工具MCP 的价值在于统一了“工具怎么被发现、怎么被配置、怎么被调用”。维度function callMCP工具定义位置每次请求的tools参数Server 端集中定义跨 SDK 复用需重写适配一次编写多处挂载传输方式随请求走stdio / sse上下文维护手动拼messagesClient 自动管理适用场景少量固定工具多工具、跨客户端注意MCP 不是让你抛弃 function call而是让你从“为每个 SDK 写胶水”变成“写一个 Server 到处挂”。3. TaoToken 前置统一 Key 与 API 通道在写 MCP Server 之前先把模型通道固定下来。我用 TaoToken 作为统一入口好处是 Key 和 base_url 只配一次stdio 和 sse 两种 Server 都复用同一套凭证不用在多个 SDK 之间来回改。先去控制台创建 API Keyhttps://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite拿到 Key 后API 通道固定为https://taotoken.net/api如果你要跑 Claude Code 这类编码 Agent可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewriteKey 管理页在这里方便后续轮换https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite把 Key 写进环境变量后面所有配置都引用它避免硬编码export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api4. Python SDK 下 stdio 与 sse 的 config 骨架4.1 安装依赖pip install mcp openaiMCP Python SDK 提供了FastMCP用装饰器就能把普通函数变成 tool省去手写inputSchema。4.2 stdio 方式本地进程启动stdio 模式下Host 会根据配置在本地拉起 Server 进程通过标准输入输出通信。先写一个最小 Server# weather_server.py from mcp.server.fastmcp import FastMCP mcp FastMCP(weather-demo) mcp.tool() def get_weather(city: str) - str: 获取指定城市的天气 return {Celsius: 27, type: sunny} if __name__ __main__: mcp.run(transportstdio)对应的settings.json骨架command指向 Python 解释器args指向脚本路径{ mcpServers: { weather-demo: { command: python, args: [/absolute/path/to/weather_server.py], env: { TAOTOKEN_API_KEY: sk-你的key, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }stdio 的关键点command必须是本地可执行文件路径用绝对路径否则 Host 找不到脚本。env里把 TaoToken 的 Key 透传给 ServerServer 内部调用模型时直接读环境变量。4.3 sse 方式远程 HTTP 服务sse 模式下Server 作为独立 HTTP 服务运行Host 通过 URL 连接。Server 端改成# weather_server_sse.py from mcp.server.fastmcp import FastMCP mcp FastMCP(weather-demo-sse) mcp.tool() def get_weather(city: str) - str: 获取指定城市的天气 return {Celsius: 27, type: sunny} if __name__ __main__: mcp.run(transportsse, host127.0.0.1, port8000)启动后终端会输出监听地址。对应的settings.json骨架{ mcpServers: { weather-demo-sse: { url: http://127.0.0.1:8000/sse, disabled: false, timeout: 30 } } }注意sse 配置里不要写0.0.0.0客户端连接时用127.0.0.1。我试过用0.0.0.0作为 URL直接返回 502换成127.0.0.1才通。4.4 两种方式怎么选stdio 适合本地工具、文件操作、需要访问本机资源的场景进程随 Host 启停隔离性好。sse 适合远程服务、多客户端共享、需要独立部署的场景Server 可以跑在另一台机器上。如果你只是本地跑个文件读取工具stdio 更省事如果工具要被团队多个客户端共用sse 更合适。5. 验证请求与成功结果5.1 用 Python 客户端直连验证不依赖任何 GUI直接用 MCP SDK 的客户端验证连通性。下面这段代码同时适用于 stdio 和 sse改一下连接参数即可import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params StdioServerParameters( commandpython, args[/absolute/path/to/weather_server.py], env{TAOTOKEN_API_KEY: sk-你的key} ) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() print(可用工具:, [t.name for t in tools.tools]) result await session.call_tool(get_weather, {city: 上海}) print(调用结果:, result.content[0].text) asyncio.run(main())成功时你会看到类似输出可用工具: [get_weather] 调用结果: {Celsius: 27, type: sunny}5.2 sse 方式的验证把连接部分换成 ssefrom mcp.client.sse import sse_client async def main(): async with sse_client(http://127.0.0.1:8000/sse) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() print(可用工具:, [t.name for t in tools.tools]) result await session.call_tool(get_weather, {city: 上海}) print(调用结果:, result.content[0].text) asyncio.run(main())先启动 Server再跑客户端输出和 stdio 一致就说明链路通了。这一步能跑通说明 Server 定义、传输方式、工具调用三件事都对了。5.3 在对话客户端里验证模型调用如果你用的是支持 MCP 的对话客户端把上面的settings.json填进去保存成功后勾选 Server然后发一句“帮我查一下上海的天气”。模型会自动调用get_weather返回结果。想单独验证模型对话能力可以用模型对话入口https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite6. 本篇常见错排查6.1 stdio 启动失败找不到脚本或解释器最常见的是args里用了相对路径。Host 的工作目录和你终端不一样必须写绝对路径。另一个坑是command用了python但系统里只有python3改成python3或写完整路径。6.2 sse 连接 502前面提过URL 写0.0.0.0会 502改成127.0.0.1。另外确认 Server 真的在监听curl http://127.0.0.1:8000/sse能返回事件流才算启动成功。6.3 工具列表为空mcp.tool()装饰器要求函数有类型注解和 docstring否则 SDK 无法生成inputSchema。检查你的函数是不是长这样mcp.tool() def get_weather(city: str) - str: 获取指定城市的天气 ...缺了city: str或 docstring工具可能注册不上。6.4 模型不调用工具如果 Host 内部用 function call 触发 MCP 工具模型可能因为描述不清而不调用。把 docstring 写具体参数名用标准命名别用a、b这种。工具描述越清晰模型选择越准。6.5 Key 没透传导致 401stdio 模式下 Server 是独立进程不会自动继承你终端的export。必须在settings.json的env里显式传入TAOTOKEN_API_KEY否则 Server 调模型时拿不到 Key。7. 什么时候该上 MCP什么时候 function call 够用判断标准我总结成三条。工具数量少于三个、逻辑固定、只在一个 SDK 里用function call 完全够别为了 MCP 而 MCP。工具要跨多个客户端复用、要动态增删、要团队共享MCP 的配置化挂载能省掉大量适配代码。需要本地文件、数据库、系统命令这类有状态操作MCP Server 的进程隔离比在脚本里直接调更安全。如果你打算长期做编码 Agent 或工具链集成建议从 stdio 起步跑通一个工具后再扩到 sse。Key 和通道统一走 TaoTokenstdio 和 sse 复用同一套凭证切换传输方式时不用改模型配置。接入细节可以对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite最后留一个实操建议先把weather_server.py跑通再用客户端list_tools确认工具注册成功最后才接对话客户端。三步分开验证出问题时能快速定位是 Server、传输还是 Host 配置的锅。
返回列表