☰
MCP协议开发实战:用Python从零搭建AI Agent工具链Server与TaoToken配置
2026/9/28 4:20:46 网站建设 项目流程

1. 为什么 AI Agent 工具链总在重复造轮子

如果你写过两个以上的 AI Agent 项目,大概率遇到过同一个尴尬:给 Agent 加一个「查天气」工具,代码里塞一段函数调用;再加一个「单位换算」,又塞一段;等到第三个、第四个工具进来,主流程里全是 if-else 和 JSON schema,模型换一个、工具换一个,整条链路就得重写。这就是 MCP 协议想解决的问题。

MCP(Model Context Protocol)是一套开放协议,它把「模型怎么发现工具、怎么调用工具、怎么拿回结果」这件事标准化了。你可以把它理解成 AI 世界里的 USB-C 接口:Server 是各种外设(天气、数据库、计算器),Client 是主机(Agent/模型),只要都遵守同一个插口规范,谁都能插谁。对开发者来说,最直接的好处是工具和 Agent 解耦——工具用 Python 写一次,任何支持 MCP 的客户端都能复用。

这篇内容聚焦一件事:用 Python 从零搭一个 MCP Server,把它接进 AI Agent 工具链,并用 TaoToken 的统一 Key/API 通道完成模型侧调用配置。适合已经会写 Python、想跑通 MCP 工具链但还没落地的开发者。全程给可复制的骨架、配置片段和验证动作,不堆概念。

2. TaoToken 前置:统一 Key 与 API 通道准备

MCP Server 本身只负责「暴露工具」,真正决定 Agent 智能程度的是背后的模型。这里我用 TaoToken 作为统一的模型调用通道,原因是它把多个模型的 Key 和 endpoint 收敛成一个入口,Agent 侧不用为每个模型改配置。

你需要先拿到一个 API Key。登录官网后进入控制台,在 API Keys 页面创建一个新 Key,复制保存。注意 Key 只在创建时完整显示一次,丢了就重新建。

  • 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
  • 控制台(建 Key):https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console
  • API Keys 管理:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc

API 基地址统一用https://taotoken.net/api,这个地址不加任何查询参数,直接作为 OpenAI 兼容的base_url使用。也就是说,你原来用openai库写的代码,只需要改base_url和api_key两个字段,其余调用方式不变。

注意:Key 属于敏感凭证,不要写进会提交到 Git 的代码里。下面所有配置我都用环境变量读取,你本地可以放到.env或 shell 的 export 里。

3. 可复制配置:MCP Server 骨架与 settings.json

先建项目目录,装依赖。MCP 官方 Python SDK 包名是mcp,模型调用用openai库即可(因为 TaoToken 兼容 OpenAI 协议)。

mkdir mcp-agent-toolchain && cd mcp-agent-toolchain python -m venv .venv && source .venv/bin/activate pip install "mcp[cli]" openai python-dotenv

3.1 写一个提供两个工具的 MCP Server

新建weather_server.py。这个 Server 暴露两个工具:get_weather(模拟天气)和convert_unit(单位换算)。工具 Schema 用 SDK 的装饰器声明,输入参数用类型注解描述。

# weather_server.py import asyncio from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app = Server("weather-tools") # 工具清单:tools/list 返回的内容 @app.list_tools() async def list_tools() -> list[Tool]: return [ Tool( name="get_weather", description="查询指定城市的当前天气,返回摄氏度", inputSchema={ "type": "object", "properties": { "city": {"type": "string", "description": "城市名,如 北京"} }, "required": ["city"], }, ), Tool( name="convert_unit", description="温度单位换算,支持 c2f(摄氏转华氏)和 f2c", inputSchema={ "type": "object", "properties": { "value": {"type": "number", "description": "待换算数值"}, "mode": {"type": "string", "enum": ["c2f", "f2c"]}, }, "required": ["value", "mode"], }, ), ] # 工具调用:tools/call 的实际执行逻辑 @app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: if name == "get_weather": city = arguments["city"] # 这里用模拟数据,真实场景替换为天气 API 请求 fake = {"北京": 26.0, "上海": 29.0, "广州": 31.0} temp = fake.get(city, 25.0) return [TextContent(type="text", text=f"{city}当前气温 {temp} 摄氏度")] if name == "convert_unit": v, mode = arguments["value"], arguments["mode"] if mode == "c2f": result = v * 9 / 5 + 32 return [TextContent(type="text", text=f"{v}°C = {result:.1f}°F")] result = (v - 32) * 5 / 9 return [TextContent(type="text", text=f"{v}°F = {result:.1f}°C")] raise ValueError(f"未知工具: {name}") async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ == "__main__": asyncio.run(main())

这段代码的关键点:@app.list_tools()负责「工具发现」,@app.call_tool()负责「工具执行」,两者通过name字段对应。传输层用stdio_server,也就是标准输入输出,这是本地 MCP Server 最常用的方式。

3.2 settings.json 配置片段

如果你用的是支持 MCP 的客户端(比如 Claude Code 这类工具),通常通过一个settings.json或mcp.json注册 Server。下面是一个通用片段,把上面的 Python Server 挂进去:

{ "mcpServers": { "weather-tools": { "command": "python", "args": ["/absolute/path/to/weather_server.py"], "env": { "TAOTOKEN_API_KEY": "你的Key", "TAOTOKEN_BASE_URL": "https://taotoken.net/api" } } } }

command和args指向你的 Python 解释器和脚本绝对路径。env里注入 TaoToken 的 Key 和基地址,Server 内部如果要调模型就能直接读。

3.3 config.toml 配置片段

有些工具链用 TOML 管理配置,等价写法如下:

[mcp_servers.weather-tools] command = "python" args = ["/absolute/path/to/weather_server.py"] [mcp_servers.weather-tools.env] TAOTOKEN_API_KEY = "你的Key" TAOTOKEN_BASE_URL = "https://taotoken.net/api"

两种格式选一种即可,核心是「命令 + 参数 + 环境变量」三要素。

4. 验证请求:跑通工具发现与调用

配置写完别急着接 Agent,先用 MCP 自带的 CLI 验证 Server 能不能正常响应。SDK 装了mcp[cli]之后会带一个mcp命令。

# 启动并列出工具 mcp dev weather_server.py

mcp dev会拉起一个调试界面,你能看到get_weather和convert_unit两个工具,并手动填参数调用。如果界面里能看到工具列表,说明tools/list通了;点调用返回文本,说明tools/call通了。

再写一个最小 Client 脚本,模拟 Agent 侧「发现工具 → 调用工具」的完整链路:

# client_demo.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params = StdioServerParameters( command="python", args=["weather_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() print("发现工具:", [t.name for t in tools.tools]) result = await session.call_tool( "convert_unit", {"value": 26, "mode": "c2f"} ) print("调用结果:", result.content[0].text) asyncio.run(main())

运行python client_demo.py,预期输出:

发现工具: ['get_weather', 'convert_unit'] 调用结果: 26°C = 78.8°F

看到这两行,说明 MCP 工具链的 Server 端和 Client 端已经打通。接下来把模型接进来,让 Agent 自己决定调哪个工具。

4.1 接入 TaoToken 让 Agent 自主选工具

Agent 循环的核心是:把 MCP 发现的工具转成 OpenAI 的tools格式,交给模型决策,模型返回tool_calls后执行对应 MCP 工具,再把结果喂回模型。

# agent_demo.py import asyncio, json, os from openai import OpenAI from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url="https://taotoken.net/api", ) def to_openai_tools(mcp_tools): return [ { "type": "function", "function": { "name": t.name, "description": t.description, "parameters": t.inputSchema, }, } for t in mcp_tools ] async def main(): params = StdioServerParameters(command="python", args=["weather_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()).tools oai_tools = to_openai_tools(tools) messages = [ {"role": "user", "content": "北京今天多少度?帮我换成华氏度"} ] resp = client.chat.completions.create( model="gpt-4o-mini", messages=messages, tools=oai_tools, ) msg = resp.choices[0].message messages.append(msg) for call in msg.tool_calls or []: args = json.loads(call.function.arguments) result = await session.call_tool(call.function.name, args) messages.append({ "role": "tool", "tool_call_id": call.id, "content": result.content[0].text, }) final = client.chat.completions.create( model="gpt-4o-mini", messages=messages ) print(final.choices[0].message.content) asyncio.run(main())

运行前先导出环境变量:

export TAOTOKEN_API_KEY="你的Key" python agent_demo.py

预期模型会先调get_weather拿到北京温度,再调convert_unit转华氏度,最后输出类似「北京当前 26°C,约 78.8°F」。这一步跑通,整条 MCP 工具链就闭环了。

5. 本篇常见错排查

报错一:ModuleNotFoundError: No module named 'mcp'虚拟环境没激活,或者装到了全局 Python。确认which python指向.venv/bin/python,再pip install "mcp[cli]"。

报错二:Client 连不上 Server,卡在 initialize多半是args里的脚本路径不对。stdio_client用的是相对路径时,工作目录取决于你从哪运行脚本。建议统一写绝对路径,或者用os.path.dirname(__file__)拼。

报错三:模型返回tool_calls为空检查to_openai_tools转换后的parameters是否是合法 JSON Schema。MCP 的inputSchema一般能直接用,但如果你的工具没写required,模型可能不敢调。补上必填字段。

报错四:TaoToken 返回 401Key 没读到或写错。用echo $TAOTOKEN_API_KEY确认环境变量存在,注意base_url结尾不要多加/v1,直接用https://taotoken.net/api。

报错五:工具调用结果中文乱码stdio传输默认编码在部分 Windows 环境是 GBK。在 Server 启动参数里加env={"PYTHONIOENCODING": "utf-8"}即可。

报错六:多个 Server 工具重名当 Agent 同时挂多个 MCP Server,工具名冲突会导致调用错乱。给每个 Server 的工具名加前缀,比如weather_get_weather、calc_convert_unit,在list_tools里统一处理。

6. 下一步:把工具链接到你的真实场景

到这里你已经有了一个能跑的最小闭环:Python MCP Server 暴露工具,Client 发现并调用,TaoToken 提供模型通道。接下来最值得做的不是继续加工具,而是把其中一个模拟工具换成真实 API——比如把get_weather里的假数据换成一次 HTTP 请求,你会立刻遇到超时、重试、错误码这些生产问题,那才是工具链真正开始变有用的地方。

如果你要长期跑编码类 Agent,建议把模型通道固定成 Coding Plan 模式,省得每次调参;只是想验证某个模型对工具调用的支持程度,直接去模型对话页面手动试几轮更快。接入细节和参数说明都在文档里,遇到 401 或工具发现为空,先回第 5 节对一遍。

  • 模型对话验证:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=chat
  • Coding Plan(长期编码/Agent):https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc
  • API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys

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

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

立即咨询