feat(backend): Implement Story 5.5 - Core MCP Resources Implementation

Implemented 6 core MCP Resources for read-only AI agent access to ColaFlow data:
- projects.list - List all projects in current tenant
- projects.get/{id} - Get project details with full hierarchy
- issues.search - Search issues (Epics, Stories, Tasks) with filters
- issues.get/{id} - Get issue details (Epic/Story/Task)
- sprints.current - Get currently active Sprint(s)
- users.list - List team members in current tenant

Changes:
- Created IMcpResource interface and related DTOs (McpResourceRequest, McpResourceContent, McpResourceDescriptor)
- Implemented IMcpResourceRegistry and McpResourceRegistry for resource discovery and routing
- Created ResourcesReadMethodHandler for handling resources/read MCP method
- Updated ResourcesListMethodHandler to return actual resource catalog
- Implemented 6 concrete resource classes with multi-tenant isolation
- Registered all resources and handlers in McpServiceExtensions
- Added module references (ProjectManagement, Identity, IssueManagement domains)
- Updated package versions to 9.0.1 for consistency
- Created comprehensive unit tests (188 tests passing)
- Tests cover resource registry, URI matching, resource content generation

Technical Details:
- Multi-tenant isolation using TenantContext.GetCurrentTenantId()
- Resource URI routing supports templates (e.g., {id} parameters)
- Uses read-only repository queries (AsNoTracking) for performance
- JSON serialization with System.Text.Json
- Proper error handling with McpNotFoundException, McpInvalidParamsException
- Supports query parameters for filtering and pagination
- Auto-registration of resources at startup

Test Coverage:
- Resource registry tests (URI matching, registration, descriptors)
- Resource content generation tests
- Multi-tenant isolation verification
- All 188 tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Yaojia Wang
2025-11-08 21:25:28 +01:00
parent c00c909489
commit bfd8642d3c
19 changed files with 1422 additions and 8 deletions

View File

@@ -1,5 +1,7 @@
using ColaFlow.Modules.Mcp.Application.Handlers;
using ColaFlow.Modules.Mcp.Application.Resources;
using ColaFlow.Modules.Mcp.Application.Services;
using ColaFlow.Modules.Mcp.Contracts.Resources;
using ColaFlow.Modules.Mcp.Domain.Repositories;
using ColaFlow.Modules.Mcp.Infrastructure.Middleware;
using ColaFlow.Modules.Mcp.Infrastructure.Persistence;
@@ -34,12 +36,24 @@ public static class McpServiceExtensions
// Register application services
services.AddScoped<IMcpApiKeyService, McpApiKeyService>();
// Register resource registry (Singleton - shared across all requests)
services.AddSingleton<IMcpResourceRegistry, McpResourceRegistry>();
// Register MCP Resources
services.AddScoped<IMcpResource, ProjectsListResource>();
services.AddScoped<IMcpResource, ProjectsGetResource>();
services.AddScoped<IMcpResource, IssuesSearchResource>();
services.AddScoped<IMcpResource, IssuesGetResource>();
services.AddScoped<IMcpResource, SprintsCurrentResource>();
services.AddScoped<IMcpResource, UsersListResource>();
// Register protocol handler
services.AddScoped<IMcpProtocolHandler, McpProtocolHandler>();
// Register method handlers
services.AddScoped<IMcpMethodHandler, InitializeMethodHandler>();
services.AddScoped<IMcpMethodHandler, ResourcesListMethodHandler>();
services.AddScoped<IMcpMethodHandler, ResourcesReadMethodHandler>();
services.AddScoped<IMcpMethodHandler, ToolsListMethodHandler>();
services.AddScoped<IMcpMethodHandler, ToolsCallMethodHandler>();
@@ -57,6 +71,9 @@ public static class McpServiceExtensions
/// </summary>
public static IApplicationBuilder UseMcpMiddleware(this IApplicationBuilder app)
{
// Initialize resource registry (register all resources)
InitializeResourceRegistry(app);
// 1. Correlation ID middleware (FIRST - needed for all subsequent logging)
app.UseMiddleware<McpCorrelationIdMiddleware>();
@@ -74,4 +91,20 @@ public static class McpServiceExtensions
return app;
}
/// <summary>
/// Initialize resource registry by registering all resources
/// This is called once at startup
/// </summary>
private static void InitializeResourceRegistry(IApplicationBuilder app)
{
using var scope = app.ApplicationServices.CreateScope();
var registry = scope.ServiceProvider.GetRequiredService<IMcpResourceRegistry>();
var resources = scope.ServiceProvider.GetServices<IMcpResource>();
foreach (var resource in resources)
{
registry.RegisterResource(resource);
}
}
}