MCP Hub
Um hub MCP leve para centralizar seus servidores MCP em um só lugar.
Documentação
MCP-Hub
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_PORTouPORT. 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 comotruepara 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 deurl)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:
npxoupython3ausentes 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 deimage)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 dehost: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
- Use o flag
-i: O hub executa contêineres comdocker run -ipara stdin/stdout interativos - Saída sem buffer: Garanta que as saídas do seu servidor estejam sem buffer (use
python -uouflush()) - Somente Stdin/Stdout: O protocolo MCP usa stdin para entrada e stdout para saída
- Stderr para logs: Use stderr para registro (visível nos logs do hub)
- Limpeza: Os contêineres são executados com
--rmpara 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
| Transporte | Caso de Uso | Prós | Contras |
|---|---|---|---|
| stdio | Servidores MCP locais com acesso direto | Rápido, baixa sobrecarga | Requer runtime (Node.js/Python) instalado |
| Docker | Servidores MCP isolados e reproduzíveis | Sem dependências de runtime, versionamento fácil | Sobrecarga ligeiramente maior, requer Docker |
| HTTP | Servidores MCP remotos/hospedados na nuvem | Escalável, pode ser balanceado por carga | Latê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:
- A nova configuração é carregada e validada
- As alterações são comparadas com a configuração anterior
- Ações apropriadas são tomadas (iniciar/parar/recarregar servidores)
- O registro é atualizado automaticamente
- 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