mcp-csharp-create
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseC# MCP Server Creation
C# MCP 服务器创建
Create Model Context Protocol servers using the official C# SDK ( NuGet package) and the project template. Servers expose tools, prompts, and resources that LLMs can discover and invoke via the MCP protocol.
ModelContextProtocoldotnet new mcpserver使用官方C# SDK( NuGet包)和项目模板创建Model Context Protocol服务器。服务器会对外暴露工具、提示词和资源,LLM可以通过MCP协议发现并调用这些能力。
ModelContextProtocoldotnet new mcpserverWhen to Use
适用场景
- Starting a new MCP server project from scratch
- Adding tools, prompts, or resources to an existing MCP server
- Choosing between stdio () and HTTP (
--transport local) transport--transport remote - Setting up ASP.NET Core hosting for an HTTP MCP server
- Wrapping an external API or service as MCP tools
- 从零开始启动新的MCP服务器项目
- 向现有MCP服务器添加工具、提示词或资源
- 在stdio()和HTTP(
--transport local)传输方式之间做选择--transport remote - 为HTTP MCP服务器设置ASP.NET Core托管
- 将外部API或服务封装为MCP工具
Stop Signals
禁用信号
- Server already exists and needs debugging? → Use
mcp-csharp-debug - Need tests or evaluations? → Use
mcp-csharp-test - Ready to publish? → Use
mcp-csharp-publish - Building an MCP client, not a server → This skill is server-side only
- 服务器已存在需要调试? → 使用
mcp-csharp-debug - 需要测试或评估? → 使用
mcp-csharp-test - 准备发布? → 使用
mcp-csharp-publish - 构建MCP客户端而非服务器 → 本技能仅适用于服务端开发
Inputs
输入项
| Input | Required | Description |
|---|---|---|
| Transport type | Yes | |
| Project name | Yes | PascalCase name for the project (e.g., |
| .NET SDK version | Recommended | .NET 10.0+ required. Check with |
| Service/API to wrap | Recommended | External API or service the tools will interact with |
| 输入项 | 是否必填 | 描述 |
|---|---|---|
| 传输类型 | 是 | |
| 项目名称 | 是 | 采用大驼峰命名的项目名(例如 |
| .NET SDK 版本 | 推荐 | 要求.NET 10.0及以上版本,可通过 |
| 待封装的服务/API | 推荐 | 工具将要交互的外部API或服务 |
Workflow
工作流
Commit strategy: Commit after completing each step so scaffolding and implementation are separately reviewable.
提交策略: 每完成一步就提交代码,这样脚手架搭建和功能实现可以分开评审。
Step 1: Verify prerequisites
步骤1:确认前置依赖
-
Confirm .NET 10+ SDK:(install from https://dotnet.microsoft.com if < 10.0)
dotnet --version -
Check if the MCP server template is already installed:bash
dotnet new list mcpserverIf "No templates found" → install:dotnet new install Microsoft.McpServer.ProjectTemplates
-
确认已安装.NET 10+ SDK:执行命令,如果版本低于10.0可以从https://dotnet.microsoft.com 下载安装
dotnet --version -
检查是否已安装MCP服务器模板:bash
dotnet new list mcpserver如果提示"No templates found" → 执行安装命令:dotnet new install Microsoft.McpServer.ProjectTemplates
Step 2: Choose transport
步骤2:选择传输方式
| Choose stdio if… | Choose HTTP if… |
|---|---|
| Local CLI tool or IDE plugin | Cloud/web service deployment |
| Single user at a time | Multiple simultaneous clients |
| Running as subprocess (VS Code, GitHub Copilot) | Cross-network access needed |
| Simpler setup, no network config | Containerized deployment (Docker/Azure) |
Default: stdio — simpler, works for most local development. Users can add HTTP later.
| 符合以下场景选择 stdio | 符合以下场景选择 HTTP |
|---|---|
| 本地CLI工具或IDE插件 | 云端/网页服务部署 |
| 同一时间仅单用户使用 | 支持多客户端同时访问 |
| 作为子进程运行(VS Code、GitHub Copilot) | 需要跨网络访问 |
| 配置更简单,无需网络设置 | 容器化部署(Docker/Azure) |
默认选择: stdio —— 配置更简单,适合大多数本地开发场景,用户后续也可以自行添加HTTP支持。
Step 3: Scaffold the project
步骤3:搭建项目脚手架
stdio server:
bash
dotnet new mcpserver -n <ProjectName>If the template times out or is unavailable, use and add .
dotnet new console -n <ProjectName>dotnet add package ModelContextProtocolHTTP server:
bash
dotnet new web -n <ProjectName>
cd <ProjectName>
dotnet add package ModelContextProtocol.AspNetCoreThis is the recommended approach — faster and more reliable than the template. The template also supports HTTP via , but gives you more control over the project structure.
dotnet new mcpserver -n <ProjectName> --transport remotedotnet new webTemplate flags reference: (stdio, default), (ASP.NET Core HTTP), , .
--transport local--transport remote--aot--self-containedstdio服务器:
bash
dotnet new mcpserver -n <ProjectName>如果模板加载超时或不可用,可以使用创建控制台项目,再执行安装依赖。
dotnet new console -n <ProjectNamedotnet add package ModelContextProtocolHTTP服务器:
bash
dotnet new web -n <ProjectName>
cd <ProjectName>
dotnet add package ModelContextProtocol.AspNetCore这是推荐的实现方式,比模板更快更可靠。你也可以通过模板命令创建HTTP服务器,但方式对项目结构的可控性更强。
dotnet new mcpserver -n <ProjectName> --transport remotedotnet new web模板参数参考: (stdio,默认值)、(ASP.NET Core HTTP)、、。
--transport local--transport remote--aot--self-containedStep 4: Implement tools
步骤4:实现工具功能
Tools are the primary way MCP servers expose functionality. Add a class with and methods with :
[McpServerToolType][McpServerTool]csharp
using ModelContextProtocol.Server;
using System.ComponentModel;
[McpServerToolType]
public static class MyTools
{
[McpServerTool, Description("Brief description of what the tool does.")]
public static async Task<string> DoSomething(
[Description("What this parameter controls")] string input,
CancellationToken cancellationToken = default)
{
// Implementation
return $"Result: {input}";
}
}Critical rules:
- Every tool method must have a attribute — LLMs use this to decide when to call the tool
[Description] - Every parameter must have a attribute
[Description] - Accept in all async tools
CancellationToken - Use only if the default method name is unclear
[McpServerTool(Name = "custom_name")]
DI injection patterns — the SDK supports two styles:
-
Method parameter injection (static class): DI services appear as method parameters. The SDK resolves them automatically — they do not appear in the tool schema.
-
Constructor injection (non-static class): Use when tools need shared state or multiple services:
csharp
[McpServerToolType]
public class ApiTools(HttpClient httpClient, ILogger<ApiTools> logger)
{
[McpServerTool, Description("Fetch a resource by ID.")]
public async Task<string> FetchResource(
[Description("Resource identifier")] string id,
CancellationToken cancellationToken = default)
{
logger.LogInformation("Fetching {Id}", id);
return await httpClient.GetStringAsync($"/api/{id}", cancellationToken);
}
}Register services in Program.cs:
csharp
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace);
builder.Services.AddHttpClient(); // registers IHttpClientFactory + HttpClient
// ILogger<T> is registered by default — no extra setup needed.
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly(); // discovers non-static [McpServerToolType] classes
await builder.Build().RunAsync();For the full attribute reference, return types, DI injection, and builder API patterns, see references/api-patterns.md.
工具是MCP服务器对外暴露能力的主要方式。新增一个带特性的类,并为类方法添加特性:
[McpServerToolType][McpServerTool]csharp
using ModelContextProtocol.Server;
using System.ComponentModel;
[McpServerToolType]
public static class MyTools
{
[McpServerTool, Description("Brief description of what the tool does.")]
public static async Task<string> DoSomething(
[Description("What this parameter controls")] string input,
CancellationToken cancellationToken = default)
{
// Implementation
return $"Result: {input}";
}
}核心规则:
- 每个工具方法必须添加特性 —— LLM会通过这个描述判断什么时候调用该工具
[Description] - 每个参数必须添加特性
[Description] - 所有异步工具都要接收参数
CancellationToken - 仅当默认方法名含义不清晰时,才使用自定义工具名
[McpServerTool(Name = "custom_name")]
DI注入模式 —— SDK支持两种注入风格:
-
方法参数注入(静态类): DI服务作为方法参数传入,SDK会自动解析这些服务,它们不会出现在工具的Schema中。
-
构造函数注入(非静态类): 当工具需要共享状态或依赖多个服务时使用:
csharp
[McpServerToolType]
public class ApiTools(HttpClient httpClient, ILogger<ApiTools> logger)
{
[McpServerTool, Description("Fetch a resource by ID.")]
public async Task<string> FetchResource(
[Description("Resource identifier")] string id,
CancellationToken cancellationToken = default)
{
logger.LogInformation("Fetching {Id}", id);
return await httpClient.GetStringAsync($"/api/{id}", cancellationToken);
}
}在Program.cs中注册服务:
csharp
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace);
builder.Services.AddHttpClient(); // registers IHttpClientFactory + HttpClient
// ILogger<T> is registered by default — no extra setup needed.
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly(); // discovers non-static [McpServerToolType] classes
await builder.Build().RunAsync();完整的特性参考、返回类型、DI注入、构建API模式请查看 references/api-patterns.md。
Step 5: Add prompts and resources (optional)
步骤5:添加提示词和资源(可选)
Prompts — reusable LLM interaction templates:
csharp
[McpServerPromptType]
public static class MyPrompts
{
[McpServerPrompt, Description("Summarize content into one sentence.")]
public static ChatMessage Summarize(
[Description("Content to summarize")] string content) =>
new(ChatRole.User, $"Summarize this into one sentence: {content}");
}Resources — data the LLM can read:
csharp
[McpServerResourceType]
public static class MyResources
{
[McpServerResource(UriTemplate = "config://app", Name = "App Config",
MimeType = "application/json"), Description("Application configuration")]
public static string GetConfig() => JsonSerializer.Serialize(AppConfig.Current);
}提示词 —— 可复用的LLM交互模板:
csharp
[McpServerPromptType]
public static class MyPrompts
{
[McpServerPrompt, Description("Summarize content into one sentence.")]
public static ChatMessage Summarize(
[Description("Content to summarize")] string content) =>
new(ChatRole.User, $"Summarize this into one sentence: {content}");
}资源 —— LLM可以读取的数据:
csharp
[McpServerResourceType]
public static class MyResources
{
[McpServerResource(UriTemplate = "config://app", Name = "App Config",
MimeType = "application/json"), Description("Application configuration")]
public static string GetConfig() => JsonSerializer.Serialize(AppConfig.Current);
}Step 6: Configure Program.cs
步骤6:配置Program.cs
stdio transport:
csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace); // CRITICAL: stderr only
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();HTTP transport:
csharp
using ModelContextProtocol.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly();
// Register services your tools need via DI
// builder.Services.AddHttpClient();
// builder.Services.AddSingleton<IMyService, MyService>();
var app = builder.Build();
app.MapMcp(); // exposes MCP endpoint at /mcp (Streamable HTTP)
app.MapGet("/health", () => "ok"); // health check for container orchestrators
app.Run();Key HTTP details: defaults to path. For containers, set and . The MCP HTTP protocol uses Streamable HTTP — no special client config needed beyond the URL.
MapMcp()/mcpASPNETCORE_URLS=http://+:8080EXPOSE 8080For transport configuration details (stateless mode, auth, path prefix, ), see references/transport-config.md.
HttpContextAccessorstdio传输:
csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(options =>
options.LogToStandardErrorThreshold = LogLevel.Trace); // CRITICAL: stderr only
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();HTTP传输:
csharp
using ModelContextProtocol.Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithToolsFromAssembly();
// Register services your tools need via DI
// builder.Services.AddHttpClient();
// builder.Services.AddSingleton<IMyService, MyService>();
var app = builder.Build();
app.MapMcp(); // exposes MCP endpoint at /mcp (Streamable HTTP)
app.MapGet("/health", () => "ok"); // health check for container orchestrators
app.Run();HTTP核心说明: 默认暴露的路径是。容器部署时请设置并开放端口。MCP HTTP协议使用可流HTTP传输,除了URL之外无需额外的客户端配置。
MapMcp()/mcpASPNETCORE_URLS=http://+:80808080传输配置详情(无状态模式、鉴权、路径前缀、)请查看 references/transport-config.md。
HttpContextAccessorStep 7: Verify the server starts
步骤7:验证服务器启动
bash
cd <ProjectName>
dotnet build
dotnet runFor stdio: the process starts and waits for JSON-RPC input on stdin.
For HTTP: the server listens on the configured port.
bash
cd <ProjectName>
dotnet build
dotnet runstdio模式:进程启动后会等待stdin输入的JSON-RPC请求。
HTTP模式:服务器会在配置的端口上监听请求。
Validation
校验清单
- Project builds with no errors ()
dotnet build - All tool classes have attribute
[McpServerToolType] - All tool methods have and
[McpServerTool]attributes[Description] - All parameters have attributes
[Description] - stdio: logging directed to stderr, not stdout
- HTTP: is called in Program.cs
app.MapMcp() - Server starts successfully with
dotnet run
- 项目编译无错误(执行)
dotnet build - 所有工具类都添加了特性
[McpServerToolType] - 所有工具方法都添加了和
[McpServerTool]特性[Description] - 所有参数都添加了特性
[Description] - stdio模式:日志输出到stderr而非stdout
- HTTP模式:Program.cs中调用了
app.MapMcp() - 执行服务器可以正常启动
dotnet run
Common Pitfalls
常见问题
| Pitfall | Solution |
|---|---|
| stdio server outputs garbage or hangs | Logging to stdout corrupts JSON-RPC protocol. Set |
| Tool not discovered by LLM clients | Missing |
| LLM doesn't understand when to use a tool | Add clear |
| Reflection-based discovery is incompatible with Native AOT. Use |
| Parameters not appearing in tool schema | |
| HTTP server returns 404 | |
| 问题 | 解决方案 |
|---|---|
| stdio服务器输出乱码或卡住 | 日志输出到stdout会破坏JSON-RPC协议,请设置 |
| LLM客户端无法发现工具 | 类缺少 |
| LLM不知道什么时候调用工具 | 请为方法和所有参数添加清晰的 |
AOT模式下 | 基于反射的发现机制和Native AOT不兼容,请改用 |
| 参数没有出现在工具Schema中 | |
| HTTP服务器返回404 | 必须调用 |
Related Skills
相关技能
- — Run, debug, and test with MCP Inspector
mcp-csharp-debug - — Unit tests, integration tests, evaluations
mcp-csharp-test - — NuGet, Docker, Azure deployment
mcp-csharp-publish
- —— 使用MCP Inspector运行、调试和测试
mcp-csharp-debug - —— 单元测试、集成测试、评估
mcp-csharp-test - —— NuGet、Docker、Azure部署
mcp-csharp-publish
Reference Files
参考文件
- references/api-patterns.md — Complete attribute reference, return types, DI injection, builder API, dynamic tools, experimental APIs. Load when: implementing tools, prompts, or resources beyond the basic patterns shown above.
- references/transport-config.md — Detailed transport configuration: stateless HTTP mode, OAuth/auth, custom path prefix, , OpenTelemetry observability. Load when: configuring advanced transport options or authentication.
HttpContextAccessor
- references/api-patterns.md —— 完整的特性参考、返回类型、DI注入、构建API、动态工具、实验性API。加载时机: 实现超出上述基础模式的工具、提示词或资源时
- references/transport-config.md —— 详细的传输配置:无状态HTTP模式、OAuth/鉴权、自定义路径前缀、、OpenTelemetry可观测性。加载时机: 配置高级传输选项或身份验证时
HttpContextAccessor
More Info
更多信息
- C# MCP SDK — Official SDK repository
- Build an MCP server (.NET) — Microsoft quickstart
- MCP Specification — Protocol specification
- C# MCP SDK —— 官方SDK仓库
- Build an MCP server (.NET) —— 微软官方快速入门文档
- MCP Specification —— 协议规范