Remove McpService and refactor dependency injection for MCP tools
- Deleted the McpService class, which was previously responsible for executing Model Context Protocol (MCP) tools. - Updated the ApiBootstrap class to change the registration of IMcpService to the new Managing.Mcp.McpService implementation. - Added new MCP tool implementations for DataTools, BotTools, and IndicatorTools to enhance functionality.
This commit is contained in:
@@ -1,236 +0,0 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Users;
|
||||
using Managing.Mcp.Tools;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.LLM;
|
||||
|
||||
/// <summary>
|
||||
/// Service for executing Model Context Protocol (MCP) tools
|
||||
/// </summary>
|
||||
public class McpService : IMcpService
|
||||
{
|
||||
private readonly BacktestTools _backtestTools;
|
||||
private readonly ILogger<McpService> _logger;
|
||||
|
||||
public McpService(BacktestTools backtestTools, ILogger<McpService> logger)
|
||||
{
|
||||
_backtestTools = backtestTools;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<object> ExecuteToolAsync(User user, string toolName, Dictionary<string, object>? parameters = null)
|
||||
{
|
||||
_logger.LogInformation("Executing MCP tool: {ToolName} for user: {UserId}", toolName, user.Id);
|
||||
|
||||
try
|
||||
{
|
||||
return toolName.ToLowerInvariant() switch
|
||||
{
|
||||
"get_backtests_paginated" => await ExecuteGetBacktestsPaginated(user, parameters),
|
||||
_ => throw new InvalidOperationException($"Unknown tool: {toolName}")
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error executing MCP tool {ToolName} for user {UserId}", toolName, user.Id);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IEnumerable<McpToolDefinition>> GetAvailableToolsAsync()
|
||||
{
|
||||
var tools = new List<McpToolDefinition>
|
||||
{
|
||||
new McpToolDefinition
|
||||
{
|
||||
Name = "get_backtests_paginated",
|
||||
Description = "Retrieves paginated backtests with filtering and sorting capabilities. Supports filters for score, winrate, drawdown, tickers, indicators, duration, and trading type.",
|
||||
Parameters = new Dictionary<string, McpParameterDefinition>
|
||||
{
|
||||
["page"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "integer",
|
||||
Description = "Page number (defaults to 1)",
|
||||
Required = false,
|
||||
DefaultValue = 1
|
||||
},
|
||||
["pageSize"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "integer",
|
||||
Description = "Number of items per page (defaults to 50, max 100)",
|
||||
Required = false,
|
||||
DefaultValue = 50
|
||||
},
|
||||
["sortBy"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Field to sort by (Score, WinRate, GrowthPercentage, MaxDrawdown, SharpeRatio, FinalPnl, StartDate, EndDate, PositionCount)",
|
||||
Required = false,
|
||||
DefaultValue = "Score"
|
||||
},
|
||||
["sortOrder"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Sort order - 'asc' or 'desc' (defaults to 'desc')",
|
||||
Required = false,
|
||||
DefaultValue = "desc"
|
||||
},
|
||||
["scoreMin"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "number",
|
||||
Description = "Minimum score filter (0-100)",
|
||||
Required = false
|
||||
},
|
||||
["scoreMax"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "number",
|
||||
Description = "Maximum score filter (0-100)",
|
||||
Required = false
|
||||
},
|
||||
["winrateMin"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "integer",
|
||||
Description = "Minimum winrate filter (0-100)",
|
||||
Required = false
|
||||
},
|
||||
["winrateMax"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "integer",
|
||||
Description = "Maximum winrate filter (0-100)",
|
||||
Required = false
|
||||
},
|
||||
["maxDrawdownMax"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "number",
|
||||
Description = "Maximum drawdown filter",
|
||||
Required = false
|
||||
},
|
||||
["tickers"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Comma-separated list of tickers to filter by (e.g., 'BTC,ETH,SOL')",
|
||||
Required = false
|
||||
},
|
||||
["indicators"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Comma-separated list of indicators to filter by",
|
||||
Required = false
|
||||
},
|
||||
["durationMinDays"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "number",
|
||||
Description = "Minimum duration in days",
|
||||
Required = false
|
||||
},
|
||||
["durationMaxDays"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "number",
|
||||
Description = "Maximum duration in days",
|
||||
Required = false
|
||||
},
|
||||
["name"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Filter by name (contains search)",
|
||||
Required = false
|
||||
},
|
||||
["tradingType"] = new McpParameterDefinition
|
||||
{
|
||||
Type = "string",
|
||||
Description = "Trading type filter (Spot, Futures, BacktestSpot, BacktestFutures, Paper)",
|
||||
Required = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Task.FromResult<IEnumerable<McpToolDefinition>>(tools);
|
||||
}
|
||||
|
||||
private async Task<object> ExecuteGetBacktestsPaginated(User user, Dictionary<string, object>? parameters)
|
||||
{
|
||||
var page = GetParameterValue<int>(parameters, "page", 1);
|
||||
var pageSize = GetParameterValue<int>(parameters, "pageSize", 50);
|
||||
var sortByString = GetParameterValue<string>(parameters, "sortBy", "Score");
|
||||
var sortOrder = GetParameterValue<string>(parameters, "sortOrder", "desc");
|
||||
var scoreMin = GetParameterValue<double?>(parameters, "scoreMin", null);
|
||||
var scoreMax = GetParameterValue<double?>(parameters, "scoreMax", null);
|
||||
var winrateMin = GetParameterValue<int?>(parameters, "winrateMin", null);
|
||||
var winrateMax = GetParameterValue<int?>(parameters, "winrateMax", null);
|
||||
var maxDrawdownMax = GetParameterValue<decimal?>(parameters, "maxDrawdownMax", null);
|
||||
var tickers = GetParameterValue<string?>(parameters, "tickers", null);
|
||||
var indicators = GetParameterValue<string?>(parameters, "indicators", null);
|
||||
var durationMinDays = GetParameterValue<double?>(parameters, "durationMinDays", null);
|
||||
var durationMaxDays = GetParameterValue<double?>(parameters, "durationMaxDays", null);
|
||||
var name = GetParameterValue<string?>(parameters, "name", null);
|
||||
var tradingTypeString = GetParameterValue<string?>(parameters, "tradingType", null);
|
||||
|
||||
// Parse sortBy enum
|
||||
if (!Enum.TryParse<BacktestSortableColumn>(sortByString, true, out var sortBy))
|
||||
{
|
||||
sortBy = BacktestSortableColumn.Score;
|
||||
}
|
||||
|
||||
// Parse tradingType enum
|
||||
TradingType? tradingType = null;
|
||||
if (!string.IsNullOrWhiteSpace(tradingTypeString) &&
|
||||
Enum.TryParse<TradingType>(tradingTypeString, true, out var parsedTradingType))
|
||||
{
|
||||
tradingType = parsedTradingType;
|
||||
}
|
||||
|
||||
return await _backtestTools.GetBacktestsPaginated(
|
||||
user,
|
||||
page,
|
||||
pageSize,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
scoreMin,
|
||||
scoreMax,
|
||||
winrateMin,
|
||||
winrateMax,
|
||||
maxDrawdownMax,
|
||||
tickers,
|
||||
indicators,
|
||||
durationMinDays,
|
||||
durationMaxDays,
|
||||
name,
|
||||
tradingType);
|
||||
}
|
||||
|
||||
private T GetParameterValue<T>(Dictionary<string, object>? parameters, string key, T defaultValue)
|
||||
{
|
||||
if (parameters == null || !parameters.ContainsKey(key))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var value = parameters[key];
|
||||
if (value == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Handle nullable types
|
||||
var targetType = typeof(T);
|
||||
var underlyingType = Nullable.GetUnderlyingType(targetType);
|
||||
|
||||
if (underlyingType != null)
|
||||
{
|
||||
// It's a nullable type
|
||||
return (T)Convert.ChangeType(value, underlyingType);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(value, targetType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user