diff --git a/BotSharp.sln b/BotSharp.sln
index c6c75391..1e8ac13d 100644
--- a/BotSharp.sln
+++ b/BotSharp.sln
@@ -127,9 +127,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Core.Rules", "src\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.DeepSeekAI", "src\Plugins\BotSharp.Plugin.DeepSeekAI\BotSharp.Plugin.DeepSeekAI.csproj", "{AF329442-B48E-4B48-A18A-1C869D1BA6F5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.MCP", "src\Infrastructure\BotSharp.MCP\BotSharp.MCP.csproj", "{8ED8EEF4-06DD-45F5-AA91-BD2395E901B5}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.MCP", "src\Infrastructure\BotSharp.MCP\BotSharp.MCP.csproj", "{684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.PizzaBot.MCPServer", "tests\BotSharp.PizzaBot.MCPServer\BotSharp.PizzaBot.MCPServer.csproj", "{AD91B4ED-0623-4710-913E-6D7C893E76EF}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.PizzaBot.MCPServer", "tests\BotSharp.PizzaBot.MCPServer\BotSharp.PizzaBot.MCPServer.csproj", "{8D2AD45F-836A-516F-DE6A-71443CEBB18A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Core.Realtime", "src\Infrastructure\BotSharp.Core.Realtime\BotSharp.Core.Realtime.csproj", "{781F1465-365C-0F22-1775-25025DAFA4C7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -523,6 +525,30 @@ Global
{AF329442-B48E-4B48-A18A-1C869D1BA6F5}.Release|Any CPU.Build.0 = Release|Any CPU
{AF329442-B48E-4B48-A18A-1C869D1BA6F5}.Release|x64.ActiveCfg = Release|Any CPU
{AF329442-B48E-4B48-A18A-1C869D1BA6F5}.Release|x64.Build.0 = Release|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Debug|x64.Build.0 = Debug|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Release|x64.ActiveCfg = Release|Any CPU
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C}.Release|x64.Build.0 = Release|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Debug|x64.Build.0 = Debug|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Release|x64.ActiveCfg = Release|Any CPU
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A}.Release|x64.Build.0 = Release|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Debug|x64.Build.0 = Debug|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Release|x64.ActiveCfg = Release|Any CPU
+ {781F1465-365C-0F22-1775-25025DAFA4C7}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -584,6 +610,9 @@ Global
{F812BAAE-5A7D-4DF7-8E71-70696B51C61F} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
{AFD64412-4D6A-452E-82A2-79E5D8842E29} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
{AF329442-B48E-4B48-A18A-1C869D1BA6F5} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
+ {684781D5-3DD4-6A0B-B53F-0A362CD6BB0C} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
+ {8D2AD45F-836A-516F-DE6A-71443CEBB18A} = {32FAFFFE-A4CB-4FEE-BF7C-84518BBC6DCC}
+ {781F1465-365C-0F22-1775-25025DAFA4C7} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
diff --git a/Directory.Packages.props b/Directory.Packages.props
index aa76cf61..80231ce1 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -6,6 +6,7 @@
+
@@ -13,13 +14,15 @@
-
+
+
+
@@ -106,6 +109,7 @@
+
diff --git a/src/Infrastructure/BotSharp.MCP/BotSharp.MCP.csproj b/src/Infrastructure/BotSharp.MCP/BotSharp.MCP.csproj
index e9727f7f..037ed776 100644
--- a/src/Infrastructure/BotSharp.MCP/BotSharp.MCP.csproj
+++ b/src/Infrastructure/BotSharp.MCP/BotSharp.MCP.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Infrastructure/BotSharp.MCP/Functions/McpToolFunction.cs b/src/Infrastructure/BotSharp.MCP/Functions/McpToolFunction.cs
index 97ec724f..0e755df5 100644
--- a/src/Infrastructure/BotSharp.MCP/Functions/McpToolFunction.cs
+++ b/src/Infrastructure/BotSharp.MCP/Functions/McpToolFunction.cs
@@ -2,6 +2,7 @@ using BotSharp.Abstraction.Agents;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Functions;
+using BotSharp.Abstraction.Utilities;
using McpDotNet.Client;
using McpDotNet.Protocol.Types;
using Microsoft.Extensions.DependencyInjection;
@@ -49,8 +50,8 @@ public class McpToolFunction : IFunctionCallback
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));
+ message.Content = json.JsonContent();
+
return true;
}
diff --git a/src/Infrastructure/BotSharp.MCP/Hooks/MCPResponseHook.cs b/src/Infrastructure/BotSharp.MCP/Hooks/MCPResponseHook.cs
new file mode 100644
index 00000000..0b939f2e
--- /dev/null
+++ b/src/Infrastructure/BotSharp.MCP/Hooks/MCPResponseHook.cs
@@ -0,0 +1,41 @@
+using BotSharp.Abstraction.Agents.Enums;
+using BotSharp.Abstraction.Agents.Settings;
+using BotSharp.Abstraction.Agents;
+using BotSharp.Abstraction.Conversations;
+using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.Abstraction.Infrastructures.Enums;
+using BotSharp.Abstraction.Translation;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Text.Json;
+
+namespace BotSharp.MCP.Hooks;
+
+public class MCPResponseHook : ConversationHookBase
+{
+ private readonly IServiceProvider _services;
+ private readonly IConversationStateService _states;
+ private const string AIAssistant = BuiltInAgentId.AIAssistant;
+
+ public MCPResponseHook(IServiceProvider services,
+ IConversationStateService states)
+ {
+ _services = services;
+ _states = states;
+ }
+ public override async Task OnResponseGenerated(RoleDialogModel message)
+ {
+ var agentService = _services.GetRequiredService();
+ var agent = await agentService.LoadAgent(message.CurrentAgentId);
+ if(agent.McpTools.Any(item => item.Functions.Any(x=> x.Name == message.FunctionName)))
+ {
+ message.Data = JsonSerializer.Deserialize(message.Content, typeof(object));
+ }
+ await base.OnResponseGenerated(message);
+ }
+}
+
diff --git a/tests/BotSharp.PizzaBot.MCPServer/BotSharp.PizzaBot.MCPServer.csproj b/tests/BotSharp.PizzaBot.MCPServer/BotSharp.PizzaBot.MCPServer.csproj
index 1158e06a..03b092b1 100644
--- a/tests/BotSharp.PizzaBot.MCPServer/BotSharp.PizzaBot.MCPServer.csproj
+++ b/tests/BotSharp.PizzaBot.MCPServer/BotSharp.PizzaBot.MCPServer.csproj
@@ -8,9 +8,10 @@
enable
-
-
-
-
+
+
+
+
+
diff --git a/tests/BotSharp.PizzaBot.MCPServer/Program.cs b/tests/BotSharp.PizzaBot.MCPServer/Program.cs
index 5e8633f8..b2477c99 100644
--- a/tests/BotSharp.PizzaBot.MCPServer/Program.cs
+++ b/tests/BotSharp.PizzaBot.MCPServer/Program.cs
@@ -1,3 +1,4 @@
+using McpDotNet.Protocol.Messages;
using McpDotNet.Protocol.Transport;
using McpDotNet.Protocol.Types;
using McpDotNet.Server;
@@ -20,30 +21,42 @@ namespace BotSharp.PizzaBot.MCPServer
ServerInfo = new Implementation() { Name = "PizzaServer", Version = "1.0.0" },
Capabilities = new ServerCapabilities()
{
- Tools = new(),
- Resources = new(),
- Prompts = new(),
+ //Tools = ConfigureTools(),
},
- ProtocolVersion = "2024-11-05"
+ ProtocolVersion = "2024-11-05",
+ ServerInstructions = "This is a test server with only stub functionality"
};
var loggerFactory = CreateLoggerFactory();
- McpServerFactory factory = new McpServerFactory(new StdioServerTransport("PizzaServer", loggerFactory), options, loggerFactory,
- "This is a test server with only stub functionality");
+ McpServerFactory factory = new McpServerFactory(new StdioServerTransport("PizzaServer", loggerFactory), options, loggerFactory);
IMcpServer server = factory.CreateServer();
+ ConfigureTools(server);
Console.WriteLine("Server object created, registering handlers.");
- #region Tools
- server.ListToolsHandler = (request, cancellationToken) =>
+ Console.WriteLine("Server initialized.");
+
+ await server.StartAsync();
+
+ Console.WriteLine("Server started.");
+
+ // Run until process is stopped by the client (parent process)
+ while (true)
{
- return Task.FromResult(new ListToolsResult()
+ await Task.Delay(1000);
+ }
+ }
+
+ private static void ConfigureTools(IMcpServer server)
+ {
+ server.ListToolsHandler = (request, cancellationToken) =>
{
- Tools =
- [
- new Tool()
+ return Task.FromResult(new ListToolsResult()
+ {
+ Tools = [
+ new Tool()
{
Name = "make_payment",
- Description = "call this function to make payment",
+ Description = "call this function to make payment",
InputSchema = new JsonSchema()
{
Type = "object",
@@ -51,9 +64,9 @@ namespace BotSharp.PizzaBot.MCPServer
{
["order_number"] = new JsonSchemaProperty() { Type = "string", Description = "order number." },
["total_amount"] = new JsonSchemaProperty() { Type = "string", Description = "total amount." },
- },
+ },
Required = new List() { "order_number", "total_amount" }
- },
+ },
},
new Tool()
{
@@ -63,7 +76,7 @@ namespace BotSharp.PizzaBot.MCPServer
{
Type = "object",
Properties = new Dictionary()
- {
+ {
["pizza_type"] = new JsonSchemaProperty() { Type = "string", Description = "The pizza type." },
["quantity"] = new JsonSchemaProperty() { Type = "string", Description = "quantity of pizza." },
@@ -79,7 +92,7 @@ namespace BotSharp.PizzaBot.MCPServer
{
Type = "object",
Properties = new Dictionary()
- {
+ {
["pizza_type"] = new JsonSchemaProperty() { Type = "string", Description = "The pizza type." },
["quantity"] = new JsonSchemaProperty() { Type = "number", Description = "quantity of pizza." },
["unit_price"] = new JsonSchemaProperty() { Type = "number", Description = "unit price" },
@@ -88,19 +101,19 @@ namespace BotSharp.PizzaBot.MCPServer
Required = new List(){"pizza_type", "quantity", "unit_price" }
}
}
- ]
- });
- };
+ ]
+ });
+ };
server.CallToolHandler = async (request, cancellationToken) =>
{
- if (request.Name == "make_payment")
+ if (request.Params.Name == "make_payment")
{
- if (request.Arguments is null || !request.Arguments.TryGetValue("order_number", out var order_number))
+ if (request.Params.Arguments is null || !request.Params.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))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("total_amount", out var total_amount))
{
throw new McpServerException("Missing required argument 'total_amount'");
}
@@ -113,17 +126,17 @@ namespace BotSharp.PizzaBot.MCPServer
var jsonMessage = JsonSerializer.Serialize(message, jso);
return new CallToolResponse()
- {
- Content = [new Content() { Text = jsonMessage , Type = "text" }]
+ {
+ Content = [new Content() { Text = jsonMessage, Type = "text" }]
};
}
- else if(request.Name == "get_pizza_prices")
+ else if (request.Params.Name == "get_pizza_prices")
{
- if (request.Arguments is null || !request.Arguments.TryGetValue("pizza_type", out var pizza_type))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("pizza_type", out var pizza_type))
{
throw new McpServerException("Missing required argument 'pizza_type'");
}
- if (request.Arguments is null || !request.Arguments.TryGetValue("quantity", out var quantity))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("quantity", out var quantity))
{
throw new McpServerException("Missing required argument 'quantity'");
}
@@ -139,23 +152,23 @@ namespace BotSharp.PizzaBot.MCPServer
Content = [new Content() { Text = jsonMessage, Type = "text" }]
};
}
- else if (request.Name == "place_an_order")
+ else if (request.Params.Name == "place_an_order")
{
- if (request.Arguments is null || !request.Arguments.TryGetValue("pizza_type", out var pizza_type))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("pizza_type", out var pizza_type))
{
throw new McpServerException("Missing required argument 'pizza_type'");
}
- if (request.Arguments is null || !request.Arguments.TryGetValue("quantity", out var quantity))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("quantity", out var quantity))
{
throw new McpServerException("Missing required argument 'quantity'");
}
- if (request.Arguments is null || !request.Arguments.TryGetValue("unit_price", out var unit_price))
+ if (request.Params.Arguments is null || !request.Params.Arguments.TryGetValue("unit_price", out var unit_price))
{
throw new McpServerException("Missing required argument 'unit_price'");
}
dynamic message = new ExpandoObject();
message.order_number = "P123-01";
- message.Content = "The order number is P123-01";
+ message.Content = "The order number is P123-01";
// Serialize the message to JSON
var jso = new JsonSerializerOptions() { WriteIndented = true };
var jsonMessage = JsonSerializer.Serialize(message, jso);
@@ -166,22 +179,9 @@ namespace BotSharp.PizzaBot.MCPServer
}
else
{
- throw new McpServerException($"Unknown tool: {request.Name}");
+ throw new McpServerException($"Unknown tool: {request.Params.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()
diff --git a/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json b/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
index 7ec18d46..9699d5ab 100644
--- a/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
+++ b/tests/BotSharp.Plugin.PizzaBot/data/agents/c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd/agent.json
@@ -20,6 +20,6 @@
}
]
}
- ]
+ ],
"labels": [ "experiment" ]
}
\ No newline at end of file