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);
    }
}

Tecnologias e ferramentas utilizadas:

  • Geral:
    1. .NET - .NET SDK 9;
  • Testes:
    1. XUnit - Testes unitários para garantir a estabilidade do código;
  • Tecnologia de Contêineres:
    1. Docker - Contêinerização do aplicativo para facilitar os testes;
  • Ferramentas:
    1. MCP - Model context protocol (Versão: 0.3.0-preview.1);
    2. Claude - Aplicativo de desktop Claude para cliente MCP (Versão Windows: 0.10.38).