ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

回顾|Let‘s Learn MCP:Python C# 双语言接入 TaoToken 配置实战

回顾|Let‘s Learn MCP:Python  C# 双语言接入 TaoToken 配置实战 1. 为什么要在 Python 和 C# 里同时接 MCPMCPModel Context Protocol是一套让模型和外部工具、数据源之间按统一格式交换上下文与函数调用的协议。你可以把它理解成「模型世界的 USB-C 接口」以前每个客户端要对接不同模型的函数调用格式现在只要按 MCP 约定写好工具描述和调用入口模型侧就能用同一套方式发现工具、传参、拿结果。它适合谁适合手里同时有 Python 脚本和 C# 服务、又想把多模型 Key 收拢到一处管理的开发者。我这次要解决的真实场景是这样的一个内部知识助手Python 侧负责数据清洗和向量检索C# 侧是一个 .NET 控制台服务负责业务查询两边都要调用大模型但 Key 分散在各自的配置文件里换模型、换额度、排查 401 都要改好几处。目标是把两端的模型通道统一到 TaoToken 的 API 地址上用同一套 Key 管理然后各写一个最小的 MCP 工具调用验证连通性。下面给出 Python 与 C# 两端的可复制配置骨架包含settings.json和config.toml示例并演示一次工具调用与连通性验证。全程只依赖官方 API 地址不涉及任何网络加速手段。2. TaoToken 前置准备Key、地址与文档入口在写代码之前先把「通道」准备好。TaoToken 在这里扮演的是统一模型接入层你拿到一个 API Key把请求的 base URL 指向它Python 和 C# 就都能走同一条通道不用为每个模型单独维护一套鉴权。需要准备的东西只有三样第一一个可用的 API Key。登录后在控制台的 API Keys 页面创建建议按项目命名比如mcp-python-demo、mcp-csharp-demo方便后面按 Key 排查调用来源。第二确认 API 基地址。代码里统一使用https://taotoken.net/api注意这个地址后面不要带多余的路径具体端点由 SDK 或请求体决定。第三把文档放在手边。接入细节和参数说明以官方文档为准遇到字段不确定时先查文档再改代码比反复试错快得多。提示Key 只放在环境变量或本地配置文件里不要提交到 Git。C# 项目里尤其注意appsettings.json别把真实 Key 写进仓库。如果你还想先确认模型侧是否正常可以先用模型对话页面发一条消息确认账号和额度没问题再回到代码里调。3. Python 端 MCP 接入settings.json 与最小工具调用Python 侧我用的是「配置 客户端封装」的写法把模型通道参数集中到一个settings.json代码只读配置不硬编码。3.1 settings.json 配置骨架{ mcp: { server_name: taotoken-demo, transport: stdio }, llm: { base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model: gpt-4o-mini, timeout: 30 }, tools: [ { name: get_weather, description: 根据城市名查询当前天气, parameters: { type: object, properties: { city: { type: string, description: 城市名称例如 Shanghai } }, required: [city] } } ] }这里的关键点base_url指向 TaoToken 的 API 地址api_key_env写的是环境变量名而不是 Key 本身这样配置可以安全地进版本库。tools数组就是 MCP 里工具描述的最小形态模型靠description和parameters决定要不要调用、怎么传参。3.2 读取配置并注册工具import json import os from openai import OpenAI with open(settings.json, r, encodingutf-8) as f: cfg json.load(f) client OpenAI( base_urlcfg[llm][base_url], api_keyos.environ[cfg[llm][api_key_env]], timeoutcfg[llm][timeout], ) def get_weather(city: str) - str: fake_db {Shanghai: 26C cloudy, Beijing: 22C sunny} return fake_db.get(city, unknown) tools [ { type: function, function: { name: t[name], description: t[description], parameters: t[parameters], }, } for t in cfg[tools] ]注意tools的转换MCP 里描述工具用的是 JSON Schema而多数模型 SDK 的函数调用格式是{type: function, function: {...}}中间这层映射自己写一次就够了后面加工具只改settings.json。3.3 发起一次带工具调用的请求messages [{role: user, content: 上海现在天气怎么样}] resp client.chat.completions.create( modelcfg[llm][model], messagesmessages, toolstools, tool_choiceauto, ) msg resp.choices[0].message if msg.tool_calls: call msg.tool_calls[0] args json.loads(call.function.arguments) result get_weather(**args) print(tool_call:, call.function.name, args) print(tool_result:, result) else: print(direct_answer:, msg.content)跑通后你会看到类似tool_call: get_weather {city: Shanghai}和tool_result: 26C cloudy的输出。这说明模型正确识别了工具、按 Schema 传参而请求全程走的是 TaoToken 的通道。4. C# 端 MCP 接入config.toml 与工具调用C# 侧我用 .NET 的控制台项目配置换成config.toml方便和 Python 侧的 JSON 形成对照也便于团队里不同技术栈的人各看各的。4.1 config.toml 配置骨架[mcp] server_name taotoken-demo-dotnet transport stdio [llm] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY model gpt-4o-mini timeout_seconds 30 [[tools]] name get_weather description 根据城市名查询当前天气 [tools.parameters] type object [tools.parameters.properties.city] type string description 城市名称例如 Shanghai [tools.parameters.required] cities [city]TOML 的嵌套写法比 JSON 啰嗦一点但可读性好尤其是工具多起来之后每个[[tools]]块边界清晰。4.2 读取配置与构造请求using System.Text.Json; using Tomlyn; using Tomlyn.Model; var toml File.ReadAllText(config.toml); var model Toml.ToModel(toml); var llm (TomlTable)model[llm]; var baseUrl llm[base_url]!.ToString(); var apiKey Environment.GetEnvironmentVariable(llm[api_key_env]!.ToString()!)!; var modelName llm[model]!.ToString(); using var http new HttpClient(); http.DefaultRequestHeaders.Add(Authorization, $Bearer {apiKey}); var payload new { model modelName, messages new[] { new { role user, content 北京现在天气怎么样 } }, tools new[] { new { type function, function new { name get_weather, description 根据城市名查询当前天气, parameters new { type object, properties new { city new { type string } }, required new[] { city } } } } }, tool_choice auto }; var json JsonSerializer.Serialize(payload); var content new StringContent(json, System.Text.Encoding.UTF8, application/json); var resp await http.PostAsync(${baseUrl}/v1/chat/completions, content); var body await resp.Content.ReadAsStringAsync(); Console.WriteLine(body);这里有两个容易踩的点一是baseUrl拼接端点时用/v1/chat/completions不要重复写/api二是Authorization头必须是Bearer加 Key中间一个空格少写会直接 401。4.3 解析工具调用结果using var doc JsonDocument.Parse(body); var message doc.RootElement .GetProperty(choices)[0] .GetProperty(message); if (message.TryGetProperty(tool_calls, out var toolCalls)) { var call toolCalls[0]; var fnName call.GetProperty(function).GetProperty(name).GetString(); var fnArgs call.GetProperty(function).GetProperty(arguments).GetString(); Console.WriteLine($tool_call: {fnName} {fnArgs}); } else { Console.WriteLine($direct_answer: {message.GetProperty(content).GetString()}); }拿到tool_calls后按name分发到你自己的 C# 方法即可和 Python 侧逻辑完全对称。5. 连通性验证与常见报错排查两端都写完后先做一次最小连通性验证再排查问题顺序别反。5.1 三步验证法第一步只验证鉴权。用 curl 发一条最简单的请求确认 Key 和地址没问题curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:ping}]}返回里有choices字段就说明通道通了。第二步跑 Python 脚本看是否出现tool_call。第三步跑 C# 控制台对比输出结构是否一致。三步都过说明 MCP 接入骨架成立。5.2 常见报错对照报错现象可能原因处理方式401 UnauthorizedKey 未读到或格式错检查环境变量名与Bearer空格404 Not Foundbase_url 拼了多余路径基地址只留https://taotoken.net/api模型不识别工具tools 结构不符合 SDK 格式确认包了type: function外层C# 读 TOML 报错表嵌套写法不对对照[[tools]]与[tools.parameters]层级超时timeout 设太短Python 调timeoutC# 调HttpClient.Timeout注意如果 Python 能通、C# 报 401八成是 C# 侧环境变量没设进当前进程重启终端或 IDE 再试。排查时优先用 curl 定位是通道问题还是代码问题这一步能省掉大量猜测。接入参数和端点细节以接入文档为准别凭记忆改。6. 后续怎么把这套骨架用起来跑通之后我建议做两件事。一是把工具描述从settings.json和config.toml里抽出来做成两端共享的一份 Schema避免 Python 加了工具、C# 忘了同步。二是把 Key 按用途拆开比如对话类、编码类各用一个方便在控制台看用量。如果你后面要做长期编码或 Agent 类任务可以了解下 Coding Plan它更适合持续性的开发场景日常验证模型是否正常用模型对话页面最快需要新建或轮换 Key就去 API Keys 页面操作。把这两端骨架留着下次接新工具时只改配置、不动主逻辑这才是统一 Key 管理真正省事的地方。
返回列表