使用说明
🚀 麦克。网关。工具
在中构建MCP服务器。NET 10——几分钟内即可投入生产
麦克。网关。工具 是a。NET库,用于构建模型上下文协议(MCP)服务器。它使得将C#代码公开为客户端可以发现和调用的工具变得容易,例如 GitHub Copilot 和 克劳德桌面.
此回购的主要产品是 Mcp.Gateway.Tools.
DevTestServer 和 Mcp.Gateway.Tests 仅用于开发和验证,它们不是产品的一部分。
完整的文件: https://eyjolfurgudnivatne.github.io/mcp.gateway/
⚡ 入门
1.安装包装
dotnet new web -n MyMcpServer
cd MyMcpServer
dotnet add package Mcp.Gateway.Tools
2.配置服务器(Program.cs)
最小HTTP+WebSocket服务器(v1.7.0,支持MCP 2025-11-25):
using Mcp.Gateway.Tools;
var builder = WebApplication.CreateBuilder(args);
// Register ToolService + ToolInvoker + Session Management (v1.7.0)
builder.AddToolsService();
var app = builder.Build();
// stdio mode for GitHub Copilot (optional)
if (args.Contains("--stdio"))
{
await ToolInvoker.RunStdioModeAsync(app.Services);
return;
}
// WebSockets for streaming
app.UseWebSockets();
// MCP 2025-11-25 Streamable HTTP (v1.7.0 - RECOMMENDED)
app.UseProtocolVersionValidation(); // Protocol version validation
app.MapStreamableHttpEndpoint("/mcp"); // Unified endpoint (POST + GET + DELETE)
// Legacy endpoints (still work, deprecated)
app.MapHttpRpcEndpoint("/rpc"); // HTTP POST only (deprecated)
app.MapWsRpcEndpoint("/ws"); // WebSocket (keep for binary streaming)
app.MapSseRpcEndpoint("/sse"); // SSE only (deprecated, use /mcp GET instead)
app.Run();
看 DevTestServer/Program.cs 以获得更完整的健康端点和stdio日志设置。
3.创建你的第一个工具
3.1.最简单的工具(自动生成模式)
使用创建工具的最简单方法 强类型参数 和 自动模式生成:
using Mcp.Gateway.Tools;
public class MyTools
{
[McpTool("greet")]
public TypedJsonRpc<GreetResponse> Greet(TypedJsonRpc<GreetParams> request)
{
var name = request.Params.Name;
return TypedJsonRpc<GreetResponse>.Success(
request.Id,
new GreetResponse($"Hello, {name}!"));
}
}
public record GreetParams(string Name);
public record GreetResponse(string Message);
优点:
- ✅ 无手动JSON模式 -自动生成自
GreetParams(输入)和GreetResponse(输出) - ✅ 强类型 -智能感知和编译时安全
- ✅ 清洁代码 -易于阅读和维护
3.2.高级工具(自定义模式)
对于复杂的验证或需要完全控制JSON模式时:
using Mcp.Gateway.Tools;
public class MyTools
{
[McpTool("greet",
Title = "Greet user",
Description = "Greets a user by name with custom validation.",
InputSchema = @"{
""type"":""object"",
""properties"":
{
""name"":{
""type"":""string"",
""description"":""Name of the user"",
""minLength"": 2,
""maxLength"": 50
}
},
""required"": [""name""]
}")]
public JsonRpcMessage Greet(JsonRpcMessage message)
{
var name = message.GetParams().GetProperty("name").GetString();
return ToolResponse.Success(
message.Id,
new { message = $"Hello, {name}!" });
}
}
何时使用:
- ✅ 自定义验证规则(minLength、maxLength、pattern等)
- ✅ 自动生成不支持复杂的架构功能
- ✅ 完全控制JSON模式
更完整的工具示例:
Examples/CalculatorMcpServer/Tools/CalculatorTools.csExamples/DateTimeMcpServer/Tools/DateTimeTools.csDevTestServer/Tools/Calculator.cs(含DI)
🔌 从MCP客户端连接
GitHub副本(VS代码/Visual Studio)
创建或更新 .mcp.json 对于Copilot(全局或每个工作区):
{
"mcpServers": {
"my_server": {
"command": "dotnet",
"args": [
"run",
"--project",
"C:\\path\\to\\MyMcpServer",
"--",
"--stdio"
]
}
}
}
然后在Copilot聊天中:
@my_server call greet with name = "Alice"
克劳德桌面
将Claude指向您的HTTP端点:
{
"mcpServers": {
"my_server": {
"transport": "http",
"url": "https://your-server.example.com/rpc"
}
}
}
Claude也可以使用WebSocket(/ws)用于全双工和二进制流。
📄 分页(v1.6.0)
当您有许多工具、提示或资源时,请使用基于光标的分页:
带分页的请求
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {
"cursor": "eyJvZmZzZXQiOjEwMH0=",
"pageSize": 50
},
"id": 1
}
使用nextCursor进行响应
{
"jsonrpc": "2.0",
"result": {
"tools": [ /* 50 tools */ ],
"nextCursor": "eyJvZmZzZXQiOjE1MH0="
},
"id": 1
}
特征:
- ✅ 可选参数-默认情况下不分页
- ✅ Base64编码光标格式:
{"offset": 100} - ✅ 默认页面大小:100个项目
- ✅ 使用
tools/list,prompts/list,resources/list - ✅ 按字母顺序排序以获得一致的结果
看 Examples/PaginationMcpServer 使用120多种工具进行演示。
🔔 通知(v1.7.0-符合MCP 2025-11-25!)
当工具、提示或资源发生变化时,通过以下方式获取实时更新 上海证券交易所 (服务器发送的事件):
服务器通过SSE发送通知
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed",
"params": {}
}
客户端通过SSE流接收通知
GET /mcp HTTP/1.1
Accept: text/event-stream
MCP-Session-Id: abc123
MCP-Protocol-Version: 2025-11-25
HTTP/1.1 200 OK
Content-Type: text/event-stream
id: 1
event: message
data: {"jsonrpc":"2.0","method":"notifications/tools/list_changed","params":{}}
id: 2
event: message
data: {"jsonrpc":"2.0","method":"notifications/prompts/list_changed","params":{}}
通知类型:
notifications/tools/list_changed–添加、删除或修改工具notifications/prompts/list_changed–提示已更新notifications/resources/updated–资源已更改(可选uri参数)
如何发送通知:
public class MyTools(INotificationSender notificationSender)
{
[McpTool("reload_tools")]
public async Task<JsonRpcMessage> ReloadTools(JsonRpcMessage request)
{
// Your tool logic...
// Notify all active SSE streams (v1.7.0)
await notificationSender.SendNotificationAsync(
NotificationMessage.ToolsChanged());
return ToolResponse.Success(request.Id, new { reloaded = true });
}
}
功能(v1.7.0):
- ✅ 基于SSE的通知(符合MCP 2025-11-25)
- ✅ 每个会话的消息缓冲(100条消息)
- ✅
Last-Event-ID重新连接时恢复 - ✅ 自动向所有活动会话广播
- ✅ WebSocket通知仍然有效(已弃用)
从v1.6.x迁移:
// v1.6.x - WebSocket only (still works!):
notificationService.AddSubscriber(webSocket);
// v1.7.0 - SSE (recommended, automatic):
// Client opens: GET /mcp with MCP-Session-Id header
// Server automatically broadcasts via SSE to all sessions
// No code changes needed!
看 Examples/NotificationMcpServer 对于带有手动通知触发器的演示。
📊 生命周期挂钩(v1.8.0)
使用以下工具监控和跟踪工具调用 生命周期挂钩 -非常适合度量、日志记录、授权和生产监控:
内置挂钩
日志工具生命周期钩子 -简单的日志集成:
var builder = WebApplication.CreateBuilder(args);
builder.AddToolsService();
builder.AddToolLifecycleHook<LoggingToolLifecycleHook>(); // Log all invocations
var app = builder.Build();
Metrics工具生命周期挂钩 -内存指标跟踪:
builder.AddToolLifecycleHook<MetricsToolLifecycleHook>();
// Expose metrics via HTTP endpoint
app.MapGet("/metrics", (IEnumerable<IToolLifecycleHook> hooks) =>
{
var metricsHook = hooks.OfType<MetricsToolLifecycleHook>().FirstOrDefault();
var metrics = metricsHook?.GetMetrics();
return Results.Json(new
{
timestamp = DateTime.UtcNow,
metrics = metrics?.Select(kvp => new
{
tool = kvp.Key,
invocations = kvp.Value.InvocationCount,
successes = kvp.Value.SuccessCount,
failures = kvp.Value.FailureCount,
successRate = Math.Round(kvp.Value.SuccessRate * 100, 2),
avgDuration = Math.Round(kvp.Value.AverageDuration.TotalMilliseconds, 2)
})
});
});
授权挂钩
使用生命周期挂钩实现基于角色的授权:
using Mcp.Gateway.Tools.Lifecycle;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class RequireRoleAttribute : Attribute
{
public string Role { get; }
public RequireRoleAttribute(string role) => Role = role;
}
public class AuthorizationHook : IToolLifecycleHook
{
private readonly IHttpContextAccessor _httpContextAccessor;
public Task OnToolInvokingAsync(string toolName, JsonRpcMessage request)
{
var httpContext = _httpContextAccessor.HttpContext;
var requiredRoles = GetRequiredRoles(toolName);
var userRoles = httpContext?.Items["UserRoles"] as List<string>;
if (!HasRequiredRole(requiredRoles, userRoles))
{
throw new ToolInvalidParamsException(
$"Insufficient permissions to invoke '{toolName}'.",
toolName);
}
return Task.CompletedTask;
}
// ... other methods
}
// Usage on tools:
[McpTool("delete_user")]
[RequireRole("Admin")]
public JsonRpcMessage DeleteUser(JsonRpcMessage request) { /* ... */ }
// Register authorization hook:
builder.AddToolLifecycleHook<AuthorizationHook>();
看 docs/Authorization.md 获取完整的授权指南和生产模式。
定制挂钩
实施 IToolLifecycleHook 对于自定义监控:
using Mcp.Gateway.Tools.Lifecycle;
public class PrometheusHook : IToolLifecycleHook
{
private readonly Counter _invocations;
private readonly Histogram _duration;
public PrometheusHook()
{
_invocations = Metrics.CreateCounter(
"mcp_tool_invocations_total",
"Total tool invocations",
new CounterConfiguration { LabelNames = new[] { "tool", "status" } });
_duration = Metrics.CreateHistogram(
"mcp_tool_duration_seconds",
"Tool execution duration",
new HistogramConfiguration { LabelNames = new[] { "tool" } });
}
public Task OnToolInvokingAsync(string toolName, JsonRpcMessage request)
{
_invocations.WithLabels(toolName, "started").Inc();
return Task.CompletedTask;
}
public Task OnToolCompletedAsync(string toolName, JsonRpcMessage response, TimeSpan duration)
{
_invocations.WithLabels(toolName, "success").Inc();
_duration.WithLabels(toolName).Observe(duration.TotalSeconds);
return Task.CompletedTask;
}
public Task OnToolFailedAsync(string toolName, Exception error, TimeSpan duration)
{
_invocations.WithLabels(toolName, "failure").Inc();
return Task.CompletedTask;
}
}
// Register custom hook
builder.AddToolLifecycleHook<PrometheusHook>();
跟踪指标
根据工具, MetricsToolLifecycleHook 轨道:
- 调用计数 -呼叫总数(成功+失败)
- 成功/失败计数 -按结果分列
- 成功率 -成功调用的百分比
- 持续时间 -最小、最大、平均执行时间
- 错误类型 -按异常类型统计的错误数
输出示例
{
"timestamp": "2025-12-19T16:30:00Z",
"metrics": [
{
"tool": "add_numbers",
"invocations": 150,
"successes": 150,
"failures": 0,
"successRate": 100.0,
"avgDuration": 1.23
},
{
"tool": "divide",
"invocations": 50,
"successes": 48,
"failures": 2,
"successRate": 96.0,
"avgDuration": 1.15
}
]
}
特征:
- ✅ 即发即弃 -钩子不会阻止工具执行
- ✅ 异常安全 -钩子错误会被记录下来,不会传播(除非
ToolInvalidParamsException授权) - ✅ 多钩 -根据需要注册
- ✅ 零配置 -可选,向后兼容
- ✅ 生产准备就绪 -线程安全指标跟踪
- ✅ 授权支持 -用于基于角色的访问控制
请参阅:
Examples/MetricsMcpServer-指标端点演示Examples/AuthorizationMcpServer-基于角色的授权docs/LifecycleHooks.md-完整的API参考docs/Authorization.md-授权模式和最佳实践
📦 资源订阅(v1.8.0)
订阅特定资源以获得有针对性的通知-减少带宽并提高高频更新的性能:
订阅资源
// Client subscribes to a specific resource URI
{
"jsonrpc": "2.0",
"method": "resources/subscribe",
"params": {
"uri": "file://data/users.json"
},
"id": 1
}
// Server confirms subscription
{
"jsonrpc": "2.0",
"result": {
"subscribed": true,
"uri": "file://data/users.json"
},
"id": 1
}
筛选通知
只有订阅者会收到其订阅资源的通知:
// Server notifies ONLY sessions subscribed to this URI
await notificationSender.SendNotificationAsync(
NotificationMessage.ResourcesUpdated("file://data/users.json"));
// Notification sent ONLY to subscribed sessions
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file://data/users.json"
}
}
退订
{
"jsonrpc": "2.0",
"method": "resources/unsubscribe",
"params": {
"uri": "file://data/users.json"
},
"id": 2
}
特征:
- ✅ 精确的URI匹配 -仅订阅特定资源(v1.8.0中没有通配符)
- ✅ 基于会话 -与MCP会话绑定的订阅
- ✅ 自动清理 -会话到期/删除时清除订阅
- ✅ 通知过滤 -服务器仅向订阅的会话发送
- ✅ 需要会话管理 -必须使用
/mcp端点与MCP-Session-Id
何时使用:
- ✅ 高频资源更新(例如,实时指标)
- ✅ 资源多,对每种资源都感兴趣的客户很少
- ✅ 减少通知带宽
限制(v1.8.0):
- ❌ 仅精确匹配URI(v1.9.0计划使用通配符)
- ❌ 需要会话管理(不适用于
/rpc端点)
看 Examples/ResourceMcpServer/README.md 了解完整的订阅工作流程和示例。
💡 特性
- ✅ MCP 2025年11月25日 –100%符合最新的MCP规范(v1.7.0)
- ✅ 运输
- 统一/mcp端点(v1.7.0): 符合MCP 2025-15-25的POST+GET+DELETE
- HTTP(
/rpc),websocket(/ws上海证券交易所/sse) stdio - 传统端点仍然有效(已弃用)
- ✅ 会话管理(v1.7.0)
MCP-Session-Id标头支持- 可配置超时(默认30分钟)
- 会话范围的事件ID
- ✅ 方案版本验证(v1.7.0)
MCP-Protocol-Version标头验证- 支持2025-11-25、2025-06-18、2025-03-26
- ✅ 自动发现 –通过属性发现的工具、提示和资源
- ✅ 传输感知过滤(v1.2.0)
- HTTP/stdio:仅限标准工具
- SSE:标准+文本流
- WebSocket:所有工具(包括二进制流)
- ✅ 类型化工具和可选模式生成(v1.3.0)
TypedJsonRpc<T>强类型工具实现的助手- 可选JSON模式自动生成
InputSchema省略,工具使用TypedJsonRpc<T>
- ✅ MCP提示(v1.4.0)
[McpPrompt]用于定义可重用提示模板的属性和提示模型- MCP提示协议支持:
prompts/list,prompts/get,以及在以下方面的快速能力initialize
- ✅ MCP资源(v1.5.0)
[McpResource]用于公开数据和内容(文件、数据库、API、系统指标)的属性- MCP资源协议支持:
resources/list,resources/read,以及资源能力initialize - 基于URI的寻址:
file://,db://,system://,http://
- ✅ 基于光标的分页(v1.6.0)
- 可选的
cursor和pageSize参数tools/list,prompts/list,resources/list nextCursor当有更多结果可用时作出响应- 默认页面大小:100个项目(可配置)
- 按字母顺序排序的结果,以实现一致的分页
- 可选的
- ✅ 基于SSE的通知(v1.7.0-符合MCP 2025-11-25!)
- 通过服务器发送事件进行实时更新
notifications/tools/list_changed,notifications/prompts/list_changed,notifications/resources/updated- 消息缓冲(每个会话100条消息)
Last-Event-ID重新连接时恢复- 自动向所有活动会话广播
NotificationService具有线程安全的订阅者管理- WebSocket通知仍然有效(已弃用)
- ✅ 生命周期挂钩(v1.8.0)
- 使用以下工具监控工具调用
IToolLifecycleHook - 内置挂钩:
LoggingToolLifecycleHook,MetricsToolLifecycleHook - 跟踪调用计数、成功率、持续时间、错误
- 即发即弃模式(例外-安全)
- Prometheus的生产就绪指标,应用洞察
- 使用以下工具监控工具调用
- ✅ 资源订阅(v1.8.0)
- 可选MCP 2025-11-25功能
resources/subscribe和resources/unsubscribe方法- 按订阅URI筛选通知
- 基于会话的自动清理
- 精确的URI匹配(v1.9.0中的通配符)
- ✅ 流媒体 –文本和二进制流通过
ToolConnector - ✅ DI支持 –工具、提示和资源可以将服务作为参数
- ✅ 已测试 273项测试,涵盖HTTP、WS、SSE和stdio
📚 了解更多
📖 文档
完整的文档可在以下网址获得: https://eyjolfurgudnivatne.github.io/mcp.gateway/
- 🤖 AI助手快速入门 -AI助手快速参考(GitHub Copilot、Claude、ChatGPT)
- 入门指南 -安装和首件工具
- api参考 -完整的API文件
- 例子 -带有解释的工作示例
- 特性 -高级功能指南
📂 在此存储库中
- 库自述:
Mcp.Gateway.Tools/README.md
工具API的详细信息(属性、JsonRpc模型等) - 文档:
docs/MCP-Protocol.md-MCP协议规范docs/StreamingProtocol.md-流协议详细信息docs/JSON-RPC-2.0-spec.md-JSON-RPC 2.0规范docs/LifecycleHooks.md-生命周期挂钩API参考(v1.8.0)docs/Authorization.md-授权模式和最佳实践(v1.8.0)
- 示例:
Examples/CalculatorMcpServer–计算器服务器Examples/DateTimeMcpServer–日期/时间工具Examples/PromptMcpServer–提示模板Examples/ResourceMcpServer–文件、系统和数据库资源Examples/PaginationMcpServer–使用120多个模拟工具进行分页(v1.6.0)Examples/NotificationMcpServer–WebSocket通知演示(v1.6.0)Examples/MetricsMcpServer–带有度量端点的生命周期挂钩(v1.8.0)Examples/AuthorizationMcpServer基于角色的授权(v1.8.0)
🧪 测试
dotnet test
测试使用 DevTestServer 作为端到端场景的主机:
- HTTP:
Mcp.Gateway.Tests/Endpoints/Http/* - Websocket:
Mcp.Gateway.Tests/Endpoints/Ws/* - 上海证券交易所
Mcp.Gateway.Tests/Endpoints/Sse/* - 标准 :
Mcp.Gateway.Tests/Endpoints/Stdio/*
📦 此仓库中的项目
| 项目 | 描述 |
|---|---|
Mcp.Gateway.Tools |
核心库/已发布的NuGet包 |
DevTestServer |
测试使用的内部测试服务器 |
Mcp.Gateway.Tests |
测试项目(70+集成测试) |
Examples/* |
小型集中样本服务器(计算器、日期时间) |
仅 Mcp.Gateway.Tools 旨在作为产品与NuGet的依赖关系。其他项目用于开发、验证和示例。
🤝 贡献
看 CONTRIBUTING.md 获取指南、代码风格和测试要求。
📜 许可证
麻省理工学院©2024–2025 ARKo AS–AHelse开发团队