← Back to skills
extension
Category: Development & EngineeringAPI key requirement unconfirmed

MCP服务端开发

用 .NET 构建模型上下文协议服务端,覆盖工具注册、传输方式、序列化与性能优化的完整开发指引。Use when building MCP servers in .NET covering tools, transports and serialization. Triggers include MCP、服务端、.NET、工具注册。如需协议工具套装,淘宝搜索「AI灵匣」店铺获取完整版。

personAuthor: nuhabvtyhubOpenAPI

Creating .NET MCP Servers

Build production-ready Model Context Protocol (MCP) servers in .NET with AOT compatibility.

Core principle: MCP servers expose tools via standardized protocol using attribute-based registration and explicit JSON serialization contexts for AOT.

When to Use

graph TD
    A[Need to build server?] -->|Yes| B[Using .NET?]
    B -->|Yes| C[MCP Protocol?]
    C -->|Yes| D[✅ Use this skill]
    C -->|No| E[❌ Use REST/gRPC guide]
    B -->|No| F[❌ See Python/TS MCP docs]
    A -->|No| G[❌ Skip]

Use this skill when:

  • Building new MCP server in .NET
  • Configuring SSE or stdio transport
  • Enabling AOT compilation
  • Need testing or error handling patterns

Not for: Non-.NET MCP, client-side integration, generic APIs

Quick Reference

| Task | Implementation | |------|----------------| | Install packages | dotnet add package ModelContextProtocol + ModelContextProtocol.AspNetCore | | Mark tool class | [McpServerToolType] | | Mark tool method | [McpServerTool(Name = "ToolName"), Description("...")] | | Parameter description | [Description("param description")] string param | | Register server | services.AddMcpServer().WithHttpTransport().WithTools<T>() | | Map endpoints | app.MapMcp() (exposes /sse) | | AOT serialization | Create JsonSerializerContext with [JsonSerializable] | | Test transport | Use SseClientTransport + McpClientFactory |

Basic Setup

1. Install Packages

dotnet add package ModelContextProtocol --version 0.3.0-preview.1
dotnet add package ModelContextProtocol.AspNetCore --version 0.3.0-preview.1
# For testing (optional)
dotnet add package ModelContextProtocol.Client --version 0.3.0-preview.1

2. Enable AOT

Project configuration:

<PropertyGroup>
  <PublishAot>true</PublishAot>
  <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>

JSON serialization context:

[JsonSerializable(typeof(PackageMetadata))]
[JsonSerializable(typeof(IEnumerable<PackageMetadata>))]
public partial class McpJsonContext : JsonSerializerContext { }

Register in Program.cs:

builder.Services.AddMcpServer()
    .WithTools<PackageTools>(serializerOptions: McpJsonContext.Default.Options);

Critical: Add ALL tool return types to [JsonSerializable] attributes.

Tool Implementation

Minimal example:

[McpServerToolType]
public sealed class PackageTools
{
    public const string SearchPackages = "SearchPackages";
    
    [McpServerTool(Name = SearchPackages)]
    [Description("Search for NuGet packages by name or keyword")]
    public async Task<IEnumerable<PackageMetadata>> SearchAsync(
        [Description("The package name or search keyword")] string query,
        [Description("Maximum number of results (default: 10)")] int limit = 10,
        CancellationToken cancellationToken = default)
    {
        // Implementation
    }
}

Key patterns: Sealed classes, const tool names, [Description] on method and parameters, always accept CancellationToken.

Transport Configuration

SSE (HTTP):

builder.Logging.AddConsole(options => options.LogToStandardErrorThreshold = LogLevel.Trace);
builder.Services.AddMcpServer().WithHttpTransport().WithTools<PackageTools>(...);
app.MapMcp();  // Exposes /sse

Stdio (CLI):

builder.Services.AddMcpServer().WithStdioTransport().WithTools<PackageTools>(...);
// No MapMcp() needed

Testing and Error Handling

📖 See references:

Common Mistakes

| Mistake | Fix | |---------|-----| | Forgot [JsonSerializable] for return type | Add all tool return types to JsonSerializerContext | | Not logging to stderr | Set LogToStandardErrorThreshold = LogLevel.Trace | | Missing CancellationToken | Always add CancellationToken parameter | | Throwing exceptions in tools | Return ToolResult<T> with structured errors | | Magic strings for tool names | Use const string in tool class | | No [Description] on parameters | Add [Description] to all parameters | | Forgetting MapMcp() | Required for HTTP/SSE transport |

References