Como criar seu próprio servidor de MCP

Um guia prático para construir seu primeiro servidor Model Context Protocol (MCP) do zero e conectá-lo ao Claude for Desktop

Como criar seu próprio servidor de MCP

Construir seu próprio servidor Model Context Protocol (MCP) pode parecer intimidador no início, mas este guia vai mostrar que é mais simples do que você imagina. Vamos criar um servidor de previsão do tempo passo a passo e conectá-lo ao Claude for Desktop.

O que vamos construir

Nosso servidor de exemplo vai expor duas ferramentas principais:

  • get_alerts: Para buscar alertas meteorológicos

  • get_forecast: Para obter previsões do tempo

Embora este tutorial use o Claude for Desktop como cliente MCP para simplificar, vale lembrar que servidores MCP podem se conectar a qualquer cliente compatível. A comunidade já desenvolveu diversos clientes alternativos, e você pode até mesmo construir o seu próprio.

Conceitos fundamentais do MCP

Antes de começarmos, é importante entender os três tipos principais de capacidades que servidores MCP podem fornecer:

  1. Resources: Dados similares a arquivos que podem ser lidos pelos clientes (como respostas de APIs ou conteúdo de arquivos)

  2. Tools: Funções que podem ser chamadas pelo LLM (com aprovação do usuário)

  3. Prompts: Templates pré-escritos que ajudam usuários a realizar tarefas específicas

Nosso foco neste tutorial será principalmente em tools (ferramentas).

Escolha sua linguagem de programação

O MCP suporta múltiplas linguagens de programação. Neste tutorial, vamos focar em Python e TypeScript, mas você também pode usar Java, Kotlin, C# ou Rust. Escolha a linguagem com a qual você se sente mais confortável.

Configurando o ambiente (Python)

Requisitos do sistema:

  • Python 3.10 ou superior

  • Python MCP SDK 1.2.0 ou superior

Importante sobre logging em servidores MCP

Para servidores baseados em STDIO, nunca escreva para stdout. Isso vai corromper as mensagens JSON-RPC e quebrar seu servidor. A função print() escreve para stdout por padrão, mas pode ser usada com segurança especificando file=sys.stderr.

Para servidores baseados em HTTP, logging padrão de saída é aceitável, pois não interfere com as respostas HTTP.

Instalando as dependências

Primeiro, vamos instalar o uv e configurar nosso projeto Python:

macOS/Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows:
Baixe o instalador do site oficial do uv.

Após a instalação, reinicie seu terminal e execute:

# Criar diretório para o projeto
uv init weather
cd weather

# Criar ambiente virtual e ativá-lo
uv venv
source .venv/bin/activate  # No Windows: .venv\Scripts\activate

# Instalar dependências
uv add "mcp[cli]" httpx

# Criar arquivo do servidor
touch weather.py

Construindo o servidor

Importando pacotes e configurando a instância

Adicione ao topo do seu arquivo weather.py:

from typing import Any

import httpx
from mcp.server.fastmcp import FastMCP

# Inicializar servidor FastMCP
mcp = FastMCP("weather")

# Constantes
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"

A classe FastMCP usa type hints do Python e docstrings para gerar automaticamente definições de ferramentas, facilitando a criação e manutenção de tools MCP.

Funções auxiliares

Vamos adicionar funções auxiliares para consultar e formatar dados da API do National Weather Service:

async def make_nws_request(url: str) -> dict[str, Any] | None:
    """Fazer uma requisição para a API NWS com tratamento de erros apropriado."""
    headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, headers=headers, timeout=30.0)
            response.raise_for_status()
            return response.json()
        except Exception:
            return None


def format_alert(feature: dict) -> str:
    """Formatar um alerta em uma string legível."""
    props = feature["properties"]
    return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""

Implementando a execução das ferramentas

O handler de execução de ferramentas é responsável por executar a lógica de cada tool:

@mcp.tool()
async def get_alerts(state: str) -> str:
    """Obter alertas meteorológicos para um estado dos EUA.

    Args:
        state: Código de duas letras do estado dos EUA (ex: CA, NY)
    """
    url = f"{NWS_API_BASE}/alerts/active/area/{state}"
    data = await make_nws_request(url)

    if not data or "features" not in data:
        return "Não foi possível buscar alertas ou nenhum alerta encontrado."

    if not data["features"]:
        return "Nenhum alerta ativo para este estado."

    alerts = [format_alert(feature) for feature in data["features"]]
    return "\n---\n".join(alerts)


@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """Obter previsão do tempo para uma localização.

    Args:
        latitude: Latitude da localização
        longitude: Longitude da localização
    """
    # Primeiro, obter o endpoint da grade de previsão
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)

    if not points_data:
        return "Não foi possível buscar dados de previsão para esta localização."

    # Obter a URL de previsão da resposta de pontos
    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)

    if not forecast_data:
        return "Não foi possível buscar previsão detalhada."

    # Formatar os períodos em uma previsão legível
    periods = forecast_data["properties"]["periods"]
    forecasts = []
    for period in periods[:5]:  # Mostrar apenas os próximos 5 períodos
        forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
        forecasts.append(forecast)

    return "\n---\n".join(forecasts)

Executando o servidor

Por fim, vamos inicializar e executar o servidor:

def main():
    # Inicializar e executar o servidor
    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()

Seu servidor está completo! Execute uv run weather.py para iniciar o servidor MCP, que ficará aguardando mensagens de hosts MCP.

Testando com Claude for Desktop

Instalação e configuração

Primeiro, certifique-se de ter o Claude for Desktop instalado e atualizado para a versão mais recente. Você pode baixá-lo em claude.ai/download.

Nota: Claude for Desktop ainda não está disponível para Linux. Usuários Linux podem prosseguir para construir um cliente MCP próprio.

Configurando o servidor

Abra o arquivo de configuração do Claude for Desktop em ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) ou %APPDATA%\Claude\claude_desktop_config.json (Windows). Crie o arquivo se ele não existir.

Por exemplo, usando VS Code:

code ~/Library/Application\ Support/Claude/claude_desktop_config.json

Adicione seu servidor na chave mcpServers:

{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/CAMINHO/ABSOLUTO/PARA/PASTA/weather",
        "run",
        "weather.py"
      ]
    }
  }
}

Importante: Use sempre o caminho absoluto para seu servidor. Você pode obtê-lo executando pwd no macOS/Linux ou cd no Windows Command Prompt. No Windows, use barras duplas (\\) ou barras normais (/) no caminho JSON.

Salve o arquivo e reinicie completamente o Claude for Desktop:

  • Windows: Clique com o botão direito no ícone do Claude na bandeja do sistema e selecione "Sair"

  • macOS: Use Cmd+Q ou selecione "Quit Claude" na barra de menu

Simplesmente fechar a janela não encerra completamente a aplicação.

Testando o servidor

Após reiniciar o Claude for Desktop, procure pelo ícone "Add files, connectors, and more /" na interface. Clique no ícone de mais (+) e passe o mouse sobre o menu "Connectors". Você deve ver o servidor weather listado.

Agora teste seu servidor com comandos como:

  • "Qual é a previsão do tempo em Sacramento?"

  • "Quais são os alertas meteorológicos ativos no Texas?"

Nota: Como estamos usando o National Weather Service dos EUA, as consultas funcionarão apenas para localizações americanas.

Como funciona por baixo dos panos

Quando você faz uma pergunta:

  1. O cliente envia sua pergunta para o Claude

  2. Claude analisa as ferramentas disponíveis e decide qual(is) usar

  3. O cliente executa a(s) ferramenta(s) escolhida(s) através do servidor MCP

  4. Os resultados são enviados de volta para o Claude

  5. Claude formula uma resposta em linguagem natural

  6. A resposta é exibida para você

Troubleshooting comum

Servidor não aparece no Claude

  1. Verifique a sintaxe do arquivo claude_desktop_config.json

  2. Certifique-se de que o caminho para seu projeto é absoluto, não relativo

  3. Reinicie o Claude for Desktop completamente

Obtendo logs do Claude for Desktop

Os logs relacionados ao MCP são gravados em ~/Library/Logs/Claude:

  • mcp.log contém logging geral sobre conexões MCP

  • Arquivos nomeados mcp-server-SERVERNAME.log contêm logs de erro do servidor específico

Execute o seguinte comando para visualizar logs recentes:

tail -n 20 -f ~/Library/Logs/Claude/mcp*.log

Chamadas de ferramentas falham silenciosamente

Se o Claude tenta usar as ferramentas mas elas falham:

  1. Verifique os logs do Claude para erros

  2. Verifique se seu servidor compila e executa sem erros

  3. Tente reiniciar o Claude for Desktop

Próximos passos

Agora que você construiu seu primeiro servidor MCP, aqui estão algumas sugestões para continuar:

  • Construa um cliente MCP: Aprenda a criar seu próprio cliente que pode se conectar ao seu servidor

  • Explore servidores de exemplo: Confira a galeria de servidores MCP oficiais e implementações da comunidade

  • Aprenda debugging avançado: Domine técnicas de debugging para servidores MCP

  • Use LLMs para acelerar o desenvolvimento: Aprenda a usar Claude e outros LLMs para construir servidores MCP mais rapidamente

Recursos adicionais

Recurso

Descrição

SDK Python

Documentação completa do SDK MCP para Python

SDK TypeScript

Guias e referências para desenvolvimento em TypeScript

Especificação MCP

Documentação técnica completa do protocolo

Comunidade

Fórum da comunidade para tirar dúvidas e compartilhar projetos

Conclusão

Você acabou de construir seu primeiro servidor MCP funcional! Este é apenas o começo - o Model Context Protocol abre um mundo de possibilidades para integrar LLMs com ferramentas e dados externos. Continue experimentando, construindo e compartilhando suas criações com a comunidade.

Lembre-se: a melhor maneira de aprender é construindo. Experimente adicionar novas ferramentas ao seu servidor, conecte-se a outras APIs, e explore as capacidades completas do MCP.