1. 为什么 .NET 开发者需要关注 MCP
如果你是一名 C# 开发者,最近大概率被 MCP 这个词刷过屏。MCP 全称 Model Context Protocol,模型上下文协议,说白了就是一套让 AI 大模型和外部工具、数据源之间用统一方式对话的规范。它解决的问题很具体:大模型本身知识很广,但它碰不到你本机的东西——你的文件夹、你的数据库、你正在跑的服务。以前要么手动复制粘贴,要么针对每个模型单独写函数调用,重复劳动多、维护成本高。MCP 把这件事标准化了,Server 端负责暴露能力,Client 端负责调用,模型只负责决策什么时候调。
对 .NET 开发者来说,这件事的意义在于:你不需要换语言、不需要学 Python 生态,用熟悉的 C# 和 NuGet 就能把本地工具包装成 MCP Server,然后接进支持 MCP 的 AI 客户端。官方 C# SDK 已经发布,和微软合作维护,配合Microsoft.Extensions.Hosting那套依赖注入写法,上手成本比想象中低。
这篇文章面向的是第一次接触 MCP 的 .NET 开发者。我会带你从零建一个最小可用的 MCP Server,暴露两个工具方法,用 stdio 传输,然后在客户端里完成一次真实调用验证。整个过程控制在 30 分钟内,项目结构、NuGet 依赖、注册代码、排错点都会给全。你不需要提前了解 MCP 协议细节,跟着敲就行。
先说清楚适用场景:你有一个本地能力想给 AI 用,比如查日志、读配置、算个业务规则,但又不想把它做成 HTTP 接口暴露到公网。MCP Server 跑在本地,通过标准输入输出和客户端通信,安全边界清晰。这就是它最适合的切入点。
2. TaoToken 前置准备:拿到接入凭证
在写 Server 之前,得先把模型侧的接入准备好。MCP Server 本身只负责暴露工具,真正决定“调不调、怎么调”的是背后的大模型。所以你需要一个能稳定调用模型的入口。这里用 TaoToken 来做,它提供统一的 API 接入,兼容常见的模型调用格式,对 .NET 开发者来说就是换个 Base URL 和 Key 的事。
第一步,打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册账号。注册流程很常规,邮箱加密码,验证后进控制台。
第二步,进控制台创建 API Key。地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。在 API Keys 页面点新建,复制生成的 Key,形如sk-开头的一串。这个 Key 只显示一次,先存到安全的地方,后面配置客户端要用。
第三步,确认你要用的模型 ID。不同客户端对模型名的写法略有差异,但核心就是 Base URL 加 Key 加 Model ID 三件套。TaoToken 的 API 根地址是 https://taotoken.net/api ,注意这个地址不带查询参数,配置时直接填。
如果你只是想先验证模型能不能通,可以用模型对话页面快速试一句: https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。输入一句话看有没有正常返回,确认 Key 有效。
如果你打算长期做编码类或 Agent 类的工作,建议了解一下 Coding Plan: https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。它针对持续编码场景做了额度优化,比按次调用更划算。
接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面列了各客户端的配置示例,遇到格式问题可以对照。
这里要强调一点:MCP Server 和模型接入是两件事。Server 跑在你本地,模型调用走 TaoToken 的 API。客户端负责把两者串起来——它既连模型,又连 MCP Server。所以你的 Key 是配在客户端里的,不是配在 Server 代码里的。这个区分很重要,后面排错时会用到。
3. 可复制配置:建项目、装依赖、写 Server
现在进入实操。先建项目。打开终端,执行:
dotnet new console -n McpDemoServer cd McpDemoServer然后装 NuGet 包。官方 C# SDK 的包名是ModelContextProtocol,配合 Hosting 用:
dotnet add package ModelContextProtocol --prerelease dotnet add package Microsoft.Extensions.Hosting装完后csproj里应该能看到类似引用。注意 SDK 还在演进,用--prerelease拿最新预览版,正式版发布后去掉即可。
接下来改Program.cs。最小 Server 的写法是这样:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ModelContextProtocol.Server; using System.ComponentModel; var builder = Host.CreateEmptyApplicationBuilder(settings: null); builder.Services .AddMcpServer() .WithStdioServerTransport() .WithToolsFromAssembly(); await builder.Build().RunAsync();这段代码做了三件事:创建一个空的主机 builder,注册 MCP Server 并指定用 stdio 传输,然后从当前程序集扫描所有带McpServerToolType的类。WithStdioServerTransport是关键,它让 Server 通过标准输入输出和客户端通信,不需要开端口。
然后加工具类。新建一个EchoTool.cs:
using ModelContextProtocol.Server; using System.ComponentModel; [McpServerToolType] public static class EchoTool { [McpServerTool, Description("Echoes the message back to the client.")] public static string Echo(string message) => $"Hello from C#: {message}"; [McpServerTool, Description("Echoes in reverse the message sent.")] public static string ReverseEcho(string message) => new string(message.Reverse().ToArray()); }McpServerToolType标记这个类包含工具,McpServerTool标记具体方法,Description里的文字会暴露给模型,模型靠它判断什么时候调这个工具。所以描述要写清楚,别写“处理数据”这种模糊话。
编译一下确认没问题:
dotnet build如果报找不到ModelContextProtocol.Server命名空间,检查包是否装成功,或者版本是否匹配。预览版包名偶尔会调整,以 NuGet 页面为准。
到这里 Server 就写完了。整个项目结构就两个文件:Program.cs和EchoTool.cs,加上csproj。没有配置文件,没有端口,没有数据库。这就是 stdio 传输的好处——进程启动即服务,进程结束即停止。
4. 验证请求:接进客户端跑通闭环
Server 写好了,得让客户端能调它。这里以支持 MCP 的客户端配置为例,核心是告诉客户端:怎么启动这个 Server 进程,以及模型走哪个 API。
先发布或找到 Server 的可执行入口。开发阶段可以直接用dotnet run,但客户端通常需要绝对路径。先拿到项目路径:
pwd假设输出是/Users/you/projects/McpDemoServer,那么启动命令就是dotnet,参数是run --project /Users/you/projects/McpDemoServer。更稳妥的做法是dotnet build后直接用生成的 dll:
dotnet build -c Release产物在bin/Release/net8.0/McpDemoServer.dll,启动命令变成dotnet加这个 dll 的绝对路径。
客户端的 MCP 配置一般是一个 JSON,结构类似:
{ "mcpServers": { "mcp-demo": { "command": "dotnet", "args": [ "/Users/you/projects/McpDemoServer/bin/Release/net8.0/McpDemoServer.dll" ] } } }把这段填进客户端的 MCP 配置文件,保存后刷新。客户端会拉起这个进程,通过 stdio 握手,然后列出可用工具。你应该能看到Echo和ReverseEcho两个工具,以及它们的描述。
模型侧的配置在同一个客户端里,填 TaoToken 的三件套:
{ "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的Key", "model": "你的模型ID" }注意 Base URL 是https://taotoken.net/api,不要多加斜杠或路径。Key 用第 2 步生成的。Model ID 按文档填。
配置完成后,在客户端对话框里输入:“用 Echo 工具把 hello mcp 传进去”。模型会决定调用Echo,参数message为hello mcp,然后你会在对话里看到返回Hello from C#: hello mcp。再试一句“用 ReverseEcho 反转 abcdef”,应该返回fedcba。
看到这两个结果,最小闭环就跑通了。整个过程里,Server 没联网,模型调用走 TaoToken,客户端做调度。你可以打开客户端的日志面板,能看到工具调用的请求和响应,确认参数传递正确。
如果客户端支持,还可以试试让它连续调两次不同工具,观察模型怎么根据描述选择。这一步能帮你理解 MCP 的设计意图:工具描述写得好,模型选得准。
5. 本篇常见错排查
跑不通的时候,按下面几个真实报错对照。
401 Unauthorized。这个基本是 Key 问题。检查三处:Key 有没有复制完整(前后空格)、有没有过期、Base URL 是不是写成了带路径的地址。TaoToken 的根地址是https://taotoken.net/api,如果你填成https://taotoken.net/api/v1/chat之类,可能路径不匹配。另外确认 Key 是配在客户端而不是 Server 代码里。
local proxy failed 或连接被拒绝。这类报错通常出现在客户端启动 Server 进程失败时。先手动在终端跑一遍启动命令,看能不能正常起来。如果终端里报Unhandled exception,说明 Server 代码有问题,先解决代码。如果终端能跑但客户端报错,检查 args 里的路径是不是绝对路径,Windows 下注意反斜杠转义。
reading choices 相关报错。这多半是模型返回格式和客户端预期不一致。确认 Model ID 填对了,有些客户端对模型名大小写敏感。如果换了模型还是报,检查客户端版本是否支持当前 API 格式,必要时升级客户端。
OAuth 相关报错。如果你在客户端里配了需要 OAuth 的模型入口,但没走完授权流程,会卡在这里。TaoToken 的 API Key 方式不需要 OAuth,确认你没混用两种认证方式。如果客户端强制走 OAuth,检查是不是选错了接入类型。
工具列表为空。客户端连上了 Server,但看不到工具。原因通常是WithToolsFromAssembly没扫到类。检查工具类是否是public static,是否带了McpServerToolType,方法是否带了McpServerTool。另外确认这些类在同一个程序集里,跨程序集需要额外注册。
调用工具时报参数错误。检查方法参数名和客户端传的是否一致。C# 方法参数string message,客户端传的 JSON 字段也应该是message。如果模型传了别的字段名,说明工具描述不够明确,把参数说明写进Description里。
进程启动后立即退出。stdio 模式下,如果标准输入被关闭,进程会退出。检查客户端是否正确保持了管道。手动测试时可以用echo管道喂一个初始化请求,但更简单的方法是直接用客户端验证。
排错的核心思路:先确认 Server 能独立启动,再确认客户端能拉起进程,最后确认模型调用链路。分段隔离,别一上来就怀疑协议。
6. 继续深入的方向
最小闭环跑通后,你可以往几个方向扩展。一是加更多工具,比如读本地文件、查 SQLite、调内部 API,每个工具就是一个带McpServerTool的方法。二是换传输方式,stdio 适合本地,如果要做远程共享,可以研究 SSE 或 HTTP 传输。三是把工具描述写得更精细,让模型选择更准,这是实际项目里最影响体验的部分。
如果你要接 Claude Code 这类编码工具,配置思路类似,Base URL 和 Key 的填法参考文档: https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。API Key 管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,需要新建或轮换时去那里。长期做 Agent 开发的话,Coding Plan 的额度模型更适合持续调用: https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
最后给一个实用建议:把工具方法的Description当成给模型看的 API 文档来写,写清楚“什么时候用、参数是什么、返回什么”。我试过把描述从“查询数据”改成“根据用户 ID 查询订单状态,返回状态码和更新时间”,模型选工具的准确率明显提升。这个细节比换模型更管用。