MCP Hub

Um hub MCP leve para centralizar seus servidores MCP em um só lugar.

Documentação

MCP-Hub

Docker Hub Docker Pulls Docker Image Size Build Status

Um hub baseado em Go que agrega múltiplos servidores MCP (Model Context Protocol) e expõe suas ferramentas através de uma API HTTP unificada.

Recursos

  • Protocolo MCP Padrão: Suporte completo à especificação MCP 2024-11-05
  • Múltiplos Tipos de Transporte:
    • Stdio: Para servidores MCP locais (Node.js, Python, etc.)
    • HTTP/SSE: Para servidores MCP remotos
  • Baseado em Configuração: Configuração JSON compatível com o formato Cursor/VSCode
  • Pronto para Docker: Implantação fácil em contêineres com montagens de volume
  • Agregação de Ferramentas: Combine ferramentas de múltiplos servidores MCP em um só lugar
  • API HTTP: Endpoints RESTful para descoberta e execução de ferramentas

Início Rápido

1. Compilar

cd cmd/mcp-hub
go build -o ../../mcp-hub

2. Criar Configuração

Crie um arquivo config.json (veja config.example.json para um modelo):

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

3. Executar

# Using default config.json
./mcp-hub

# Or specify a config file
./mcp-hub --config /path/to/config.json

Observações:

  • O endereço de escuta HTTP pode ser substituído pela variável de ambiente MCP_HUB_PORT ou PORT. Se o valor contiver dois pontos, é tratado como um endereço completo (ex.: 0.0.0.0:8080), caso contrário, é tratado como uma porta e é prefixado com dois pontos.
  • O binário aceita um flag --config (padrão: config.json).

4. Usar a API

Listar todas as ferramentas disponíveis:

curl http://localhost:8080/mcp/tools

Executar uma ferramenta:

curl -X POST http://localhost:8080/mcp/execute \
  -H 'Content-Type: application/json' \
  -d '{
    "plugin_id": "filesystem",
    "tool_name": "read_file",
    "arguments": {"path": "/tmp/test.txt"}
  }'

Listar servidores conectados:

curl http://localhost:8080/mcp/servers

Formato de Configuração

O arquivo de configuração usa o formato padrão mcpServers compatível com Cursor, VSCode e Claude Desktop.

Servidores Stdio (Locais)

Para servidores MCP que executam como processos locais:

{
  "mcpServers": {
    "server-name": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-package"],
      "env": {
        "API_KEY": "${YOUR_API_KEY}"
      },
      "timeout": 30
    }
  }
}

Campos:

  • command: Executável a ser executado (obrigatório)
  • args: Argumentos de linha de comando (opcional)
  • env: Variáveis de ambiente (opcional, suporta expansão de ${VAR})
  • timeout: Tempo limite de solicitação em segundos (opcional, padrão: 30)
  • disabled: Defina como true para desabilitar um servidor (opcional)

Servidores HTTP (Remotos)

Para servidores MCP acessíveis via HTTP:

{
  "mcpServers": {
    "remote-server": {
      "type": "http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      },
      "timeout": 45
    }
  }
}

Campos:

  • type: Defina como "http" para transporte HTTP (ou detectado automaticamente a partir de url)
  • url: URL do endpoint HTTP (obrigatório)
  • headers: Cabeçalhos HTTP a incluir (opcional, suporta expansão de ${VAR})
  • timeout: Tempo limite de solicitação em segundos (opcional, padrão: 30)

Variáveis de Ambiente

As variáveis de ambiente na configuração são expandidas usando a sintaxe ${VAR_NAME}. Por exemplo:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

Depois execute:

GITHUB_TOKEN=your_token_here ./mcp-hub

Implantação com Docker

Variantes de Imagem

O repositório fornece duas variantes de imagem Docker, otimizadas para diferentes casos de uso:

1. Imagem Padrão (Dockerfile / mcp-hub:latest)

  • Tamanho: ~47MB
  • Inclui: Alpine Linux + Docker CLI + binário mcp-hub
  • Use quando: Você precisa de transporte Docker para executar servidores MCP em contêineres, ou transportes mistos
  • Melhor para: Implantações de produção com servidores MCP baseados em contêineres

2. Imagem de Servidores MCP Locais (Dockerfile.local / mcp-hub:local)

  • Tamanho: ~800MB
  • Inclui: Node.js 20, Python 3, uv, curl, git e binário mcp-hub
  • Use quando: Você quer executar servidores MCP locais baseados em stdio (Node.js, Python) no mesmo contêiner
  • Melhor para: Implantações autossuficientes onde o hub e todos os servidores MCP executam juntos

Compilar Imagem Docker

Para compilar uma imagem específica localmente:

# Standard image (with Docker CLI)
docker build -t mcp-hub:latest .

# Local MCP servers image (with Node.js, Python, uv)
docker build -f Dockerfile.local -t mcp-hub:local .

Executar com Docker

# Create a config directory
mkdir -p config

# Put your config.json in the config directory
cp config.json config/

# Run the container
docker run -d \
  -p 8080:8080 \
  -v $(pwd)/config:/config:ro \
  -e GITHUB_TOKEN=${GITHUB_TOKEN} \
  mcp-hub

Docker Compose

version: '3.8'
services:
  mcp-hub:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ./config:/config:ro
      - ./plugins:/plugins:ro  # Optional: mount custom plugins
    environment:
      - GITHUB_TOKEN=${GITHUB_TOKEN}
      - BRAVE_API_KEY=${BRAVE_API_KEY}

Referência da API HTTP

GET /mcp/tools

Lista todas as ferramentas disponíveis de todos os servidores MCP conectados.

Resposta:

[
  {
    "id": "read_file",
    "name": "read_file",
    "description": "Read contents of a file",
    "plugin_id": "filesystem"
  }
]

POST /mcp/execute

Executa uma ferramenta em um servidor MCP específico.

Solicitação:

{
  "plugin_id": "filesystem",
  "tool_name": "read_file",
  "arguments": {
    "path": "/tmp/test.txt"
  }
}

Resposta: Resultado da chamada de ferramenta MCP (o formato depende da ferramenta)

GET /mcp/servers

Lista todos os servidores MCP conectados.

Resposta:

{
  "servers": ["filesystem", "github", "brave-search"]
}

GET /mcp/stream

Fluxo de Server-Sent Events de atualizações do registro de ferramentas (para descoberta de ferramentas em tempo real).

Exemplos

Exemplo 1: Usando Servidores MCP Oficiais

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "${BRAVE_API_KEY}"
      }
    }
  }
}

Exemplo 2: Servidor MCP Python Personalizado

{
  "mcpServers": {
    "custom-tools": {
      "command": "python3",
      "args": ["/app/plugins/custom_mcp_server.py"]
    }
  }
}

Exemplo 3: Servidores Locais e Remotos Mistos

{
  "mcpServers": {
    "local-filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
    },
    "remote-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      }
    }
  }
}

Desenvolvimento

Estrutura do Projeto

.
├── cmd/
│   └── mcp-hub/
│       └── main.go           # Entry point
├── internal/
│   ├── config/
│   │   └── config.go         # Configuration parsing
│   ├── mcp/
│   │   └── protocol.go       # MCP protocol structures
│   ├── plugin/
│   │   └── manager.go        # Server management
│   ├── registry/
│   │   └── registry.go       # Tool registry
│   ├── server/
│   │   └── server.go         # HTTP server
│   └── transport/
│       ├── transport.go      # Transport interface
│       ├── stdio.go          # Stdio transport
│       └── http.go           # HTTP transport
├── config.example.json       # Example configuration
└── README.md

Adicionando Novos Tipos de Transporte

Implemente a interface Transport em internal/transport/:

type Transport interface {
    Start(ctx context.Context) error
    SendRequest(ctx context.Context, req interface{}) (json.RawMessage, error)
    SendNotification(ctx context.Context, notification interface{}) error
    Close() error
    IsConnected() bool
}

Solução de Problemas

O servidor falha ao iniciar

Verifique os logs para mensagens de erro específicas. Problemas comuns:

  • npx ou python3 ausentes no PATH
  • Nomes de pacotes de servidor MCP inválidos
  • Variáveis de ambiente ausentes
  • Caminhos de arquivo incorretos na configuração

A execução da ferramenta falha

  • Verifique se o servidor MCP está inicializado corretamente (verifique /mcp/servers)
  • Garanta que os argumentos da ferramenta correspondam ao esquema esperado
  • Verifique os logs do servidor (a saída de stderr é visível nos logs do hub)

Erros de tempo limite

Aumente o valor de timeout na configuração do servidor:

{
  "mcpServers": {
    "slow-server": {
      "command": "...",
      "timeout": 120
    }
  }
}

Licença

MIT

Servidores Docker (Containerizados)

Para servidores MCP executando em contêineres Docker:

{
  "mcpServers": {
    "containerized-server": {
      "type": "docker",
      "image": "my-mcp-server:latest",
      "args": ["--option", "value"],
      "env": {
        "API_KEY": "${YOUR_API_KEY}"
      },
      "volumes": {
        "/host/path": "/container/path",
        "${HOME}/data": "/data"
      },
      "network": "mcp-network",
      "timeout": 60
    }
  }
}

Campos:

  • type: Defina como "docker" para transporte Docker (ou detectado automaticamente a partir de image)
  • image: Nome da imagem Docker (obrigatório)
  • args: Argumentos de comando a passar para o entrypoint do contêiner (opcional)
  • env: Variáveis de ambiente (opcional, suporta expansão de ${VAR})
  • volumes: Montagens de volume como mapeamentos de host:container (opcional, suporta expansão de ${VAR})
  • network: Rede Docker à qual conectar (opcional)
  • timeout: Tempo limite de solicitação em segundos (opcional, padrão: 30)

Benefícios do Transporte Docker:

  • Não é necessário instalar Node.js, Python ou outros runtimes no host do hub
  • Dependências isoladas por servidor MCP
  • Gerenciamento fácil de versões com tags Docker
  • Ambiente consistente em todas as implantações

Compilando Imagens Docker para Servidores MCP

Você pode containerizar qualquer servidor MCP para evitar instalar suas dependências no host do hub.

Exemplo: Containerizando um Servidor MCP Python

Dockerfile:

FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy MCP server code
COPY mcp_server.py .

# Run as non-root user
RUN useradd -m -u 1000 mcpuser && chown -R mcpuser:mcpuser /app
USER mcpuser

# The server should read from stdin and write to stdout
ENTRYPOINT ["python", "-u", "mcp_server.py"]

Compilar e usar:

# Build the image
docker build -t my-mcp-server:latest .

# Add to config.json
{
  "mcpServers": {
    "my-server": {
      "image": "my-mcp-server:latest"
    }
  }
}

Exemplo: Containerizando um Servidor MCP Node.js

Dockerfile:

FROM node:20-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --production

# Copy server code
COPY . .

# Run as non-root user
RUN addgroup -g 1000 mcpuser && \
    adduser -D -u 1000 -G mcpuser mcpuser && \
    chown -R mcpuser:mcpuser /app
USER mcpuser

ENTRYPOINT ["node", "server.js"]

Observações Importantes para Servidores MCP Docker

  1. Use o flag -i: O hub executa contêineres com docker run -i para stdin/stdout interativos
  2. Saída sem buffer: Garanta que as saídas do seu servidor estejam sem buffer (use python -u ou flush())
  3. Somente Stdin/Stdout: O protocolo MCP usa stdin para entrada e stdout para saída
  4. Stderr para logs: Use stderr para registro (visível nos logs do hub)
  5. Limpeza: Os contêineres são executados com --rm para limpeza automática

Imagens de Servidor MCP Pré-compiladas

Crie um registro de imagens Docker para servidores MCP comuns:

# Example: Build an echo server image
cd examples/plugins
cat > Dockerfile << 'DOCKERFILE'
FROM python:3.11-slim
COPY mcp_echo.py /app/server.py
WORKDIR /app
RUN chmod +x server.py
ENTRYPOINT ["python", "-u", "server.py"]
DOCKERFILE

docker build -t mcp-echo:latest .

Depois use:

{
  "mcpServers": {
    "echo": {
      "image": "mcp-echo:latest"
    }
  }
}

Comparação de Transportes

TransporteCaso de UsoPrósContras
stdioServidores MCP locais com acesso diretoRápido, baixa sobrecargaRequer runtime (Node.js/Python) instalado
DockerServidores MCP isolados e reproduzíveisSem dependências de runtime, versionamento fácilSobrecarga ligeiramente maior, requer Docker
HTTPServidores MCP remotos/hospedados na nuvemEscalável, pode ser balanceado por cargaLatência de rede, requer infraestrutura de servidor

Quando Usar Transporte Docker

Escolha o transporte Docker quando:

  • ✅ Você quer evitar instalar Node.js, Python ou outros runtimes no host do hub
  • ✅ Você precisa de ambientes consistentes e reproduzíveis entre implantações
  • ✅ Você quer gerenciamento fácil de versões com tags Docker
  • ✅ Você está executando o hub em um ambiente containerizado (Kubernetes, Docker Compose)
  • ✅ Você precisa isolar dependências do servidor
  • ✅ Você quer usar imagens de servidor MCP pré-compiladas de um registro

Escolha o transporte stdio quando:

  • ✅ Você está desenvolvendo localmente e quer iteração mais rápida
  • ✅ As dependências de runtime já estão instaladas
  • ✅ Você precisa da menor latência absoluta

Escolha o transporte HTTP quando:

  • ✅ Os servidores MCP estão hospedados remotamente
  • ✅ Você precisa escalar servidores independentemente
  • ✅ Você quer usar serviços de servidor MCP gerenciados

Exemplo: Configuração Docker Completa

Aqui está um exemplo completo executando múltiplos servidores MCP em Docker:

# 1. Build your custom MCP server image
docker build -t my-mcp-server:v1.0 ./my-server

# 2. Create Docker network for inter-container communication
docker network create mcp-network

# 3. Configure servers
cat > config.json << 'JSON'
{
  "mcpServers": {
    "echo": {
      "image": "mcp-echo:latest"
    },
    "custom-tools": {
      "image": "my-mcp-server:v1.0",
      "env": {
        "API_KEY": "${MY_API_KEY}"
      },
      "volumes": {
        "/host/data": "/data"
      }
    }
  }
}
JSON

# 4. Run the hub
MY_API_KEY=secret123 ./mcp-hub --config config.json

Esta configuração oferece:

  • ✨ Sem dependências de runtime no host do hub
  • ✨ Ambientes isolados para cada servidor MCP
  • ✨ Atualizações fáceis alterando tags de imagem Docker
  • ✨ Implantações reproduzíveis

Implantação Containerizada

O próprio mcp-hub pode executar em um contêiner Docker. Veja DOCKER_DEPLOYMENT.md para o guia completo de implantação.

Implantação Rápida com Docker

# Build the image
docker build -t mcp-hub:latest .

# Run with your config
docker run -d \
  --name mcp-hub \
  -p 8080:8080 \
  -v $(pwd)/config.json:/app/config.json:ro \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e GITHUB_TOKEN=${GITHUB_TOKEN} \
  mcp-hub:latest

Ou use Docker Compose

docker-compose up -d

Tamanhos de Imagem:

  • Padrão (com Docker CLI): ~47MB
  • Mínima (stdio/HTTP apenas): ~6MB

As variáveis de ambiente são automaticamente repassadas e expandidas na sua configuração.

Monitoramento do Arquivo de Configuração

O MCP Hub monitora automaticamente o arquivo de configuração para alterações e atualiza o registro de acordo. Quando você modifica config.json, o hub irá:

  • Adicionar novos servidores: Iniciar automaticamente quaisquer servidores MCP recém-adicionados
  • Remover servidores: Parar servidores removidos da configuração ou desabilitados
  • Recarregar servidores: Reiniciar servidores cuja configuração foi alterada
  • Atualizar registro: Manter o registro de ferramentas sincronizado com os servidores ativos

Como Funciona

O monitor usa fsnotify para observar o arquivo de configuração para eventos de escrita. Quando alterações são detectadas:

  1. A nova configuração é carregada e validada
  2. As alterações são comparadas com a configuração anterior
  3. Ações apropriadas são tomadas (iniciar/parar/recarregar servidores)
  4. O registro é atualizado automaticamente
  5. As alterações são registradas para visibilidade

Debounce

Para evitar processar alterações rápidas e sucessivas (ex.: quando editores escrevem múltiplas vezes), o monitor inclui um atraso de debounce de 500ms. Isso garante que a configuração seja recarregada apenas uma vez após você terminar de editar.

Exemplo

# Start mcp-hub
./mcp-hub --config=config.json

# In another terminal, edit config.json
vim config.json

# The hub will automatically detect changes and log:
# "config file changed, reloading..."
# "adding server: new-server"
# "loaded MCP server: new-server (stdio transport)"

Tratamento de Erros

Se a nova configuração contiver erros:

  • JSON inválido: As alterações são rejeitadas, o hub continua com a configuração anterior
  • Campos obrigatórios ausentes: As alterações são rejeitadas com erro de validação
  • Falhas na inicialização do servidor: Registradas como avisos, outros servidores continuam executando