MCP测试SSE模式
来自公众号 十分钟入门MCPServer , 其实用不了十分钟
这次的核心库是 ModelContextProtocol ,就是官方的库
上次的库MCPSharp
还没有支持SSE
新建API项目,引用库
<ItemGroup> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> <PackageReference Include="ModelContextProtocol" Version="0.1.0-preview.2" /> <PackageReference Include="Flurl" Version="4.0.0" /> <PackageReference Include="Flurl.Http" Version="4.0.2" /> </ItemGroup>
就是开启 /sse
using Microsoft.Extensions.Options; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Transport; using ModelContextProtocol.Server; using ModelContextProtocol.Utils.Json; namespace WebSSE { public static class McpEndpointRouteBuilderExtensions { public static IEndpointConventionBuilder MapMcpSse(this IEndpointRouteBuilder endpoints) { IMcpServer? server = null; SseResponseStreamTransport? transport = null; var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>(); var mcpServerOptions = endpoints.ServiceProvider.GetRequiredService<IOptions<McpServerOptions>>(); var routeGroup = endpoints.MapGroup(""); routeGroup.MapGet("/sse", async (HttpResponse response, CancellationToken requestAborted) => { await using var localTransport = transport = new SseResponseStreamTransport(response.Body); await using var localServer = server = McpServerFactory.Create(transport, mcpServerOptions.Value, loggerFactory, endpoints.ServiceProvider); await localServer.StartAsync(requestAborted); response.Headers.ContentType = "text/event-stream"; response.Headers.CacheControl = "no-cache"; try { await transport.RunAsync(requestAborted); } catch (OperationCanceledException) when (requestAborted.IsCancellationRequested) { // RequestAborted always triggers when the client disconnects before a complete response body is written, // but this is how SSE connections are typically closed. } }); routeGroup.MapPost("/message", async context => { if (transport is null) { await Results.BadRequest("Connect to the /sse endpoint before sending messages.").ExecuteAsync(context); return; } var message = await context.Request.ReadFromJsonAsync<IJsonRpcMessage>(McpJsonUtilities.DefaultOptions, context.RequestAborted); if (message is null) { await Results.BadRequest("No message in request body.").ExecuteAsync(context); return; } await transport.OnMessageReceivedAsync(message, context.RequestAborted); context.Response.StatusCode = StatusCodes.Status202Accepted; await context.Response.WriteAsync("Accepted"); }); return routeGroup; } } }
把之前的工具类放上
using Flurl.Http; using ModelContextProtocol.Server; using System.ComponentModel; namespace WebSSE.Tools { [McpServerToolType] public static class ERPCost { [McpServerTool("get-cost-bycode"), Description("通过物料编号得到核价")] public static string GetCostByCode( IMcpServer thisServer, [Description("物料编号")] string code) { var response = "http://localhost/api/CRM/GetCostByCode" .WithHeader("accept", "*/*") .WithHeader("Content-Type", "application/json-patch+json") .PostJsonAsync(new { GUID = "B02C2304120019", hasCode = "", data = new { CostCode = code, } }) .GetAwaiter().GetResult(); // 处理响应 var responseString = response.GetStringAsync().GetAwaiter().GetResult(); var dis = @"Code 1 表示成功 ,非1表示有错误 Message ""成功"" 或 其他错误消息 MB001 品号 MB002 品名 MB003 规格 MB004 单位 CostUnitCost 当前成本(该物料在该账套的最近核价含税) HasNoCost 1表示BOM中有价格为0的物料,0表示没有价格为0的物料 "; return responseString + dis; } } }
注意这里的 类的声明McpServerToolType
和 方法声明McpServerTool
注册工具
builder.Services.AddMcpServer().WithToolsFromAssembly(); app.MapMcpSse();
启动就行了
这样就可以部署到docker进行远程调用了
本文作者:没想好
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!