
1. 从“我这里明天下雨吗”说起地区智能查询 MCP 到底解决什么问题“我这里明天下雨吗”——这句话丢给普通大模型它大概率会反问你一句“你在哪个城市”。原因很简单模型本身不知道你在哪它没有实时定位能力也没有一个稳定的通道去调用外部地理信息接口。你只能老老实实补一句“杭州”它才能继续往下查。这个体验在 2024 年之前还能忍但在 MCPModel Context Protocol模型上下文协议已经普及的今天就显得很割裂了。地区智能查询 MCP 要做的就是把“我在哪”这件事从用户嘴里挪到服务端自动完成。它的核心链路是客户端发起一次自然语言请求 → 大模型判断需要调用定位工具 → MCP Server 通过 IP 反查拿到当前城市 → 把城市名回传给模型 → 模型再决定是否调用天气类工具。整条链路里用户不需要输入任何地理信息这就是所谓“零输入”无感交互。适合谁来跟做这篇内容三类人最合适。第一类是想入门 MCP 开发但被协议细节劝退的 Python 开发者FastMCP 能把样板代码砍掉一大半第二类是在华为开发者空间里做 AI 应用实验的高校师生云主机开箱即用省去本地环境折腾第三类是已经在用 ChatBoxAI 这类多模型客户端、想给自己加个“生活助手”插件的人。你不需要精通异步编程只要能跑通一个 Python 脚本、会改 TOML 和 JSON 配置就能把整套东西搭起来。我试过把这套服务接到日常问答里最直观的变化是以前问天气要打一长串“杭州明天早上八点会不会下雨”现在直接问“我这里明天要带伞吗”模型自己就把定位和天气两步串起来了。下面从环境准备开始一步步把 FastMCP 的配置骨架、TaoToken 统一通道、ChatBoxAI 接入和排障全部走一遍。2. 华为开发者空间 DeepSeek TaoToken前置准备与统一通道配置2.1 华为开发者空间云主机为什么选它做 MCP 实验华为开发者空间给每位开发者免费提供一台云主机每年 180 小时使用时长预装了 CodeArts IDE、代码仓以及 JDK、Python 等运行时插件。对 MCP 开发来说这一点很关键FastMCP 依赖 Python 3.10而很多本地机器上 Python 版本混乱、pip 源慢、缺少编译依赖光配环境就能耗掉半天。云主机把这些前置问题都抹平了你登录进去基本就能直接pip install。云主机还配了 5G 免费云存储代码工程、配置文件、日志都能存进去换设备也不丢。对做 MCP 这种需要反复调试、改配置的实验性项目来说云存储相当于一个免费的版本快照位。领取入口在华为开发者空间官网PC 端和移动端都能操作按提示开通即可这里不展开注册流程重点放在拿到机器之后怎么用。2.2 DeepSeek 作为推理侧模型能力边界与调用方式DeepSeek 在推理和工具调用上的表现是这套方案能跑通的前提。它需要准确判断“我这里明天下雨吗”这句话背后隐含了两步操作先定位、再查天气。DeepSeek-V3 支持 128K 上下文DeepSeek-R1 在推理链路上做了优化对 MCP 这种“模型决定调哪个工具”的场景比较友好。你可以在华为云 ModelArts 的在线推理预置服务里领取免费额度也可以走统一的 API 通道来调用。这里要引入一个关键角色TaoToken。它的作用是把你手头多个模型供应商的 Key 收敛成一个统一入口Base URL 固定为https://taotoken.net/api模型 ID 按需切换。对 MCP 项目来说好处是你不用在 ChatBoxAI、脚本、IDE 插件里分别填不同的 Key改一处就能全局生效。下面先把 TaoToken 的 Key 拿到再进入配置环节。2.3 获取 TaoToken API Key 与可用模型清单打开 TaoToken 控制台进入 API Keys 页面创建一个新 Key。创建时建议按用途命名比如mcp-location-dev方便后面排查是哪个项目在用。创建完成后复制这串 Key它只会完整显示一次。模型 ID 方面DeepSeek 系列常用的有deepseek-chat对应 V3 对话和deepseek-reasoner对应 R1 推理。如果你只是做地区查询这种轻量工具调用deepseek-chat足够如果想让模型在“要不要调工具”这一步判断得更稳可以切到deepseek-reasoner。两个模型 ID 在同一个 Key 下都能用切换只改配置里的模型字段。注意Key 不要硬编码进提交到代码仓的脚本里。云主机上建议用环境变量或单独的.env文件并在.gitignore里排除。拿到 Key 之后先别急着写 MCP Server先用一条 curl 验证通道是否通curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: deepseek-chat, messages: [{role: user, content: 只回复两个字通了}] }返回里能看到choices[0].message.content为“通了”说明 Key、Base URL、模型 ID 三件套都对。这一步过了后面 MCP 接入才有意义。3. FastMCP 配置骨架config.toml 与 settings.json 可复制片段3.1 安装 FastMCP 与最小可运行 Server在华为开发者空间云主机的终端里执行sudo pip3 install fastmcp httpx -i https://mirrors.aliyun.com/pypi/simplefastmcp是框架本体httpx用来发异步 HTTP 请求查 IP 信息。装完之后先写一个最小 Server 确认框架能跑from fastmcp import FastMCP mcp FastMCP(simple-server) mcp.tool() def hello() - str: 问候语 return Hello from MCP Server! if __name__ __main__: mcp.run()保存为simple_server.py运行python3 simple_server.py。如果终端没有报错、进程挂起等待连接说明 FastMCP 环境正常。这个最小例子用的是装饰器风格写起来比手动注册list_tools和call_tool清爽很多。3.2 config.toml 骨架把服务参数外置FastMCP 支持从配置文件读取服务元信息避免把端口、名称、指令写死在代码里。在项目根目录建一个config.toml[server] name location-server version 1.0.0 instructions A MCP server for IP and location services. transport stdio [server.limits] request_timeout 15 max_retries 2 [upstream] ip_api https://ipinfo.io/json ip_fallback http://ifconfig.metransport stdio表示走标准输入输出这是 ChatBoxAI 本地 MCP 最常用的方式。request_timeout设 15 秒是因为 IP 反查接口偶尔会慢设太短会误报超时。upstream段把两个外部接口地址抽出来后面换服务商只改这里。3.3 settings.jsonTaoToken 统一 Key 与模型通道ChatBoxAI 以及很多支持 OpenAI 兼容协议的工具都认settings.json这种配置形态。下面这份可以直接改 Key 后用{ provider: openai-compatible, baseURL: https://taotoken.net/api, apiKey: sk-你的TaoTokenKey, model: deepseek-chat, models: [ { id: deepseek-chat, name: DeepSeek V3, contextWindow: 128000 }, { id: deepseek-reasoner, name: DeepSeek R1, contextWindow: 128000 } ], mcpServers: { location-server: { command: python3, args: [/home/dev/location_server.py], env: { TAOTOKEN_API_KEY: sk-你的TaoTokenKey } } } }这份配置里三件套齐全Base URL 是https://taotoken.net/apiKey 是 TaoToken 的 KeyModel ID 是deepseek-chat。mcpServers段把本地 MCP Server 的启动命令和参数也一并声明了ChatBoxAI 读取后会自动拉起进程。路径/home/dev/location_server.py按你云主机上的实际位置改。提示如果你的客户端不读settings.json而是走图形界面把上面provider、baseURL、apiKey、model四个字段对应填进去即可mcpServers部分在 MCP 设置页单独添加。3.4 地区查询 MCP Server 完整实现把定位和城市查询两个工具写进location_server.pyimport httpx from fastmcp import FastMCP mcp FastMCP( namelocation-server, version1.0.0, instructionsA MCP server for IP and location services. ) mcp.tool() async def get_public_ip() - str: 获取当前公网IP地址 try: async with httpx.AsyncClient(timeout15) as client: resp await client.get(http://ifconfig.me) resp.raise_for_status() return resp.text.strip() except Exception as e: return fError: {str(e)} mcp.tool() async def get_current_city() - str: 获取当前所在城市名称 try: async with httpx.AsyncClient(timeout15) as client: resp await client.get(https://ipinfo.io/json) resp.raise_for_status() data resp.json() return data.get(city, Unknown) except Exception as e: return fError: {str(e)} if __name__ __main__: mcp.run()装饰器风格下FastMCP 会自动从函数签名和 docstring 生成工具的inputSchema和描述模型看到的就是get_current_city这个工具“获取当前所在城市名称”。两个工具都不需要入参这正是“零输入”的基础——模型调用它们时不用向用户索要任何信息。4. 验证请求与成功结果从“我在哪里”到“我这里下雨吗”4.1 本地启动与工具列表自检在云主机终端启动服务python3 /home/dev/location_server.py进程挂起后另开一个终端用 FastMCP 自带的客户端做一次工具枚举。如果你用的是支持 MCP 的客户端直接在对话里问“请列出当前可用的所有 MCP 工具及其功能”模型会返回类似- get_public_ip: 获取当前公网IP地址 - get_current_city: 获取当前所在城市名称这一步能列出两个工具说明 Server 注册成功、客户端也读到了工具清单。如果只列出一个或一个都没有先回到第 5 节看排障。4.2 单工具验证问“我在哪里”在 ChatBoxAI 新会话里确认 MCP 开关已启用location-server然后输入“我在哪里”。预期行为是模型调用get_current_city返回一个城市名比如“Hangzhou”。这一步验证的是定位链路本身通不通。如果返回的是Unknown多半是ipinfo.io在当前网络下没返回city字段可以临时把get_current_city里的接口换成带 token 的版本或者先用get_public_ip拿到 IP 再人工核对。云主机的出口 IP 归属地可能和你本人所在地不一致这是正常现象做实验时以云主机出口为准。4.3 组合验证问“我这里明天下雨吗”这是整套方案的目标场景。在只启用location-server时模型会先调get_current_city拿到城市如果你同时启用了天气类 MCP比如高德地图 MCP模型会接着调天气接口最终返回类似你所在的城市明天有雨建议带伞。整个过程中你没有输入任何城市名。模型自己完成了“判断需要定位 → 调 get_current_city → 拿到城市 → 调天气工具 → 汇总回答”这条链。实测下来DeepSeek 在工具选择上的准确率比较稳偶尔会在“要不要先定位”这一步犹豫把模型从deepseek-chat切到deepseek-reasoner通常能改善。4.4 用 curl 直接验证 MCP 之外的模型通道为了排除是 MCP 的问题还是模型通道的问题可以单独用 curl 打一次 TaoToken 接口带上工具描述做一次模拟curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: deepseek-chat, messages: [ {role: user, content: 我在哪里如果需要定位请调用工具。} ], tools: [ { type: function, function: { name: get_current_city, description: 获取当前所在城市名称, parameters: {type: object, properties: {}} } } ] }如果返回的finish_reason是tool_calls说明模型通道和工具调用协议都正常问题就落在 MCP 客户端配置上。这一步能把故障域缩小到具体环节。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth5.1 401 UnauthorizedKey 或 Base URL 不匹配最常见的报错是Error: 401 Unauthorized原因通常有两个。一是 Key 复制时带了空格或换行尤其是从网页复制到settings.json时容易多一个尾部空格。二是 Base URL 写成了https://taotoken.net而漏了/api或者写成了带 UTM 参数的地址。正确写法是https://taotoken.net/api不带任何查询参数。排查动作把 Key 和 Base URL 单独拎出来跑第 2.3 节那条 curl能通就说明配置本身没问题问题在客户端读取配置的路径上。5.2 local proxy failed本地 MCP 进程没起来ChatBoxAI 报local proxy failed to connect意思是它按mcpServers里的command去拉进程但没拉起来。常见原因args里的脚本路径写错、python3不在 PATH 里、脚本有语法错误启动即退出。排查动作是在终端手动执行一遍commandargs拼出来的命令看报什么错。如果是ModuleNotFoundError: No module named fastmcp说明装库时用的 pip 和运行时用的 python 不是同一个用python3 -m pip install fastmcp重装。5.3 reading choices 报错响应结构不符合预期Error: reading choices - undefined这个报错一般出现在客户端把非 OpenAI 兼容格式的响应当成标准格式解析时。如果你在settings.json里把provider写成了某个特定厂商而不是openai-compatible客户端可能按错误的 schema 解析。改成openai-compatible并确认baseURL指向https://taotoken.net/api。另外如果模型返回的是流式分片而客户端按非流式解析也会出现类似报错检查客户端是否开启了 stream 选项。5.4 OAuth 相关报错MCP Server 鉴权模式不匹配OAuth authorization required或invalid_token这类报错通常出现在你接入的是远程 MCP Server走 SSE 或 HTTP而对方要求 OAuth 鉴权。本篇的location-server是本地 stdio 模式不涉及 OAuth。如果你同时接了高德地图 MCP 这类远程服务需要在对应 MCP 的配置里填它自己的 Key而不是复用 TaoToken 的 Key。两套鉴权是独立的别混。5.5 工具列不出来MCP 开关或缓存问题有时候配置都对但对话里模型说“没有可用工具”。先确认 ChatBoxAI 对话框下方的 MCP 按钮是启用状态再确认location-server前面的开关是开的。如果还不行重启一次 ChatBoxAI让它重新读取settings.json并重新拉起 MCP 进程。改完配置不重启是最高频的“假故障”。6. 把通道固定下来长期编码与 Agent 场景的接入建议地区查询 MCP 跑通之后你手里其实有了一套可复用的骨架一个 FastMCP Server、一份config.toml、一份带 TaoToken 统一通道的settings.json。接下来不管是加天气工具、加 POI 查询还是把定位能力接到更复杂的 Agent 流程里都只需要在location_server.py里加一个mcp.tool()函数其余配置不用动。如果你打算长期做 MCP 开发和 Agent 实验建议把模型通道固定成 TaoToken 的统一入口Base URL 保持https://taotoken.net/api模型 ID 按任务切换。这样你在 ChatBoxAI、CodeArts IDE 插件、自己写的脚本里用的是同一套 Key换模型只改一个字段不用到处翻配置。需要看可用模型和额度时直接进模型对话页面确认要管理 Key 就去 API Keys 页面接入细节和协议说明在接入文档里如果后面要做更重的编码类 Agent可以了解 Coding Plan 的用法。最后留一个实用习惯每次改完settings.json或config.toml先跑一遍第 2.3 节的 curl再重启客户端。这两步能把九成的配置类故障挡在对话之前。