☰
LangChain+MCP(模型上下文协议)实现案例:用 TaoToken 统一 Key 打通 Agent 工具链
2026/9/25 3:20:32 网站建设 项目流程

1. 从一次本地多工具联调说起:LangChain Agent 接 MCP 到底卡在哪

如果你正在用 LangChain 搭 Agent,又想让它调用本地文件、数据库、内部接口这类外部能力,大概率会碰到同一个问题:工具怎么接、Key 怎么管、多个工具怎么统一调度。MCP(模型上下文协议)就是为解决这件事而生的,它把「模型能调用什么工具」抽象成一套标准协议,LangChain 通过langchain-mcp-adapters就能把 MCP Server 暴露的工具直接变成 Agent 的 tools。

但真正动手时,链路会变得很碎:math_server 用 stdio 传输、weather_server 用 SSE 传输、模型侧还要配 base_url 和 API Key,如果每个模型、每个工具都单独配一套凭证,本地联调很快就会乱成一锅粥。这篇就聚焦这个场景,用 TaoToken 统一 Key 把模型调用这一层收敛掉,再给出config.toml与settings.json骨架、Key 的填入位置,以及一次 Agent 调用工具的完整验证动作和预期返回,让你能照着复现一条可运行的 MCP 接入流程。

适合谁看:已经会写基础 LangChain Agent、想接 MCP 工具但被配置链路劝退的同学;以及本地同时跑多个 MCP Server、想统一管理模型凭证的开发者。下面所有步骤都在本地环境完成,不涉及任何网络层特殊配置。

2. TaoToken 前置:统一 Key 在 MCP 链路里的位置

先说清楚 TaoToken 在这条链路里扮演什么角色。MCP 负责「工具侧」的协议标准化,TaoToken 负责「模型侧」的凭证统一。你原本可能要在.env里分别写DEEPSEEK_API_KEY、ZHIPUAI_API_KEY、OPENAI_API_KEY,每换一个模型就改一次配置;用 TaoToken 之后,模型调用统一走一个 base_url 和一个 Key,Agent 侧只需要认这一套凭证。

具体来说,LangChain 里ChatOpenAI兼容 OpenAI 协议,所以只要把openai_api_base指向 TaoToken 的 API 地址,openai_api_key填 TaoToken 生成的 Key,模型名按需切换即可。这样 MCP 工具链不变,模型层却可以随时换。

你需要先拿到 Key。进入控制台创建 API Key,地址是:

https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_console

创建后复制那串sk-开头的 Key,后面填进.env或settings.json。API 基础地址统一用:

https://taotoken.net/api

注意这个地址不加任何 UTM 参数,直接作为openai_api_base使用。如果你对模型对话能力想先单独验证,可以走模型对话入口:

https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_chat

长期做编码或 Agent 联调、调用量比较大的,可以看 Coding Plan:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_plan

接入文档在:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_doc

API Keys 管理页在:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_keys

3. 可复制配置:config.toml 与 settings.json 骨架

这一节给出两份配置文件骨架。config.toml用来描述 MCP Server 的启动方式,settings.json用来放模型凭证和运行参数。两者配合,Agent 启动时读配置、连 Server、拿 tools。

先看config.toml,它把两个 MCP Server 的传输方式和启动命令写清楚:

# config.toml [llm] provider = "openai-compatible" base_url = "https://taotoken.net/api" model = "glm-4-flashx" api_key_env = "TAOTOKEN_API_KEY" [mcp_servers.math] transport = "stdio" command = "python" args = ["./math_server.py"] [mcp_servers.weather] transport = "sse" url = "http://localhost:8000/sse" [agent] max_iterations = 8 verbose = true

这里api_key_env指向环境变量名,而不是把 Key 明文写进 toml,避免误提交。模型名glm-4-flashx只是示例,你可以按 TaoToken 支持的模型列表替换。

再看settings.json,它承担运行期参数和 Key 的注入:

{ "llm": { "base_url": "https://taotoken.net/api", "api_key": "${TAOTOKEN_API_KEY}", "model": "glm-4-flashx", "temperature": 0.2 }, "mcp": { "math": { "command": "python", "args": ["./math_server.py"], "transport": "stdio" }, "weather": { "url": "http://localhost:8000/sse", "transport": "sse" } }, "runtime": { "timeout_seconds": 60, "retry": 2 } }

Key 的填入位置就在settings.json的llm.api_key,用${TAOTOKEN_API_KEY}占位,实际值放.env:

# .env TAOTOKEN_API_KEY=sk-你的TaoToken密钥

这样模型侧只认一个 Key,MCP 侧只认配置文件里的 Server 列表,职责清晰。依赖安装:

pip install langchain-mcp-adapters langgraph langchain-openai python-dotenv

Python 版本要求 3.10 及以上。

4. 验证请求:一次 Agent 调用工具的完整动作与预期返回

配置就绪后,写两个 MCP Server。math_server.py用 stdio 传输:

# math_server.py from mcp.server.fastmcp import FastMCP mcp = FastMCP("Math") @mcp.tool() def add(a: int, b: int) -> int: """对两个整数相加""" return a + b @mcp.tool() def multiple(a: int, b: int) -> int: """对两个整数相乘""" return a * b if __name__ == "__main__": mcp.run(transport="stdio")

weather_server.py用 SSE 传输,默认监听 8000 端口:

# weather_server.py from mcp.server.fastmcp import FastMCP mcp = FastMCP("Weather") @mcp.tool() async def get_weather(location: str) -> str: """获取位置的天气。""" return f"{location}当前天气晴朗,温度 25°C" if __name__ == "__main__": mcp.run(transport="sse")

开两个终端分别启动:

python math_server.py python weather_server.py

stdio 的 Server 启动后没有输出是正常的,SSE 的会通过 uvicorn 起一个 HTTP 服务。接着写客户端,把模型指向 TaoToken:

# client.py import asyncio import os from dotenv import load_dotenv from langchain_mcp_adapters.client import MultiServerMCPClient from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI load_dotenv() model = ChatOpenAI( openai_api_base="https://taotoken.net/api", openai_api_key=os.getenv("TAOTOKEN_API_KEY"), model_name="glm-4-flashx", ) async def run_client(): async with MultiServerMCPClient( { "math": { "command": "python", "args": ["./math_server.py"], "transport": "stdio", }, "weather": { "url": "http://localhost:8000/sse", "transport": "sse", }, } ) as client: agent = create_react_agent(model, client.get_tools()) math_response = await agent.ainvoke( {"messages": "请问(3 + 5) x 12=多少?"} ) print("Math Response:", math_response["messages"][-1].content) weather_response = await agent.ainvoke( {"messages": "请问北京今天天气怎么样?"} ) print("Weather Response:", weather_response["messages"][-1].content) if __name__ == "__main__": asyncio.run(run_client())

运行python client.py,预期返回类似:

Math Response: (3 + 5) x 12 = 96 Weather Response: 北京当前天气晴朗,温度 25°C

看到这两行,说明 Agent 已经通过 MCP 成功调用了两个 Server 的工具,模型侧走的是 TaoToken 统一 Key。这一步是整个链路的关键验证点:工具被真实触发、参数被正确传递、结果被模型整合成自然语言。

5. 本篇常见错排查:NotImplementedError 与配置踩坑

第一个高频报错是NotImplementedError,出现在实例化MultiServerMCPClient的过程中,尤其在 Windows + Python 3.12 环境下。根因是 asyncio 的 subprocess 在 Windows 默认事件循环下不支持,而 stdio 传输依赖子进程。处理方式是在入口处显式设置事件循环策略:

import asyncio import sys if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())

把这段放在asyncio.run()之前。如果是在 FastAPI 里调用,注意 FastAPI 自己管理事件循环,需要在应用启动时设置策略,而不是在路由函数里临时改。

第二个坑是路径问题。args里的./math_server.py是相对当前工作目录的,如果你从别的目录启动 client,会找不到文件。稳妥做法是用绝对路径:

import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) "args": [os.path.join(BASE_DIR, "math_server.py")]

第三个坑是 SSE Server 没起来就去连,报连接拒绝。确认weather_server.py已经在 8000 端口监听,再跑 client。stdio 的 Server 不需要手动确认端口,但它的进程必须能被 client 拉起。

第四个坑是 Key 没读到。load_dotenv()要在读取os.getenv之前调用,且.env文件要在当前工作目录。如果返回 401,先检查TAOTOKEN_API_KEY是否为空,再确认 base_url 是https://taotoken.net/api而不是别的路径。

报错现象可能原因处理方式
NotImplementedErrorWindows 事件循环不支持子进程设置 ProactorEventLoopPolicy
FileNotFoundErrorServer 路径为相对路径改用绝对路径
Connection refusedSSE Server 未启动先启动 weather_server
401 UnauthorizedKey 未加载或错误检查 .env 与 base_url

6. 把 Key 收敛之后,MCP 联调才真正可维护

走到这里,你应该已经跑通了一条完整的链路:两个 MCP Server 分别用 stdio 和 SSE 传输,LangChain Agent 通过MultiServerMCPClient拿到 tools,模型侧用 TaoToken 统一 Key 调用。整个过程里,模型凭证只有一处,工具配置只有一份,换模型不用动 MCP 配置,加工具不用动模型配置。

如果你后面要把这套东西接到 FastAPI 里做接口,建议把 model、MCPClient、Agent 的创建封装成单例或依赖注入,不要在每次请求里重新实例化MultiServerMCPClient,否则既慢又容易触发事件循环相关问题。长期做编码和 Agent 联调的话,Coding Plan 会比按量调用更省心:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_plan_end

需要新建或轮换 Key 时走 API Keys 页:

https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_keys_end

接入细节和参数说明以官方文档为准:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=mcp_doc_end

先把client.py跑出那两行预期返回,再往 FastAPI 封装走,顺序别反,能省掉大半排障时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询