1. 为什么我要自己写一个 MCP 服务器MCP 服务器Model Context Protocol Server说白了就是给大模型外挂的一双手模型本身只会生成文字但通过 MCP 协议它可以调用你注册好的工具函数去查数据库、读文件、发请求、算数据。适合谁适合手里有一堆内部接口、想让 AI 直接调用的后端和桌面开发者。我这次用 C# 从零搓一个最小可用的 MCP 服务器把协议握手、工具注册、调用链路全部跑通再通过 TaoToken 的统一 Key 把 AI 工具接进来让整条链路真正能对话、能执行。很多人卡在第一步以为 MCP 是个很玄的东西。其实它就是一个约定好的 JSON-RPC 通信规范客户端和服务端按格式交换消息服务端告诉客户端我有哪些工具、参数是什么客户端把模型的调用意图翻译成请求发过来服务端执行完把结果塞回去。你只要把这三件事做对MCP 服务器就活了。这篇会交付一个可复制的项目骨架、一份 config.toml 配置示例以及一次完整的本地验证动作。全程不需要你懂什么高深协议跟着敲就行。2. TaoToken 前置准备统一 Key 与通道在写代码之前先把 AI 侧的通道准备好。MCP 服务器本身只负责执行工具真正发起对话、决定调用哪个工具的是模型客户端。我用 TaoToken 来做统一入口好处是一个 Key 走通模型对话和工具调用不用在多个平台之间来回切。你需要先拿到 API Key。打开控制台页面登录后进入 API Keys 管理新建一个 Key 并复制保存。这个 Key 就是后面配置里要填的凭证。控制台入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharpAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharp接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmcp_csharpAPI 的基础地址是https://taotoken.net/api注意这个地址不带任何查询参数配置时直接填这个即可。模型对话、工具调用都走同一个通道省去了维护多套凭证的麻烦。提示Key 只显示一次复制后立刻存到本地配置文件或环境变量里别直接硬编码进提交到仓库的源码。如果你后面要做长期编码或 Agent 类任务可以了解下 Coding Plan它更适合高频调用场景只是验证模型和工具链路的话用模型对话页面配合本地服务就够了。3. 可复制配置项目骨架与 config.toml先建项目。用 .NET CLI 起一个 Web 项目MCP 的 C# SDK 目前以预览包形式提供安装时带上--prerelease。dotnet new web -n McpDemo cd McpDemo dotnet add package ModelContextProtocol --prerelease项目结构保持简单McpDemo/ ├── Program.cs ├── Tools/ │ └── MyTools.cs ├── config.toml └── McpDemo.csprojconfig.toml用来放模型通道和服务器参数避免散落在代码里[server] name mcp-demo transport sse port 5180 [ai] base_url https://taotoken.net/api api_key sk-你的Key model claude-3-5-sonnet [tools] enabled [GeneratePraise, Add, GetServerTime]然后在Program.cs里读取配置、注册 MCP 服务并映射路由using ModelContextProtocol.Server; using Tomlyn; var builder WebApplication.CreateBuilder(args); // 读取 config.toml var configText File.ReadAllText(config.toml); var config Toml.ToModel(configText); builder.Services.AddMcpServer() .WithToolsFromAssembly(); var app builder.Build(); app.MapMcpSse(); app.Run();这里WithToolsFromAssembly()会自动扫描当前程序集里所有带[McpServerToolType]的类把[McpServerTool]标注的方法注册成可调用工具。你不需要手写路由映射SDK 帮你做了。工具类长这样using System.ComponentModel; using ModelContextProtocol.Server; [McpServerToolType] public class MyTools { [McpServerTool] [Description(根据名字生成一句彩虹屁)] public string GeneratePraise(string name) { return ${name} 老师真是玉树临风代码一写一个准。; } [McpServerTool] [Description(计算两个整数之和)] public int Add(int a, int b) { return a b; } [McpServerTool] [Description(返回服务器当前时间)] public string GetServerTime() { return DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); } }Description特性很关键它不是写给人看的注释而是会随工具列表一起发给模型模型靠它判断这个工具是干嘛的、什么时候该调。描述写得越清楚模型选错工具的概率越低。4. 验证请求跑通一次完整调用代码写完先本地启动dotnet run看到监听http://localhost:5180就说明服务起来了。MCP 的 SSE 端点默认挂在/sse路径下客户端连上后会先收到一条 endpoint 事件里面带着后续发消息用的地址。验证分两步。第一步确认工具列表能正确暴露用 curl 模拟客户端握手curl -N http://localhost:5180/sse正常会持续输出事件流包含event: endpoint和data: /message?sessionIdxxx。拿到 sessionId 后发一条初始化请求curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2024-11-05, capabilities: {}, clientInfo: { name: curl-test, version: 1.0 } } }返回里会带上服务端的能力声明。接着请求工具列表curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }你应该能看到GeneratePraise、Add、GetServerTime三个工具每个都带着参数 schema。最后真正调用一次curl -X POST http://localhost:5180/message?sessionId你的sessionId \ -H Content-Type: application/json \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: Add, arguments: { a: 3, b: 5 } } }返回结果里content字段会包含8。到这一步MCP 服务器的握手、工具注册、调用链路就全部跑通了。整个过程没有任何魔法就是标准的 JSON-RPC 一来一回。5. 本篇常见错排查启动报端口占用config.toml里默认 5180被占了就改port或者用dotnet run --urls http://localhost:5190临时覆盖。tools/list 返回空数组九成是工具类没加[McpServerToolType]或者方法不是public。SDK 只扫描公开方法私有方法会被忽略。另外确认WithToolsFromAssembly()调用的是当前程序集工具类别放到另一个没被引用的项目里。调用工具报 method not found检查tools/call里的name是否和 C# 方法名完全一致大小写敏感。如果你用了[McpServerTool(Name xxx)]重命名就要用重命名后的名字。SSE 连上但收不到 endpoint 事件确认路由映射用的是MapMcpSse()而不是别的并且请求路径是/sse。有些反向代理会缓冲 SSE 流本地直连一般没这问题。模型侧不调用工具先确认工具描述是否清晰模糊的描述会让模型犹豫。再检查客户端是否真的把工具列表传给了模型有些客户端需要显式开启工具调用能力。用 TaoToken 通道时确认base_url填的是https://taotoken.net/apiKey 没有多余空格。中文参数乱码请求头带上Content-Type: application/json; charsetutf-8服务端默认按 UTF-8 解析一般不会出问题但 curl 在某些终端下需要显式声明。6. 把链路接到 AI 工具上本地验证通过后就可以把 MCP 服务器接到真实的 AI 客户端里。在客户端的 MCP 配置中填入你的 SSE 地址http://localhost:5180/sse模型就能看到你注册的工具。对话时你说帮我算一下 3 加 5模型会自己决定调用Add工具拿到结果再组织成自然语言回复你。模型通道这边统一走 TaoToken 的 API 地址一个 Key 同时管对话和工具调用。想先感受下模型对话效果可以直接在模型对话页面里试要做长期编码或 Agent 任务Coding Plan 更合适接入细节和参数说明都在接入文档里。我踩过的一个坑是一开始把工具描述写得太笼统模型经常在该调用工具的时候选择直接编答案。后来把每个Description改成什么场景下用、参数是什么含义命中率明显上来了。MCP 服务器的质量一半在代码一半在描述。到这里一个能跑、能调、能接 AI 的 C# MCP 服务器就完整了。接下来你可以往MyTools里继续加方法每加一个带[McpServerTool]的公开方法模型就多一项能力。
企业数字化 ERP 产品动态
相关推荐
Atlas 300V Pro 24GB部署YOLO实战:从硬件选型到推理调优完整记录 Atlas 300V Pro 24GB部署YOLO实战:从硬件选型到推理调优的完整记录如果你最近在关注边缘端的AI推理部署,大概率刷到过Atlas这个系列的名号。但说实话,很多刚接触昇腾生态的朋友第一反应都是:Atlas 300V 24G到底是不是一张运算加速… · 2026/9/25 13:14:35
Meta主动记忆干预长程智能体:TaoToken统一Key下的配置骨架与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 13:14:17
高并发下缓存穿透与击穿的防御实践:基于Redis的封装方案 做了这么多年后端,缓存穿透和缓存击穿这个问题我几乎在每个高并发项目里都要重新讲一遍。最近我把这两类问题的防御逻辑统一封装成了一个可复用的工具包,基于Redis实现,核心围绕布隆过滤器、分布式锁、本地缓存和空值缓存这套组合拳。这篇就是… · 2026/9/25 13:14:04
KytyPS5着色器重编译器深度剖析:RDNA 2指令解码→IR优化→SPIR-V生成的完整技术旅程 KytyPS5着色器重编译器深度剖析:RDNA 2指令解码→IR优化→SPIR-V生成的完整技术旅程 【免费下载链接】KytyPS5 PlayStation 5 emulator for Windows, Linux and MacOS 项目地址: https://gitcode.com/gh_mirrors/ky/KytyPS5
KytyPS5 是一款运行在 Windows、L… · 2026/9/25 13:52:48
Atlas 300V推理卡部署YOLO全攻略:从环境配置到性能调优 1. Atlas 300V到底是什么卡:先说清楚它的定位最近好几个做安防和工业视觉的朋友都在问同一个问题:Atlas 300V 24G 是不是运算加速卡?能不能用来跑YOLO?说实话,这个问题背后反映出一个普遍现象——很多人把昇腾的推理卡… · 2026/9/25 13:52:36
Agent技能模块化实战:解耦、注册表与稳定性设计 第一次尝试构建一个全能型Agent时,我很快发现了一个尴尬的事实:无论我把主循环写得多么巧妙,真正决定好不好用的,永远是那些挂在外面的小工具。我最早的那个Agent,里塞了几十种能力,从查天气到读PDF再到调用… · 2026/9/25 13:52:29
2026年冯校长老火锅靠谱吗,服务质量值得信赖吗 立足餐饮消费升级浪潮,锚定川味火锅文化传播新使命
顺应餐饮消费升级趋势,回应大众多元餐饮需求当前国内餐饮消费市场正从规模扩张向品质升级深度转型,消费者对餐饮的需求早已超越简单的果腹功能,转而追求地道的风味体验、多元的场… · 2026/9/25 13:52:16
果味黄酒可以兑什么?苏打水、果汁、茶饮搭配指南 果味黄酒冰镇纯饮已经顺口,但很多人更喜欢兑着喝,让口感更清爽或更丰富。这篇围绕苏打水、果汁、茶饮三类常见搭配,给出具体比例和口味说明,再补充几个容易踩坑的细节。下文以缤果日纪果味黄酒为例:7%vol 半甜型&#… · 2026/9/25 13:52:10
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37