feat(backend): Implement Story 5.6 - Resource Registration & Discovery
Implemented pluggable resource registration and auto-discovery mechanism for MCP Resources. Changes: - Enhanced McpResourceDescriptor with metadata (Category, Version, Parameters, Examples, Tags, IsEnabled) - Created ResourceDiscoveryService for Assembly scanning and auto-discovery - Updated McpResourceRegistry with category support and grouping methods - Enhanced ResourcesListMethodHandler to return categorized resources with full metadata - Created ResourceHealthCheckHandler for resource availability verification - Updated all existing Resources (Projects, Issues, Sprints, Users) with Categories and Versions - Updated McpServiceExtensions to use auto-discovery at startup - Added comprehensive unit tests for discovery and health check Features: ✅ New Resources automatically discovered via Assembly scanning ✅ Resources organized by category (Projects, Issues, Sprints, Users) ✅ Rich metadata for documentation (parameters, examples, tags) ✅ Health check endpoint (resources/health) for monitoring ✅ Thread-safe registry operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
using ColaFlow.Modules.Mcp.Application.Services;
|
||||
using ColaFlow.Modules.Mcp.Contracts.Resources;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace ColaFlow.Modules.Mcp.Tests.Services;
|
||||
|
||||
public class ResourceDiscoveryServiceTests
|
||||
{
|
||||
private readonly IResourceDiscoveryService _discoveryService;
|
||||
private readonly ILogger<ResourceDiscoveryService> _mockLogger;
|
||||
|
||||
public ResourceDiscoveryServiceTests()
|
||||
{
|
||||
_mockLogger = Substitute.For<ILogger<ResourceDiscoveryService>>();
|
||||
_discoveryService = new ResourceDiscoveryService(_mockLogger);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DiscoverResourceTypes_ShouldFindAllResourceImplementations()
|
||||
{
|
||||
// Act
|
||||
var resourceTypes = _discoveryService.DiscoverResourceTypes();
|
||||
|
||||
// Assert
|
||||
resourceTypes.Should().NotBeEmpty();
|
||||
resourceTypes.Should().AllSatisfy(type =>
|
||||
{
|
||||
typeof(IMcpResource).IsAssignableFrom(type).Should().BeTrue();
|
||||
type.IsInterface.Should().BeFalse();
|
||||
type.IsAbstract.Should().BeFalse();
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DiscoverResourceTypes_ShouldFindKnownResources()
|
||||
{
|
||||
// Act
|
||||
var resourceTypes = _discoveryService.DiscoverResourceTypes();
|
||||
|
||||
// Assert - should find at least these known resources
|
||||
var typeNames = resourceTypes.Select(t => t.Name).ToList();
|
||||
typeNames.Should().Contain("ProjectsListResource");
|
||||
typeNames.Should().Contain("ProjectsGetResource");
|
||||
typeNames.Should().Contain("IssuesSearchResource");
|
||||
typeNames.Should().Contain("IssuesGetResource");
|
||||
typeNames.Should().Contain("SprintsCurrentResource");
|
||||
typeNames.Should().Contain("UsersListResource");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DiscoverResourceTypes_ShouldNotIncludeInterfaces()
|
||||
{
|
||||
// Act
|
||||
var resourceTypes = _discoveryService.DiscoverResourceTypes();
|
||||
|
||||
// Assert
|
||||
resourceTypes.Should().NotContain(t => t.IsInterface);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DiscoverResourceTypes_ShouldNotIncludeAbstractClasses()
|
||||
{
|
||||
// Act
|
||||
var resourceTypes = _discoveryService.DiscoverResourceTypes();
|
||||
|
||||
// Assert
|
||||
resourceTypes.Should().NotContain(t => t.IsAbstract);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user