feat: add pizza mcp test server
This commit is contained in:
parent
8a0df48079
commit
b8926a2c18
11
BotSharp.sln
11
BotSharp.sln
|
|
@ -129,6 +129,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.DeepSeekAI"
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.MCP", "src\Infrastructure\BotSharp.MCP\BotSharp.MCP.csproj", "{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.PizzaBot.MCPServer", "tests\BotSharp.PizzaBot.MCPServer\BotSharp.PizzaBot.MCPServer.csproj", "{AD91B4ED-0623-4710-913E-6D7C893E76EF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -529,6 +531,14 @@ Global
|
|||
{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -591,6 +601,7 @@ Global
|
|||
{AFD64412-4D6A-452E-82A2-79E5D8842E29} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
|
||||
{AF329442-B48E-4B48-A18A-1C869D1BA6F5} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
||||
{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
|
||||
{AD91B4ED-0623-4710-913E-6D7C893E76EF} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ public class McpToolFunction : IFunctionCallback
|
|||
);
|
||||
|
||||
// Extract the text content from the result
|
||||
// For simplicity in this sample, we'll just concatenate all text content
|
||||
message.Content = string.Join("\n", result.Content
|
||||
var json = string.Join("\n", result.Content
|
||||
.Where(c => c.Type == "text")
|
||||
.Select(c => c.Text));
|
||||
message.Content = json;
|
||||
message.Data = JsonSerializer.Deserialize(json,typeof(object));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,10 @@ public class McpPlugin : IBotSharpPlugin
|
|||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var settings = config.GetSection("MCPSettings").Get<MCPSettings>();
|
||||
services.AddScoped<MCPSettings>(provider => { return settings; });
|
||||
services.AddSingleton<MCPClientManager>(provider =>
|
||||
{
|
||||
var loggerFactory = provider.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
|
||||
return new MCPClientManager(settings, loggerFactory);
|
||||
});
|
||||
services.AddScoped<MCPSettings>(provider => { return settings; });
|
||||
|
||||
clientManager = new MCPClientManager(settings, NullLoggerFactory.Instance);
|
||||
services.AddSingleton(clientManager);
|
||||
|
||||
foreach (var server in settings.McpServerConfigs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\tests\BotSharp.PizzaBot.MCPServer\BotSharp.PizzaBot.MCPServer.csproj" />
|
||||
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
||||
<ProjectReference Include="..\BotSharp.ServiceDefaults\BotSharp.ServiceDefaults.csproj" />
|
||||
<ProjectReference Include="..\Infrastructure\BotSharp.MCP\BotSharp.MCP.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="mcpdotnet" Version="1.0.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
125
tests/BotSharp.PizzaBot.MCPServer/Program.cs
Normal file
125
tests/BotSharp.PizzaBot.MCPServer/Program.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using McpDotNet.Protocol.Transport;
|
||||
using McpDotNet.Protocol.Types;
|
||||
using McpDotNet.Server;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog;
|
||||
using System.Dynamic;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BotSharp.PizzaBot.MCPServer
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Starting server...");
|
||||
|
||||
McpServerOptions options = new McpServerOptions()
|
||||
{
|
||||
ServerInfo = new Implementation() { Name = "PizzaServer", Version = "1.0.0" },
|
||||
Capabilities = new ServerCapabilities()
|
||||
{
|
||||
Tools = new(),
|
||||
Resources = new(),
|
||||
Prompts = new(),
|
||||
},
|
||||
ProtocolVersion = "2024-11-05"
|
||||
};
|
||||
var loggerFactory = CreateLoggerFactory();
|
||||
McpServerFactory factory = new McpServerFactory(new StdioServerTransport("PizzaServer", loggerFactory), options, loggerFactory,
|
||||
"This is a test server with only stub functionality");
|
||||
IMcpServer server = factory.CreateServer();
|
||||
|
||||
Console.WriteLine("Server object created, registering handlers.");
|
||||
|
||||
#region Tools
|
||||
server.ListToolsHandler = (request, cancellationToken) =>
|
||||
{
|
||||
return Task.FromResult(new ListToolsResult()
|
||||
{
|
||||
Tools =
|
||||
[
|
||||
new Tool()
|
||||
{
|
||||
Name = "make_payment",
|
||||
Description = "call this function to make payment",
|
||||
InputSchema = new JsonSchema()
|
||||
{
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, JsonSchemaProperty>()
|
||||
{
|
||||
["order_number"] = new JsonSchemaProperty() { Type = "string", Description = "order number." },
|
||||
["total_amount"] = new JsonSchemaProperty() { Type = "string", Description = "total amount." },
|
||||
},
|
||||
Required = new List<string>() { "order_number", "total_amount" }
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
server.CallToolHandler = async (request, cancellationToken) =>
|
||||
{
|
||||
if (request.Name == "make_payment")
|
||||
{
|
||||
if (request.Arguments is null || !request.Arguments.TryGetValue("order_number", out var order_number))
|
||||
{
|
||||
throw new McpServerException("Missing required argument 'order_number'");
|
||||
}
|
||||
if (request.Arguments is null || !request.Arguments.TryGetValue("total_amount", out var total_amount))
|
||||
{
|
||||
throw new McpServerException("Missing required argument 'total_amount'");
|
||||
}
|
||||
dynamic message = new ExpandoObject();
|
||||
message.pepperoni_unit_price = 3.2;
|
||||
message.cheese_unit_price = 3.5;
|
||||
message.margherita_unit_price = 3.8;
|
||||
|
||||
// Serialize the message to JSON
|
||||
var jso = new JsonSerializerOptions() { WriteIndented = true };
|
||||
var jsonMessage = JsonSerializer.Serialize(message, jso);
|
||||
|
||||
return new CallToolResponse()
|
||||
{
|
||||
Content = [new Content() { Text = jsonMessage , Type = "text" }]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new McpServerException($"Unknown tool: {request.Name}");
|
||||
}
|
||||
};
|
||||
#endregion
|
||||
|
||||
Console.WriteLine("Server initialized.");
|
||||
|
||||
await server.StartAsync();
|
||||
|
||||
Console.WriteLine("Server started.");
|
||||
|
||||
// Run until process is stopped by the client (parent process)
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
private static ILoggerFactory CreateLoggerFactory()
|
||||
{
|
||||
// Use serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.Verbose() // Capture all log levels
|
||||
.WriteTo.File(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "TestServer_.log"),
|
||||
rollingInterval: RollingInterval.Day,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.CreateLogger();
|
||||
|
||||
var logsPath = Path.Combine(AppContext.BaseDirectory, "testserver.log");
|
||||
return LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddSerilog();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
using BotSharp.Abstraction.Conversations.Models;
|
||||
//using BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
namespace BotSharp.Plugin.PizzaBot.Functions;
|
||||
//namespace BotSharp.Plugin.PizzaBot.Functions;
|
||||
|
||||
public class MakePaymentFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "make_payment";
|
||||
//public class MakePaymentFn : IFunctionCallback
|
||||
//{
|
||||
// public string Name => "make_payment";
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
message.Content = "Payment proceed successfully. Thank you for your business. Have a great day!";
|
||||
message.Data = new
|
||||
{
|
||||
Transaction = Guid.NewGuid().ToString(),
|
||||
Status = "Success"
|
||||
};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// public async Task<bool> Execute(RoleDialogModel message)
|
||||
// {
|
||||
// message.Content = "Payment proceed successfully. Thank you for your business. Have a great day!";
|
||||
// message.Data = new
|
||||
// {
|
||||
// Transaction = Guid.NewGuid().ToString(),
|
||||
// Status = "Success"
|
||||
// };
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@
|
|||
"disabled": false,
|
||||
"isPublic": true,
|
||||
"profiles": [ "pizza" ],
|
||||
"McpTools": {
|
||||
"ServerId": "b284db86-e9c2-4c25-a59e-4649797dd130",
|
||||
"Disabled": "false",
|
||||
"Functions": [
|
||||
{
|
||||
"Name": "make_payment"
|
||||
}
|
||||
]
|
||||
},
|
||||
"routingRules": [
|
||||
{
|
||||
"field": "order_number",
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"name": "make_payment",
|
||||
"description": "call this function to make payment",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_number": {
|
||||
"type": "string",
|
||||
"description": "order number."
|
||||
},
|
||||
"total_amount": {
|
||||
"type": "string",
|
||||
"description": "total amount."
|
||||
}
|
||||
},
|
||||
"required": [ "order_number", "total_amount" ]
|
||||
}
|
||||
}
|
||||
//{
|
||||
// "name": "make_payment",
|
||||
// "description": "call this function to make payment",
|
||||
// "parameters": {
|
||||
// "type": "object",
|
||||
// "properties": {
|
||||
// "order_number": {
|
||||
// "type": "string",
|
||||
// "description": "order number."
|
||||
// },
|
||||
// "total_amount": {
|
||||
// "type": "string",
|
||||
// "description": "total amount."
|
||||
// }
|
||||
// },
|
||||
// "required": [ "order_number", "total_amount" ]
|
||||
// }
|
||||
//}
|
||||
Loading…
Reference in a new issue