Merge branch 'SciSharp:master' into master

This commit is contained in:
evan-cao-wb 2025-03-28 10:07:31 -05:00 committed by GitHub
commit b4c8bbde2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 146 additions and 122 deletions

View file

@ -110,7 +110,8 @@
<PackageVersion Include="MSTest.TestFramework" Version="3.1.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageVersion Include="ModelContextProtocol" Version="0.1.0-preview.1.25171.12" />
<PackageVersion Include="ModelContextProtocol" Version="0.1.0-preview.2" />
<PackageVersion Include="System.Linq.Async" Version="6.0.1" />
</ItemGroup>
<ItemGroup>
<PackageVersion Include="BotSharp.Core" Version="$(BotSharpVersion)" />

View file

@ -47,7 +47,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
<ProjectReference Include="..\BotSharp.Core\BotSharp.Core.csproj" />
<ProjectReference Include="..\BotSharp.MCP\BotSharp.MCP.csproj" />
</ItemGroup>
<ItemGroup>

View file

@ -1,4 +1,7 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Core.Mcp;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol.Types;
namespace BotSharp.OpenAPI.Controllers;
@ -9,15 +12,19 @@ public class AgentController : ControllerBase
private readonly IAgentService _agentService;
private readonly IUserIdentity _user;
private readonly IServiceProvider _services;
private readonly MCPClientManager _clientManager;
public AgentController(
IAgentService agentService,
IUserIdentity user,
IServiceProvider services)
IServiceProvider services,
MCPClientManager mCPClientManager
)
{
_agentService = agentService;
_user = user;
_services = services;
_clientManager = mCPClientManager;
}
[HttpGet("/agent/settings")]
@ -167,6 +174,16 @@ public class AgentController : ControllerBase
return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList();
}
[HttpGet("/agent/mcp/tools")]
public async Task<IEnumerable<Tool>> GetMCPTools(string serverId)
{
var client = await _clientManager.GetMcpClientAsync(serverId);
var tools = await client.ListToolsAsync().ToListAsync();
return tools.Where(x => !string.IsNullOrWhiteSpace(x.Name))
.OrderBy(x => x.Name).ToList();
}
[HttpGet("/agent/labels")]
public async Task<IEnumerable<string>> GetAgentLabels()
{

View file

@ -30,7 +30,6 @@
<ItemGroup>
<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">
@ -73,6 +72,7 @@
<ProjectReference Include="..\Plugins\BotSharp.Plugin.MetaGLM\BotSharp.Plugin.MetaGLM.csproj" />
<ProjectReference Include="..\Plugins\BotSharp.Plugin.Planner\BotSharp.Plugin.Planner.csproj" />
<ProjectReference Include="..\Plugins\BotSharp.Plugin.TencentCos\BotSharp.Plugin.TencentCos.csproj" />
<ProjectReference Include="..\Infrastructure\BotSharp.MCP\BotSharp.MCP.csproj" />
</ItemGroup>
<ItemGroup>

View file

@ -2,7 +2,8 @@ using BotSharp.PizzaBot.MCPServer;
using ModelContextProtocol;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer().WithTools();
builder.Services.AddMcpServer()
.WithToolsFromAssembly();
var app = builder.Build();
app.MapGet("/", () => "This is a test server with only stub functionality!");

View file

@ -4,10 +4,10 @@ using System.ComponentModel.DataAnnotations;
namespace BotSharp.PizzaBot.MCPServer.Tools;
[McpToolType]
[McpServerToolType]
public static class MakePayment
{
[McpTool(name: "make_payment"), Description("call this function to make payment.")]
[McpServerTool(name: "make_payment"), Description("call this function to make payment.")]
public static string Make_Payment(
[Description("order number"),Required] string order_number,
[Description("total amount"),Required] int total_amount)

View file

@ -6,10 +6,10 @@ using System.Text.Json;
namespace BotSharp.PizzaBot.MCPServer.Tools;
[McpToolType]
[McpServerToolType]
public static class PizzaPrices
{
[McpTool(name: "get_pizza_prices"), Description("call this function to get pizza unit price.")]
[McpServerTool(name: "get_pizza_prices"), Description("call this function to get pizza unit price.")]
public static string GetPizzaPrices(
[Description("The pizza type."), Required] string pizza_type,
[Description("quantity of pizza"), Required] int quantity)

View file

@ -4,10 +4,10 @@ using System.ComponentModel.DataAnnotations;
namespace BotSharp.PizzaBot.MCPServer.Tools;
[McpToolType]
[McpServerToolType]
public static class PlaceOrder
{
[McpTool(name: "place_an_order"), Description("Place an order when user has confirmed the pizza type and quantity.")]
[McpServerTool(name: "place_an_order"), Description("Place an order when user has confirmed the pizza type and quantity.")]
public static string PlaceAnOrder(
[Description("The pizza type."), Required] string pizza_type,
[Description("quantity of pizza"), Required] int quantity,

View file

@ -1,21 +1,21 @@
//using BotSharp.Abstraction.Conversations.Models;
//using System.Text.Json;
using BotSharp.Abstraction.Conversations.Models;
using System.Text.Json;
//namespace BotSharp.Plugin.PizzaBot.Functions;
namespace BotSharp.Plugin.PizzaBot.Functions;
//public class GetPizzaPricesFn : IFunctionCallback
//{
// public string Name => "get_pizza_price";
public class GetPizzaPricesFn : IFunctionCallback
{
public string Name => "get_pizza_price";
// public async Task<bool> Execute(RoleDialogModel message)
// {
// message.Data = new
// {
// pepperoni_unit_price = 3.2,
// cheese_unit_price = 3.5,
// margherita_unit_price = 3.8,
// };
// message.Content = JsonSerializer.Serialize(message.Data);
// return true;
// }
//}
public async Task<bool> Execute(RoleDialogModel message)
{
message.Data = new
{
pepperoni_unit_price = 3.2,
cheese_unit_price = 3.5,
margherita_unit_price = 3.8,
};
message.Content = JsonSerializer.Serialize(message.Data);
return true;
}
}

View file

@ -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;
}
}

View file

@ -1,24 +1,24 @@
//using BotSharp.Abstraction.Conversations;
//using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Conversations.Models;
//namespace BotSharp.Plugin.PizzaBot.Functions;
namespace BotSharp.Plugin.PizzaBot.Functions;
//public class PlaceOrderFn : IFunctionCallback
//{
// public string Name => "place_an_order";
public class PlaceOrderFn : IFunctionCallback
{
public string Name => "place_an_order";
// private readonly IServiceProvider _service;
// public PlaceOrderFn(IServiceProvider service)
// {
// _service = service;
// }
private readonly IServiceProvider _service;
public PlaceOrderFn(IServiceProvider service)
{
_service = service;
}
// public async Task<bool> Execute(RoleDialogModel message)
// {
// message.Content = "The order number is P123-01";
// var state = _service.GetRequiredService<IConversationStateService>();
// state.SetState("order_number", "P123-01");
public async Task<bool> Execute(RoleDialogModel message)
{
message.Content = "The order number is P123-01";
var state = _service.GetRequiredService<IConversationStateService>();
state.SetState("order_number", "P123-01");
// return true;
// }
//}
return true;
}
}

View file

@ -32,16 +32,20 @@ public class PizzaBotConversationHook : ConversationHookBase
return base.OnTaskCompleted(message);
}
#if USE_BOTSHARP
public override async Task OnResponseGenerated(RoleDialogModel message)
{
var agentService = _services.GetRequiredService<IAgentService>();
var state = _services.GetRequiredService<IConversationStateService>();
var agent = await agentService.LoadAgent(message.CurrentAgentId);
if (agent.McpTools.Any(item => item.Functions.Any(x => x.Name == message.FunctionName)))
{
var data = JsonDocument.Parse(JsonSerializer.Serialize(message.Data));
state.SaveStateByArgs(data);
}
await base.OnResponseGenerated(message);
}
#endif
}

View file

@ -1,18 +1,18 @@
//{
// "name": "get_pizza_price",
// "description": "call this function to get the pizza price",
// "parameters": {
// "type": "object",
// "properties": {
// "pizza_type": {
// "type": "string",
// "description": "The pizza type."
// },
// "quantity": {
// "type": "string",
// "description": "quantity of pizza."
// }
// },
// "required": [ "pizza_type", "quantity" ]
// }
//}
{
"name": "get_pizza_price",
"description": "call this function to get the pizza price",
"parameters": {
"type": "object",
"properties": {
"pizza_type": {
"type": "string",
"description": "The pizza type."
},
"quantity": {
"type": "string",
"description": "quantity of pizza."
}
},
"required": [ "pizza_type", "quantity" ]
}
}

View file

@ -1,22 +1,22 @@
//{
// "name": "place_an_order",
// "description": "Place an order when user has confirmed the pizza type and quantity.",
// "parameters": {
// "type": "object",
// "properties": {
// "pizza_type": {
// "type": "string",
// "description": "The pizza type."
// },
// "quantity": {
// "type": "number",
// "description": "quantity of pizza."
// },
// "unit_price": {
// "type": "number",
// "description": "unit price"
// }
// },
// "required": [ "pizza_type", "quantity", "unit_price" ]
// }
//}
{
"name": "place_an_order",
"description": "Place an order when user has confirmed the pizza type and quantity.",
"parameters": {
"type": "object",
"properties": {
"pizza_type": {
"type": "string",
"description": "The pizza type."
},
"quantity": {
"type": "number",
"description": "quantity of pizza."
},
"unit_price": {
"type": "number",
"description": "unit price"
}
},
"required": [ "pizza_type", "quantity", "unit_price" ]
}
}

View file

@ -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" ]
}
}