77b9587fa6
- McpToolsTests: 33 tests covering tool registration, enum validation, state transitions, auth resolution (JWT, API key, X-Agent-Id), create/read/update/activity/handoff workflows via McpToolsFixture - McpServerConfigurationTests: 5 tests verifying MCP server DI registration, tool type attribute, MapMcp endpoint wiring, service extensions, and NuGet package reference
86 lines
3.4 KiB
C#
86 lines
3.4 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using ModelContextProtocol.Server;
|
|
using Nexus.Api.Services;
|
|
using Xunit;
|
|
|
|
namespace Nexus.Api.Tests;
|
|
|
|
/// <summary>
|
|
/// Verifies that the MCP server configuration is correct:
|
|
/// all tools are registered, the streamable-http transport is configured
|
|
/// via the service extensions, and MapMcp is called in Program.cs.
|
|
/// </summary>
|
|
public sealed class McpServerConfigurationTests
|
|
{
|
|
[Fact]
|
|
public void McpServer_CanBeRegistered_WithoutError()
|
|
{
|
|
var services = new ServiceCollection();
|
|
services.AddLogging();
|
|
services.AddOptions();
|
|
services.AddHttpContextAccessor();
|
|
|
|
// Simulate what AddNexusApplicationServices does
|
|
services.AddMcpServer()
|
|
.WithHttpTransport(options => options.Stateless = true)
|
|
.WithTools<NexusMcpTools>();
|
|
|
|
// Build the container — this should not throw
|
|
var provider = services.BuildServiceProvider();
|
|
|
|
// Verify the ToolType is properly decorated
|
|
var attr = typeof(NexusMcpTools).GetCustomAttributes(
|
|
typeof(McpServerToolTypeAttribute), inherit: false);
|
|
Assert.Single(attr);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpServer_ToolTypeAttribute_IsPresent()
|
|
{
|
|
var attr = typeof(NexusMcpTools).GetCustomAttributes(
|
|
typeof(McpServerToolTypeAttribute), inherit: false);
|
|
Assert.Single(attr);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpEndpoint_MapMcp_IsCalledInProgram()
|
|
{
|
|
// Source path relative to the test output directory
|
|
var programPath = ResolveSourcePath("backend", "Program.cs");
|
|
Assert.True(File.Exists(programPath), $"Program.cs not found at {programPath}");
|
|
var source = File.ReadAllText(programPath);
|
|
Assert.Contains("MapMcp", source, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpServerRegistration_IsCalledInServiceExtensions()
|
|
{
|
|
var extPath = ResolveSourcePath("backend", "Extensions", "ServiceCollectionExtensions.cs");
|
|
Assert.True(File.Exists(extPath), $"ServiceCollectionExtensions.cs not found at {extPath}");
|
|
var source = File.ReadAllText(extPath);
|
|
Assert.Contains("AddMcpServer", source, StringComparison.Ordinal);
|
|
Assert.Contains("WithHttpTransport", source, StringComparison.Ordinal);
|
|
Assert.Contains("Stateless", source, StringComparison.Ordinal);
|
|
Assert.Contains("WithTools<NexusMcpTools>", source, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void NuGetPackage_ModelContextProtocol_AspNetCore_IsReferenced()
|
|
{
|
|
var csprojPath = ResolveSourcePath("backend", "Nexus.Api.csproj");
|
|
Assert.True(File.Exists(csprojPath), $"Nexus.Api.csproj not found at {csprojPath}");
|
|
var source = File.ReadAllText(csprojPath);
|
|
Assert.Contains("ModelContextProtocol.AspNetCore", source, StringComparison.Ordinal);
|
|
}
|
|
|
|
private static string ResolveSourcePath(params string[] segments)
|
|
{
|
|
// Navigate from test output directory to the repo root
|
|
// Test DLL is at: backend-tests/bin/Debug/net10.0/Nexus.Api.Tests.dll
|
|
// We go up 4 levels (net10.0 → Debug → bin → backend-tests) to reach repo root
|
|
var baseDir = AppContext.BaseDirectory;
|
|
var repoRoot = Path.GetFullPath(Path.Combine(baseDir, "..", "..", "..", ".."));
|
|
return Path.Combine(new[] { repoRoot }.Concat(segments).ToArray());
|
|
}
|
|
}
|