MCP SeriesGenerator
Um servidor .NET para gerar e validar números de série de veículos.
Documentação
Este é um repositório para testes com o Model Context Protocol
Instruções para executar o projeto
Executando com docker:
1. Acesse a pasta do diretório raiz no terminal, exemplo:
cd mcp_seriesgenerator
2. Execução do contêiner:
docker-compose up -d
3. Em seguida, execute o comando do script powershell abaixo, o arquivo docker.ps1 está localizado no diretório raiz (O script copiará os arquivos do contêiner docker para sua máquina local)
powershell -ExecutionPolicy ByPass -File docker.ps1
Executando com o aplicativo de desktop Claude:
1. Abra o aplicativo de desktop Claude para configuração
2. Menu - Arquivo - Configurações - Desenvolvedor - Editar Config
3. Abra o arquivo de configuração no local: \user\AppData\Roaming\Claude\claude_desktop_config.json (Salve o arquivo e reinicie o Claude para Desktop)
{
"mcpServers": {
"serialNumberGenerator": {
"command": "dotnet",
"args": [
"run",
"--project",
"C:\\ABSOLUTE\\PATH\\TO\\PROJECT",
"--no-build"
]
}
}
}
4. Procure pelo ícone "Search & Tools", digite algo como Upload Vehicle e insira o arquivo com os números de série. Exemplo:
series.txt
1313MEXXXA7989-1
0708BRAXXC4014-3
1414ARGXXA5834-9
1213ASMXXC8348-2
0202ARGXXC2614-E
0606BRAXXA6466-8
0606MEXXXA3820-4
5. Mais informações em: https://modelcontextprotocol.io/quickstart/server
Testes com o Mcp Server sem aplicativos clientes:
1. O Model Context Protocol (MCP) permite que servidores exponham ferramentas que podem ser invocadas externamente de forma padronizada.
1.1. Primeiro, é necessário configurar o Mcp Server e suas ferramentas que serão expostas no aplicativo. Aqui configuramos com StdioServerTransport:
//class src/McpSeriesGenerator.App/Program.cs
builder.Services.AddMcpServer()
.WithStdioServerTransport()
.WithTools<VehicleTool>();
builder.Services.AddScoped<VehicleTool>();
1.2. No projeto, existem recursos criados para a ferramenta do Mcp Server. Entre alguns deles, temos, por exemplo, ReturnsIfTheSerialNumberIsValid.
//class src/McpSeriesGenerator.App/McpServer/VehicleTool.cs
[McpServerTool(Name = "ReturnsIfTheSerialNumberIsValid"), Description("Validate serial number with check digit.")]
public string ReturnsIfTheSerialNumberIsValid(
[Description("Enter a serial number with check digit")] string SerialNumber)
{
if (string.IsNullOrWhiteSpace(SerialNumber))
{
return "Serial number cannot be empty.";
}
var vehicle = Vehicle.Create(SerialNumber);
if (vehicle.VehicleSerialNumber.ValidateCheckDigit())
{
return "This serial number is valid";
}
return "This serial number is invalid";
}
2. No projeto de teste de integração, há comunicação via StdioServerTransport para simulação real de uma integração entre o aplicativo cliente e o Mcp Server.
2.1. No código a seguir, no método construtor, uma instância de processo é criada para executar o projeto do Mcp Server externamente ao projeto de teste de integração.
//class test/McpSeriesGenerator.Integration/McpServer/ProcessFixture.cs
public ProcessFixture()
{
string appDll = Path.Combine(AppContext.BaseDirectory, "McpSeriesGenerator.App.dll");
_process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"\"{appDll}\"",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
_process.Start();
if (_process == null)
{
throw new InvalidOperationException("Failed to start MCP server process");
}
}
2.2. Exemplo de método de teste com a ferramenta ReturnsIfTheSerialNumberIsValid:
//class test/McpSeriesGenerator.Integration/McpServer/VehicleToolTest.cs
public async Task MCPServer_ShouldResponseToReturnsIfTheSerialNumberIsValid()
{
Assert.NotNull(_fixture._process);
_ = Task.Run(async () =>
{
string? err;
while ((err = await _fixture._process.StandardError.ReadLineAsync()) != null)
Console.WriteLine("[STDERR] " + err);
});
var jsonString = JsonSerializer.Serialize(new
{
jsonrpc = "2.0",
id = 1,
method = "tools/call",
@params = new
{
name = "ReturnsIfTheSerialNumberIsValid",
arguments = new { SerialNumber = "0202ARGXXC2614-E" }
}
});
await _fixture._process.StandardInput.WriteLineAsync(jsonString);
await _fixture._process.StandardInput.FlushAsync();
if (_fixture._process.StandardOutput.Peek() > 0)
{
var responseOut = await _fixture._process.StandardOutput.ReadLineAsync();
Assert.True(!string.IsNullOrWhiteSpace(responseOut));
Assert.Contains("jsonrpc", responseOut);
JsonNode? node = JsonNode.Parse(responseOut);
Assert.NotNull(node);
Assert.NotNull(node?["result"]);
Assert.NotNull(node?["result"]?["isError"]);
Assert.True(bool.TryParse(node?["result"]?["isError"]?.ToString(), out bool isError));
Assert.False(isError);
}
}