news 2026/9/17 14:38:46

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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_source=taotoken_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 而不是 conda

conda 的问题是它不只是一个 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 以模型广场当时列表里的写法为准,不要凭印象自己加日期后缀。原文.envMODEL=deepseek-chat保持不变,这一步只是把 Key 的来源从 DeepSeek 官方换成了 TaoToken。后面确实想换模型,也是回到这个页面看列表,改.env里一行MODEL就行,客户端脚本不用动。

到这一步为止,.env需要的三件材料已经齐了:一把 Key(YOUR_API_KEY)、一个通道地址(下一节写)、一个模型 ID(deepseek-chat)。

3. 第十步改写:.env 里的 BASE_URL 指向 TaoToken 统一通道

原文第十步是在项目根目录新建.env,填三行:BASE_URL=https://api.deepseek.comMODEL=deepseek-chatOPENAI_API_KEY="sk-xxxxxxxxx"。这一篇只改第一行,其余两行的键名和写法不动。

3.1 .env 最终长这样

BASE_URL=https://taotoken.net/api MODEL=deepseek-chat OPENAI_API_KEY="YOUR_API_KEY"

三行,键名分别是BASE_URLMODELOPENAI_API_KEY,和 client_new.py 里os.getenv读的三个变量名一一对应。YOUR_API_KEY换成你从 TaoToken 控制台 创建的那把 Key,引号可以加可以不加,加了更保险,避免开头结尾多个空格。

注意BASE_URL里填的是https://taotoken.net/api,这是给客户端脚本用的接口根地址,不是给人点的网页。网页注册、看模型、看用量走的是https://taotoken.net/?utm_source=taotoken_aicg_blog_end,两者不要混:.env里千万不要把带?utm_source=的那串网址填进去,写在脚本里跑起来会报错。

3.2 为什么末尾不能加 /v1

OpenAI 官方 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.py:MCP 的 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发请求,参数是q=cityappid=OPENWEATHER_API_KEYunits=metriclang=zh_cn,返回原始 JSON。
  • format_weather(data):把 JSON 里的城市、温度、湿度、风速、天气描述抽出来,拼成几行可读文本。

真正对外暴露的工具是@mcp.tool()装饰的query_weather(city: str) -> str,它调用上面两个函数,返回拼好的字符串。这里的city要求传英文名,比如BeijingTokyo,因为 OpenWeather 的城市检索参数是按英文索引的。最后mcp.run(transport='stdio')让 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_key=self.openai_api_key, base_url=self.base_url)

self.openai_api_key来自.envOPENAI_API_KEYself.base_url来自.envBASE_URL。也就是说,MCP 客户端调用大模型的所有请求,都从这个OpenAI实例发出。把.env里的BASE_URL指向https://taotoken.net/api,就等于把 client_new.py 的模型调用切到 TaoToken 的兼容通道上,其他代码一行不动。

再往下看process_query,逻辑分四步:

  1. self.session.list_tools()问 server 要工具清单,把每个工具转成 OpenAI 的tools参数格式(type: function加上function.namedescriptioninput_schema)。
  2. self.client.chat.completions.create(model=..., messages=..., tools=...),把用户问题和工具清单一并交给模型。
  3. 检查content.finish_reason,如果是tool_calls,就解析出tool_nametool_args,通过self.session.call_tool让 server 真正执行。
  4. 把模型的工具调用和工具执行结果都追加进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_KEYBASE_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,比如自己凭印象加了日期后缀。回到网站看模型广场当时的写法,把.envMODEL一字不差地抄过来。

6.3 模型没有调用 query_weather

表现为:输入Beijing,模型直接用自己的知识回答天气,而没有出现[Calling tool query_weather ...]。这不是通道问题,而是工具描述没让模型产生调用意愿。可以从两个方向调:

第一,server.pyquery_weather的 docstring 要写清楚"输入指定城市的英文名称,返回今日天气",如果原来的文档不足以让模型判断何时调用,可以再补一句"当用户询问某个城市的天气时使用此工具"。

第二,输入时把意图说清楚,比如直接输入Beijing而不是一句含糊的话,模型更容易识别成天气查询。跑通一次之后再尝试更自然的表达,看模型的判定边界。

7. 跑通之后回控制台对一下这次调用

前面六节走完,.env里三行配置指向 TaoToken,client_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就顺手把本地目录、数据库连接之类的东西挂进去。工具描述的边界,就是模型能做事的边界。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 14:38:17

Notepad-- 文件对比:文本逐行高亮差异,10M 内二进制也能比

Notepad-- 文件对比:文本逐行高亮差异,10M 内二进制也能比 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/note…

作者头像 李华
网站建设 2026/9/17 14:37:26

自然连接⋈的真相:不是自动匹配,而是隐式多条件陷阱

1. 项目概述:为什么“自然连接”是数据库里最常被误解、也最该被吃透的操作?“土话笔记:数据库——自然连接(符号⋈)”这个标题,乍看像学生课后随手记的潦草笔记,但恰恰是这种带点烟火气的命名,戳中了数据库…

作者头像 李华
网站建设 2026/9/17 14:32:36

DataGrip连接达梦数据库完整指南:从JDBC驱动到排障实战

最近接手一个从Oracle往达梦数据库迁移的项目,数据切过去了,开发工具却卡了我整整两天。打开DataGrip一看,驱动列表里根本没达梦这一项。网上翻了很多资料,一半是讲达梦自带的DM管理工具怎么用,另一半是零散提问没人完…

作者头像 李华