ARTICLE DETAIL

资讯详情

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

MCP极简入门:用TaoToken统一Key跑通MCP服务端与客户端

MCP极简入门:用TaoToken统一Key跑通MCP服务端与客户端 1. MCP 服务端与客户端到底在解决什么问题MCPModel Context Protocol模型上下文协议说白了就是给大模型装了一根“标准数据线”。以前你想让模型查天气、读数据库、调内部接口每个客户端都得单独写一套适配代码现在只要服务端按 MCP 规范暴露工具Tools、资源Resources、提示Prompts任何支持 MCP 的客户端都能即插即用。它解决的问题不是“让模型更聪明”而是“让模型能稳定地拿到外部上下文并执行动作”。这套架构里有三个角色要分清。主机Host是跑大模型的应用程序比如 Claude Desktop、Cline、Cursor客户端Client是主机内部负责跟服务端建立 1:1 连接的模块服务端Server则是你写的那个真正提供工具的程序。工作链路是主机启动客户端 → 客户端连接服务端 → 服务端注册工具 → 模型决定调用哪个工具 → 客户端把调用结果回传给模型。理解这条链路后面排错才不会抓瞎。适合谁看如果你已经会用 Python 写点脚本想让本地模型或 IDE 里的 AI 助手调用你自己的函数但又不想研究各家私有插件协议那 MCP 就是最短路径。我试过从零起一个本地 MCP 服务再让客户端完成握手和工具调用整个最小链路跑通大概二十分钟难点不在代码而在配置路径和 Key 的接入方式。这篇会聚焦“最小可运行链路”先起一个本地 MCP 服务端再让客户端完成初始化握手、列出工具、成功调用一次。同时把 TaoToken 统一 Key 和 API 通道的接入写法嵌进去这样你后面换模型、换客户端都不用到处改配置。三步验证动作会贯穿全文服务端日志出现初始化、客户端列出工具、成功调用一次。2. TaoToken 统一 Key 与 API 通道的前置准备在动手写代码前先把“钥匙”和“通道”准备好。MCP 客户端在调用模型时需要一个兼容 Anthropic 或 OpenAI 风格的 API 端点TaoToken 在这里扮演的就是统一入口你只维护一个 Key就能在模型对话、Coding Plan、API Keys 之间切换不用为每个客户端单独申请凭证。第一步打开 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录。登录后进入控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在左侧找到 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 点“创建新 Key”。创建时建议按用途命名比如mcp-client-local方便后面排查是哪个客户端在消耗额度。Key 只显示一次复制后先存到密码管理器里。第二步确认 API 通道地址。TaoToken 的 API 基础地址是 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为 Base URL 使用。如果你用的是 Anthropic SDK它默认会往/v1/messages发请求如果你用的是 OpenAI 兼容 SDK则走/v1/chat/completions。TaoToken 的通道对这两种风格都做了适配所以你在客户端里只需要把 Base URL 指向它再把 Key 填进去即可。第三步想清楚你要跑哪种场景。如果只是验证 MCP 工具调用能不能通用模型对话 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 先手动问一句“你能看到哪些工具”就够了如果你打算长期在 IDE 里跑编码 Agent那更适合开 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 遇到参数不确定时优先查这里。这里有个容易踩的坑很多人把 Key 直接写进代码里提交到 Git结果 Key 泄露被刷额度。正确做法是写进.env文件并且第一时间把.env加进.gitignore。后面客户端配置里我会给出完整的.env写法。另外TaoToken 的 Key 是统一凭证服务端本身不需要 Key只有客户端调用模型时才需要所以服务端代码里不要塞 Key避免权限扩散。3. 可复制的服务端与客户端配置先起服务端。用uv管理环境最省事Windows 下打开 PowerShelluv init mcp-weather cd mcp-weather uv venv .venv\Scripts\activate uv add mcp[cli] httpx new-item weather.py然后把下面这段服务端代码完整复制进weather.py。它用FastMCP注册了两个工具get_alerts查美国州级天气预警get_forecast按经纬度查未来五天预报。注意mcp.run(transportstdio)这行stdio 是本地 MCP 最常用的传输方式客户端通过标准输入输出跟它通信。from typing import Any import httpx from mcp.server.fastmcp import FastMCP mcp FastMCP(weather) NWS_API_BASE https://api.weather.gov USER_AGENT weather-app/1.0 async def make_nws_request(url: str) - dict[str, Any] | None: headers {User-Agent: USER_AGENT, Accept: application/geojson} async with httpx.AsyncClient() as client: try: response await client.get(url, headersheaders, timeout30.0) response.raise_for_status() return response.json() except Exception: return None def format_alert(feature: dict) - str: props feature[properties] return fEvent: {props.get(event, Unknown)}\nArea: {props.get(areaDesc, Unknown)}\nSeverity: {props.get(severity, Unknown)} mcp.tool() async def get_alerts(state: str) - str: Get weather alerts for a US state. Args: state: Two-letter US state code. url f{NWS_API_BASE}/alerts/active/area/{state} data await make_nws_request(url) if not data or features not in data: return Unable to fetch alerts. if not data[features]: return No active alerts. return \n---\n.join(format_alert(f) for f in data[features]) mcp.tool() async def get_forecast(latitude: float, longitude: float) - str: Get weather forecast for a location. points_url f{NWS_API_BASE}/points/{latitude},{longitude} points_data await make_nws_request(points_url) if not points_data: return Unable to fetch forecast data. forecast_url points_data[properties][forecast] forecast_data await make_nws_request(forecast_url) if not forecast_data: return Unable to fetch detailed forecast. periods forecast_data[properties][periods] return \n---\n.join( f{p[name]}: {p[temperature]}°{p[temperatureUnit]} {p[detailedForecast]} for p in periods[:5] ) if __name__ __main__: mcp.run(transportstdio)服务端起好后客户端这边要解决“连哪个服务端”和“用哪个模型”两件事。先建项目uv init mcp-client cd mcp-client uv venv .venv\Scripts\activate uv add mcp anthropic python-dotenv new-item client.py new-item .env.env文件里写 TaoToken 的 Key 和 Base URL。注意这里用的是 Anthropic SDK 风格所以变量名保持ANTHROPIC_API_KEY但值换成 TaoToken 的 Key同时把ANTHROPIC_BASE_URL指向 TaoToken 的 API 通道ANTHROPIC_API_KEYsk-你的TaoTokenKey ANTHROPIC_BASE_URLhttps://taotoken.net/api紧接着把.env排除出版本控制echo .env .gitignore客户端代码的核心是connect_to_server和process_query两个方法。前者用StdioServerParameters拉起服务端进程并完成session.initialize()握手后者把服务端返回的工具列表转成 Anthropic 的tools参数再处理tool_use类型的响应。下面这段可以直接用import asyncio import sys from typing import Optional from contextlib import AsyncExitStack from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() class MCPClient: def __init__(self): self.session: Optional[ClientSession] None self.exit_stack AsyncExitStack() self.anthropic Anthropic() async def connect_to_server(self, server_script_path: str): is_python server_script_path.endswith(.py) command python if is_python else node server_params StdioServerParameters( commandcommand, args[server_script_path], envNone ) stdio_transport await self.exit_stack.enter_async_context(stdio_client(server_params)) self.stdio, self.write stdio_transport self.session await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write)) await self.session.initialize() response await self.session.list_tools() print(\nConnected with tools:, [t.name for t in response.tools]) async def process_query(self, query: str) - str: messages [{role: user, content: query}] response await self.session.list_tools() available_tools [{ name: t.name, description: t.description, input_schema: t.inputSchema } for t in response.tools] response self.anthropic.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens1000, messagesmessages, toolsavailable_tools ) final_text [] assistant_content [] for content in response.content: if content.type text: final_text.append(content.text) assistant_content.append(content) elif content.type tool_use: result await self.session.call_tool(content.name, content.input) final_text.append(f[Calling {content.name} with {content.input}]) assistant_content.append(content) messages.append({role: assistant, content: assistant_content}) messages.append({role: user, content: [{ type: tool_result, tool_use_id: content.id, content: result.content }]}) response self.anthropic.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens1000, messagesmessages, toolsavailable_tools ) final_text.append(response.content[0].text) return \n.join(final_text) async def chat_loop(self): print(\nMCP Client Started! Type quit to exit.) while True: query input(\nQuery: ).strip() if query.lower() quit: break print(\n await self.process_query(query)) async def cleanup(self): await self.exit_stack.aclose() async def main(): if len(sys.argv) 2: print(Usage: python client.py path_to_server_script) sys.exit(1) client MCPClient() try: await client.connect_to_server(sys.argv[1]) await client.chat_loop() finally: await client.cleanup() if __name__ __main__: asyncio.run(main())如果你用的是 Claude Code 或 Cline 这类客户端配置方式不是写 Python而是改 JSON。以 Claude Code 的settings.json为例MCP 服务端配置长这样{ mcpServers: { weather: { command: uv, args: [--directory, T:/PythonProject/mcp-weather, run, weather.py] } } }注意路径必须用绝对路径Windows 下反斜杠要转义或直接写正斜杠。Cline 的 MCP 配置在cline_mcp_settings.json里结构类似但多一个disabled和autoApprove字段。Codex 的auth.json则是另一套它管的是模型凭证而不是 MCP 服务端别混在一起。无论哪种客户端只要涉及模型调用三件套必须齐全Base URL 指向https://taotoken.net/api、Key 填 TaoToken 的 Key、Model ID 填你实际要用的模型名。4. 三步验证日志、工具列表、成功调用配置写完不代表通了必须按顺序验证三步任何一步失败都能快速定位问题层。第一步验证服务端能独立启动。在服务端目录下直接跑uv run weather.py如果 stdio 模式下没有报错、进程挂起等待输入说明服务端本身没问题。更直观的方式是看日志FastMCP 在收到客户端初始化请求时会打印类似Initialized server session或工具注册信息。如果你在客户端里连不上先回到这一步确认服务端单独能跑。这一步对应“服务端日志出现初始化”。第二步验证客户端能列出工具。运行客户端并传入服务端脚本路径uv run client.py T:/PythonProject/mcp-weather/weather.py如果握手成功终端会打印Connected with tools: [get_alerts, get_forecast]。这行输出就是“客户端列出工具”的验证点。如果这里报Connection closed或卡住不动八成是路径写错、Python 环境不对或者服务端脚本里有语法错误导致进程直接退出。可以先把服务端脚本单独跑一遍确认没有 import 错误。第三步验证工具调用能真正执行。在Query:提示符下输入whats the weather in NY正常流程是客户端把工具列表发给模型 → 模型返回tool_use调用get_alerts参数stateNY→ 客户端执行session.call_tool→ 服务端请求 NWS API → 结果回传模型 → 模型生成自然语言回答。终端会先打印[Calling get_alerts with {state: NY}]然后输出预警内容。看到这个说明整条链路通了。如果你用的是 Claude Desktop 而不是自己写的 Python 客户端验证方式略有不同改完claude_desktop_config.json后必须彻底退出 Claude任务管理器里结束进程再重新打开。对话框下方出现锤子图标就代表 MCP 服务加载成功点开能看到工具列表。然后在对话里问天气观察是否触发工具调用。这里有个细节Claude Desktop 的配置文件路径在 Windows 下是C:\Users\你的用户名\AppData\Roaming\Claude\claude_desktop_config.json路径写错它不会报错只是静默不加载。三步验证的核心逻辑是分层排查服务端独立能跑 → 客户端能握手并列出工具 → 工具能实际执行并返回结果。任何一步失败问题一定在那一层不用瞎猜。5. 常见报错排查401、local proxy failed、reading choices、OAuth跑 MCP 最容易遇到的报错就那么几个逐个拆。401 Unauthorized。这个几乎都是 Key 的问题。检查.env里ANTHROPIC_API_KEY是不是 TaoToken 的 Key有没有多余空格或换行检查ANTHROPIC_BASE_URL是不是https://taotoken.net/api末尾不要多加/v1SDK 会自己拼。如果你用的是 OpenAI 兼容客户端变量名可能是OPENAI_API_KEY和OPENAI_BASE_URL别填错。还有一种情况是 Key 被禁用或额度耗尽去控制台 API Keys 页面确认状态。local proxy failed。这个报错通常出现在客户端尝试连接本地服务端时。原因一般是command或args里的路径不对比如uv不在 PATH 里或者--directory指向的目录不存在。Windows 下特别注意路径分隔符JSON 里反斜杠要写成\\或直接用/。另外如果你在虚拟环境里装了mcp但客户端用的是全局 Python也会因为找不到模块而失败。解决办法是统一用uv run让 uv 自己管理环境。Error reading choices。这个报错多见于模型返回格式不符合预期或者客户端解析响应时字段缺失。常见诱因是模型 ID 写错比如把claude-3-5-sonnet-20241022写成了别的版本导致 API 返回错误结构。另一个原因是max_tokens设得太小模型还没输出完tool_use就被截断。把max_tokens调到 1000 以上并确认 Model ID 跟 TaoToken 文档里列的一致。OAuth 相关报错。如果你用的是 Claude Code 或某些需要 OAuth 的客户端可能会遇到OAuth token expired或invalid_grant。这类问题跟 MCP 服务端无关是客户端自身的登录态失效。重新走一遍客户端的登录流程即可。注意不要把 OAuth token 和 TaoToken 的 API Key 搞混前者是客户端登录凭证后者是模型调用凭证两者作用域不同。排查时有个通用技巧把客户端和服务端的日志都打开。Python 客户端可以在connect_to_server前后加print服务端可以在mcp.run之前加日志配置。看到底是哪一步断了比盲目改配置快得多。另外如果你同时装了多个 MCP 服务端某个服务端启动失败可能导致整个客户端初始化卡住建议先只配一个跑通再加。6. 把统一 Key 接入你的日常编码流最小链路跑通后下一步是把它变成日常工具。如果你主要在 IDE 里写代码可以把 MCP 服务端配置进 Cline 或 Claude Code让 AI 助手直接调用你的本地工具。这时候 TaoToken 的统一 Key 优势就体现出来了你不需要为每个客户端单独申请凭证改一处 Base URL 和 Key所有走 API 通道的客户端都生效。长期跑编码 Agent 的话建议开 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它的额度模型更适合高频调用场景。如果只是偶尔验证模型能力用模型对话 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 手动问几句就够了。接入过程中遇到参数问题优先查接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面按客户端分类列了配置示例。最后提醒一个实操细节MCP 服务端的工具描述docstring会直接影响模型是否愿意调用。get_alerts的 docstring 里写清楚参数格式和用途模型命中率会高很多。如果你发现模型老是“忘记”调用工具先检查工具描述是不是太模糊。这个坑我踩过把描述补全后同样的问法就能稳定触发工具调用了。
返回列表