MCP网关工具库

Mcp.Gateway.Tools是一个用于构建Model Context Protocol (MCP)服务器的.NET库,支持多种传输协议和工具自动发现。

  • by eyjolfurgudnivatne
  • C#
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 eyjolfurgudnivatne/mcp.gateway

使用说明

🚀 麦克。网关。工具

在中构建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.cs
  • Examples/DateTimeMcpServer/Tools/DateTimeTools.cs
  • DevTestServer/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/

📂 在此存储库中

  • 库自述: 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开发团队