Token导航 LogoToken导航TokenDH.com
Agente MCP logo
AI代理stdio官方级别未说明来源级核验

Agente MCP

MCP Server

@modelcontextprotocol/inspector

使用Model Context Protocol (MCP)在C#中创建AI代理的工具,支持本地和远程连接,适用于开发AI辅助功能。

工具数

0

提示词数

0

GitHub Stars

0

资源数

0
AI代理C#ClaudeLLM交互Claude DesktopClaudeVS Code

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

annabsb

提供方

annabsb

最后核验

2026/5/17 20:22

运行时

Node.js

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

npx @modelcontextprotocol/inspector dotnet run

详细介绍

Workshop: Criando Agentes de IA com MCP em C#

📋 Índice

📚 Documentação Complementar

Este README é o guia prático principal. Para aprofundamento teórico, consulte:


Sobre este Workshop

Este workshop ensina como criar agentes de IA usando o Model Context Protocol (MCP) em C#. O MCP é um protocolo aberto que padroniza como aplicações fornecem contexto para Large Language Models (LLMs).

O que você vai aprender

  • ✅ Criar MCP Servers em C#
  • ✅ Implementar Tools (ferramentas) que LLMs podem usar
  • ✅ Criar Prompts reutilizáveis
  • ✅ Conectar servidores localmente (stdio) e remotamente (HTTP)
  • ✅ Integrar com GitHub Copilot e ferramentas de IA
  • ✅ Debugar comunicação com MCP Inspector

Estrutura Real do Projeto

Este workshop contém implementações funcionais prontas para uso:

src/
├── ToolsServer/              → Servidor com ferramentas (calculadora + texto)
├── PromptsServer/            → Servidor com prompts para LLMs
│   └── PromptsServer/
├── ClienteLocal/             → Cliente stdio (conexão local)
│   └── McpClient/
├── ClienteRemoto/            → Cliente HTTP (conexão remota)
│   └── HttpMcpClient/
└── ServidorRemoto/           → Servidor HTTP
    └── HttpMcpServer/

Cada projeto está completo e pode ser executado independentemente!


Pré-requisitos

Software Necessário

  1. Visual Studio Code

- Instalar de:

  1. .NET 9.0 SDK (ou superior)
   dotnet --version
   # Deve retornar 9.0 ou superior

- Instalar de:

  1. Node.js (v18+) - para ferramentas auxiliares
   node --version
   npm --version

- Instalar de:

  1. MCP Inspector (para debug)
   npm install -g @modelcontextprotocol/inspector
  1. GitHub Copilot CLI (opcional)
   npm install -g @github/copilot

Extensões do VS Code Recomendadas

  • C# Dev Kit
  • C# (Microsoft)
  • REST Client (para testar endpoints HTTP)

Conhecimentos Prévios

  • C# básico a intermediário
  • Conceitos de async/await
  • JSON básico
  • Linha de comando (PowerShell)

Configuração do Ambiente

1. Clone ou Baixe este Repositório

git clone 
cd AgentesWorkShop

2. Estrutura do Projeto

Agentes/
├── README.md (este arquivo)
├── src/
│   ├── ToolsServer/           # Servidor MCP com ferramentas (calculadora, texto)
│   ├── PromptsServer/         # Servidor MCP com prompts reutilizáveis
│   │   └── PromptsServer/
│   ├── ClienteLocal/          # Cliente MCP usando conexão stdio
│   │   └── McpClient/
│   ├── ClienteRemoto/         # Cliente MCP usando conexão HTTP
│   │   └── HttpMcpClient/
│   └── ServidorRemoto/        # Servidor MCP acessível via HTTP
│       └── HttpMcpServer/
├── configs/
│   ├── copilot-config.json
│   └── copilot-cli-config.json
└── docs/
    └── referencias.md

3. Compilar Todos os Projetos

# Compilar solução principal (todos os projetos)
cd src
dotnet build AgentesWorkShop.sln

# Ou compilar individualmente:

# ToolsServer
cd ToolsServer
dotnet build

# PromptsServer
cd ..\PromptsServer\PromptsServer
dotnet build

# ClienteLocal
cd ..\..\ClienteLocal\McpClient
dotnet build

# ServidorRemoto
cd ..\..\ServidorRemoto\HttpMcpServer
dotnet build

# ClienteRemoto
cd ..\..\ClienteRemoto\HttpMcpClient
dotnet build

4. Informações Importantes

Versões Utilizadas:

  • .NET: 9.0
  • ModelContextProtocol: 0.4.0-preview.1
  • ModelContextProtocol.AspNetCore: 0.4.0-preview.1
  • Microsoft.Extensions.Hosting: 9.0.9

Principais Mudanças em Relação à Versão Inicial:

  • ✅ Uso correto de McpClient.CreateAsync() com opções configuráveis
  • ✅ Implementação de ServerInfo e ServerInstructions para melhor contexto
  • ✅ Configuração de logging para stderr (separado do protocolo)
  • ✅ Uso de MapMcp() simplificado para servidores HTTP
  • ✅ Suporte a HttpClientTransport com auto-detecção de modo
  • ✅ Tratamento robusto de conteúdo (TextContentBlock vs JsonContentBlock)
  • ✅ Configurações de timeout e capabilities no cliente
  • ✅ Atributo [McpServerTool(Name = "...")] para nomes explícitos

Módulo 1: Fundamentos do MCP

O que é MCP?

O Model Context Protocol permite que LLMs acessem ferramentas e dados de forma padronizada. Pense nele como uma "API universal" para LLMs.

Componentes principais:

  • Server: Expõe ferramentas (tools) e prompts
  • Client: Conecta-se ao servidor e usa suas capacidades
  • Transport: Canal de comunicação (stdio ou HTTP)

🎯 Arquitetura do Protocolo no Projeto

O MCP é baseado em JSON-RPC 2.0 (Especificação) e define três componentes principais implementados neste workshop:

┌─────────────────┐         ┌─────────────────┐         ┌──────────────────┐
│  McpClient      │ ◄─────► │   Transport     │ ◄─────► │  MCP Server      │
│  (Host/Cliente) │         │ (stdio ou HTTP) │         │  (Tools/Prompts) │
└─────────────────┘         └─────────────────┘         └──────────────────┘

Implementações no Projeto

Clientes:

Servidores:

Transports:

  • stdio: Comunicação através de stdin/stdout (local)
  • HTTP/SSE: Comunicação através de HTTP com Server-Sent Events (remoto)

📚 Conceitos Fundamentais Implementados

1. Tools (Ferramentas)

Funções executáveis que o LLM pode chamar. São stateless e idempotentes quando possível.

Exemplo do ToolsServer:

[McpServerTool(Name = "add"), Description("Soma dois números")]
public static double Add(
    [Description("Primeiro número")] double a,
    [Description("Segundo número")] double b)
{
    return a + b;
}

Fluxo de Execução (implementado em McpClient):

// 1. Cliente solicita lista de tools
var tools = await client.ListToolsAsync(cancellationToken: cts.Token);

// 2. Servidor responde com metadados (nome, descrição, parâmetros)
foreach (var tool in tools)
{
    Console.WriteLine($"  • {tool.Name}: {tool.Description}");
}

// 3. Cliente chama tool específica
var addResult = await client.CallToolAsync(
    "add",
    new Dictionary { ["a"] = 10, ["b"] = 5 },
    cancellationToken: cts.Token);

// 4. Servidor executa e retorna resultado

Categorias de Tools no Projeto:

a) Operações Matemáticas (CalculatorTools):

  • add, subtract, multiply, divide
  • Validação: divisão por zero

b) Manipulação de Texto (TextTools):

  • toUpperCase, toLowerCase, reverseText
  • countWords, countCharacters
  • Validação: entrada não nula/vazia

c) Informações do Sistema (RemoteTools):

  • GetSystemInfo: informações de máquina, SO, CPU
  • GenerateUuid: geração de identificadores únicos
  • CalculateHash: hash SHA256 de texto
  • GetCurrentTime: data/hora em múltiplos formatos
  • GetProcessInfo: estatísticas do processo

⚠️ Pontos de Atenção da Implementação:

  • Use o atributo Name explicitamente para controlar o nome da tool
  • Sempre adicione Description para parâmetros e métodos (ajuda o LLM a entender)
  • Ferramentas devem ser static e marcadas com [McpServerTool]
  • A classe deve ser marcada com [McpServerToolType]
  • Valide entradas (exemplo: ArgumentException.ThrowIfNullOrEmpty)

2. Prompts (Templates)

Templates reutilizáveis para interações com LLM. Permitem parametrização e consistência.

Exemplo do PromptsServer:

[McpServerPrompt(Name = "code_review"), Description("Cria um prompt de revisão de código")]
public static ChatMessage CodeReview(
    [Description("Código para revisar")] string code,
    [Description("Linguagem de programação")] string language = "C#")
{
    return new ChatMessage(ChatRole.User, 
        $"Revise o seguinte código {language} e forneça sugestões de melhoria:\n\n{code}");
}

Quando usar Prompts vs Tools:

AspectoPromptsTools
PropósitoGuiar conversação, análisesExecutar ações, buscar dados
RetornoChatMessageDados estruturados
EstadoStatelessStateless (idealmente)
Exemplo no Projetocode_review, summarize_textadd, GetSystemInfo

Categorias de Prompts no Projeto:

a) Desenvolvimento (DeveloperPrompts):

  • code_review: revisão de código
  • explain_code: explicação didática
  • document_function: geração de documentação XML
  • refactor_code: refatoração com objetivo específico

b) Escrita (WritingPrompts):

  • summarize_text: resumo com limite de palavras
  • improve_writing: melhoria de redação
  • translate_text: tradução para idioma alvo
  • check_grammar: correção gramatical

c) Tools Auxiliares (PromptHelpers):

  • list_available_prompts: lista todos os prompts
  • get_prompt_info: informações detalhadas de um prompt
  • validate_prompt_args: valida argumentos JSON

⚠️ Pontos de Atenção da Implementação:

  • Use ChatMessage do namespace Microsoft.Extensions.AI
  • Prompts devem retornar ChatMessage com role apropriado (ChatRole.User)
  • A classe deve ser marcada com [McpServerPromptType]
  • Use parâmetros opcionais com valores padrão úteis

3. Resources (Recursos)

Dados ou arquivos que o servidor disponibiliza. Podem ser estáticos ou dinâmicos.

Tipos suportados pelo protocolo:

  • file:// - Arquivos locais
  • http:// - Recursos web
  • Custom URIs - Esquemas personalizados

📝 Nota: Resources não foram implementados neste workshop básico, mas são parte da Especificação MCP.

🔄 Ciclo de Vida de uma Sessão MCP

Implementado em todos os clientes (McpClient, HttpMcpClient):

1. Initialize    → Cliente e servidor trocam capabilities
                   (McpClient.CreateAsync)
                   
2. Initialized   → Sessão estabelecida
                   (Informações do servidor disponíveis)
                   
3. Request/Response → Troca de mensagens
                      • ListToolsAsync() - listar tools
                      • CallToolAsync() - chamar tool
                      • GetPromptAsync() - obter prompt
                      
4. Notifications → Mudanças de estado (opcional)
                   
5. Shutdown      → Encerramento gracioso
                   (await using - IAsyncDisposable)

Exemplo de Inicialização (McpClient/Program.cs):

var clientOptions = new McpClientOptions
{
    ClientInfo = new Implementation
    {
        Name = "McpClient Demo",
        Version = "1.0.0"
    },
    InitializationTimeout = TimeSpan.FromSeconds(30),
    Capabilities = new ClientCapabilities()
};

await using var client = await McpClient.CreateAsync(
    clientTransport,
    clientOptions,
    loggerFactory,
    cts.Token);

// Sessão estabelecida - informações disponíveis
Console.WriteLine($"Servidor: {client.ServerInfo.Name} v{client.ServerInfo.Version}");
Console.WriteLine($"Protocolo: {client.NegotiatedProtocolVersion}");

📊 ServerInfo e ServerInstructions

Conceito importante: Fornecer contexto rico para o LLM entender as capacidades do servidor.

Implementação em ToolsServer:

builder.Services
    .AddMcpServer(options =>
    {
        options.ServerInfo = new()
        {
            Name = "ToolsServer",
            Version = "1.0.0"
        };
        options.ServerInstructions = "Servidor MCP com ferramentas de calculadora e manipulação de texto.";
    })

Implementação em HttpMcpServer:

options.ServerInstructions = """
    Este é um servidor MCP HTTP remoto que fornece ferramentas de informações do sistema.
    Ferramentas disponíveis:
    - GetSystemInfo: Retorna informações detalhadas do sistema...
    - GenerateUuid: Gera um UUID único
    - CalculateHash: Calcula hash SHA256
    ...
    """;

Benefício: LLMs usam essas informações para decidir quando e como usar as tools disponíveis.

🔗 Referências da Especificação

ConceitoImplementado emLink Oficial
Core ProtocolTodos os servidores/clientesEspecificação Core
ToolsToolsServer, HttpMcpServer, PromptsServerEspecificação Tools
PromptsPromptsServerEspecificação Prompts
Transport stdioToolsServer, PromptsServer, McpClientEspecificação Transports
Transport HTTPHttpMcpServer, HttpMcpClientEspecificação HTTP/SSE

Módulo 2: Primeiro MCP Server com Tools

Objetivo

Criar um servidor MCP simples que expõe ferramentas úteis usando transporte stdio.

Localização

src/ToolsServer/

Estrutura do Projeto

O projeto utiliza:

  • .NET 9.0 como framework
  • ModelContextProtocol 0.4.0-preview.1 - pacote principal do SDK
  • Microsoft.Extensions.Hosting 9.0.9 - para hospedagem e dependency injection

Configuração do Servidor

Pontos-chave da implementação:

  1. Configuração de Logging:
   builder.Logging.AddConsole(options =>
   {
       options.LogToStandardErrorThreshold = LogLevel.Trace;
   });

⚠️ Importante: O MCP usa stdout para comunicação do protocolo, então logs devem ir para stderr.

  1. Configuração do Servidor MCP:
   builder.Services
       .AddMcpServer(options =>
       {
           options.ServerInfo = new()
           {
               Name = "ToolsServer",
               Version = "1.0.0"
           };
           options.ServerInstructions = "Servidor MCP com ferramentas de calculadora e manipulação de texto.";
       })
       .WithStdioServerTransport()
       .WithToolsFromAssembly();

⚠️ Importante: ServerInfo e ServerInstructions ajudam LLMs a entender as capacidades do servidor.

Implementação das Tools

O servidor implementa duas categorias de ferramentas:

1. CalculatorTools - Operações matemáticas

Pontos-chave:

[McpServerToolType]
public static class CalculatorTools
{
    [McpServerTool(Name = "add"), Description("Soma dois números")]
    public static double Add(
        [Description("Primeiro número")] double a,
        [Description("Segundo número")] double b)
    {
        return a + b;
    }

    [McpServerTool(Name = "divide"), Description("Divide dois números")]
    public static double Divide(
        [Description("Numerador (dividendo)")] double a,
        [Description("Denominador (divisor)")] double b)
    {
        if (b == 0)
            throw new ArgumentException("Não é possível dividir por zero");
        return a / b;
    }
}

⚠️ Pontos de Atenção:

  • Nomes explícitos com Name = "..." (camelCase)
  • Validação de entrada (divisão por zero)
  • Descrições claras para parâmetros

2. TextTools - Manipulação de texto

Pontos-chave:

[McpServerToolType]
public static class TextTools
{
    [McpServerTool(Name = "toUpperCase"), Description("Converte texto para maiúsculas")]
    public static string ToUpperCase(
        [Description("Texto a converter")] string text)
    {
        ArgumentException.ThrowIfNullOrEmpty(text, nameof(text));
        return text.ToUpper();
    }

    [McpServerTool(Name = "countWords"), Description("Conta o número de palavras no texto")]
    public static int CountWords(
        [Description("Texto para contar palavras")] string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return 0;
        
        return text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

⚠️ Pontos de Atenção:

  • Validação robusta de entrada
  • Tratamento de casos especiais (texto vazio, null)
  • Retorno de tipos simples (string, int, double)

Executar o Servidor

cd src\ToolsServer
dotnet run

💡 Dica: O servidor aguardará conexões via stdin/stdout e não exibirá output visível até que um cliente se conecte.

Referência Completa

Veja a implementação completa em src/ToolsServer/Program.cs

🏗️ Padrões de Design Utilizados no Projeto

Padrão 1: Validação de Entrada em Tools

Onde: ToolsServer/Program.cs, HttpMcpServer/Program.cs

Problema: Entradas inválidas podem causar exceções ou comportamento inesperado.

Solução implementada:

// Validação em TextTools
[McpServerTool(Name = "toUpperCase")]
public static string ToUpperCase([Description("Texto a converter")] string text)
{
    ArgumentException.ThrowIfNullOrEmpty(text, nameof(text));  // ✅ Validação
    return text.ToUpper();
}

// Validação em CalculatorTools
[McpServerTool(Name = "divide")]
public static double Divide(double a, double b)
{
    if (b == 0)  // ✅ Validação de regra de negócio
        throw new ArgumentException("Não é possível dividir por zero");
    return a / b;
}

// Validação em RemoteTools
[McpServerTool]
public static string CalculateHash(string input)
{
    if (string.IsNullOrEmpty(input))  // ✅ Validação explícita
        throw new ArgumentException("A entrada não pode ser nula ou vazia", nameof(input));
    
    using var sha256 = System.Security.Cryptography.SHA256.Create();
    // ... implementação
}

Benefícios:

  • Mensagens de erro claras para o LLM
  • Evita comportamento indefinido
  • Facilita debug

Padrão 2: Extração Robusta de Conteúdo

Onde: McpClient/Program.cs, HttpMcpClient/Program.cs

Problema: Tools podem retornar diferentes tipos de conteúdo (text, json).

Solução implementada em McpClient:

static string ExtractTextContent(CallToolResult result)
{
    // ✅ Verificação de null
    if (result?.Content == null || !result.Content.Any())
        return "N/A";

    // ✅ Procurar por conteúdo do tipo texto
    var textContent = result.Content.FirstOrDefault(c => c.Type == "text");
    if (textContent != null)
    {
        // ✅ Serialização segura para acessar propriedades
        var json = JsonSerializer.SerializeToElement(textContent);
        if (json.TryGetProperty("text", out var textProp))
        {
            return textProp.GetString() ?? "N/A";
        }
    }

    return "N/A";  // ✅ Fallback
}

Solução implementada em HttpMcpClient:

static string GetContentString(CallToolResult result)
{
    // ✅ Tentar TextContentBlock primeiro
    if (result.Content.FirstOrDefault(c => c.Type == "text") is TextContentBlock textBlock)
    {
        return textBlock.Text ?? "N/A";
    }

    // ✅ Tentar JSON block - handle como JsonElement
    if (result.Content.FirstOrDefault(c => c.Type == "json") is var jsonBlock && jsonBlock != null)
    {
        try
        {
            var jsonProp = jsonBlock.GetType().GetProperty("Json");
            if (jsonProp?.GetValue(jsonBlock) is JsonElement jsonElement)
            {
                return JsonSerializer.Serialize(jsonElement, new JsonSerializerOptions { WriteIndented = true });
            }
        }
        catch { /* Fallback */ }
    }

    return "N/A";  // ✅ Fallback
}

Benefícios:

  • Trata múltiplos tipos de retorno
  • Nunca falha (sempre retorna algo)
  • Código robusto e resiliente

Padrão 3: Logging para stderr

Onde: Todos os servidores (ToolsServer, PromptsServer, HttpMcpServer)

Problema: MCP usa stdout para comunicação do protocolo.

Solução implementada:

// ✅ Configurar logs para stderr
builder.Logging.AddConsole(options =>
{
    options.LogToStandardErrorThreshold = LogLevel.Trace;
});

Por que é importante:

  • stdout: reservado para mensagens JSON-RPC do protocolo MCP
  • stderr: usado para logs, debug, diagnóstico
  • Separação evita corrupção da comunicação

Referência: Especificação stdio Transport


Padrão 4: Tratamento de Erros Hierárquico

Onde: McpClient/Program.cs

Problema: Diferentes tipos de erro requerem tratamentos diferentes.

Solução implementada:

try
{
    // ... código do cliente ...
}
catch (OperationCanceledException)
{
    Console.WriteLine("\n❌ Operação cancelada pelo usuário.");
}
catch (TimeoutException ex)
{
    Console.WriteLine($"\n❌ Timeout durante conexão: {ex.Message}");
}
catch (McpException ex)  // ✅ Exceção específica do protocolo
{
    Console.WriteLine($"\n❌ Erro do protocolo MCP: {ex.Message}");
}
catch (Exception ex)  // ✅ Catch-all como último recurso
{
    Console.WriteLine($"\n❌ Erro inesperado: {ex.GetType().Name}");
    Console.WriteLine($"   Mensagem: {ex.Message}");
}

Hierarquia:

  1. Mais específico (OperationCanceledException)
  2. Médio (TimeoutException, McpException)
  3. Genérico (Exception)

Benefícios:

  • Mensagens de erro apropriadas ao contexto
  • Facilita troubleshooting
  • UX melhor para o usuário

Padrão 5: Tool Discovery Pattern

Onde: PromptsServer/Program.cs - [PromptHelpers]

Problema: LLMs precisam descobrir quais prompts estão disponíveis e como usá-los.

Solução implementada:

[McpServerToolType]
public static class PromptHelpers
{
    // ✅ Tool para listar todos os prompts disponíveis
    [McpServerTool(Name = "list_available_prompts")]
    public static string ListAvailablePrompts()
    {
        return @"Prompts Disponíveis:
        
📝 DESENVOLVIMENTO:
  • code_review - Revisa código e fornece sugestões
  • explain_code - Explica o funcionamento do código
  ...";
    }

    // ✅ Tool para obter informações detalhadas
    [McpServerTool(Name = "get_prompt_info")]
    public static string GetPromptInfo(string promptName)
    {
        return promptName.ToLower() switch
        {
            "code_review" => "Revisa código em qualquer linguagem...",
            _ => $"Prompt '{promptName}' não encontrado."
        };
    }

    // ✅ Tool para validar argumentos antes de usar
    [McpServerTool(Name = "validate_prompt_args")]
    public static string ValidatePromptArgs(string promptName, string argsJson)
    {
        // ... validação
    }
}

Benefícios:

  • LLM pode descobrir capacidades dinamicamente
  • Validação antes de executar
  • Documentação self-service

Padrão relacionado: API Discovery Pattern


Padrão 6: Dependency Injection com Generic Host

Onde: ToolsServer/Program.cs, PromptsServer/Program.cs

Problema: Configurar e inicializar servidor MCP de forma estruturada.

Solução implementada:

var builder = Host.CreateApplicationBuilder(args);

// ✅ Configurar serviços via DI
builder.Services
    .AddMcpServer(options =>
    {
        options.ServerInfo = new() { Name = "ToolsServer", Version = "1.0.0" };
        options.ServerInstructions = "...";
    })
    .WithStdioServerTransport()
    .WithToolsFromAssembly();  // ✅ Descoberta automática via reflexão

await builder.Build().RunAsync();

Benefícios:

  • Configuração centralizada
  • Testabilidade (pode injetar mocks)
  • Descoberta automática de tools/prompts via reflexão
  • Ciclo de vida gerenciado

Referência: Generic Host - Microsoft Docs


Padrão 7: Configuration-Based Endpoints

Onde: HttpMcpClient/Program.cs, appsettings.json

Problema: Endpoints hardcoded dificultam deploy em diferentes ambientes.

Solução implementada:

appsettings.json:

{
  "McpServer": {
    "Endpoint": "http://localhost:5000"
  }
}

Program.cs:

var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .Build();   

// ✅ Ler de configuração com fallback
var endpoint = configuration["McpServer:Endpoint"] ?? "http://localhost:5000";

Benefícios:

  • Fácil mudança entre ambientes (dev, staging, prod)
  • Não requer recompilação
  • Suporta reload dinâmico

Padrão relacionado: Configuration Pattern


Padrão 8: Resource Disposal com await using

Onde: Todos os clientes (McpClient, HttpMcpClient)

Problema: Conexões e recursos precisam ser liberados corretamente.

Solução implementada:

await using var transport = new HttpClientTransport(transportOptions);
await using var client = await McpClient.CreateAsync(transport);

// ✅ Ao sair do escopo, Dispose/DisposeAsync é chamado automaticamente

Benefícios:

  • Garantia de cleanup mesmo com exceções
  • Prevenção de resource leaks
  • Código mais limpo (sem try-finally explícito)

Referência: IAsyncDisposable Pattern


Padrão 9: CORS Configuration para APIs Públicas

Onde: HttpMcpServer/Program.cs

Problema: Browsers bloqueiam requisições cross-origin por padrão.

Solução implementada:

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader()
              .WithExposedHeaders("Mcp-Session-Id");  // ✅ Expor header importante
    });
});

var app = builder.Build();
app.UseCors();  // ✅ Ativar middleware CORS

⚠️ Nota de Segurança: AllowAnyOrigin() é adequado para desenvolvimento. Em produção, especifique origens permitidas:

policy.WithOrigins("https://app.exemplo.com", "https://admin.exemplo.com")

Referência: CORS - MDN


Padrão 10: Health Check e Info Endpoints

Onde: HttpMcpServer/Program.cs

Problema: Monitoramento e observabilidade de servidores remotos.

Solução implementada:

// ✅ Health check para load balancers e monitoramento
app.MapGet("/health", () => Results.Ok(new
{
    status = "saudavel",
    service = "Servidor MCP HTTP",
    version = "1.0.0",
    timestamp = DateTime.UtcNow
}));

// ✅ Endpoint de informações para descoberta
app.MapGet("/info", () => Results.Ok(new
{
    name = "HttpMcpServer",
    version = "1.0.0",
    transport = "HTTP (Streamable HTTP)",
    endpoints = new { mcp = "/", health = "/health", info = "/info" }
}));

Benefícios:

  • Integração com Kubernetes/Docker health checks
  • Facilita troubleshooting
  • API self-documenting

Referência: Health Checks in ASP.NET Core


Exercício Prático

  1. Adicione uma nova tool IsPalindrome que verifica se um texto é palíndromo
  2. Adicione uma tool Power que calcula potenciação (base^expoente)
  3. Teste suas tools com o MCP Inspector

Módulo 3: Trabalhando com Prompts

Objetivo

Criar prompts reutilizáveis que LLMs podem usar, combinados com tools auxiliares.

Localização

src/PromptsServer/PromptsServer/

Estrutura do Projeto

O projeto utiliza:

  • ModelContextProtocol 0.4.0-preview.1 - para servidor e client
  • Microsoft.Extensions.AI - para abstrações de chat (ChatMessage, ChatRole)

Configuração do Servidor

Pontos-chave:

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithPromptsFromAssembly()
    .WithToolsFromAssembly();

⚠️ Importante: Este servidor expõe tanto prompts quanto tools auxiliares.

Implementação dos Prompts

1. DeveloperPrompts - Prompts para desenvolvimento

Exemplo de implementação:

[McpServerPromptType]
public static class DeveloperPrompts
{
    [McpServerPrompt(Name = "code_review"), Description("Cria um prompt para revisão de código")]
    public static ChatMessage CodeReview(
        [Description("Código para revisar")] string code,
        [Description("Linguagem de programação")] string language = "C#")
    {
        return new ChatMessage(ChatRole.User, 
            $"Revise o seguinte código {language} e forneça sugestões de melhoria:\n\n{code}");
    }

    [McpServerPrompt(Name = "refactor_code"), Description("Cria um prompt para refatoração de código")]
    public static ChatMessage RefactorCode(
        [Description("Código para refatorar")] string code,
        [Description("Objetivo da refatoração")] string goal = "melhorar legibilidade")
    {
        return new ChatMessage(ChatRole.User, 
            $"Refatore este código com foco em {goal}:\n\n{code}");
    }
}

⚠️ Pontos de Atenção:

  • Use ChatMessage com ChatRole.User para prompts
  • Parâmetros opcionais têm valores padrão úteis
  • Mantenha prompts focados e claros

2. WritingPrompts - Prompts para redação

Exemplo de implementação:

[McpServerPromptType]
public static class WritingPrompts
{
    [McpServerPrompt(Name = "summarize_text"), Description("Cria um prompt para resumir texto")]
    public static ChatMessage Summarize(
        [Description("Texto para resumir")] string content,
        [Description("Número máximo de palavras")] int maxWords = 100)
    {
        return new ChatMessage(ChatRole.User, 
            $"Resuma o seguinte texto em no máximo {maxWords} palavras:\n\n{content}");
    }

    [McpServerPrompt(Name = "translate_text"), Description("Cria um prompt para tradução de texto")]
    public static ChatMessage TranslateText(
        [Description("Texto para traduzir")] string text,
        [Description("Idioma de destino")] string targetLanguage = "inglês")
    {
        return new ChatMessage(ChatRole.User, 
            $"Traduza o seguinte texto para {targetLanguage}, mantendo o tom e contexto:\n\n{text}");
    }
}

Tools Auxiliares

O servidor também expõe tools para ajudar a descobrir e validar prompts:

Pontos-chave:

[McpServerToolType]
public static class PromptHelpers
{
    [McpServerTool(Name = "list_available_prompts"), Description("Lista todos os prompts disponíveis no servidor")]
    public static string ListAvailablePrompts()
    {
        return @"Prompts Disponíveis:

📝 DESENVOLVIMENTO:
  • code_review - Revisa código e fornece sugestões
  • explain_code - Explica o funcionamento do código
  ...";
    }

    [McpServerTool(Name = "get_prompt_info"), Description("Obtém informações detalhadas sobre um prompt específico")]
    public static string GetPromptInfo(
        [Description("Nome do prompt")] string promptName)
    {
        return promptName.ToLower() switch
        {
            "code_review" => "Revisa código em qualquer linguagem...",
            _ => $"Prompt '{promptName}' não encontrado."
        };
    }
}

⚠️ Pontos de Atenção:

  • Tools auxiliares facilitam descoberta de prompts
  • Use switch expressions para mapeamentos limpos
  • Forneça mensagens úteis para casos de erro

Executar o Servidor

cd src\PromptsServer\PromptsServer
dotnet run

Configuração para Claude Desktop

O projeto inclui um arquivo de exemplo claude_desktop_config.json mostrando como configurar o servidor para uso com Claude Desktop.

Referência Completa

Veja a implementação completa em src/PromptsServer/PromptsServer/Program.cs

Exercício Prático

  1. Crie um prompt GenerateTests que gera testes unitários
  2. Adicione uma tool validate_prompt_args que valida argumentos JSON
  3. Teste seus prompts com o cliente exemplo em ClientExample.txt

Módulo 4: Conexão Local (stdio)

Objetivo

Criar um cliente que se conecta ao servidor MCP usando transporte stdio (standard input/output) para uso local.

Localização

src/ClienteLocal/McpClient/

O que é stdio?

stdio (standard input/output) permite que o servidor e cliente se comuniquem através de streams de entrada/saída padrão. É ideal para:

  • ✅ Desenvolvimento local
  • ✅ Ferramentas CLI
  • ✅ Integração com editores (VS Code, etc.)
  • ✅ Debug e testes rápidos

Configuração do Cliente

Pontos-chave da implementação:

  1. Configuração de Logging:
   using var loggerFactory = LoggerFactory.Create(builder =>
   {
       builder
           .AddConsole()
           .SetMinimumLevel(LogLevel.Warning);
   });
  1. Criação do Transport:
   var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
   {
       Name = "ToolsServerClient",
       Command = "dotnet",
       Arguments = ["run", "--project", "../../ToolsServer"],
   });
  1. Criação do Cliente com Opções:
   var clientOptions = new McpClientOptions
   {
       ClientInfo = new Implementation
       {
           Name = "McpClient Demo",
           Version = "1.0.0"
       },
       InitializationTimeout = TimeSpan.FromSeconds(30),
       Capabilities = new ClientCapabilities()
   };

   await using var client = await McpClient.CreateAsync(
       clientTransport,
       clientOptions,
       loggerFactory,
       cts.Token);

⚠️ Pontos de Atenção:

  • Use await using para garantir disposal correto
  • Configure timeout adequado para inicialização
  • Forneça informações do cliente para logging

Usando o Cliente

1. Listar Tools:

var tools = await client.ListToolsAsync(cancellationToken: cts.Token);
foreach (var tool in tools)
{
    Console.WriteLine($"  • {tool.Name}: {tool.Description}");
}

2. Chamar Tools:

var addResult = await client.CallToolAsync(
    "add",
    new Dictionary { ["a"] = 10, ["b"] = 5 },
    cancellationToken: cts.Token);

3. Extrair Conteúdo de Forma Robusta:

static string ExtractTextContent(CallToolResult result)
{
    if (result?.Content == null || !result.Content.Any())
        return "N/A";

    var textContent = result.Content.FirstOrDefault(c => c.Type == "text");
    if (textContent != null)
    {
        var json = JsonSerializer.SerializeToElement(textContent);
        if (json.TryGetProperty("text", out var textProp))
        {
            return textProp.GetString() ?? "N/A";
        }
    }

    return "N/A";
}

⚠️ Pontos de Atenção:

  • Sempre verifique se Content não é null
  • Use serialização JSON para acessar propriedades de forma segura
  • Forneça valores padrão para casos de erro

Tratamento de Erros

O cliente implementa tratamento robusto de exceções:

try
{
    // ... código do cliente ...
}
catch (OperationCanceledException)
{
    Console.WriteLine("\n❌ Operação cancelada pelo usuário.");
}
catch (TimeoutException ex)
{
    Console.WriteLine($"\n❌ Timeout durante conexão: {ex.Message}");
}
catch (McpException ex)
{
    Console.WriteLine($"\n❌ Erro do protocolo MCP: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"\n❌ Erro inesperado: {ex.GetType().Name}");
    Console.WriteLine($"   Mensagem: {ex.Message}");
}

Executar o Cliente

cd src\ClienteLocal\McpClient
dotnet run

Saída esperada:

=== Cliente MCP - Demonstração ===

✅ Conectado ao servidor MCP com sucesso
   Servidor: ToolsServer v1.0.0
   Protocolo: 2024-11-05

📋 Ferramentas disponíveis:
  • add: Soma dois números
  • subtract: Subtrai dois números
  ...

🧮 Exemplo 1: Ferramentas de Calculadora
  ➕ Adição: 10 + 5 = 15
  ➖ Subtração: 20 - 8 = 12
  ...

Configuração para GitHub Copilot

Para usar o servidor com GitHub Copilot, edite as configurações do VS Code:

{
  "github.copilot.advanced": {
    "mcp": {
      "enabled": true,
      "servers": {
        "csharp-tools": {
          "command": "dotnet",
          "args": ["run", "--project", "D:\\Agentes\\src\\ToolsServer"],
          "transport": "stdio"
        }
      }
    }
  }
}

⚠️ Importante: Use caminhos absolutos corretos para seu sistema.

Testando com MCP Inspector

cd src\ToolsServer
npx @modelcontextprotocol/inspector dotnet run

Isso abrirá uma interface web onde você pode:

  • 📋 Ver todas as tools disponíveis
  • 🧪 Testar cada tool interativamente
  • 📊 Ver logs de comunicação
  • 🔍 Debugar problemas

Referência Completa

Veja a implementação completa em src/ClienteLocal/McpClient/Program.cs

Exercício Prático

  1. Modifique o cliente para se conectar ao PromptsServer
  2. Adicione retry logic para chamadas de tools
  3. Implemente cache de resultados para tools determinísticas

Módulo 5: Conexão Remota (HTTP)

Objetivo

Criar e conectar a um servidor MCP acessível via HTTP com Server-Sent Events (SSE), permitindo acesso remoto através de uma API web.

Localizações

O que é HTTP/SSE?

HTTP com SSE (Server-Sent Events) ou Streamable HTTP permite comunicação bidirecional através de HTTP. É ideal para:

  • ✅ Acesso remoto a servidores MCP
  • ✅ Serviços web e APIs públicas
  • ✅ Integração com aplicações web
  • ✅ Deploy em nuvem (Azure, AWS, etc.)
  • ✅ Compartilhamento de ferramentas entre equipes
  • ✅ Escalabilidade e load balancing

Quando usar HTTP vs stdio?

Característicastdio (Módulo 4)HTTP/SSE (Módulo 5)
UsoLocal, mesmo processoRemoto, através da rede
CenárioDesenvolvimento, CLIProdução, web apps
SegurançaIsoladoRequer autenticação
Escalabilidade1 clienteMúltiplos clientes
LatênciaMuito baixaDepende da rede

Implementação do Servidor HTTP

Pacotes necessários:

  • ModelContextProtocol.AspNetCore 0.4.0-preview.1 - para suporte HTTP

Pontos-chave da configuração:

  1. Logging para stderr:
   builder.Logging.ClearProviders();
   builder.Logging.AddConsole(options =>
   {
       options.LogToStandardErrorThreshold = LogLevel.Information;
   });
  1. Configuração do servidor MCP:
   builder.Services
       .AddMcpServer(options =>
       {
           options.ServerInfo = new Implementation
           {
               Name = "HttpMcpServer",
               Version = "1.0.0"
           };
           
           options.ServerInstructions = """
               Este é um servidor MCP HTTP remoto que fornece ferramentas de informações do sistema.
               Ferramentas disponíveis:
               - GetSystemInfo: Retorna informações do sistema
               - GenerateUuid: Gera um UUID único
               - CalculateHash: Calcula hash SHA256
               ...
               """;
       })
       .WithHttpTransport(httpOptions =>
       {
           httpOptions.IdleTimeout = TimeSpan.FromHours(2);
           httpOptions.MaxIdleSessionCount = 10_000;
           // httpOptions.Stateless = true; // Para ambientes com load balancing
       })
       .WithToolsFromAssembly();

⚠️ Pontos de Atenção:

  • ServerInstructions fornece contexto rico para LLMs
  • Configure IdleTimeout apropriadamente
  • Use Stateless = true para ambientes distribuídos
  1. Configuração CORS:
   builder.Services.AddCors(options =>
   {
       options.AddDefaultPolicy(policy =>
       {
           policy.AllowAnyOrigin()
                 .AllowAnyMethod()
                 .AllowAnyHeader()
                 .WithExposedHeaders("Mcp-Session-Id");
       });
   });
  1. Mapeamento de endpoints:
   var app = builder.Build();

   app.UseCors();
   app.MapMcp();  // Mapeia MCP na raiz "/"

   // Endpoints auxiliares
   app.MapGet("/health", () => Results.Ok(new { status = "saudavel", ... }));
   app.MapGet("/info", () => Results.Ok(new { name = "HttpMcpServer", ... }));

   app.Run();

Implementação das Tools Remotas

Exemplo de tools otimizadas para uso remoto:

[McpServerToolType]
public static class RemoteTools
{
    [McpServerTool]
    [Description("Obtém informações detalhadas do sistema...")]
    public static object GetSystemInfo()
    {
        return new
        {
            MachineName = Environment.MachineName,
            OSVersion = Environment.OSVersion.ToString(),
            ProcessorCount = Environment.ProcessorCount,
            CurrentTime = DateTime.Now,
            CurrentTimeUtc = DateTime.UtcNow,
            Uptime = TimeSpan.FromMilliseconds(Environment.TickCount64),
            // ... mais informações
        };
    }

    [McpServerTool]
    [Description("Gera um identificador único (UUID/GUID)")]
    public static string GenerateUuid()
    {
        return Guid.NewGuid().ToString();
    }

    [McpServerTool]
    [Description("Calcula hash SHA256 de um texto")]
    public static string CalculateHash(
        [Description("Texto de entrada")] string input)
    {
        if (string.IsNullOrEmpty(input))
            throw new ArgumentException("A entrada não pode ser nula ou vazia");

        using var sha256 = System.Security.Cryptography.SHA256.Create();
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
        byte[] hash = sha256.ComputeHash(bytes);
        return Convert.ToHexString(hash);
    }
}

⚠️ Pontos de Atenção:

  • Valide sempre entradas de usuários
  • Retorne objetos estruturados para JSON
  • Forneça informações detalhadas nas descrições

Executar o Servidor

cd src\ServidorRemoto\HttpMcpServer
dotnet run

URLs disponíveis:

  • MCP Endpoint: http://localhost:5000/
  • Health Check: http://localhost:5000/health
  • Server Info: http://localhost:5000/info

Implementação do Cliente HTTP

Pontos-chave:

  1. Configuração via appsettings:
   {
     "McpServer": {
       "Endpoint": "http://localhost:5000"
     }
   }
  1. Criação do transport HTTP:
   var transportOptions = new HttpClientTransportOptions
   {
       Endpoint = new Uri(endpoint),
       TransportMode = HttpTransportMode.AutoDetect,
       Name = "HttpMcpClient"
   };
   
   await using var transport = new HttpClientTransport(transportOptions);
   await using var client = await McpClient.CreateAsync(transport);

⚠️ Pontos de Atenção:

  • AutoDetect escolhe automaticamente entre StreamableHttp e SSE
  • Use await using para disposal correto
  1. Tratamento de diferentes tipos de conteúdo:
   static string GetContentString(CallToolResult result)
   {
       // Tentar TextContentBlock
       if (result.Content.FirstOrDefault(c => c.Type == "text") is TextContentBlock textBlock)
       {
           return textBlock.Text ?? "N/A";
       }

       // Tentar JSON
       if (result.Content.FirstOrDefault(c => c.Type == "json") is var jsonBlock && jsonBlock != null)
       {
           var jsonProp = jsonBlock.GetType().GetProperty("Json");
           if (jsonProp?.GetValue(jsonBlock) is JsonElement jsonElement)
           {
               return JsonSerializer.Serialize(jsonElement, new JsonSerializerOptions { WriteIndented = true });
           }
       }

       return "N/A";
   }

⚠️ Pontos de Atenção:

  • Ferramentas podem retornar text ou JSON
  • Use JsonElement para conteúdo JSON
  • Sempre forneça fallback

Executar o Cliente

Terminal 1 (Servidor):

cd src\ServidorRemoto\HttpMcpServer
dotnet run

Terminal 2 (Cliente):

cd src\ClienteRemoto\HttpMcpClient
dotnet run

Testando com cURL

# Health check
curl http://localhost:5000/health

# Server info
curl http://localhost:5000/info

Configurações de Produção

1. HTTPS:

// appsettings.json
{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:5001"
      }
    }
  }
}

2. Rate Limiting e Timeouts:

{
  "Kestrel": {
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxConcurrentUpgradedConnections": 100,
      "MaxRequestBodySize": 10485760,
      "KeepAliveTimeout": "00:02:00",
      "RequestHeadersTimeout": "00:00:30"
    }
  }
}

Referências Completas

Exercício Prático

  1. Adicione autenticação por API Key ao servidor
  2. Implemente retry logic no cliente com backoff exponencial
  3. Configure o servidor para HTTPS com certificado
  4. Adicione métricas de uso (número de chamadas, latência)

Módulo 6: Integração com Clientes de IA

GitHub Copilot (VS Code)

Configurar Settings

Abra VS Code Settings (JSON) pressionando Ctrl+Shift+P e digitando "Preferences: Open User Settings (JSON)":

{
  "github.copilot.advanced": {
    "mcp": {
      "enabled": true,
      "servers": {
        "csharp-tools": {
          "command": "dotnet",
          "args": ["run", "--project", "D:\\Agentes\\src\\ToolsServer"],
          "transport": "stdio",
          "env": {
            "DOTNET_ENVIRONMENT": "Production"
          }
        },
        "csharp-prompts": {
          "command": "dotnet",
          "args": ["run", "--project", "D:\\Agentes\\src\\PromptsServer\\PromptsServer"],
          "transport": "stdio"
        }
      }
    }
  }
}

⚠️ Importante:

  • Use caminhos absolutos corretos para seu sistema
  • Configure variáveis de ambiente se necessário
  • Teste cada servidor individualmente antes

Usar no Chat

  1. Abra o GitHub Copilot Chat (Ctrl+Shift+I)
  2. Digite comandos como:

- @mcp/csharp-tools add 15 e 25 - @mcp/csharp-tools countWords "Olá mundo MCP" - @mcp/csharp-prompts get code_review para revisar meu código

  1. O Copilot usará suas tools automaticamente!

GitHub Copilot CLI

Configuração

Crie ou edite ~/.config/github-copilot/config.yml:

mcp:
  servers:
    csharp-tools:
      command: dotnet
      args: ["run", "--project", "D:\\Agentes\\src\\ToolsServer"]
      transport: stdio

Usar na Linha de Comando

# Usar ferramentas
gh copilot suggest "calculate 15 plus 25"

# O Copilot detectará automaticamente suas tools disponíveis

Claude Desktop

Configuração

Edite o arquivo de configuração do Claude Desktop:

Windows: %APPDATA%\Claude\claude_desktop_config.json macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "csharp-tools": {
      "command": "dotnet",
      "args": [
        "run",
        "--project",
        "D:\\Agentes\\src\\ToolsServer"
      ],
      "env": {
        "DOTNET_ENVIRONMENT": "Production"
      }
    },
    "csharp-prompts": {
      "command": "dotnet",
      "args": [
        "run",
        "--project",
        "D:\\Agentes\\src\\PromptsServer\\PromptsServer"
      ]
    }
  }
}

Usar no Claude

  1. Reinicie o Claude Desktop
  2. Os servidores MCP aparecerão como ferramentas disponíveis
  3. Claude usará as tools automaticamente quando relevante

MCP Inspector

O que é?

Ferramenta oficial para debugar servidores MCP. Permite:

  • 🔍 Inspecionar tools e prompts
  • 🧪 Testar ferramentas interativamente
  • 📊 Ver comunicação em tempo real
  • 🐛 Debugar problemas de protocolo
  • 📝 Ver logs detalhados

Instalação

npm install -g @modelcontextprotocol/inspector

Usar com Servidor stdio

# Navegar até o diretório do servidor
cd src\ToolsServer

# Iniciar com Inspector
npx @modelcontextprotocol/inspector dotnet run

Isso abrirá uma interface web em http://localhost:5173 onde você pode:

  1. Ver todas as tools:

- Nomes, descrições e parâmetros - Tipos de retorno

  1. Testar tools:

- Fornecer argumentos - Ver resultados em tempo real

  1. Ver logs de comunicação:

- Mensagens JSON-RPC - Erros e avisos

Usar com Servidor HTTP

# Iniciar o servidor HTTP normalmente
cd src\ServidorRemoto\HttpMcpServer
dotnet run

# Em outro terminal, conectar o Inspector
npx @modelcontextprotocol/inspector http://localhost:5000

Dicas de Debug

Problemas comuns identificados pelo Inspector:

  1. Tool não aparece:

- Verifique atributos [McpServerTool] e [McpServerToolType] - Confirme que .WithToolsFromAssembly() está configurado

  1. Erro ao chamar tool:

- Veja a mensagem de erro no Inspector - Verifique tipos de parâmetros - Confirme validações de entrada

  1. Timeout de conexão:

- Verifique se o servidor está rodando - Confirme que não há conflitos de porta - Veja logs em stderr

Testando Integração Completa

Fluxo de teste recomendado:

  1. Testar servidor isolado com Inspector:
   cd src\ToolsServer
   npx @modelcontextprotocol/inspector dotnet run
  1. Testar com cliente stdio:
   cd src\ClienteLocal\McpClient
   dotnet run
  1. Configurar no GitHub Copilot:

- Adicionar nas configurações do VS Code - Testar com comandos simples no chat

  1. Monitorar comportamento:

- Observar quais tools o LLM escolhe usar - Ver como interpreta descrições - Ajustar descrições se necessário

Arquivo de Configuração Exemplo

Veja exemplos completos em:

Exercício Prático

  1. Configure todos os três servidores (Tools, Prompts, HTTP) no GitHub Copilot
  2. Teste interações complexas que usam múltiplas tools
  3. Use o MCP Inspector para debugar uma tool com erro
  4. Configure e teste com Claude Desktop

Troubleshooting

Problema: Servidor não responde

Sintomas:

  • Cliente trava ao conectar
  • Timeout de conexão
  • Sem output no console

Soluções:

  1. Verificar se o servidor está rodando:
   # Listar processos dotnet
   Get-Process dotnet
  1. Verificar logs em stderr:
   # Redirecionar stderr para arquivo
   dotnet run 2> error.log
  1. Testar com MCP Inspector primeiro:
   cd src\ToolsServer
   npx @modelcontextprotocol/inspector dotnet run
  1. Verificar caminhos de projeto:

- Use caminhos absolutos em configs - Confirme que .csproj existe no caminho

Problema: Tools não aparecem no cliente

Sintomas:

  • ListToolsAsync() retorna lista vazia
  • LLM não vê as ferramentas

Soluções:

  1. Verificar atributos:
   // ✅ Correto
   [McpServerToolType]
   public static class MyTools
   {
       [McpServerTool(Name = "myTool")]
       [Description("...")]
       public static string MyTool() { ... }
   }

   // ❌ Incorreto - faltam atributos
   public static class MyTools
   {
       public static string MyTool() { ... }
   }
  1. Confirmar registro no servidor:
   builder.Services
       .AddMcpServer()
       .WithStdioServerTransport()
       .WithToolsFromAssembly();  // ← Importante!
  1. Recompilar projeto:
   dotnet clean
   dotnet build
  1. Verificar com Inspector:

- Deve mostrar todas as tools - Se aparecer no Inspector mas não no cliente, o problema é na comunicação

Problema: Erro ao chamar tool

Sintomas:

  • Exceção ao chamar CallToolAsync
  • Erro "Tool not found"
  • Timeout na chamada

Soluções:

  1. Verificar nome da tool:
   // Nome definido no servidor
   [McpServerTool(Name = "add")]

   // Deve corresponder ao usado no cliente
   await client.CallToolAsync("add", ...);
  1. Verificar tipos de argumentos:
   // Servidor espera double
   public static double Add(double a, double b)

   // Cliente deve enviar double, não string
   await client.CallToolAsync("add", new Dictionary
   {
       ["a"] = 10.0,    // ✅ double
       ["b"] = 5.0      // ✅ double
   });
  1. Ver detalhes do erro:
   try
   {
       await client.CallToolAsync(...);
   }
   catch (McpException ex)
   {
       Console.WriteLine($"Erro MCP: {ex.Message}");
       Console.WriteLine($"Detalhes: {ex.InnerException?.Message}");
   }
  1. Testar com Inspector:

- Fornece interface para testar argumentos - Mostra erro exato do servidor

Problema: Erro de conexão HTTP

Sintomas:

  • Cliente HTTP não conecta
  • "Connection refused"
  • Timeout na requisição

Soluções:

  1. Verificar se servidor está rodando:
   # Testar health check
   curl http://localhost:5000/health
  1. Verificar porta disponível:
   # Ver o que está usando a porta
   netstat -ano | findstr :5000
  1. Confirmar URL correta:
   // appsettings.json ou código
   "Endpoint": "http://localhost:5000"  // Sem /mcp no final!
  1. Verificar firewall:

- Windows pode bloquear a porta - Adicionar exceção se necessário

  1. Testar com curl primeiro:
   # Health check deve responder
   curl http://localhost:5000/health

   # Info do servidor
   curl http://localhost:5000/info

Problema: Conteúdo null ou "N/A"

Sintomas:

  • Tool executa mas retorna "N/A"
  • Content é null no resultado

Soluções:

  1. Verificar tipo de retorno:
   // ✅ Tipos suportados
   public static string MyTool()  // text
   public static int MyTool()     // number
   public static object MyTool()  // json

   // ❌ Tipos não suportados diretamente
   public static MyCustomClass MyTool()
  1. Usar extraction robusta:
   static string ExtractTextContent(CallToolResult result)
   {
       if (result?.Content == null || !result.Content.Any())
           return "N/A";

       // Tentar como texto
       var textContent = result.Content.FirstOrDefault(c => c.Type == "text");
       if (textContent != null)
       {
           var json = JsonSerializer.SerializeToElement(textContent);
           if (json.TryGetProperty("text", out var textProp))
           {
               return textProp.GetString() ?? "N/A";
           }
       }

       return "N/A";
   }
  1. Verificar logs do servidor:

- Ver se tool está sendo executada - Confirmar que não há exceções

Problema: MCP Inspector não abre

Sintomas:

  • Comando não inicia interface web
  • Erro "inspector not found"

Soluções:

  1. Reinstalar Inspector:
   npm uninstall -g @modelcontextprotocol/inspector
   npm install -g @modelcontextprotocol/inspector
  1. Verificar instalação:
   npx @modelcontextprotocol/inspector --version
  1. Limpar cache do npm:
   npm cache clean --force
  1. Usar npx diretamente:
   # Sem instalar globalmente
   npx @modelcontextprotocol/inspector dotnet run

Problema: GitHub Copilot não vê o servidor

Sintomas:

  • Servidor configurado mas Copilot não usa tools
  • Sem erro, mas tools não aparecem

Soluções:

  1. Verificar sintaxe do JSON:
   {
     "github.copilot.advanced": {
       "mcp": {
         "enabled": true,  // ← Não esquecer
         "servers": { ... }
       }
     }
   }
  1. Usar caminhos absolutos:
   {
     "args": ["run", "--project", "D:\\Agentes\\src\\ToolsServer"]
                                 // ↑ Caminho completo
   }
  1. Reiniciar VS Code:

- Fechar completamente - Reabrir - Aguardar carregamento completo

  1. Verificar logs do VS Code:

- Ver console de desenvolvedor (Help > Toggle Developer Tools) - Procurar por erros relacionados a MCP

  1. Testar servidor isoladamente:

- Confirmar que funciona com Inspector - Confirmar que funciona com cliente C# - Só depois integrar com Copilot

Logs de Debug

Habilitar logs detalhados no servidor:

builder.Logging.AddConsole(options =>
{
    options.LogToStandardErrorThreshold = LogLevel.Trace;  // ← Debug máximo
});

Habilitar logs detalhados no cliente:

using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
        .AddConsole()
        .SetMinimumLevel(LogLevel.Debug);  // ← Debug máximo
});

Capturar logs em arquivo:

# Windows PowerShell
dotnet run 2> logs.txt

# Ou redirecionar ambos stdout e stderr
dotnet run > output.txt 2>&1

Checklist Geral de Debug

Quando algo não funciona, siga esta ordem:

  • [ ] 1. Servidor compila sem erros?
  • [ ] 2. Servidor inicia sem exceções?
  • [ ] 3. Tools aparecem no MCP Inspector?
  • [ ] 4. Tools funcionam no Inspector?
  • [ ] 5. Cliente consegue listar tools?
  • [ ] 6. Cliente consegue chamar tools?
  • [ ] 7. Configuração de cliente IA está correta?
  • [ ] 8. Cliente IA está reiniciado?
  • [ ] 9. Logs mostram algo anormal?
  • [ ] 10. Versões de pacotes estão corretas?

Recursos Adicionais

Documentação Oficial

Pacotes NuGet

Versões usadas neste workshop:

  • ModelContextProtocol 0.4.0-preview.1

- Pacote principal com servidor e cliente stdio -

  • ModelContextProtocol.AspNetCore 0.4.0-preview.1

- Extensões para servidores HTTP com ASP.NET Core -

  • ModelContextProtocol.Core 0.4.0-preview.1

- APIs de baixo nível do cliente e servidor -

  • Microsoft.Extensions.Hosting 9.0.9

- Hospedagem e dependency injection -

  • Microsoft.Extensions.AI.Abstractions

- Abstrações para integração com LLMs (ChatMessage, ChatRole) -

Frameworks e Tecnologias

  • .NET: 9.0
  • C# Language: 13.0 (latest)
  • MCP Protocol: Specification 2024-11-05

Exemplos e Tutoriais

Referências Complementares

Para uma lista completa de recursos, tutoriais avançados e casos de uso, consulte:

📖 docs/referencias.md

Este arquivo contém:

  • Tutoriais aprofundados
  • Padrões e best practices
  • Casos de uso reais
  • Exemplos de projetos avançados
  • Roadmap do MCP
  • Lista de ferramentas úteis

Comunidade e Suporte

CanalDescriçãoLink
Discord MCPComunidade oficialhttps://discord.gg/modelcontextprotocol
GitHub DiscussionsDiscussões técnicashttps://github.com/modelcontextprotocol/csharp-sdk/discussions
Stack OverflowQ&A técnicoTag: model-context-protocol

Ferramentas Úteis

FerramentaPropósitoLink
MCP InspectorDebug de servidoresnpm install -g @modelcontextprotocol/inspector
PostmanTestar endpoints HTTPhttps://www.postman.com/
InsomniaCliente RESThttps://insomnia.rest/
REST ClientExtensão VS CodeMarketplace

Leitura Complementar

  1. Understanding LLM Agents

- https://www.anthropic.com/index/claude-agent - Como LLMs usam ferramentas efetivamente

  1. Tool Use Best Practices

- https://docs.anthropic.com/claude/docs/tool-use - Padrões para criar tools úteis

  1. Prompt Engineering Guide

- https://www.promptingguide.ai/ - Como escrever prompts efetivos

  1. Async/Await in C#

- https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/ - Programação assíncrona

Projetos de Exemplo Avançados

Ideias para próximos projetos:

  1. File System Server

- Tools para ler/escrever arquivos - Buscar arquivos por padrão - Listar diretórios

  1. Database Query Server

- Executar queries SQL seguras - Ver schemas de tabelas - Exports de dados

  1. API Gateway Server

- Integrar múltiplas APIs externas - Weather, stocks, news, etc. - Cache e rate limiting

  1. Development Tools Server

- Formatar código - Lint e análise estática - Gerar testes unitários

Próximos Passos

Depois de completar este workshop, você pode:

  1. Explorar os exemplos oficiais

- Ver casos de uso mais complexos - Aprender padrões avançados

  1. Criar seu próprio servidor MCP

- Integrar com suas ferramentas - Expor APIs internas como tools

  1. Contribuir com a comunidade

- Compartilhar seus servidores - Abrir issues e PRs - Ajudar outros desenvolvedores

  1. Deploy em produção

- Configurar HTTPS e autenticação - Deploy na nuvem (Azure, AWS) - Monitorar uso e performance

  1. Integrar com projetos existentes

- Adicionar MCP a aplicações .NET - Expor funcionalidades via tools - Criar interfaces conversacionais

Como Contribuir

Para este Workshop

  • 🐛 Encontrou um bug? Abra uma issue
  • 💡 Tem uma sugestão? Crie uma discussion
  • 🔧 Quer contribuir? Envie um pull request
  • 📝 Melhorou algo? Compartilhe sua experiência

Para o SDK C#

  1. Fork do repositório oficial
  2. Crie branch feature: git checkout -b feature/minha-feature
  3. Commit mudanças: git commit -am 'Adiciona feature X'
  4. Push branch: git push origin feature/minha-feature
  5. Abra Pull Request

Atualizações Futuras

Este workshop será atualizado conforme:

  • Novas versões do SDK C#
  • Novos recursos do protocolo MCP
  • Feedback da comunidade
  • Melhores práticas emergentes

Última atualização: Janeiro 2025

Versão do workshop: 2.0.0 (atualizada para SDK 0.4.0-preview.1)


Feedback e Contribuições

Este é um projeto educacional em constante evolução. Seu feedback é essencial!

Como ajudar:

  • ⭐ Dê uma estrela no repositório se achou útil
  • 🐛 Reporte bugs ou problemas
  • 💡 Sugira melhorias
  • 📝 Compartilhe sua experiência
  • 🔧 Contribua com código
  • 📖 Melhore a documentação

Contato:

  • GitHub Issues: Para bugs e features
  • GitHub Discussions: Para perguntas e ideias
  • Discord MCP: Para discussões em tempo real

Licença

Este workshop é disponibilizado sob licença MIT. Veja o arquivo LICENSE para mais detalhes.

Você é livre para:

  • ✅ Usar comercialmente
  • ✅ Modificar
  • ✅ Distribuir
  • ✅ Uso privado

Desde que:

  • 📋 Inclua a licença e copyright
  • 📋 Forneça atribuição

Agradecimentos

Este workshop não seria possível sem:

  • Anthropic - Pela criação do Model Context Protocol
  • Microsoft - Pelo desenvolvimento do SDK C#
  • Comunidade .NET - Pelas ferramentas e frameworks
  • Contribuidores - Por feedback e melhorias
  • Você - Por dedicar tempo para aprender!

Conclusão

🎉 Parabéns por completar o workshop!

Você agora sabe como:

  • ✅ Criar servidores MCP em C#
  • ✅ Implementar tools e prompts
  • ✅ Conectar clientes localmente e remotamente
  • ✅ Integrar com GitHub Copilot e outras ferramentas
  • ✅ Debugar problemas com MCP Inspector
  • ✅ Seguir melhores práticas de segurança
  • ✅ Deploy servidores

目录标签

目录标签

AI代理C#ClaudeLLM交互本地部署MCP协议C#开发工具集成

支持客户端

Claude DesktopClaudeVS Code

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

api-key

运行时(runtime,运行环境)

Node.js

来源包(packageName,安装包名)

@modelcontextprotocol/inspector

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdioapi-key部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP