ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

ASP.NET Core 实战:为 MCP Streamable HTTP 配置 TaoToken 统一 API 通道

ASP.NET Core 实战:为 MCP Streamable HTTP 配置 TaoToken 统一 API 通道 1. 为什么要在 ASP.NET Core 里给 MCP 套一层统一 API 通道MCP 的 Streamable HTTP 传输方式本质上是把原本跑在本地 stdio 上的工具服务改成一个标准的 HTTP 端点。你可以在 ASP.NET Core 里用ModelContextProtocol.AspNetCore这个包把McpServerTool标记的方法暴露成/路径下的 Streamable HTTP 接口然后任何支持 MCP 的客户端——Cline、CC Switch、TRAE 之类——都能通过一个 URL 连上来调用你的工具。问题出在“多工具复用”这一步。你本地跑通一个 MCP Server 之后往往不止一个客户端要用它Cline 里配一份、CC Switch 里配一份、可能还有个自研的 Agent 也要接。如果每个客户端都各自去直连上游模型 APIKey 就散落在各个配置文件里换一次 Key 要改五六个地方额度也没法统一看。更麻烦的是有些客户端对上游地址的格式要求不一样你没法保证同一套配置能原样搬过去。我试过的做法是在 ASP.NET Core 的 MCP Server 和上游模型之间插一个统一 API 通道。MCP Server 本身只负责“工具的定义与调用”真正要访问大模型能力时走同一个 Base URL 和同一把 Key。这样 Cline、CC Switch 这些客户端连的是你的 MCP Server而你的 MCP Server 连的是统一通道Key 只存在一个地方。这篇就按这个思路给你一套可复制的appsettings.json与Program.cs骨架再演示怎么用 Streamable HTTP 请求验证通道是否打通。目标是一次配置多工具复用。2. TaoToken 统一通道的前置准备TaoToken 在这里扮演的角色是那个“统一 API 通道”。它提供一个兼容常见模型调用格式的 Base URL你把 Key 配一次ASP.NET Core 里的 HttpClient 就固定往这个地址发请求。后面不管换 Cline 还是 CC Switch它们连的都是你本地的 MCP Server不需要各自再配一遍上游。你需要先拿到两样东西API Key 和 Base URL。Key 在控制台的 API Keys 页面创建地址是https://taotoken.net/api-keys。创建完复制出来后面写进appsettings.Development.json不要硬编码进Program.cs。Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数直接作为 HttpClient 的BaseAddress。如果你在文档里看到别的路径拼接方式以接入文档为准地址是https://taotoken.net/doc。有一点要提醒Key 属于敏感信息本地开发放appsettings.Development.json并加进.gitignore生产环境走环境变量或密钥管理服务。别图省事写死在代码里后面换 Key 会很难受。3. 可复制的 appsettings.json 与 Program.cs 配置骨架先建一个 ASP.NET Core Web API 项目目标框架选 .NET 8 或更高。然后通过 NuGet 安装ModelContextProtocol.AspNetCore记得勾选“包括预发行版”因为这个包目前还是预览状态。3.1 appsettings.json 里的通道配置把通道相关的配置集中放在一个节点下方便后面切换环境{ TaoToken: { BaseUrl: https://taotoken.net/api, ApiKey: , DefaultModel: claude-sonnet-4-20250514 }, Logging: { LogLevel: { Default: Information, Microsoft.AspNetCore: Warning } }, AllowedHosts: * }ApiKey留空实际值写在appsettings.Development.json里{ TaoToken: { ApiKey: sk-你的实际Key } }这样提交到仓库的appsettings.json不含密钥本地开发用 Development 覆盖生产用环境变量TaoToken__ApiKey覆盖命名规则是双下划线代替冒号。3.2 Program.cs 注册 MCP Server 与统一 HttpClient核心是把 MCP 服务和 HttpClient 都注册进容器HttpClient 的 BaseAddress 指向 TaoToken 通道using HelloWorldMcp.Tools; using System.Net.Http.Headers; var builder WebApplication.CreateBuilder(args); // 读取 TaoToken 通道配置 var taoTokenBaseUrl builder.Configuration[TaoToken:BaseUrl] ?? throw new InvalidOperationException(TaoToken:BaseUrl 未配置); var taoTokenApiKey builder.Configuration[TaoToken:ApiKey] ?? throw new InvalidOperationException(TaoToken:ApiKey 未配置); // 注册 MCP Server启用 Streamable HTTP 传输 builder.Services.AddMcpServer() .WithHttpTransport() .WithToolsHelloWorldTool(); // 注册统一通道 HttpClient所有模型调用走这里 builder.Services.AddHttpClient(TaoToken, client { client.BaseAddress new Uri(taoTokenBaseUrl); client.DefaultRequestHeaders.Authorization new AuthenticationHeaderValue(Bearer, taoTokenApiKey); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue(application/json)); }); var app builder.Build(); // 把 MCP 端点映射到根路径 app.MapMcp(); app.Run();这里的关键点是AddHttpClient(TaoToken, ...)这一段。命名客户端的好处是你的 Tool 里通过IHttpClientFactory.CreateClient(TaoToken)拿到的是一个已经配好 BaseAddress 和 Authorization 的实例不用每次手动拼 Header。换 Key 只改配置不动代码。3.3 一个调用统一通道的 MCP Tool 示例在Tools文件夹下建HelloWorldTool.cs里面放两个工具一个纯本地返回一个通过 TaoToken 通道发起请求using System.Text.Json; using ModelContextProtocol.Server; using System.ComponentModel; namespace HelloWorldMcp.Tools; public class HelloWorldTool(IHttpClientFactory httpClientFactory) { [McpServerTool, Description(返回一条本地问候用于验证 MCP 连接是否正常)] public string GetHelloWorld() { return Hello world from Streamable Http tool.; } [McpServerTool, Description(通过 TaoToken 统一通道发起一次模型对话请求返回模型回复文本)] public async Taskstring AskModel( [Description(要发送给模型的问题内容)] string prompt) { var client httpClientFactory.CreateClient(TaoToken); var payload new { model claude-sonnet-4-20250514, max_tokens 256, messages new[] { new { role user, content prompt } } }; using var response await client.PostAsJsonAsync(/v1/messages, payload); response.EnsureSuccessStatusCode(); using var doc await JsonDocument.ParseAsync( await response.Content.ReadAsStreamAsync()); // 按实际返回结构取文本这里以 content 数组第一段为例 var text doc.RootElement .GetProperty(content)[0] .GetProperty(text) .GetString(); return text ?? string.Empty; } }AskModel这个工具就是“统一通道”的落点它不关心上游是谁只往TaoToken这个命名客户端发请求。你后面在 Cline 或 CC Switch 里调用这个工具实际流量路径是“客户端 → 你的 MCP Server → TaoToken 通道 → 模型”。4. 验证 Streamable HTTP 请求与成功结果配置写完dotnet run启动项目。控制台会打印监听地址类似http://localhost:5295。因为原来的 Weather 示例 API 被移除了直接访问根路径可能返回 404这是正常的——MCP 端点走的是 POST 请求和特定的 Accept 头。4.1 用 curl 验证 MCP 端点先确认 MCP 服务在监听。Streamable HTTP 的握手需要Accept: application/json, text/event-streamcurl -i -X POST http://localhost:5295/ \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: { name: curl-test, version: 1.0 } } }如果返回里带result和serverInfo说明 MCP Server 已经正常响应。这一步不涉及 TaoToken 通道只是确认 MCP 本身活着。4.2 验证统一通道是否打通MCP 端点通了之后再验证AskModel工具背后的通道。最直接的方式是在客户端里调用这个工具但如果你想先在服务端确认通道可用可以临时加一个最小 API 端点做探针app.MapGet(/health/taotoken, async (IHttpClientFactory factory) { var client factory.CreateClient(TaoToken); var payload new { model claude-sonnet-4-20250514, max_tokens 32, messages new[] { new { role user, content ping } } }; using var resp await client.PostAsJsonAsync(/v1/messages, payload); return Results.Ok(new { status (int)resp.StatusCode }); });启动后访问http://localhost:5295/health/taotoken返回{status:200}就说明 Key 和 Base URL 都对了。这个探针验证完可以删掉避免暴露额外端点。4.3 在客户端里复用同一通道以 Cline 为例在 MCP 配置里加上你的本地服务地址{ mcpServers: { helloworld_mcp: { url: http://localhost:5295 } } }CC Switch 的配置方式类似填同一个 URL 即可。两个客户端连的是同一个 MCP Server而 MCP Server 连的是同一个 TaoToken 通道。你换 Key 的时候只改appsettings.Development.json一处两个客户端都不用动。如果你更习惯在命令行里做长期编码任务也可以把同一套通道配置用在 Coding Plan 场景地址是https://taotoken.net/coding-plan思路是一样的通道统一客户端只负责连本地 MCP。5. 本篇常见错误排查5.1 启动报错 “TaoToken:ApiKey 未配置”说明appsettings.Development.json没被加载或者键名拼错了。检查两点文件是否在项目根目录、ApiKey是否写在TaoToken节点下。环境变量方式的话确认变量名是TaoToken__ApiKey两个下划线。5.2 MCP 端点返回 404 或 405Streamable HTTP 要求 POST 请求并且Accept头必须同时包含application/json和text/event-stream。只带application/json会被拒。另外确认app.MapMcp()在app.Run()之前调用顺序错了端点不会注册。5.3 通道请求返回 401Key 无效或没带上。检查AuthenticationHeaderValue(Bearer, taoTokenApiKey)里的 Key 是否有多余空格以及appsettings.Development.json是否真的被读取。可以在启动时打印一下taoTokenApiKey.Length确认非零。5.4 客户端连上 MCP 但工具列表为空WithToolsHelloWorldTool()里的类型必须是public且方法带[McpServerTool]特性。如果工具类是internal反射扫不到。另外确认 NuGet 包版本一致预览版之间 API 有变动。5.5 请求超时默认 HttpClient 超时是 100 秒模型长回复可能不够。可以在注册时加client.Timeout TimeSpan.FromMinutes(5);。但更推荐在 MCP 工具层面做流式处理避免单次请求挂太久。6. 把通道固定下来客户端随便换整套配置的核心就一句话MCP Server 负责工具定义TaoToken 通道负责模型访问两者通过命名 HttpClient 解耦。你后面不管加 Cline、CC Switch 还是别的客户端都只是往mcpServers里加一个 URLKey 和 Base URL 永远只维护一份。如果你还没建 Key去https://taotoken.net/api-keys创建一个填进appsettings.Development.json然后按第 4 节的探针验证一次。通道通了之后再回头把AskModel换成你实际要用的模型调用逻辑。接入细节以https://taotoken.net/doc为准模型对话调试可以用https://taotoken.net/models先确认参数格式。
返回列表