WU / DOCSMICROFRONTENDS UNIVERSAIS
PT

API MCP: bridge, relay e ferramentas

Referência do bridge do navegador, exportações Node do relay e das 18 ferramentas MCP publicadas pelo WU.

Três interfaces com responsabilidades diferentes

O WU integra um bridge no navegador e um servidor MCP no Node. O cliente de ferramentas fala JSON-RPC por stdio com o servidor; este usa um socket WebSocket autenticado para solicitar operações à página conectada.

Interface Ambiente Acesso
wu.mcp Navegador connect, disconnect, isConnected
wu-framework/mcp-server Node Configuração, listener, servidor e helpers de protocolo
Ferramentas wu_* Cliente MCP Catálogo publicado por tools/list

Importar wu-framework/mcp-server não inicia um listener nem assume stdin/stdout. Executar wu-mcp-server, ou chamar main(env), inicia o serviço. A receita executável de IA/MCP conecta todas as pontas com um navegador real e uma action local sem provedor LLM.

Bridge do navegador

import wu from 'wu-framework';

await wu.aiReady();
await wu.mcp.connect(relayUrl, { token: sessionToken });

// Consulta de estado; connect no espera el resultado de autenticación.
const connected = wu.mcp.isConnected();

// Al retirar la integración:
wu.mcp.disconnect();

relayUrl e sessionToken vêm de uma integração confiável do host. O token não deve fazer parte de URLs, bundles públicos ou estado persistido no store.

Método Parâmetros Retorno e ciclo de vida
connect(url?, options?) URL WebSocket; padrão ws://localhost:19100; token obrigatório, exceto com { insecure: true } em loopback Promise<void> de carregamento/início. Inicia o handshake após abrir o socket
disconnect() Nenhum void. Fecha o socket, interrompe reconexões e libera a inscrição e os interceptores do bridge
isConnected() Nenhum boolean. Verifica o socket aberto e o estado de autenticação conhecido pelo cliente

O bridge 4.0 autentica o relay com um handshake HMAC mútuo v2 sem enviar o token. Atualize bridge e relay juntos: relays anteriores ao 4.0 não entendem v2; o novo relay mantém v1 para bridges antigos. A ausência de token falha com WU_MCP_TOKEN_REQUIRED. O modo local exige { insecure: true } e WU_MCP_INSECURE=1 no relay. Fora de loopback exige wss://; uma URL insegura falha com WU_MCP_INSECURE_URL.

O bridge evita abrir outra conexão se já estiver conectando ou conectado. Uma desconexão acidental pode iniciar reconexões; disconnect() cancela essa intenção. Fechar o MCP não desmonta automaticamente todas as apps nem cancela promises arbitrárias de handlers já iniciados.

Configuração do servidor

import { loadConfig } from 'wu-framework/mcp-server';

const config = loadConfig(process.env);

loadConfig valida as variáveis e retorna um objeto imutável. Não imprime nem expõe o token a um cliente. Valores inválidos lançam um erro em vez de recorrer silenciosamente ao padrão.

Variável Padrão Contrato
WU_MCP_TOKEN Obrigatório String de 16–4096 bytes UTF-8
WU_MCP_HOST 127.0.0.1 Host do listener; sem espaços nem /
WU_MCP_PORT 19100 Inteiro 1–65535
WU_MCP_TIMEOUT 30000 Timeout por comando ao bridge, 50–300000 ms
WU_MCP_AUTH_TIMEOUT 5000 Tempo para autenticar, 50–60000 ms
WU_MCP_MAX_PAYLOAD 1048576 Limite WebSocket, 1024–16777216 bytes
WU_MCP_ORIGINS HTTP(S) loopback Lista de origens exatas separadas por vírgulas, sem caminho
WU_MCP_INSECURE Desativado Apenas 1 permite omitir o token. Se houver um token, ele continua obrigatório

O resultado contém host, port, timeout, authTimeout, maxPayload, token, insecure e allowedOrigins. Esta última propriedade é um Set ou null, não um array enviado ao navegador.

Origin é verificado durante o upgrade HTTP do WebSocket. Um Origin ausente ou não permitido recebe 403. Depois, o handshake de autenticação é concluído. O relay permite um bridge autenticado ativo por vez; conhecer o token não permite substituir silenciosamente uma sessão já ativa.

Listener Puente

import { Puente, loadConfig } from 'wu-framework/mcp-server';

const puente = new Puente(loadConfig(process.env));
await puente.ready();

// Estas consultas no requieren una página autenticada.
const address = puente.address();
const connected = puente.conectado();

// Cuando el host termine su sesión:
await puente.close();

A construção inicia o listener. ready() resolve quando pode escutar e rejeita em caso de falha de bind; não espera uma página. Você pode injetar { logger } como segundo argumento do construtor; ele deve expor error(...args). Os logs do serviço devem ir para stderr para não corromper o protocolo de stdout.

Método Retorno Falhas ou limites
ready() Promise<Puente> Rejeita se a inicialização falhar
address() Endereço do listener Não indica se há uma página conectada
conectado() boolean Leitura instantânea; a sessão pode fechar depois
enviar(command, params = {}) Promise<unknown> Rejeita sem bridge, por desconexão, timeout ou erro de resposta
close() Promise<void> Rejeita pendências, fecha sockets e listener; não reinicia o serviço

enviar recebe o nome do comando do bridge, por exemplo list_actions. O nome MCP externo correspondente é wu_list_actions. Não confunda os dois níveis.

Cada solicitação mantém um identificador, um timeout e o socket que deve responder. O relay remove a entrada pendente ao concluir ou falhar. close() libera as pendências e força o encerramento de sockets que não fecharam após o prazo de fechamento.

Construir ou iniciar o servidor MCP

import { main } from 'wu-framework/mcp-server';

// El entorno debe contener la configuración de autenticación.
await main(process.env);

main(env) cria o listener, aguarda sua inicialização, registra ferramentas e conecta o transporte stdio. Instala o tratamento de SIGINT/SIGTERM para fechar servidor e ponte. Resolve a inicialização e não retorna um objeto para gerenciar a sessão. Em um cliente externo, o executável equivalente é wu-mcp-server.

Para um host que administra explicitamente seu ciclo de vida:

Exportação Contrato
createMcpServer(puente, config) Retorna um servidor com connect(transport) e close(); registra as 18 ferramentas
createCommandRunner(puente) Retorna uma função (commandName, params?) => Promise<WuMcpToolResult> que adapta a resposta do bridge

O host fornece um transporte MCP compatível a connect. Ao fechar uma integração embarcada, feche tanto o servidor MCP quanto Puente; um não substitui o ciclo de vida do outro. A receita para download usa o executável empacotado e um cliente stdio mínimo, sem precisar importar classes privadas do SDK incluído no bundle.

Catálogo de ferramentas

Este é o catálogo registrado pelo servidor. Os parâmetros das ferramentas passam pelos schemas do relay; as permissões de execução são verificadas novamente no bridge ou em wu.ai.execute.

Ferramenta Argumentos Resultado principal Permissão da página
wu_conexion {} { puerto, host, requiere_token, app_conectada } Não precisa de página conectada
wu_list_actions {} { actions, count } Bridge autenticado; listar não concede execução
wu_execute_action { action, params? } { action, success, result?, reason? } executeActions e permissões da action
wu_status {} Framework, apps, chaves raiz, quantidade de ações/eventos Bridge autenticado; chaves raiz exigem readStore
wu_list_apps {} Descritores e estado das apps Bridge autenticado
wu_list_events { limit? } Eventos recentes com dados sensíveis ocultados readDiagnostics
wu_get_state { path? } { path, value } readStore
wu_set_state { path, value } { path, value, updated: true } writeStore
wu_emit_event { event, data? } { emitted, data } emitEvents; namespaces internos proibidos
wu_navigate { route } { navigated: route } emitEvents; writeStore para atualizar currentPath
wu_snapshot { appName? } App, árvore acessível e timestamp readDOM
wu_screenshot { selector?, quality? } Captura DOM, metadados ou erro readDOM
wu_click { selector?, text? } Elemento ativado ou erro modifyDOM
wu_type { selector, text, clear?, submit? } Resultado da escrita ou erro modifyDOM
wu_console { level?, limit? } Entradas do console com dados sensíveis ocultados readDiagnostics
wu_network { method?, status?, limit? } Metadados de rede filtrados readDiagnostics
wu_mount_app { appName, container? } App montada modifyDOM e o contrato normal de montagem
wu_unmount_app { appName } App desmontada modifyDOM

Detalhes dos parâmetros:

  • limit de eventos: inteiro de 1–200, padrão 20. O buffer circular contém no máximo 200 entradas.
  • limit de console e rede: inteiro de 1–500, padrão 50. O console aceita level: 'all' | 'log' | 'warn' | 'error', padrão all; a rede aceita status entre 100 e 599.
  • quality: 0–1, padrão 0.8 do bridge. O helper usa captura DOM/foreignObject e PNG por padrão; essa qualidade não modifica a compressão PNG nem garante a fidelidade de uma captura privilegiada.
  • clear e submit: false por padrão. Escrever pode emitir eventos do controle; submit: true pode acionar o envio de um formulário.
  • event: string de 1–200 caracteres. Os prefixos wu:, system: e app: são rejeitados no relay e no bridge.
  • path vazio na leitura seleciona a raiz; a escrita exige um path não vazio. Os dados de diagnóstico passam pela ocultação de dados sensíveis antes de sair do bridge.

wu_navigate emite shell:navigate: o shell deve tratar esse evento. O resultado isolado não prova que a página mudou, e o gate usado é emitEvents, não o flag IA navigate. wu_status retorna storeKeys: [] quando readStore está desativado.

JSON-RPC e resultados negativos

Após inicializar a sessão MCP, uma chamada a uma action tem esta forma:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "wu_execute_action",
    "arguments": { "action": "sum_local", "params": { "a": 2, "b": 3 } }
  }
}

O servidor entrega conteúdo textual em content[0].text. A função createCommandRunner marca isError quando o bridge retorna um campo error, ou quando o transporte falha. Um resultado de ação com success: false pode permanecer dentro de um envelope isError: false.

Verifique a camada MCP e a camada da action separadamente. Não interprete um HTTP correto, um socket aberto ou um envelope sem isError como prova de que o handler obteve autorização e terminou com sucesso.

tools/list lista as ferramentas da versão instalada. wu_list_actions lista outro catálogo: os handlers que a página registrou no subsistema de IA. Para executar uma action, ambos os registros e as permissões adequadas são necessários.

Helpers de autenticação e nomes

Exportação Assinatura Comportamento
isOriginAllowed (origin, allowedOrigins = null) => boolean Com null, permite apenas origens HTTP(S) exatas de loopback
tokenMatches (candidate, expectedDigest) => boolean Compara o SHA-256 do candidato com um digest esperado de 32 bytes usando timingSafeEqual
isReservedEvent (eventName) => boolean Detecta os três namespaces internos reservados

tokenMatches espera um digest, não o token em texto como segundo argumento. Um digest de tamanho incorreto pode causar um erro de comparação. Esses helpers não abrem sockets nem concedem permissões de domínio.

Cancelamento, segurança e testes

O protocolo desta implementação não propaga um cancelamento MCP até o handler de wu.ai.execute. A receita cancela uma espera e observa que o cálculo já iniciado continua. disconnect e close liberam transporte e pendências, mas não implementam compensação de efeitos.

Use ações próprias limitadas e um serviço autenticado para operações privilegiadas. As flags de IA do navegador são controles técnicos dessa página; não substituem autorização de negócio, idempotência nem um registro durável de operações.

node examples/mcp/local-relay.mjs
node scripts/verify-server-examples.mjs --mcp

O teste inclui handshake, token incorreto, ferramentas e ações reais, soma, schema inválido, permissões negadas, evento reservado, cancelamento observável e limpeza. O token é gerado em memória, todos os listeners são locais e não é necessário um provedor LLM. Você pode baixar as receitas completas ou revisar ações de IA e MCP executáveis.

CONSTRUA O WU CONOSCO

Encontrou um bug? Tem uma ideia?

Sua experiência melhora o WU. Conte o que falhou ou ajude a manter seu desenvolvimento.