Task 25 — MCP-адаптер
Phase: 2
Status: done
Owner: —
Slug: mcp-adapter
Goal
Hercules может потреблять выбранные MCP-серверы и экспонировать подходящие инструменты через MCP-совместимый адаптер. Built-in tools остаются .NET-имплементациями без отдельного процесса.
Acceptance criteria
Sub-tasks
McpToolAdapter.cs— wrapsMcpClientToolasITool: name=mcp.{serverName}.{toolName}, callsMcpClient.CallToolAsync(tool.Name, args)via captured client reference, converts result toToolResultMcpClientService.cs— manages multiple MCP server connections: connects viaMcpClient.CreateAsync(StdioClientTransport or HttpClientTransport), tracksIReadOnlyList<McpClient>per server, exposesGetServers()andGetServerHealth(serverName)McpServerHost.cs—BackgroundService: runs in-process MCP server viaAddMcpServer().WithStdioServerTransport()+SingleSessionMcpServerHostedService; wraps eachIToolasMcpServerTool; graceful shutdown onStopAsyncHerculesMcpServerTool.cs— adapter:McpServerToolfromITooldescription +ParametersSchema→ JSON schema for MCP protocolMcpController.cs— WebAPI:GET /api/mcp/servers(name, transport, status, toolCount),GET /api/mcp/servers/{name}(server info + tools),POST /api/mcp/servers/reload(reload from config)Program.cs(CLI + WebAPI) — registerMcpClientServiceas singleton; conditionally startMcpServerHostwhenMcpConfig.Server.Enabled=true; callMcpClientService.InitializeAsync()at startupConfig/AppConfig.cs— extendMcpConfig: addMcpServerConfig.Enabled(default true),McpServerConfig.HealthCheckEnabled(default true),McpServerConfig.TimeoutSeconds(default 30)- Unit-тесты:
McpToolAdapterTests.cs— 16 тестов: tool name format, arguments passthrough, success/error conversion, null result handling, constructor guards - Unit-тесты:
McpClientServiceTests.cs— 8 тестов: connect, register tools, health tracking, graceful degradation on server unavailable, reload, dispose dotnet buildпроходит без warnings (NU1902 pre-existing OTel advisory)dotnet testпроходит (764/771; 7 pre-existing failures in OtelService, BudgetGuard, WasmTool — unrelated to task_025)
Scope / Likely files
src/agent/Mcp/, src/agent/Tools/McpAdapter/
Dependencies
- блокирует / опирается на: task_024 — tool-registry
Implementation notes
2026-08-12
Добавлено:
src/agent/Mcp/Models.cs — McpServerHealthStatus enum + McpServerState record: Name, Transport, Status, ConnectedAt, LastErrorAt, LastError, ToolCount, ServerVersion.
src/agent/Mcp/IMcpClientTool.cs — interface for testability of McpToolAdapter:
Name,Description,JsonSchemapropertiesCallAsync(IReadOnlyDictionary<string, object?>?, CancellationToken)→CallToolResult
src/agent/Mcp/McpToolAdapter.cs — ITool wrapper for MCP client tools:
- Dual constructor: production
(McpClient, McpClientTool, ...)+ testable(IMcpClientTool, ...) - Name =
mcp.{serverName}.{toolName}, Description passthrough, ParametersSchema extraction ExecuteAsync: JSON parsing →CallAsync→ExtractText→ToolResult.OkorToolResult.Fail(whenresult.IsError == true)McpClientToolAdapter— internal production bridge fromMcpClientTooltoIMcpClientTool
src/agent/Mcp/McpClientService.cs — manages MCP server connections:
InitializeAsync: connects viaMcpClient.CreateAsyncwith StdioClientTransport or HttpClientTransport- Per-server: lists tools, wraps each with
McpToolAdapter, registers withToolRegistryService McpServerConnection— holds client + state, implementsIAsyncDisposableReloadAsync: disconnects all, clears, reinitializes- Graceful degradation: failed connections recorded as Unhealthy
src/agent/Mcp/McpServerHost.cs — BackgroundService hosting Hercules tools as MCP server:
- Runs via
McpServer.Create(StdioServerTransport(...))+McpServerOptionswithMcpServerHandlers ListToolsHandler: usesHerculesMcpServerToolto buildToollistCallToolHandler: dispatches toITool.ExecuteAsync, wraps asCallToolResult- Graceful shutdown:
StopAsync+appLifetime.StopApplication()on stdio exit
src/agent/Mcp/HerculesMcpServerTool.cs — adapter converting ITool → MCP Tool:
ToMcpTool(): buildsToolwithName,Description,InputSchemafromParametersSchema- Handles missing/empty schema with default
{"type":"object"}schema
src/agent/Hercules.WebApi/Controllers/McpController.cs — 3 endpoints:
GET /api/mcp/servers— all servers with status and tool countGET /api/mcp/servers/{name}— single server detailsPOST /api/mcp/servers/reload— reload from config
src/agent/Config/AppConfig.cs — McpServerConfig extended with:
Enabled(default true),HealthCheckEnabled(default true),TimeoutSeconds(default 30)
src/agent/Tools/Registry/ToolRegistryService.cs — added RegisterTool(ITool):
- Checks allow/deny patterns, infers category from name, creates
ToolRegistryEntrywith Source=”Mcp”
Program.cs (CLI + WebAPI):
- Added
using Hercules.Mcp; McpClientServiceregistered as singletonMcpServerHostregistered asHostedServiceInitializeAsync()called at startup with error logging
tests/.../Mcp/McpToolAdapterTests.cs — 16 тестов:
- Name scoping (3), description passthrough (2), ParametersSchema (3), ExecuteAsync success/error/cancel/null (7), constructor guards (2)
tests/.../Mcp/McpClientServiceTests.cs — 8 тестов:
- No servers, empty name skip, unknown transport → unhealthy, idempotency, reload, dispose, state count
Validation:
dotnet build Hercules.csproj— 0 errors (NU1902 pre-existing)dotnet build Hercules.WebApi.csproj— 0 errors (NU1902 pre-existing)dotnet test— 764/771 passed (7 pre-existing failures: OtelService × 5, BudgetGuard × 1, WasmTool × 1 — unrelated to task_025)
Risks / Rollback
Поверхность атаки MCP-серверов; strict capability allowlist.
Links
- Backlog: ../backlog.md
- Roadmap (EN): ../../ROADMAP-EN.md
- Roadmap (RU): ../../ROADMAP-RU.md