1. 从一次 POI 查询说起:Agent 调 MCP 到底卡在哪
Agent 调用高德地图 MCP 服务,说白了就是让大模型通过 MCP 协议去调高德的地图能力,比如查 POI、算路线、做地理编码。适合谁?适合已经在写 LangGraph、Cline、Claude Code 这类 Agent 框架,想让模型自己决定「什么时候查地图」的开发者。核心检索词就三个:Agent、MCP、高德地图。
我最早的做法很直接:把高德 MCP 的 SSE 地址拼上 key,塞进MultiServerMCPClient,然后让 Qwen 去跑。跑是能跑,但问题一堆。第一个坑是 key 散落在.env、代码、MCP 配置三处,改一次要翻三个文件;第二个坑是不同模型供应商的 Base URL 和 Key 各管各的,Agent 里既有对话模型的 key,又有地图服务的 key,排查 401 时根本分不清是谁挂了;第三个坑最隐蔽——MCP 工具列表拉回来了,但模型不调用,因为它不知道每个工具的参数结构。
后来我把鉴权和转发统一到 TaoToken 这一层:对话模型走 TaoToken 的 OpenAI 兼容通道,MCP 服务端配置里需要 key 的地方也统一从 TaoToken 拿。这样 Agent 侧只需要维护一套 Base URL + Key + Model ID,出问题看一个日志就能定位。下面我把整条链路拆开,从配置片段到真实 POI 查询验证,一步步给你可复制的操作。
先说清楚 MCP 在这里的角色。MCP(Model Context Protocol)本质是一个「工具描述 + 调用」的协议层,Agent 启动时通过 SSE 或 stdio 连到 MCP Server,拉回一个工具列表,每个工具有 name、description、inputSchema。大模型看到这些描述后,决定要不要调、调哪个、传什么参数。高德地图 MCP 就是把「周边搜索」「路径规划」「地理编码」这些能力包装成了标准工具。所以调试的核心不是「地图 API 会不会用」,而是「工具描述有没有被模型正确理解、参数有没有传对」。
我实测下来,90% 的失败不是网络问题,而是三类:鉴权头没带对、工具 schema 没被正确解析、模型返回的 tool_call 参数格式和高德期望的不一致。这三类分别对应后面的 401、reading choices、参数校验报错。把这三类排掉,链路基本就通了。
2. TaoToken 前置:统一 Key 与 API 通道怎么准备
在动手配 MCP 之前,先把 TaoToken 这层准备好。它的作用是给你一个统一的 OpenAI 兼容入口,对话模型和需要走 API 的环节都用同一套凭证,省得在 Agent 里维护多套 key。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 根地址是 https://taotoken.net/api ,注意这个不带 UTM。
第一步,进控制台创建 API Key。地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,登录后在 API Keys 页面新建一个,复制出来形如sk-xxxx的字符串。这个 key 就是你后面所有配置里要填的东西。创建页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
第二步,确认你要用的模型 ID。TaoToken 的模型对话页在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面能看到当前可用的模型列表和对应的 Model ID。做 Agent 工具调用,建议选支持 function calling 的模型,否则模型不会返回结构化的 tool_call,MCP 工具就调不起来。我一般先用模型对话页发一条带工具描述的消息,确认模型能吐出 tool_call 再往下走。
第三步,理解 Base URL 的拼法。OpenAI 兼容模式下,Base URL 填https://taotoken.net/api,SDK 会自动拼/v1/chat/completions。如果你用的是langchain_openai.ChatOpenAI,base_url就填这个,api_key填刚才的 key,model填模型 ID。这三件套(Base URL + Key + Model ID)是后面所有配置的基础,缺一个都会报鉴权或模型不存在。
第四步,如果你要做长期编码或跑 Agent 任务,可以看下 Coding Plan,地址 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,它更适合高频调用场景。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,遇到参数不确定时翻这个比猜快。
这里要强调一点:TaoToken 是 API 通道,不是编辑器替代品,也不是让你绕过什么限制的工具。它的定位就是统一鉴权和请求转发,让你在 Agent 里少维护几套凭证。把 key 管好,别硬编码进代码提交到仓库,用环境变量或.env加载。
3. 可复制配置:MCP 服务端 + Agent 侧 settings 片段
这一节给你能直接抄的配置。分两块:一块是 MCP 服务端的连接配置,一块是 Agent 侧的模型配置。路径和字段名我都按实际能跑通的写。
先看 MCP 服务端配置。如果你用的是 Cline 或 Claude Code 这类支持 MCP 的客户端,配置通常是一个 JSON 文件,路径类似~/.config/cline/mcp_settings.json或项目内的.mcp.json。高德地图 MCP 走 SSE,配置长这样:
{ "mcpServers": { "amap-maps": { "url": "https://mcp.amap.com/sse?key=你的高德Key", "transport": "sse", "disabled": false, "autoApprove": [] } } }注意这里的key是高德开放平台申请的 Web 服务 Key,不是 TaoToken 的 key。这两个 key 别搞混:高德 key 用来调地图能力,TaoToken key 用来调对话模型。很多人 401 就是因为把两个 key 填反了。
再看 Agent 侧的模型配置。如果你用 LangGraph +langchain_openai,配置片段如下,我把它写成 TOML 风格方便你对照:
[llm] base_url = "https://taotoken.net/api" api_key = "sk-你的TaoTokenKey" model = "你的模型ID" temperature = 0 [mcp.amap] url = "https://mcp.amap.com/sse?key=你的高德Key" transport = "sse"如果你用 Codex 的auth.json,结构类似:
{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoTokenKey", "model": "你的模型ID" }三件套再强调一次:Base URL 是https://taotoken.net/api,Key 是 TaoToken 控制台创建的sk-开头字符串,Model ID 从模型对话页拿。这三个填对,模型侧就通了。
然后是 Agent 侧调用 MCP 的代码骨架。核心是用MultiServerMCPClient连 SSE,拉工具列表,再交给create_react_agent:
import os import asyncio from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_mcp_adapters.client import MultiServerMCPClient from langgraph.prebuilt import create_react_agent from langgraph.checkpoint.memory import InMemorySaver from langchain_core.messages import HumanMessage load_dotenv(".env") client = MultiServerMCPClient( { "amap-maps": { "url": f"https://mcp.amap.com/sse?key={os.getenv('AMAP_KEY')}", "transport": "sse", } } ) llm = ChatOpenAI( base_url="https://taotoken.net/api", api_key=os.getenv("TAOTOKEN_API_KEY"), model=os.getenv("TAOTOKEN_MODEL"), temperature=0, ) async def run_agent(user_input: str): tools = await client.get_tools() print("工具列表:", [[t.name, t.description] for t in tools]) agent = create_react_agent(llm, tools, checkpointer=InMemorySaver()) config = {"configurable": {"thread_id": "1"}} async for chunk in agent.astream( {"messages": [HumanMessage(content=user_input)]}, config=config ): print(chunk) return "done" if __name__ == "__main__": asyncio.run(run_agent("成都红牌楼附近有什么好吃的"))这段代码里,client.get_tools()是拉工具列表的关键,打印出来你能看到每个工具的 name 和 description。如果这里打印为空,说明 SSE 没连上,先查高德 key 和网络。如果打印有工具但模型不调用,说明模型不支持 function calling 或工具描述没被理解。
4. 验证请求:一次真实 POI 查询看返回结构
配置写完,得用一次真实查询验证连通性。我选的是「成都红牌楼附近有什么好吃的」这种 POI 查询,因为它会触发高德的周边搜索工具,返回结构清晰,容易判断对错。
跑起来后,日志里会先出现工具列表。高德 MCP 通常暴露这几个工具:maps_regeocode(地理编码)、maps_around_search(周边搜索)、maps_search_detail(详情)、maps_direction_walking(步行路径)等。每个工具的 description 会写清楚用途和参数。比如周边搜索的参数大概是keywords、location、radius。
模型收到问题后,会先判断需要地理编码把「红牌楼」转成经纬度,再调周边搜索。你会在流式输出里看到tool_call的 chunk,里面带name和args。args 里就是模型填的参数,比如:
{ "keywords": "美食", "location": "104.043,30.642", "radius": "1000" }如果这一步 args 是空的或者字段名不对,高德会返回参数校验错误。我踩过的坑是模型把location写成了lng,lat顺序反了,导致查出来是另一个城市。解决办法是在系统提示里明确写「location 格式为 经度,纬度」。
工具调用返回后,你会看到ToolMessage,里面是 JSON 字符串,结构大致是:
{ "status": "1", "info": "OK", "pois": [ { "name": "某火锅店", "address": "红牌楼某路", "location": "104.045,30.643", "type": "餐饮服务" } ] }status为1表示成功,pois数组就是结果。如果status是0,看info字段的报错信息。常见的是INVALID_USER_KEY(高德 key 无效)或DAILY_QUERY_OVER_LIMIT(配额用完)。
验证成功的标志有三个:工具列表非空、流式输出里出现 tool_call、ToolMessage 里 status 为 1 且有 pois。三个都满足,说明 Agent 通过 MCP 调高德地图这条链路完全通了。整个过程耗时通常在 3 到 8 秒,取决于模型响应速度和地图 API 延迟。
如果你想单独验证模型侧,可以先去模型对话页发一条简单消息,确认 TaoToken 通道正常。地址 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。模型侧通了再查 MCP,能快速定位问题在哪一层。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
这一节按真实报错来。我把踩过的坑列出来,你对照日志找。
401 Unauthorized。两种可能:一是 TaoToken key 填错或过期,二是高德 key 填错。区分方法看报错来源:如果报错发生在模型请求阶段(还没到工具调用),是 TaoToken key 问题;如果发生在工具调用阶段,是高德 key 问题。解决:去控制台重新复制 key,确认没有多余空格。TaoToken 的 key 在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 管理。
local proxy failed。这个通常出现在 MCP 客户端连 SSE 时,说明本地到 MCP 服务端的连接没建立。检查三点:URL 是否完整(带?key=)、transport 是否写sse、网络是否能访问mcp.amap.com。如果是 Cline 或 Claude Code,确认 MCP 配置文件的 JSON 格式没写错,少个逗号也会导致解析失败。
reading choices 报错。典型信息是Error reading choices或choices field missing。这说明模型返回的结构不是标准 OpenAI 格式,常见于 Base URL 填错。确认base_url是https://taotoken.net/api,不要多加/v1,SDK 会自己拼。如果用的是非 OpenAI 兼容的 SDK,检查它是否期望choices字段。
OAuth 相关报错。如果你在 Claude Code 里配 MCP,可能遇到 OAuth 流程问题。Claude Code 的 MCP 配置里,SSE 类型一般不需要 OAuth,如果它提示要授权,检查是不是把 transport 写成了需要 OAuth 的类型。正确写法是"transport": "sse"。Claude Code 的接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,里面有 MCP 配置示例。
工具列表为空。get_tools()返回空数组,说明 SSE 连上了但没拉到工具。检查高德 key 是否有 MCP 权限,有些 key 只开了 Web 服务没开 MCP。去高德开放平台确认服务类型。
模型不调用工具。工具列表有,但模型直接回答不调工具。原因通常是模型不支持 function calling,或者系统提示没引导。换一个支持工具调用的模型,或在 prompt 里明确「你必须使用提供的工具查询,不要凭记忆回答」。
参数格式错误。高德返回INVALID_PARAMS。看模型填的 args,常见是经纬度顺序、radius 类型(字符串 vs 数字)、keywords 为空。在系统提示里把参数格式写死,能大幅降低这类错误。
排查顺序建议:先确认模型侧通(模型对话页发消息),再确认 MCP 侧通(工具列表非空),最后确认工具调用通(ToolMessage status 为 1)。一层一层来,别跳。
6. 把链路固定下来:后续多智能体的接入建议
单 Agent 调高德 MCP 跑通后,下一步通常是多智能体。我的建议是把 MCP 连接和模型配置抽成独立模块,别写死在业务代码里。这样加第二个、第三个 MCP 服务时,只改配置不改逻辑。
具体做法:建一个mcp_config.json管所有 MCP 服务端,建一个.env管所有 key。Agent 启动时读配置,动态创建MultiServerMCPClient。模型侧统一走 TaoToken 的https://taotoken.net/api,所有 Agent 共用一套 Base URL 和 Key,只是 Model ID 可以按任务不同而不同。
长期跑 Agent 任务的话,Coding Plan 比按量更划算,地址 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入细节翻文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,模型列表在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。key 管理还是那个页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
最后说个实用技巧:把每次工具调用的 args 和返回的 status 记到日志里,跑一周你就能看出哪些工具最常失败、哪些参数模型老填错。针对性改系统提示,比盲目调 temperature 有效得多。链路稳定后,再往上叠多智能体编排,地基才牢。