MCP 服务里的 DeepSeek 请求走 TaoToken,uv 天气查询流程不用改

发布时间:2026/9/17 14:38:51
MCP 服务里的 DeepSeek 请求走 TaoToken,uv 天气查询流程不用改
1. uv 建环境的八步照抄分水岭在 .env原文章最讨巧的地方是用 uv 替代 conda 来搭 MCP 客户端环境新手少了一层conda 装不上、频道找不到的折腾。uv init、uv venv、activate、uv add openai python-dotenv httpx、uv pip install setuptools wheel 这几步本身和用哪家模型的 API完全无关所以这次接入配置的改写前八步一个字都不用换。真正要动的是第九步和第十步原文让你去 DeepSeek 的 API 平台注册、创建接口、充 1 块钱然后把BASE_URL指向https://api.deepseek.com。这一次把这两步换成先在 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册、创建 API Key再把.env里的BASE_URL改成统一通道地址。client_new.py 和 server.py 里的 Function Calling 链路一行不改天气查询照样能跑通。这篇文章落点在接入配置所以我会按原文的十四步顺序走前面几步快速带过重点放在 .env、client_new.py 里真正用到 BASE_URL 的那一行、以及uv run client_new.py server.py跑起来之后怎么判断 TaoToken 的 Key 是不是真的接通。1.1 为什么原文用 uv 而不是 condaconda 的问题是它不只是一个 Python 下载器它还管频道、管系统级依赖遇到公司网络或者国内镜像没配好就容易卡在 Solving environment。uv 的定位更窄它就是个比 pip 快的 Python 与包管理工具uv venv建出来的虚拟环境结构和 venv 一样.\.venv\Scripts\activate之后你看到的提示符也没有区别。对新手的实际意义是项目级依赖放在pyproject.toml环境隔离干净卸载重装成本低。MCP 的客户端脚本本身依赖很少就 openai、python-dotenv、httpx 三个主包用 uv 一次uv add就都装好了不必为了一个天气 demo 去折腾 conda 的 channel 优先级。所以这一步沿用原文不做替换。后面凡是涉及要连哪家模型的地方才切到 TaoToken。1.2 前八步命令回放在项目根目录的终端里依次执行pip install uv uv init uv venv .\.venv\Scripts\activate uv add openai python-dotenv httpx uv pip install setuptools wheel注意第五条是uv add、第六条是uv pip install这两个不要混uv add会把包写进项目的依赖清单uv pip install是临时往环境里塞包用来解决解释器基础组件缺失的问题。原文把这一点点出来了是踩过的经验不改。这八步做完.venv目录就有了后续所有 python 命令都在激活状态下执行。环境就绪接下来才是本篇文章真正改写的部分。2. 第九步改写DeepSeek 平台注册换成 TaoToken 创建 Key原文第九步是登录 DeepSeek 的 API 平台注册、创建接口、充 1 块钱。这一步在很多新手眼里是最容易卡住的注册、实名、充值、找到接口密钥页面走完一圈才拿到一把sk-开头的 Key。这一篇的改写方案是把这一步整体替换成去 TaoToken 官网创建 Key。2.1 原来的做法为什么会让新手卡住不是因为 DeepSeek 平台不好用而是因为你会开始纠结我这把 Key 只能用 DeepSeek 一家的模型吗回头想换成别的模型是不是又得在这家平台再注册一遍、再充一次MCP 客户端里模型名和 BASE_URL 都写死在.env换一次模型就要改一遍 base_url。另一种常见情况是已经有多把 Key 散落在不同项目里用哪个、去哪看用量慢慢就乱了。所以接入方式的选择其实解决的是同一套 MCP 客户端能不能反复换模型而不重写配置这个问题跟模型本身能力强不强是两回事。2.2 打开官网拿一把 Key先打开 TaoToken 注册并登录进控制台创建一把 API Key。Key 请存到本地安全位置本文里一律用占位符YOUR_API_KEY指代。同一页面也能看到模型广场当时的模型列表deepseek-chat这个模型 ID 以模型广场当时列表里的写法为准不要凭印象自己加日期后缀。原文.env里MODELdeepseek-chat保持不变这一步只是把 Key 的来源从 DeepSeek 官方换成了 TaoToken。后面确实想换模型也是回到这个页面看列表改.env里一行MODEL就行客户端脚本不用动。到这一步为止.env需要的三件材料已经齐了一把 KeyYOUR_API_KEY、一个通道地址下一节写、一个模型 IDdeepseek-chat。3. 第十步改写.env 里的 BASE_URL 指向 TaoToken 统一通道原文第十步是在项目根目录新建.env填三行BASE_URLhttps://api.deepseek.com、MODELdeepseek-chat、OPENAI_API_KEYsk-xxxxxxxxx。这一篇只改第一行其余两行的键名和写法不动。3.1 .env 最终长这样BASE_URLhttps://taotoken.net/api MODELdeepseek-chat OPENAI_API_KEYYOUR_API_KEY三行键名分别是BASE_URL、MODEL、OPENAI_API_KEY和 client_new.py 里os.getenv读的三个变量名一一对应。YOUR_API_KEY换成你从 TaoToken 控制台 创建的那把 Key引号可以加可以不加加了更保险避免开头结尾多个空格。注意BASE_URL里填的是https://taotoken.net/api这是给客户端脚本用的接口根地址不是给人点的网页。网页注册、看模型、看用量走的是https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end两者不要混.env里千万不要把带?utm_source的那串网址填进去写在脚本里跑起来会报错。3.2 为什么末尾不能加 /v1OpenAI 官方 SDK 的惯例是 base_url 到主机名就停版本路径/v1由 SDK 内部的chat.completions.create拼接实际请求的路径是{base_url}/chat/completions。如果你的 base_url 末尾又写了/v1最终请求会变成.../v1/chat/completions而 TaoToken 的兼容入口已经处理了这一段多出来的/v1会得到 404。所以.env里就写https://taotoken.net/api结尾不带斜杠、不带/v1、不带任何查询参数。这是本篇文章最容易一脚踩空的细节。3.3 .env 加载的时机client_new.py 里第一行代码就是from dotenv import load_dotenv load_dotenv()load_dotenv()在模块导入阶段就执行把.env里的三个值塞进环境变量。MCPClient.__init__里再os.getenv读出来。所以.env必须放在你执行uv run时的当前工作目录下。如果你在别的子目录里执行load_dotenv()找不到文件self.openai_api_key就是None脚本会在这里抛未找到 OpenAI API Key。稳妥的做法每次uv run client_new.py server.py之前先cd到项目根目录。4. server.py 与 client_new.pyMCP 的 Function Calling 链路没动原文第十二、十三步生成的两个脚本是本篇技术主体比配 Key 的篇幅长得多。它们的职责分离得很清楚server.py 晒出query_weather这个工具client_new.py 负责让模型自己决定要不要调它。4.1 server.py 只干天气这一件事server.py 用FastMCP(WeatherServer)起一个 stdio 服务里面两个函数fetch_weather(city)拿httpx.AsyncClient向 OpenWeather 的https://api.openweathermap.org/data/2.5/weather发请求参数是qcity、appidOPENWEATHER_API_KEY、unitsmetric、langzh_cn返回原始 JSON。format_weather(data)把 JSON 里的城市、温度、湿度、风速、天气描述抽出来拼成几行可读文本。真正对外暴露的工具是mcp.tool()装饰的query_weather(city: str) - str它调用上面两个函数返回拼好的字符串。这里的city要求传英文名比如Beijing、Tokyo因为 OpenWeather 的城市检索参数是按英文索引的。最后mcp.run(transportstdio)让 server 以标准输入输出的方式和客户端通信。server.py 里要替换的 Key 只有一处API_KEY xxx换成你自己从 OpenWeather 官网申请到的 Key。这一步和 TaoToken 无关原文第十一步就是去 openweathermap.org 注册、拿 Key照旧。4.2 client_new.py 里真正用到 BASE_URL 的是哪一行client_new.py 里和 TaoToken 直接相关的其实就一行self.client OpenAI(api_keyself.openai_api_key, base_urlself.base_url)self.openai_api_key来自.env的OPENAI_API_KEYself.base_url来自.env的BASE_URL。也就是说MCP 客户端调用大模型的所有请求都从这个OpenAI实例发出。把.env里的BASE_URL指向https://taotoken.net/api就等于把 client_new.py 的模型调用切到 TaoToken 的兼容通道上其他代码一行不动。再往下看process_query逻辑分四步用self.session.list_tools()问 server 要工具清单把每个工具转成 OpenAI 的tools参数格式type: function加上function.name、description、input_schema。调self.client.chat.completions.create(model..., messages..., tools...)把用户问题和工具清单一并交给模型。检查content.finish_reason如果是tool_calls就解析出tool_name和tool_args通过self.session.call_tool让 server 真正执行。把模型的工具调用和工具执行结果都追加进messages再请求一次模型生成最终的自然语言回答。第二步和第四步用的都是同一个self.client所以只要.env里 base_url 是对的整条链路都跟着走 TaoToken不需要分段改。4.3 MCP 客户端里加一句日志有好处原文的process_query里插了好几个print(11111)、print(2222)、print(33333)。这种打印在生产代码里不合适但在调试 MCP 时非常有用因为它能让你看清卡在哪一步是工具清单没拿到、还是模型没返回 tool_calls、还是工具执行失败。第一次跑通之前留着这些调试打印没坏处。5. uv run client_new.py server.py 之后怎么判断 TaoToken 真接通了原文第十四步就是uv run client_new.py server.py。这一句跑起来进程会以 stdio 方式拉起 server.py同时启动聊天循环。判断 TaoToken 的 Key 和 Base URL 是不是真的把 client_new.py 里的模型调用配通看下面三个信号。5.1 三个信号说明链路走通了第一个信号是启动后打印出工具清单已连接到服务器支持以下工具: [query_weather]这说明 server.py 起来了、stdio 通道通了、工具被客户端注册到了这一步和 TaoToken 无关但它是后面 Function Calling 的前提。第二个信号是你输入Beijing之后控制台出现类似[Calling tool query_weather with args {city: Beijing}]这样一行。这表示模型在第一次chat.completions.create时返回了finish_reason tool_calls也就是说模型那边确实收到了我们传的工具清单并且决定调用query_weather——这已经意味着 TaoToken 这条通道完成了第一次模型往返。第三个信号是最后输出的天气文本包含城市名、温度、湿度、风速和天气描述。这一行是模型拿到工具执行结果之后第二次请求生成的最终回答。能走到这里就说明 TaoToken 的 Key、Base URL、模型 ID 三件东西都对上了MCP 客户端里的模型调用被配通了。5.2 结果对不上时的常规自查如果第一个信号就没出现问题在 server.py 或 uv 环境不在 TaoToken先确认uv run的当前目录里有server.py以及 OpenWeather 的 Key 填了。如果出现第二个信号但没有第三个信号通常是第二次chat.completions.create出错了把异常打印出来看多半是.env里 base_url 写错或模型 ID 写错。如果两个信号都没有直接在输入城市名之后看到 API 报错那基本就是.env里的OPENAI_API_KEY或BASE_URL的问题对照下一节的排障段。6. 排障401、模型名、工具没触发跑 MCP Function Calling 最容易撞的三类错和本篇配置强相关逐个对一下。6.1 401 Unauthorized第一种可能OPENAI_API_KEY没取到。检查.env是不是放在执行uv run的目录下可以用一段最小测试确认from dotenv import load_dotenv import os load_dotenv() print(os.getenv(OPENAI_API_KEY)) print(os.getenv(BASE_URL))第二种可能Key 复制时带了空格或换行。.env里用双引号包住 Key 能避免尾部空格被截。第三种可能Key 本身已经失效或者未激活。回到 TaoToken 控制台 重新生成一把替换.env里那一行重新执行脚本即可。6.2 404 或者 model not found常见原因是BASE_URL末尾多写了/v1。改成https://taotoken.net/api就好别加斜杠。另一个原因是MODEL写成了一个当前模型广场列表里不存在的 ID比如自己凭印象加了日期后缀。回到网站看模型广场当时的写法把.env里MODEL一字不差地抄过来。6.3 模型没有调用 query_weather表现为输入Beijing模型直接用自己的知识回答天气而没有出现[Calling tool query_weather ...]。这不是通道问题而是工具描述没让模型产生调用意愿。可以从两个方向调第一server.py里query_weather的 docstring 要写清楚输入指定城市的英文名称返回今日天气如果原来的文档不足以让模型判断何时调用可以再补一句当用户询问某个城市的天气时使用此工具。第二输入时把意图说清楚比如直接输入Beijing而不是一句含糊的话模型更容易识别成天气查询。跑通一次之后再尝试更自然的表达看模型的判定边界。7. 跑通之后回控制台对一下这次调用前面六节走完.env里三行配置指向 TaoTokenclient_new.py里的模型调用走兼容通道server.py里的query_weather通过 MCP 的 Function Calling 触发整条天气查询链路就跑起来了。跑通之后建议回控制台看一眼这次调用有没有被记上这一步能帮你确认计费口径后面换模型或调整并发时心里有数。具体入口按你的下一步动作挑想先用同一把 Key 发一条文本消息验证模型 ID 和通道地址没填错可以去 TaoToken 模型对话这里能直接看到模型的返回。准备把这个 MCP 客户端当成日常写代码的助手去 Coding Plan 看看套餐是否够用。需要再建一把 Key 分给别的项目控制台 API Keys 里创建Key 一律用YOUR_API_KEY这种占位符管理不要写进任何提交到仓库的文件。如果你顺手想把这套 Function Calling 的思路挪到 Claude Code 之类的执行工具上参考 Claude Code 接入文档 里的环境变量写法把ANTHROPIC_BASE_URL也指向同一个通道。一个提醒MCP 客户端里的query_weather只能查天气不要因为看到call_tool就顺手把本地目录、数据库连接之类的东西挂进去。工具描述的边界就是模型能做事的边界。