把 AsyncOpenAI 的 base_url 改到 TaoToken 通道后,让 Codex 跑通 MCP stdio
2026/9/19 21:24:51 网站建设 项目流程

把 AsyncOpenAI 的 base_url 改到 TaoToken 通道后,让 Codex 跑通 MCP stdio

在 MCP Python SDK 里写 FastMCP 服务端和 stdio 客户端时,最容易卡住的不是@mcp.tool()的注册逻辑,而是客户端里AsyncOpenAIbase_url到底填什么。很多人把server.py跑起来了,stdio_client也连上了,list_tools()能打印出add_2_numbers,但一到chat.completions.create就报连接错误或 404。这篇就从「接入配置」视角,把AsyncOpenAIbase_url改到 TaoToken 通道(https://taotoken.net/?utm_source=taotoken_aicg_blog_end ),让 Codex 按原文的 stdio 步骤真正跑通工具调用。

一、原问题与场景:stdio 通了,模型通道没通

原文用 MCP Python SDK 写了一个 FastMCP 服务端,暴露add_2_numbersmultiply_2_numbers这类@mcp.tool(),客户端用stdio_client拉起server.py,再用AsyncOpenAI把工具列表交给大模型识别。问题出在客户端__init__里这一行:

self.client = AsyncOpenAI(api_key=api_key, base_url=base_url)

api_keybase_urlmodel三个参数是从config.json读进来的。如果base_url还是默认的 OpenAI 地址,或者填成了带/v1的地址,AsyncOpenAI在发chat.completions.create时就会走到错误的端点。表现是:stdio 握手成功、工具列表打印正常,但模型请求直接抛异常,process_query里的while assistant_message.tool_calls永远进不去,add_2_numbers也就永远不会被调用。

所以这条的核心不是改 MCP 协议代码,而是把客户端的模型通道指向 TaoToken,让AsyncOpenAI的请求能正常返回tool_calls

二、TaoToken 前置:先拿 Key,再定 base_url

在改config.json之前,先去 TaoToken 官网创建一个 Key:

  • 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end
  • 创建 Key 的页面在控制台的 API Keys 里,登录后直接新建即可
  • 拿到形如YOUR_API_KEY的字符串,后面填进config.jsonllm.api_key

这里要强调一个容易踩的点:TaoToken 的 API 地址是https://taotoken.net/api不要带/v1AsyncOpenAI内部会自己拼接路径,如果你写成https://taotoken.net/api/v1,最终请求会变成/api/v1/chat/completions这种重复路径,直接 404。原文客户端里base_url是透传给AsyncOpenAI的,所以这个值必须干净。

如果你还没创建 Key,可以先看接入文档确认当前支持的模型 ID,再决定config.jsonmodel填哪个。模型对话页面可以用来先验证通道是否通,再回到 MCP 客户端里跑工具调用。

三、可复制配置:config.json 与客户端改动

原文客户端main()里是这样读配置的:

with open("config.json", "r") as f: config = json.load(f) client = Stdio_MCPClient( config["llm"]["api_key"], config["llm"]["base_url"], config["llm"]["model"] )

所以只需要改config.json,不用动Stdio_MCPClient的构造逻辑。把文件改成:

{ "llm": { "api_key": "YOUR_API_KEY", "base_url": "https://taotoken.net/api", "model": "MODEL_ID" } }

三个字段对应关系:

  • api_key:TaoToken 控制台创建的 Key,填YOUR_API_KEY的位置
  • base_url:固定https://taotoken.net/api,结尾不要加/v1,也不要加斜杠
  • model:填 TaoToken 接入文档里列出的模型 ID,不要照抄 OpenAI 的gpt-4-turbo之类

客户端代码本身不需要改AsyncOpenAI那一行,因为它已经把base_url透传进去了。唯一要确认的是connect_to_stdio_servercommand="python"args=["server.py"]的路径对,server.pymcp.run(transport='stdio')没有被改成 sse。

如果你用的是 Codex 这类 CLI 工具去拉起这个客户端,注意 Codex 自己的config.toml和这里的config.json是两套配置,不要混。MCP 客户端的模型通道由config.json决定,Codex 只负责按 stdio 启动server.py

四、验证请求与成功结果

改完config.json后,按原文步骤跑:

python client.py

预期看到的第一段输出是 stdio 连接成功:

成功链接到testserver服务,对应的tools: ['add_2_numbers', 'multiply_2_numbers']

这说明stdio_client已经拉起server.pylist_tools()也拿到了@mcp.tool()注册的函数。接着在Query:提示符下输入:

Query: 帮我算一下 3 加 5 等于多少

如果模型通道配置正确,会看到:

calling tools add_2_numbers, with args {'a': 3, 'b': 5} Result: 8 AI: 3 加 5 等于 8

这里的calling tools add_2_numbers就是process_querysession.call_tool(tool_name, tool_args)被触发的证据。也就是说,AsyncOpenAI返回了tool_calls,客户端把add_2_numbers的参数解析出来,通过 stdio 发给服务端执行,再把result.content[0].text塞回messages做第二轮chat.completions.create

如果只想先验证模型通道,不想跑完整 MCP 流程,可以单独写一个最小脚本:

import asyncio from openai import AsyncOpenAI async def main(): client = AsyncOpenAI( api_key="YOUR_API_KEY", base_url="https://taotoken.net/api" ) resp = await client.chat.completions.create( model="MODEL_ID", messages=[{"role": "user", "content": "hi"}] ) print(resp.choices[0].message.content) asyncio.run(main())

这个能通,再回去跑 MCP 客户端,就能把问题范围缩小到 MCP 层而不是通道层。

五、本篇常见错排查

错误 1:base_url 带了/v1

现象是chat.completions.create报 404 或Not Found。检查config.jsonbase_url是不是写成了https://taotoken.net/api/v1。改成https://taotoken.net/api即可。

错误 2:api_key 没换,还是占位符

现象是 401 或invalid api key。确认config.jsonllm.api_key是 TaoToken 控制台创建的真实 Key,不是YOUR_API_KEY字面量。

错误 3:model 填了 OpenAI 的模型名

现象是模型不存在或 400。TaoToken 通道的model要用接入文档里列出的 ID,不要直接抄原文示例里的gpt-4-turbo

错误 4:stdio 连上了但 tool_calls 为空

如果list_tools()打印正常,但模型回复里没有tool_calls,先确认available_tools的构造是否正确:

self.available_tools = [ { "type": "function", "function": { "name": tool.name, "description": tool.description, "parameters": tool.inputSchema } } for tool in response.tools ]

这段是把 MCP 的inputSchema映射成 OpenAI function calling 的parameters。如果tool.description为空,模型可能不触发调用,给@mcp.tool()函数补上 docstring。

错误 5:server.py 路径不对

stdio_clientargs=["server.py"]是相对当前工作目录的。如果从别的目录启动client.py,会报找不到server.py。用绝对路径或先cd到文件所在目录。

错误 6:Codex 拉起时环境变量没传

如果通过 Codex 的config.toml配置 MCP server,注意env字段要显式传api_key等变量,否则客户端读不到。原文connect_to_stdio_serverenv={}是空字典,需要按需补。

六、语义一致 CTA

这条的改动点只有一个:把AsyncOpenAIbase_url指向 TaoToken 通道,让 MCP stdio 客户端的模型请求能正常返回tool_calls。如果你在配置config.json或创建 Key 时卡住,可以直接去 API Keys 页面和接入文档对照字段;想先确认模型通道是否通,用模型对话页面发一条最小请求即可;如果是要长期跑 Codex + MCP 这类编码 Agent 场景,Coding Plan 更适合持续调用。

base_url改对之后,原文的stdio_clientClientSessioncall_tool这套流程就能完整跑通,add_2_numbers这类@mcp.tool()也会真正被大模型识别并调用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询