{"url":"https://runzos.com/como-configurar-servidor-mcp-docker-vps/","slug":"como-configurar-servidor-mcp-docker-vps","contentType":"artigo","intent":null,"title":"Referência MCP privada com Docker em VPS: guia prático","metaDescription":"Monte uma referência MCP privada com Docker em VPS, token, logs e validação local segura. Não é integração pronta com Claude, n8n nem ambiente de produção.","publishedAt":"2026-09-01T11:07:19.000Z","updatedAt":"2026-09-01T11:07:19.000Z","contentText":"Esta referência mostra como montar um servidor MCP privado, de leitura, com Docker em uma VPS. Você precisa de VPS Linux administrada, SSH, Docker com Compose e um token aleatório. O custo depende da VPS e do domínio, portanto não é estimado aqui. O tempo também não foi medido. O exemplo não é produção nem integração pronta com Claude ou n8n. Um servidor MCP conecta clientes de IA a dados, ferramentas e workflows externos. Ele não transforma um modelo em agente confiável. Em uma VPS, entram rede, autenticação, segredos, logs e recuperação. Para uma integração local simples, stdio costuma ter menos risco. Para uma tool persistente e remota, Docker e VPS podem fazer sentido se alguém assumir essa operação.12 A ideia deste guia é a Fronteira de Ação. Cada tool deve explicitar o que o agente pode fazer, com qual identidade, em quais dados e com qual registro. A VPS compra controle operacional. Ela não compra autonomia nem segurança automática. MCP não é um agente: onde ele entra O Model Context Protocol é um protocolo aberto para ligar aplicações de IA a fontes externas de dados, ferramentas e workflows. Ele usa mensagens JSON-RPC em UTF-8. O cliente descobre uma tool, entende seu schema e pede que o servidor a execute.111 A arquitetura mínima separa responsabilidades: cliente compatível → proxy e HTTPS → autenticação → servidor MCP → allowlist e schema → API ou dado → log Claude Code, ou outro cliente compatível, decide chamar uma ferramenta. O servidor oferece a ferramenta. A API, banco ou workflow executa apenas o trabalho permitido. Um proxy entrega HTTPS, mas não substitui escopo, validação ou auditoria. stdio local ou HTTP remoto A especificação MCP define stdio e Streamable HTTP como transportes padrão. stdio liga processos locais pela entrada e saída padrão. Streamable HTTP atende cliente e servidor remotos. Publicar HTTP muda a responsabilidade sobre rede e autorização.2 Critério stdio local Streamable HTTP em VPS Alcance Cliente e processo na mesma máquina. Cliente e servidor podem ficar separados. Exposição Não publica endpoint. Exige proxy, TLS, firewall e autenticação. Operação Menos componentes para atualizar. Inclui domínio, containers, logs e restore. Cenário Teste, uso individual e tool local. Automação persistente com responsável operacional. Comece com stdio quando estiver validando uma tool, quando há um único usuário ou quando webhook e API existentes já resolvem a integração. HTTP remoto é justificável quando a tool precisa sobreviver ao notebook ou atender cliente remoto. A documentação do MCP diferencia stdio local de fluxos OAuth para servidores HTTP remotos.3 Referência MCP privada com Docker O exemplo abaixo é didático. Ele expõe uma única tool de leitura, status_operacional, e fica acessível somente em 127.0.0.1 na VPS. Ele serve para revisar Docker, secret, autorização e logs antes de conectar uma API real. Não é servidor de produção, não inclui proxy e não configura Claude Code ou n8n. 1. Crie a pasta e o secret fora do Git Crie uma pasta restrita. Guarde o token em cofre apropriado e não o cole em Git, logs ou capturas de tela. mkdir -p ~/mcp-status/secretscd ~/mcp-statusumask 077openssl rand -hex 32 > secrets/mcp_token.txtprintf \"secrets/\\n\" > .gitignore O Compose permite conceder secrets explicitamente aos serviços. Para aplicações que suportam essa leitura, a documentação do Docker recomenda secrets em vez de variável de ambiente para dados sensíveis.7 2. Salve o servidor de leitura Crie server.py. O código não acessa banco, shell, ERP nem API. Essa limitação mantém a Fronteira de Ação pequena. import jsonfrom http.server import BaseHTTPRequestHandler, ThreadingHTTPServerTOKEN_PATH = \"/run/secrets/mcp_token\"with open(TOKEN_PATH, encoding=\"utf-8\") as secret_file: TOKEN = secret_file.read().strip()TOOLS = [{ \"name\": \"status_operacional\", \"description\": \"Retorna o estado não sensível da referência MCP.\", \"inputSchema\": {\"type\": \"object\", \"properties\": {}, \"additionalProperties\": False},}]def response(request_id, result=None, error=None): body = {\"jsonrpc\": \"2.0\", \"id\": request_id} body[\"error\" if error else \"result\"] = error if error else result return bodyclass MCPHandler(BaseHTTPRequestHandler): def log_message(self, fmt, *args): print(\"mcp_http\", self.client_address[0], fmt % args, flush=True) def do_POST(self): if self.path != \"/mcp\": self.send_error(404) return if self.headers.get(\"Authorization\") != f\"Bearer {TOKEN}\": self._send(401, {\"error\": \"unauthorized\"}) return try: payload = json.loads(self.rfile.read(int(self.headers[\"Content-Length\"]))) request_id = payload.get(\"id\") method = payload[\"method\"] except (KeyError, ValueError, json.JSONDecodeError): self._send(400, response(None, error={\"code\": -32600, \"message\": \"Invalid Request\"})) return if method == \"initialize\": result = {\"protocolVersion\": payload.get(\"params\", {}).get(\"protocolVersion\", \"2025-11-25\"), \"capabilities\": {\"tools\": {}}, \"serverInfo\": {\"name\": \"mcp-status\", \"version\": \"0.1.0\"}} self._send(200, response(request_id, result)) elif method == \"tools/list\": self._send(200, response(request_id, {\"tools\": TOOLS})) elif method == \"tools/call\" and payload.get(\"params\", {}).get(\"name\") == \"status_operacional\": self._send(200, response(request_id, {\"content\": [{\"type\": \"text\", \"text\": \"status=ok; escopo=leitura\"}]})) else: self._send(200, response(request_id, error={\"code\": -32601, \"message\": \"Method not found\"})) def _send(self, status, body): raw = json.dumps(body).encode(\"utf-8\") self.send_response(status) self.send_header(\"Content-Type\", \"application/json\") self.send_header(\"Content-Length\", str(len(raw))) self.end_headers() self.wfile.write(raw)ThreadingHTTPServer((\"0.0.0.0\", 8080), MCPHandler).serve_forever() Crie Dockerfile no mesmo diretório: FROM python:3.12-alpineWORKDIR /appCOPY server.py /app/server.pyUSER 65534CMD [\"python\", \"/app/server.py\"] 3. Use Compose com bind local Salve como compose.yaml. O bind 127.0.0.1:8080:8080 impede acesso público direto durante a referência. services: mcp-server: build: . restart: unless-stopped read_only: true tmpfs: - /tmp ports: - \"127.0.0.1:8080:8080\" secrets: - source: mcp_token target: mcp_token security_opt: - no-new-privileges:truesecrets: mcp_token: file: ./secrets/mcp_token.txt Suba o container e veja os logs: docker compose up -d --builddocker compose psdocker compose logs --tail=50 mcp-server Container em execução só confirma que o processo iniciou. Não prova backup, TLS ou autorização.8 4. Valide recusa e chamada permitida Leia o token apenas para montar o cabeçalho no shell atual. A primeira chamada é um POST JSON sem Authorization; pelo código, ela deve devolver 401. As seguintes usam o token lido em $TOKEN. Elas devem devolver JSON-RPC com status_operacional e status=ok; escopo=leitura. TOKEN=\"$(<secrets/mcp_token.txt)\"curl -i -X POST http://127.0.0.1:8080/mcp \\ -H 'Content-Type: application/json' \\ --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}'curl -sS -X POST http://127.0.0.1:8080/mcp \\ -H \"Authorization: Bearer ${TOKEN}\" \\ -H 'Content-Type: application/json' \\ --data '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}'curl -sS -X POST http://127.0.0.1:8080/mcp \\ -H \"Authorization: Bearer ${TOKEN}\" \\ -H 'Content-Type: application/json' \\ --data '{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"status_operacional\",\"arguments\":{}}}' Esses resultados são comportamentos esperados do exemplo, não alegações de teste do Runzos. Se a primeira resposta não for 401, pare e revise o controle de acesso. Se as chamadas autorizadas não retornarem os valores descritos, confira docker compose logs mcp-server. 5. Conecte sem abrir a porta pública Mantenha o serviço privado e abra um túnel SSH a partir da máquina cliente: ssh -N -L 8080:127.0.0.1:8080 usuario@IP_DA_SUA_VPS O endpoint local passa a ser http://127.0.0.1:8080/mcp. Use-o apenas em cliente compatível com Streamable HTTP e com a autenticação escolhida. A documentação do Claude Code descreve a conexão a servidores MCP, mas a sintaxe depende da versão instalada. Confirme a documentação atual antes de registrar comandos.10 No n8n, os papéis são diferentes: MCP Client Tool consome servidor externo; MCP Server Trigger expõe um workflow; recursos MCP da instância atendem outro cenário.6 Esta referência não entrega a configuração pronta de nenhum deles. Segurança e problemas comuns Prompt injection é LLM01:2025 para a OWASP. Docker, TLS e OAuth resolvem partes distintas do problema. Para ações de maior impacto, use menor privilégio e aprovação humana.9 Tool com allowlist e schema de entrada estrito. Credencial por serviço, com o menor escopo possível. Token fora do Git, Compose e logs. Proxy HTTPS e firewall antes de qualquer exposição pública. Timeout em chamadas externas e logs sem headers de autorização. Aprovação humana para ação destrutiva, financeira ou irreversível. Backup de configuração e restore testado antes de chamar o processo de recuperação. Sintoma Verificação segura Correção inicial Container reinicia docker compose logs mcp-server Confirme o arquivo do secret e a leitura pelo Docker. 401 com token Compare o token sem imprimi-lo. Recrie o secret, suba o serviço e reteste no host. Cliente não lista tools Faça tools/list pelo túnel. Corrija rede e autenticação antes de culpar o cliente. Porta pública Confira firewall e bind. Remova a regra pública e preserve 127.0.0.1. Quando MCP e VPS não são a resposta MCP padroniza como clientes de IA descobrem e chamam capacidades. Não substitui API, webhook ou n8n. Use API ou webhook quando a integração for determinística. Use n8n quando o workflow visual for o centro da operação. Use MCP quando a interoperabilidade entre cliente e tools for o problema real. Evite VPS quando o caso ainda for teste local, uma integração de uma etapa já estiver resolvida, a ação for perigosa sem aprovação ou ninguém assumir atualização e restore. Se a operação remota fizer sentido, compare rotas de VPS para automações com custo e requisitos atuais e uma alternativa como a Servla VPS para n8n. Preço, região, SLA e recursos exigem consulta na página vigente. FAQ O que é um servidor MCP? É um servidor que oferece contexto, recursos ou tools para cliente compatível com MCP. O protocolo define como capacidades são descobertas e chamadas.1 Posso rodar MCP em VPS? Sim, quando há acesso remoto ou automação persistente e alguém assume autenticação, proxy, TLS, firewall, secrets, logs, atualizações e restore.2 MCP substitui API ou webhook? Não. MCP atende interoperabilidade entre cliente de IA e tools. APIs e webhooks continuam adequados para contratos e eventos determinísticos. Como proteger MCP remoto? Reduza a Fronteira de Ação com tools específicas, schema estrito, credenciais limitadas, secrets fora do Git, logs sem segredo e aprovação humana para alto impacto.39 Conclusão A referência privada é uma forma de revisar os limites antes de conectar sistemas reais. Comece com tool de leitura, mantenha a porta local e amplie o catálogo somente depois de validar escopo, autorização e recuperação. Se decidir operar uma VPS, veja a rota de infraestrutura da Turbo Cloud e escolha conforme a stack, não por promessa de autonomia.","category":{"name":"IA","slug":"ia"},"tags":[{"name":"agentes de IA","slug":"agentes-de-ia"},{"name":"Claude","slug":"claude"},{"name":"Docker","slug":"docker"},{"name":"MCP","slug":"mcp"},{"name":"n8n","slug":"n8n"},{"name":"VPS","slug":"vps"}],"author":{"name":"Maicon Ramos","slug":"maicon_ramos"},"faq":[{"question":"O que é um servidor MCP?","answer":"É um servidor que oferece contexto, recursos ou tools para cliente compatível com MCP. O protocolo define como capacidades são descobertas e chamadas."},{"question":"Posso rodar MCP em VPS?","answer":"Sim, quando há acesso remoto ou automação persistente e alguém assume autenticação, proxy, TLS, firewall, secrets, logs, atualizações e restore."},{"question":"MCP substitui API ou webhook?","answer":"Não. MCP atende interoperabilidade entre cliente de IA e tools. APIs e webhooks continuam adequados para contratos e eventos determinísticos."},{"question":"Como proteger MCP remoto?","answer":"Reduza a Fronteira de Ação com tools específicas, schema estrito, credenciais limitadas, secrets fora do Git, logs sem segredo e aprovação humana para alto impacto."}]}