111 lines
3.4 KiB
C#
111 lines
3.4 KiB
C#
using FreeCode.Core.Enums;
|
|
using FreeCode.Core.Models;
|
|
using Xunit;
|
|
|
|
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
|
|
|
namespace FreeCode.Mcp.Tests;
|
|
|
|
public class BasicTests
|
|
{
|
|
private static readonly Lock ConfigLock = new();
|
|
|
|
[Fact]
|
|
public async Task McpClientManager_LoadsConfiguredConnectionsFromDisk()
|
|
{
|
|
using var config = new McpConfigScope("""
|
|
{
|
|
"mcpServers": {
|
|
"demo": {
|
|
"command": "definitely-not-a-real-command",
|
|
"args": ["--version"],
|
|
"scope": "User"
|
|
}
|
|
}
|
|
}
|
|
""");
|
|
|
|
var manager = new McpClientManager();
|
|
await manager.ConnectServersAsync();
|
|
|
|
var connections = manager.GetConnections();
|
|
|
|
Assert.Single(connections);
|
|
Assert.Equal("demo", connections[0].Name);
|
|
Assert.IsType<StdioServerConfig>(connections[0].Config);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpServerConnection_FlagPropertiesMatchConnectionSubtype()
|
|
{
|
|
var config = new StdioServerConfig { Scope = ConfigScope.User, Command = "dotnet" };
|
|
var connected = new MCPServerConnection.Connected("demo", config, new object(), new object(), null, null, () => Task.CompletedTask)
|
|
{
|
|
Name = "demo",
|
|
Config = config
|
|
};
|
|
var failed = new MCPServerConnection.Failed("demo", config, "boom")
|
|
{
|
|
Name = "demo",
|
|
Config = config
|
|
};
|
|
|
|
Assert.True(connected.IsConnected);
|
|
Assert.False(connected.IsFailed);
|
|
Assert.True(failed.IsFailed);
|
|
Assert.False(failed.IsConnected);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpTypes_ExposeExpectedDefaultsAndRecordShapes()
|
|
{
|
|
var capabilities = new ServerCapabilities();
|
|
using var schema = System.Text.Json.JsonDocument.Parse("{\"type\":\"object\"}");
|
|
var tool = new McpToolDefinition("read_file", "Reads files", schema.RootElement.Clone(), false);
|
|
|
|
Assert.True(capabilities.Tools);
|
|
Assert.True(capabilities.Resources);
|
|
Assert.False(capabilities.Prompts);
|
|
Assert.Equal("read_file", tool.Name);
|
|
Assert.Equal("Reads files", tool.Description);
|
|
Assert.False(tool.HasDestructiveBehavior);
|
|
}
|
|
|
|
private sealed class McpConfigScope : IDisposable
|
|
{
|
|
private readonly string _configPath;
|
|
private readonly string? _originalContent;
|
|
private readonly bool _hadOriginal;
|
|
|
|
public McpConfigScope(string content)
|
|
{
|
|
Monitor.Enter(ConfigLock);
|
|
var configDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".free-code");
|
|
Directory.CreateDirectory(configDirectory);
|
|
_configPath = Path.Combine(configDirectory, "config.json");
|
|
_hadOriginal = File.Exists(_configPath);
|
|
_originalContent = _hadOriginal ? File.ReadAllText(_configPath) : null;
|
|
File.WriteAllText(_configPath, content);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try
|
|
{
|
|
if (_hadOriginal)
|
|
{
|
|
File.WriteAllText(_configPath, _originalContent!);
|
|
}
|
|
else if (File.Exists(_configPath))
|
|
{
|
|
File.Delete(_configPath);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(ConfigLock);
|
|
}
|
|
}
|
|
}
|
|
}
|