Dev Tools

O que é WebMCP? Model Context Protocol via SSE

Entenda o que é o WebMCP, como funciona o transporte SSE (Server-Sent Events) no Model Context Protocol e como criar um servidor WebMCP com Node.js.

05 de junho de 20267 min de leituraDevThru

Se você leu o nosso Guia sobre Model Context Protocol (MCP) e o nosso Tutorial de MCP Server com TypeScript, você já sabe como esse protocolo está revolucionando a integração de Inteligência Artificial localmente nas nossas IDEs favoritas, como o Cursor e o Claude Desktop.

Mas e se você quisesse conectar o seu agente de IA a um servidor remoto na nuvem? E se você quisesse criar uma aplicação baseada em navegador (Web App) que interage com agentes inteligentes usando o MCP, sem depender do sistema de arquivos local do usuário ou do terminal dele? É aqui que o WebMCP brilha.

Neste artigo, vamos explorar o conceito de WebMCP, compreender como funciona o transporte baseado em SSE (Server-Sent Events) e implementar passo a passo um servidor WebMCP remoto utilizando Node.js e TypeScript.

A Limitação do Standard I/O (stdio)

Por padrão, a maioria dos servidores MCP que configuramos localmente se comunica através do fluxo padrão de entrada e saída do sistema operacional (stdio). A IDE inicia o processo do servidor em background e se comunica com ele por meio de streams de texto.

Embora essa abordagem seja extremamente rápida, performática e segura para execuções locais, ela impõe barreiras físicas:

  • Isolamento de Máquina: A IA e o servidor MCP precisam estar no mesmo computador.
  • Incompatibilidade Web: Navegadores não possuem acesso direto para spawnar processos de sistema ou ler/escrever fluxos de stdio arbitrários por razões óbvias de sandbox e segurança.
  • Dificuldade de Compartilhamento: Se uma equipe deseja usar uma ferramenta customizada e centralizada (como um catálogo corporativo de microsserviços), cada desenvolvedor precisaria instalar e configurar o servidor MCP localmente em sua própria máquina.
💡 O WebMCP resolve isso: Em vez de se comunicar via terminal local, o cliente e o servidor MCP conversam através da rede de forma padronizada usando o protocolo HTTP e tecnologias web modernas.

A Magia do Server-Sent Events (SSE)

Para o transporte na Web, a especificação oficial do MCP adota a arquitetura de SSE (Server-Sent Events) associada a requisições HTTP POST tradicionais. Mas por que o SSE foi escolhido em vez de WebSockets ou polling simples?

O SSE é uma tecnologia nativa que permite ao servidor enviar notificações de mão única em tempo real para o cliente sobre uma conexão HTTP de longa duração. No fluxo de mensagens do WebMCP, o tráfego JSON-RPC 2.0 funciona da seguinte forma:

  1. Conexão Inicial: O cliente web (MCP Client) inicia uma conexão HTTP GET em um endpoint específico do servidor (por exemplo, /sse). O servidor responde mantendo a conexão aberta com o header Content-Type: text/event-stream.
  2. Event Stream (Servidor ➔ Cliente): Através dessa conexão aberta, o servidor pode enviar mensagens e respostas assíncronas para o cliente de forma contínua e em tempo real.
  3. Requisições HTTP POST (Cliente ➔ Servidor): Quando o cliente precisa enviar uma requisição ou comando para o servidor (como chamar uma ferramenta), ele faz uma requisição HTTP POST comum para um endpoint separado (geralmente chamado de /messages), passando a payload no corpo.

Essa arquitetura assíncrona desacoplada simplifica drasticamente o roteamento em firewalls e proxies reversos corporativos se comparado ao protocolo WebSockets, operando totalmente sob HTTPS padrão.

Tutorial Prático: Construindo um Servidor WebMCP com SSE

Vamos colocar a mão na massa e criar um servidor WebMCP funcional utilizando o SDK oficial da Anthropic (@modelcontextprotocol/sdk) e o Express no Node.js.

1. Inicialização do Projeto

Crie um diretório para o projeto e instale as dependências necessárias. Utilizaremos o SDK oficial e o Express, juntamente com o Zod para validação e suporte a TypeScript:

npm init -y
npm install @modelcontextprotocol/sdk express cors zod
npm install --save-dev typescript @types/express @types/node @types/cors ts-node

2. Escrevendo o Servidor Express com SSE

Crie um arquivo chamado server.ts. Neste arquivo, configuramos a instância clássica de Server do MCP e mapeamos os endpoints HTTP necessários para configurar o SSEServerTransport:

import express from "express";
import cors from "cors";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
  ListToolsRequestSchema,
  CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";

const app = express();
app.use(cors());
app.use(express.json());

// 1. Instanciando o Servidor MCP
const mcpServer = new Server(
  {
    name: "webmcp-demo-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {}, // Habilitando suporte a ferramentas dinâmicas
    },
  }
);

// 2. Definindo uma ferramenta para consultar informações
const CONSULTAR_DOC_TOOL = {
  name: "consultar_documentacao",
  description: "Busca informações técnicas na base interna corporativa.",
  inputSchema: {
    type: "object",
    properties: {
      termo: {
        type: "string",
        description: "Termo de busca (ex: 'deploy', 'auth', 'database')",
      },
    },
    required: ["termo"],
  },
};

// 3. Registrando handlers do MCP
mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [CONSULTAR_DOC_TOOL],
  };
});

mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "consultar_documentacao") {
    const termo = z.string().parse(args?.termo);
    let resposta = `Nenhuma documentação encontrada para: ${termo}`;

    if (termo.toLowerCase().includes("deploy")) {
      resposta = "Procedimento de Deploy: Execute 'npm run build' e depois faça o push na branch developer.";
    } else if (termo.toLowerCase().includes("auth")) {
      resposta = "Autenticação: Utilize os tokens JWT gerados via cabeçalho Authorization: Bearer.";
    }

    return {
      content: [{ type: "text", text: resposta }],
    };
  }

  throw new Error("Ferramenta não encontrada");
});

// 4. Mapeando sessões ativas do SSE
const activeTransports = new Map<string, SSEServerTransport>();

app.get("/sse", async (req, res) => {
  console.log("🔌 Novo cliente iniciando conexão SSE");
  
  // Criamos o transporte SSE apontando para a rota de mensagens HTTP POST
  const transport = new SSEServerTransport("/messages", res);
  
  // Salvamos o transporte associado ao ID da conexão
  const sessionId = transport.sessionId;
  activeTransports.set(sessionId, transport);
  
  // Conectamos o transporte ao nosso servidor MCP
  await mcpServer.connect(transport);
  
  // Removemos o transporte do cache quando a conexão é encerrada
  req.on("close", () => {
    console.log(`❌ Conexão SSE encerrada para a sessão ${sessionId}`);
    activeTransports.delete(sessionId);
  });
});

app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  const transport = activeTransports.get(sessionId);

  if (!transport) {
    res.status(404).send("Sessão ativa não encontrada.");
    return;
  }

  // Delega a leitura e parse do payload JSON-RPC para o SDK do MCP resolver
  await transport.handleMessage(req, res);
});

const PORT = 3002;
app.listen(PORT, () => {
  console.log(`🚀 Servidor WebMCP rodando em http://localhost:${PORT}`);
  console.log(`  -> Conexão SSE: http://localhost:${PORT}/sse`);
});
⚠️ Atenção ao SessionId: Note que o SSEServerTransport gera dinamicamente um identificador único de sessão (sessionId). O cliente web precisará passar este ID como query string ao fazer requisições POST para a rota de mensagens (ex: /messages?sessionId=xpto), permitindo que o servidor direcione a resposta para o túnel SSE correto.

Consumindo o Servidor WebMCP

Agora que você tem um servidor WebMCP expondo endpoints HTTP, você pode conectá-lo a clientes. No ecossistema moderno, existem duas formas principais:

1. Configurando em Ferramentas Locais

O próprio Claude Desktop e IDEs como o Cursor aceitam conexões SSE nativamente em seus arquivos de configuração. Veja um exemplo de configuração no claude_desktop_config.json:


{
  "mcpServers": {
    "meu-servidor-web-mcp": {
      "url": "http://localhost:3002/sse"
    }
  }
}

2. Integrando diretamente em Web Apps

Se você estiver desenvolvendo o seu próprio chatbot ou painel web, você pode utilizar o SDK de cliente no navegador. Veja como se conectar usando Vanilla JavaScript/TypeScript no client-side:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";

const client = new Client({
  name: "meu-web-app-client",
  version: "1.0.0"
}, {
  capabilities: {}
});

const transport = new SSEClientTransport(new URL("http://localhost:3002/sse"));
await client.connect(transport);

// A partir daqui, o cliente web está conectado de forma bidirecional!
const tools = await client.listTools();
console.log("Ferramentas disponíveis remotamente:", tools);

Conclusão

O WebMCP desamarra o Model Context Protocol do ambiente do computador local e o escala para toda a Web. Seja centralizando ferramentas e utilitários da sua equipe de engenharia em um único servidor remoto ou criando aplicações e assistentes de IA interativos que rodam inteiramente no navegador, o uso de SSE no MCP abre portas gigantescas para a computação e automação por agentes em 2026.

Que tal testar a criação de ferramentas no seu próprio servidor WebMCP para formatar dados em tempo real ou analisar payloads corporativos?

🛠️ Experimente na prática

Use nossas ferramentas online gratuitas — sem cadastro, direto no navegador.

WebMCPMCPModel Context ProtocolSSENext.jsNode.jsIA