资讯动态

把 ASP.NET Core Web API 封装成 MCP 工具:TaoToken 统一 Key 接入第三方 Agent 的 JWT 鉴权实践

发布时间:2026/10/12 22:01:51 来源:尧图企业网站定制
1. 从 Web API 到 MCP 工具第三方 Agent 调用时的 JWT 鉴权痛点你手上有一套跑得好好的 ASP.NET Core Web API比如订单查询、库存同步、天气数据这类业务接口。现在想让第三方 Agent不管是 Cursor、Cline 还是你自己写的 Agent 框架通过自然语言来调用它第一反应通常是把接口封装成 MCP 工具。这个方向没问题MCP 协议本来就是干这个的——把已有的 HTTP 能力包装成模型能理解、能选择、能传参的工具描述。但真正动手之后卡点往往不在 MCP 本身而在鉴权。你的 API 不是公开的它需要 JWT。第三方 Agent 要调用你的 MCP 工具就得先拿到合法的 Token。问题来了Token 从哪来谁来签发Agent 侧怎么携带如果每个 Agent 都自己维护一套密钥那密钥管理就变成了灾难。更麻烦的是很多 Agent 运行在浏览器或第三方托管环境里你不可能把签名密钥直接塞进去。我试过最直接的做法在 MCP Server 里加一个/auth/token接口Agent 先调这个接口拿 JWT再把 JWT 放进 MCP 请求的Authorization头。这个思路能跑通但暴露了一个新问题——/auth/token本身怎么保护如果它完全开放那等于没有鉴权如果它也需要凭证那凭证又该由谁统一管理。这就是 TaoToken 要解决的位置。它提供统一的 Key 和 API 通道让第三方 Agent 在调用你的 MCP 工具时走一条可管理、可审计的鉴权路径。你不需要把 JWT 签发逻辑散落到每个 Agent 里也不需要为每个调用方单独开账号。Agent 侧只需要配置一个统一的 Base URL、一个 Key、一个 Model ID剩下的 JWT 校验、Token 传递、请求转发由 TaoToken 通道完成。这篇文章要做的就是把这条链路完整走一遍ASP.NET Core Web API 怎么封装成 MCP 工具JWT 校验中间件怎么写TaoToken 端点怎么配Agent 侧怎么调用以及 401 报错怎么排查。适合已经有一套 ASP.NET Core API、想让第三方 Agent 安全调用的后端开发者。如果你还没写过 MCP 工具也没关系下面的步骤是从零开始的照着配就能跑。2. TaoToken 前置准备统一 Key 与 MCP 端点配置在写代码之前先把 TaoToken 这一侧的东西准备好。很多人一上来就埋头写Program.cs结果 Agent 调不通回头查半天发现是 Key 没配对或者端点写错了。所以这一步先做做完再进代码。TaoToken 的核心作用是给第三方 Agent 提供一个统一的接入通道。你的 ASP.NET Core MCP Server 暴露的是标准 HTTP EndpointAgent 不直接连你的服务器而是通过 TaoToken 的 API 通道来访问。这样做的好处是Key 由 TaoToken 统一管理JWT 校验在你的 MCP Server 里完成两边职责清晰。你需要准备三样东西Base URL、API Key、Model ID。Base URL 是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 Agent 侧配置的端点前缀。API Key 在控制台里生成路径是https://taotoken.net/console进去之后找到 API Keys 页面新建一个 Key。这个 Key 就是第三方 Agent 调用时携带的凭证不要硬编码到前端代码里放在服务端环境变量或配置文件里。Model ID 取决于你 Agent 侧用的是什么模型。如果你用的是 Claude 系列做工具调用Model ID 就填对应的模型标识如果用 GPT 系列填对应的。这个 Model ID 的作用是告诉 TaoToken 通道这次请求要转发给哪个模型做工具选择。注意Model ID 和你的 MCP 工具是两回事——MCP 工具是你自己定义的业务能力Model ID 是负责决策“调不调、调哪个”的模型。配置的时候有个细节容易踩坑Base URL 和 MCP Endpoint 是两个不同的地址。Base URL 是 TaoToken 的入口MCP Endpoint 是你自己 ASP.NET Core 应用里MapMcp()映射出来的路径通常是/mcp或者你自定义的路径。Agent 侧配置的是 Base URL你的 MCP Server 里配置的是 JWT 校验逻辑。两者通过 TaoToken 通道串起来。如果你用的是 Claude Code 这类工具配置方式会略有不同。Claude Code 的配置文件里需要填 Base URL、API Key、Model ID 三件套。Base URL 填https://taotoken.net/apiAPI Key 填控制台生成的 KeyModel ID 填你要用的模型。配置完之后Claude Code 发出的工具调用请求会先到 TaoToken再由 TaoToken 转发到你的 MCP Server。你的 MCP Server 只需要校验 JWT不需要关心请求是从哪个 Agent 来的。还有一个容易忽略的点TaoToken 的 API Key 和你的 JWT 是两层不同的认证。API Key 是 Agent 到 TaoToken 这一层的凭证JWT 是 TaoToken 到你的 MCP Server 这一层的凭证。两层分开的好处是你可以在 TaoToken 侧做 Key 的轮换和权限控制而不需要动 MCP Server 的代码。JWT 的签发和校验完全在你的 ASP.NET Core 应用里完成TaoToken 只负责传递。准备好这三样之后先别急着写 MCP 工具。打开终端用 curl 测一下 TaoToken 的端点是否可达curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer YOUR_TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: YOUR_MODEL_ID, messages: [{role: user, content: ping}] }如果返回 200 并且有正常的 JSON 响应说明 Key 和端点都没问题。如果返回 401检查 Key 是否复制完整如果返回 404检查 Base URL 是否写成了https://taotoken.net/api而不是其他路径。这一步过了再进下一节的代码配置。3. 可复制配置MCP 工具描述、JWT 中间件与 TaoToken 端点这一节是全文的核心所有配置片段都可以直接复制到你的项目里。我按文件路径来组织你对照自己的项目结构放进去就行。先看 MCP Server 的项目文件。假设你的项目叫AspNetCoreMcpServer在.csproj里需要引入三个包ItemGroup PackageReference IncludeModelContextProtocol.AspNetCore Version0.4.0-preview / PackageReference IncludeMicrosoft.AspNetCore.Authentication.JwtBearer Version10.0.0 / PackageReference IncludeMicrosoft.AspNetCore.OpenApi Version10.0.0 / /ItemGroupModelContextProtocol.AspNetCore是 MCP 官方 C# SDK 的 ASP.NET Core 支持包JwtBearer负责 JWT 校验OpenApi是可选的方便你调试接口。接下来是Program.cs里的服务注册。这一段决定了 MCP Server 怎么启动、JWT 怎么校验、CORS 怎么放行var builder WebApplication.CreateBuilder(args); // 注册 MCP Server使用无状态 HTTP 传输 builder.Services.AddMcpServer() .WithHttpTransport(options options.SessionMode HttpServerSessionMode.Stateless) .WithToolsWeatherTools(); // 配置 JWT Bearer 认证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options { options.TokenValidationParameters new TokenValidationParameters { ValidateIssuer true, ValidateAudience true, ValidateLifetime true, ValidateIssuerSigningKey true, ValidIssuer builder.Configuration[Jwt:Issuer], ValidAudience builder.Configuration[Jwt:Audience], IssuerSigningKey new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration[Jwt:SigningKey]!)) }; }); builder.Services.AddAuthorization(); // 配置 CORS允许 Agent 侧来源 builder.Services.AddCors(options { options.AddPolicy(McpAgentClient, policy { policy.WithOrigins( http://localhost:5164, https://localhost:7133) .WithMethods(POST) .WithHeaders( HeaderNames.ContentType, HeaderNames.Authorization, MCP-Protocol-Version) .WithExposedHeaders(HeaderNames.WWWAuthenticate); }); }); var app builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.UseCors(McpAgentClient); // 映射 MCP Endpoint要求授权 app.MapMcp() .RequireAuthorization() .RequireCors(McpAgentClient); app.Run();这里有几个关键点。SessionMode HttpServerSessionMode.Stateless表示 MCP Server 不保存会话状态适合无状态的工具调用场景。RequireAuthorization()加在MapMcp()后面意味着所有访问 MCP Endpoint 的请求都必须通过 JWT 校验。CORS 策略里的WithHeaders必须包含Authorization和MCP-Protocol-Version否则浏览器侧的 Agent 会在预检请求阶段被拦掉。然后是 MCP 工具的定义。这里用一个天气查询作为示例你把它替换成自己的业务逻辑就行[McpServerToolType] public sealed class WeatherTools(IHttpClientFactory httpClientFactory) { [McpServerTool(Name get_china_weather_forecast)] [Description(按中国城市名称查询实时天气和未来三天天气预报。)] public async Taskstring GetChinaWeatherForecast( [Description(中国城市名称例如北京、上海、广州、深圳。)] string city, CancellationToken cancellationToken) { var client httpClientFactory.CreateClient(OpenMeteo); // 这里替换成你自己的业务调用 var response await client.GetStringAsync( $/v1/forecast?city{Uri.EscapeDataString(city)}, cancellationToken); return response; } }[McpServerToolType]声明这个类包含 MCP 工具[McpServerTool]声明具体方法。Name属性是 Agent 侧看到的工具名Description是模型用来判断“该不该调这个工具”的依据写清楚一点模型选择会更准。JWT 签发接口单独放在一个 Controller 里路径是/auth/token[ApiController] [Route(auth)] public class AuthController(IConfiguration configuration) : ControllerBase { [HttpPost(token)] [AllowAnonymous] public IActionResult GetToken([FromBody] TokenRequest request) { // 这里做你的用户校验示例中简化处理 if (string.IsNullOrWhiteSpace(request.ClientId)) return BadRequest(ClientId is required.); var key new SymmetricSecurityKey( Encoding.UTF8.GetBytes(configuration[Jwt:SigningKey]!)); var credentials new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token new JwtSecurityToken( issuer: configuration[Jwt:Issuer], audience: configuration[Jwt:Audience], claims: new[] { new Claim(client_id, request.ClientId) }, expires: DateTime.UtcNow.AddHours(1), signingCredentials: credentials); return Ok(new { access_token new JwtSecurityTokenHandler().WriteToken(token), token_type Bearer, expires_in 3600 }); } } public record TokenRequest(string ClientId);appsettings.json里补上 JWT 配置{ Jwt: { Issuer: https://your-mcp-server, Audience: https://taotoken.net/api, SigningKey: your-256-bit-signing-key-here-at-least-32-chars } }注意Audience填 TaoToken 的 API 地址这样签出来的 JWT 在通过 TaoToken 通道转发时audience 校验能对上。SigningKey至少 32 个字符生产环境用环境变量注入不要提交到仓库。Agent 侧的配置以 Claude Code 为例在配置文件里填三件套{ mcpServers: { aspnet-core-api: { url: https://taotoken.net/api/mcp, headers: { Authorization: Bearer YOUR_TAOTOKEN_KEY } } } }如果你用的是 Cline 或者自己写的 Agent配置逻辑一样Base URL 指向 TaoTokenKey 放在 Authorization 头里Model ID 在模型配置里指定。三件套缺一不可少任何一个都会在调用阶段报错。4. 验证请求Agent 侧调用与成功结果确认配置写完接下来要验证整条链路能不能跑通。验证分两步先确认 MCP Server 本身能正常签发 JWT 并保护 MCP Endpoint再确认 Agent 通过 TaoToken 能成功调用工具。第一步启动你的 ASP.NET Core MCP Server。用dotnet run跑起来默认监听https://localhost:7133。先测 JWT 签发接口curl -X POST https://localhost:7133/auth/token \ -H Content-Type: application/json \ -d {clientId: test-agent} \ -k-k是因为本地开发证书可能不被信任生产环境不需要。正常返回应该是一个 JSON里面有access_token字段。把这个 token 复制出来下一步用。第二步直接测 MCP Endpoint 的鉴权是否生效。先不带 Token 请求curl -X POST https://localhost:7133/mcp \ -H Content-Type: application/json \ -H MCP-Protocol-Version: 2024-11-05 \ -d {jsonrpc:2.0,method:tools/list,id:1} \ -k预期返回 401。如果返回 200说明RequireAuthorization()没生效检查Program.cs里app.UseAuthentication()和app.UseAuthorization()的顺序认证必须在授权之前。再带上刚才拿到的 Token 请求curl -X POST https://localhost:7133/mcp \ -H Content-Type: application/json \ -H Authorization: Bearer YOUR_JWT_TOKEN \ -H MCP-Protocol-Version: 2024-11-05 \ -d {jsonrpc:2.0,method:tools/list,id:1} \ -k这次应该返回 200并且 JSON 里能看到get_china_weather_forecast这个工具的描述。看到这个结果说明 MCP Server 侧的 JWT 校验和工具注册都没问题。第三步通过 TaoToken 通道调用。这一步模拟 Agent 的真实行为。用 curl 直接打 TaoToken 的端点把 MCP 工具调用包装成模型请求curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer YOUR_TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: YOUR_MODEL_ID, messages: [ {role: user, content: 帮我查一下北京现在的天气} ], tools: [ { type: function, function: { name: get_china_weather_forecast, description: 按中国城市名称查询实时天气和未来三天天气预报。, parameters: { type: object, properties: { city: {type: string, description: 中国城市名称} }, required: [city] } } } ] }如果返回的 JSON 里tool_calls字段有内容说明模型正确选择了工具并且 TaoToken 通道把请求转发到了你的 MCP Server。你的 MCP Server 在收到请求后会校验 JWT校验通过后执行GetChinaWeatherForecast方法把结果返回。第四步在 Agent 侧做端到端验证。如果你用的是 Claude Code直接在对话里输入“查一下上海天气”观察它是否调用了get_china_weather_forecast工具。如果调用了并且返回了天气数据说明整条链路通了。如果 Agent 没有调用工具检查 Model ID 是否支持工具调用以及工具描述是否足够清晰。成功的结果长这样Agent 输出里会有一段工具调用记录显示get_china_weather_forecast被调用参数是{city: 上海}然后返回天气数据模型基于数据生成自然语言回答。整个过程你不需要手动传 JWTJWT 的签发和校验都在 MCP Server 内部完成Agent 侧只感知到 TaoToken 的 Key。验证通过之后建议把/auth/token接口加上限流防止被刷。ASP.NET Core 自带的 Rate Limiting 中间件就能做在Program.cs里加一行builder.Services.AddRateLimiter(...)然后在AuthController上挂[EnableRateLimiting(token)]特性。这个不是必须的但生产环境建议加上。5. 常见报错排查401、local proxy failed 与 OAuth 问题链路跑通之前大概率会碰到几个报错。这一节把最常见的几个列出来对照着排查。401 Unauthorized是最常见的。分两种情况一种是直接请求 MCP Server 时 401另一种是通过 TaoToken 调用时 401。直接请求 401先检查Authorization头有没有带格式是不是Bearer token中间有没有多余空格。然后检查 JWT 的Issuer和Audience是否和appsettings.json里配的一致。如果Audience填的是https://taotoken.net/api但签 token 的时候填的是别的值校验就会失败。还有一个容易忽略的点SigningKey在签发和校验两处必须完全一致长度不够 32 字符也会导致签名校验失败。通过 TaoToken 调用时 401先确认 TaoToken 的 Key 有没有过期。去控制台https://taotoken.net/console看一下 Key 的状态。如果 Key 正常检查 Agent 侧配置的 Base URL 是不是https://taotoken.net/api有没有多写或少写路径。Base URL 写错会导致请求根本没到 TaoToken自然也就拿不到正确的转发。local proxy failed这个报错通常出现在 Agent 侧配置了本地代理但代理服务没启动或者端口不对。如果你在 Agent 配置里写了http://localhost:xxxx作为代理先确认那个端口上有服务在跑。另一个可能是 TaoToken 的端点被本地网络策略拦了用curl -v https://taotoken.net/api看一下能不能通。如果 curl 能通但 Agent 报 proxy failed检查 Agent 的代理配置是不是覆盖了全局代理设置。reading choices 报错一般出现在模型返回格式不符合预期的时候。比如你用的 Model ID 不支持工具调用但请求里带了tools字段模型可能返回一个空的choices数组Agent 侧解析时就会报 reading choices 失败。解决办法是换一个支持工具调用的 Model ID或者在 Agent 侧加一个判断如果choices为空就降级为普通对话不强行解析工具调用。OAuth 相关报错通常是因为 Agent 侧配置了 OAuth 流程但你的 MCP Server 用的是 JWT两者不匹配。如果你不需要 OAuth把 Agent 配置里的 OAuth 相关字段删掉只保留 Base URL、Key、Model ID 三件套。如果你确实需要 OAuth那 JWT 的签发逻辑要改成 OAuth 的 token 端点TokenValidationParameters也要相应调整。大多数场景下JWT 够用了不需要上 OAuth。还有一个隐蔽的坑CORS 预检失败。浏览器侧的 Agent 在发 POST 请求之前会先发一个 OPTIONS 预检请求。如果你的 CORS 策略里没有放行OPTIONS方法预检就会失败Agent 侧看到的是网络错误而不是 401。检查WithMethods里有没有包含OPTIONS以及WithHeaders里有没有Authorization和MCP-Protocol-Version。这两个头是 MCP 请求必须的少一个预检就过不了。排查的时候善用日志。在Program.cs里加builder.Logging.AddConsole()然后在 JWT 校验失败的地方打日志。JwtBearerEvents里的OnAuthenticationFailed事件可以捕获具体的失败原因比如 token 过期、签名不匹配、audience 不对。把失败原因打出来比盲目猜要快得多。options.Events new JwtBearerEvents { OnAuthenticationFailed context { Console.WriteLine($JWT auth failed: {context.Exception.Message}); return Task.CompletedTask; } };这段代码加在AddJwtBearer的配置里跑一次就能看到具体是哪个环节出了问题。6. 接入文档与后续动作整条链路跑通之后你手上就有了一个可用的 MCP 工具ASP.NET Core Web API 封装成 MCP ToolJWT 校验在服务端完成第三方 Agent 通过 TaoToken 统一 Key 调用。这套结构的好处是职责清晰——你的业务逻辑不动鉴权逻辑复用现有的 JWT 体系Agent 侧只需要配三件套。如果你在排查 401 或者配置 JWT 中间件时卡住了可以直接看接入文档里面有更详细的参数说明和示例https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc。API Key 的生成和管理在控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsole。如果你只是想先验证模型能不能正确选择工具可以用模型对话页面快速测一下https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chat。长期做编码和 Agent 集成的建议直接上 Coding Plan省得每次手动配 Keyhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding_plan。API Keys 管理页在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keysClaude Code 的接入配置参考https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentclaude_code。最后说一个实际踩过的坑JWT 的过期时间不要设太长。示例里设了 1 小时生产环境可以根据业务调整但不要设成几天。Token 过期后Agent 侧会收到 401这时候需要重新走/auth/token拿新 Token。如果你的 Agent 框架支持自动刷新 Token在 401 处理逻辑里加上重新获取的逻辑用户体验会好很多。如果不支持就在 Token 快过期时主动刷新别等到 401 了才处理。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑