Você provavelmente já viu um agente de IA “usando” um site: ele move o cursor, clica em botões, preenche campos e, muitas vezes, uma operação simples leva minutos.
Esse método tem até nome na documentação do Chrome: Actuation, e a definição é honesta: o ato de um agente simular cliques manuais com o mouse e a entrada de texto, como se fosse um usuário humano interagindo com a sua página. É exatamente esse problema que o WebMCP resolve.
O problema é que actuation é frágil. Basta um modal inesperado, um seletor que mudou de classe ou um botão carregado via JavaScript após o tempo esperado para que tudo quebre. É como contratar um assistente que só sabe operar o seu sistema decorando a posição dos pixels na tela. O WebMCP é a resposta do navegador a esse problema. Em vez do agente adivinhar a sua interface, o seu site declara explicitamente quais ações estão disponíveis.
Neste post, quero mostrar o que é, como ele se relaciona com o MCP que você já conhece e como começar a expor ferramentas no seu próprio site, com exemplos práticos das duas APIs disponíveis.
O que é o WebMCP
O WebMCP é uma proposta de padrão web que permite que sites ofereçam ferramentas estruturadas (tools) diretamente para agentes de IA que rodam no navegador. Em vez do agente interpretar a sua UI visualmente, ele descobre uma lista de funções que o seu site expõe, com schemas claros de entrada e saída.
Na prática, o WebMCP entrega três capacidades:
- Discovery: um jeito padronizado de registrar ferramentas que os agentes conseguem descobrir.
- JSON Schemas: definições explícitas de entrada e saída, que reduzem drasticamente a alucinação do modelo.
- State: um entendimento compartilhado do contexto atual da página.
Um detalhe importante para já tirar do caminho: as ferramentas do WebMCP são efêmeras. Citando a documentação:
Elas existem apenas enquanto a sua página estiver aberta. Quando o usuário sai do site ou fecha a aba, o agente não consegue mais acessar nem agir no site. Isso altera completamente o modelo mental e é o ponto central da comparação com o MCP tradicional.
WebMCP e MCP: complementares, não concorrentes
Se você acompanha o ecossistema de IA, já ouviu falar do MCP (Model Context Protocol), se ainda tem dúvidas sobre onde ele entra, vale ler antes o guia sobre rules, skills e MCP para desenvolvedores. É fácil olhar para o “WebMCP” e achar que é a mesma coisa rodando no browser. Não é bem assim e a própria documentação do Chrome trata os dois como complementares.
| Aspecto | MCP | WebMCP |
|---|---|---|
| Onde roda | Backend / sistemas externos | Frontend, no navegador |
| Ciclo de vida | Persistente (servidor/daemon) | Efêmero (vive enquanto a aba existe) |
| Conectividade | Global (desktop, mobile, cloud, web) | Apenas agentes de navegador |
| Modelo de UI | Headless / externo | Integrado ao DOM da página |
| Descoberta | Registro específico do agente | Registro no nível da página |
A documentação resume bem: pense no WebMCP como um conjunto de APIs “inspiradas no MCP”, e não como uma implementação direta do MCP em JavaScript. Ele deixa de fora conceitos do lado servidor (como resources).
A recomendação prática é combinar os dois: MCP para a lógica de negócio central e tarefas em background, e WebMCP para interações rápidas e contextuais no navegador, aproveitando que ele já tem acesso ao estado da página que o usuário está vendo.
As duas APIs do WebMCP
O WebMCP oferece dois caminhos para expor suas ferramentas. A escolha depende de quão dinâmica é a sua interface.
1. API Imperativa (JavaScript)
Para lógica customizada, você registra ferramentas via document.modelContext.registerTool(). É a abordagem mais flexível, ideal quando a ação não se reduz a um simples formulário.
2. API Declarativa (HTML)
Aqui está a parte que mais me empolga como pessoa de front-end: você transforma formulários HTML comuns em ferramentas só anotando atributos. O navegador lê o formulário e gera o JSON Schema automaticamente, mapeando cada campo para um parâmetro da ferramenta.
O registro mais básico é literalmente isto:
<form toolname="createSupportRequest"
tooldescription="Submits a request for customer support.">
</form>Code language: HTML, XML (xml)
Os atributos principais são:
toolname— o nome da ferramenta exposta ao agente.tooldescription— o que a ferramenta faz (o agente usa isso para decidir quando chamá-la).toolparamdescription— descrição de cada campo individual.toolautosubmit— permite que o agente submeta o formulário sem ação manual do usuário.
Atenção (gotcha): remover
toolnameoutooldescriptioncancela o registro da ferramenta por completo. Os dois são obrigatórios.
Veja um exemplo mais completo, um formulário de suporte com um campo de seleção:
<form toolname="supportRequestTool"
tooldescription="Submit a request for support."
action="/submit">
<label for="firstName">First Name</label>
<input type=text name=firstName>
<label for="lastName">Last Name</label>
<input type=text name=lastName>
<select name="select" required
toolparamdescription="Determines what team this request is routed to.">
<option value="Customer happiness team">Return my purchase.</option>
<option value="Distribution team">Check where my package is.</option>
<option value="Website support team">Get help on the website.</option>
</select>
<button type=submit>Submit</button>
</form>Code language: HTML, XML (xml)
A partir desse HTML, o navegador gera sozinho um JSON Schema com os campos como propriedades, transforma as options do <select> em um enum e marca os campos required. Você ganha uma ferramenta estruturada sem escrever uma linha de JavaScript.
Quando o agente chama essa ferramenta, o navegador coloca o formulário em foco, preenche os campos e mantém o formulário visível ao usuário. Esse ponto é deliberado: o usuário acompanha o que está acontecendo. A própria spec define alguns recursos para reforçar isso, como as pseudo-classes CSS :tool-form-active e :tool-submit-active, que destacam visualmente o formulário em uso pelo agente.
Para lógica de validação, o SubmitEvent ganhou a propriedade agentInvoked (saber se foi o agente que disparou) e o método respondWith(), para devolver um resultado assíncrono:
<form toolautosubmit toolname="search_tool"
tooldescription="Search the web" action="/search">
<input type=text name=query>
</form>
<script>
document.querySelector("form").addEventListener("submit", (e) => {
e.preventDefault();
if (!myFormIsValid()) {
if (e.agentInvoked) { e.respondWith(myFormValidationErrorPromise) };
return;
}
if (e.agentInvoked) { e.respondWith(Promise.resolve("Search is done!")); }
});
</script>Code language: HTML, XML (xml)
Eventos de ciclo de vida
Além da validação no submit, a API declarativa emite eventos na window para você reagir quando um agente começa ou cancela o uso de uma ferramenta — útil para telemetria, feedback visual ou pausar animações:
window.addEventListener('toolactivated', ({ toolName }) => {
console.log(`the tool "${toolName}" execution was activated.`);
});
window.addEventListener('toolcancel', ({ toolName }) => {
console.log(`the tool "${toolName}" execution was cancelled.`);
});Code language: JavaScript (javascript)
Casos de uso: onde isso faz diferença
Tudo isso fica abstrato sem exemplos concretos. A documentação organiza os casos de uso em torno do conceito de Critical User Journey (CUJ), o caminho que o usuário percorre até o objetivo, mais o contexto necessário para chegar lá. Alguns cenários onde o WebMCP brilha:
- E-commerce:
search_products(productType, category, age),add_to_wishlist(),refine_search(priceRange),get_order_history(startdate, enddate). - Busca com filtros (ex.: imóveis):
search(max-price, location, features, rooms),apply_filters(transit, max_time, destination). - Reservas de hotel:
search_hotels(location, guests),filter_search_results(max_price, amenities). - Abertura de chamados/garantias:
start_claim_process(),populate_product_details(),describe_issue().
Um exemplo que ilustra bem o poder da API declarativa é o de um timesheet, algo que todo mundo odeia preencher manualmente. Veja como um formulário comum vira uma ferramenta que o agente preenche a partir de uma frase como “lancei 2 horas de desenvolvimento ontem”:
<form toolname="add-to-timesheet"
tooldescription="Report billing task and time to add to the timesheet."
toolautosubmit>
<fieldset>
<label for="date">Date</label>
<input name="date" type="datetime-local" toolparamdescription="Date of work.">
<label for="task_category">Task category</label>
<select id="task_category" name="task_category"
toolparamdescription="Type of task completed per time block">
<option value="admin">Admin</option>
<option value="billing">Billing</option>
<option value="client">Client meetings or communication</option>
<option value="development">Development</option>
</select>
<label for="minutes_worked">Minutes working on the task</label>
<input type="number" id="minutes_worked" name="minutes_worked" min="30" max="600"
toolparamdescription="Minutes worked on this date and task, with a minimum of 30 and maximum of 600."
placeholder="60">
<label for="work_details">Details</label>
<input name="work_details"
toolparamdescription="Additional details of work completed, for managerial review.">
</fieldset>
<button type="submit">Update timesheet</button>
</form>Code language: HTML, XML (xml)
O dado que justifica o investimento: segundo a documentação, autofill, quando bem implementado, pode reduzir a taxa de abandono de formulários em 75%. Agora imagine isso aplicado por um agente que entende a intenção do usuário, e não só completa campos repetidos.
Um princípio de design importante: deixe o agente pedir esclarecimentos ao usuário quando faltarem informações, em vez de inventar valores. E para resultados complexos (uma lista filtrada, um mapa com pins), retorne respostas estruturadas, não um blob de texto.
Boas práticas: desenhando ferramentas para agentes
Expor ferramentas é fácil. Expor ferramentas que um modelo de linguagem entende e usa corretamente é o trabalho de verdade. A documentação traz várias recomendações que valem ouro:
- Uma ferramenta, uma função. Evite ferramentas que se sobrepõem; isso confunde o modelo na hora de escolher.
- Verbos que diferenciam executar de iniciar. Prefira
create-event(que age agora) astart-event-creation-process(que só redireciona para um formulário). - Aceite a entrada bruta do usuário. Não force o modelo a fazer contas ou conversões; receba a string como o usuário falou.
- Nomes semânticos em vez de IDs.
shipping="Express"é muito melhor queshipping_id=1para o modelo raciocinar. - Valide rigorosamente no código, frouxamente no
schema. As restrições do schema não são garantidas — o modelo pode mandar qualquer coisa, então a validação real precisa estar no seu código. - Mensagens de erro descritivas. Um bom erro permite que o agente se autocorrija e tente novamente, em vez de travar.
Há também um detalhe de orçamento de contexto que muita gente esquece: cada ferramenta ocupa espaço na janela de contexto do modelo. A documentação sugere limites (sujeitos a mudança), como: descrições de ferramenta de até 500 caracteres, descrições de parâmetro de até 150 caracteres, nomes de até 30 caracteres e saída individual de ferramenta de até 1,5K caracteres. Menos é mais.
Por fim, vale internalizar o conceito de Evaluation-Driven Development: um processo repetível e testável para melhorar as saídas em pequenos passos, capturando regressões e alinhando o comportamento do modelo às expectativas do produto. Em vez de criar regras estreitas para tapar um bug específico de um modelo, prefira abstrair a ferramenta ou tornar campos opcionais com confirmação do usuário.
Segurança: o elefante na sala
Não dá para falar em dar ações executáveis a um agente de IA sem falar em segurança. O risco principal aqui é o prompt injection indireto — instruções maliciosas escondidas em conteúdo que o modelo lê e acaba obedecendo. A documentação é direta ao ponto: é impossível garantir segurança em um LLM.
O WebMCP foi desenhado com algumas barreiras importantes:
- Isolamento de origem obrigatório. O WebMCP só funciona em documentos com origem isolada. Ele é desativado se
document.domainfor definido ou se o headerOrigin-Agent-Cluster: ?0estiver presente. - Permissions Policy
tools. O padrão éself(apenas o documento top-level e same-origin). Iframes cross-origin ficam desativados a menos que você adicioneallow="tools". - Por padrão, ninguém de fora vê suas ferramentas. Outros sites e iframes cross-origin não conseguem observar nem executar as ferramentas que você expõe.
Para casos em que você precisa compartilhar ferramentas entre origens, a API imperativa oferece a opção exposedTo, junto de hints como untrustedContentHint (para dados de fontes não confiáveis, como conteúdo gerado por usuário) e readOnlyHint (para ferramentas que não modificam estado):
// https://partner.org
document.modelContext.registerTool({
name: 'my_shared_tool',
description: 'Shared across origins',
// ...
}, {
exposedTo: ['https://trusted.com', 'https://example.com']
});Code language: JavaScript (javascript)
A regra de bolso: só exponha para origens em que você confiaria a ponto de compartilhar dados do usuário (no caso de ferramentas read-only) ou de deixar agir em nome dele (no caso de ferramentas read-write).
Evals: testando um sistema probabilístico
Aqui entra uma mudança de mentalidade. Você não testa uma ferramenta de IA como testa um código determinístico. Uma mesma entrada pode gerar milhares de respostas diferentes. Por isso, o WebMCP introduz o conceito de evals — avaliações para sistemas generativos.
Vale ressaltar a própria documentação: continue escrevendo testes determinísticos clássicos para qualquer interação do sistema que não envolva o modelo. Os evals são para a fronteira onde o modelo decide algo.
Há quatro coisas que você quer validar:
- O modelo entende o propósito da ferramenta.
- Ele escolhe a ferramenta e os parâmetros adequados à intenção do usuário.
- Ele age sobre a informação retornada nas próximas chamadas.
- As jornadas completas (end-to-end) atingem o objetivo.
Um eval simples é basicamente um par de entrada e chamada esperada:
{
"messages": [ { "role": "user", "content": "I'd like a small pizza." } ],
"expectedCall": [
{ "functionName": "set_pizza_size", "arguments": { "size": "Small" } }
]
}Code language: JSON / JSON with Comments (json)
Quando algo dá errado, costuma cair em um destes padrões de falha — e cada um tem uma pista de onde investigar:
| Falha | Exemplo | Onde investigar |
|---|---|---|
| Ferramenta errada | chamar checkout em vez de addToCart | Clareza da description, do nome da função, sobreposição de schemas |
| Ordem errada | checkout antes de addToCart | Descrições sobrepostas; conferir se o state expõe as ferramentas certas |
| Argumentos errados | addToCart com o produto errado | Definir valores de enum com descrições explícitas |
| Erro de saída | viewCart retorna o total em vez dos itens | Validar a lógica da tool e a clareza da saída para o LLM |
Para jornadas completas, os evals suportam aninhar passos ordered e unordered, porque às vezes a ordem importa (buscar antes de detalhar) e às vezes não (pesquisar dois produtos diferentes em paralelo):
{
"messages": [
{ "role": "user", "content": "I am looking to buy a black jacket and a pair of jeans." }
],
"expectedCall": [
{ "functionName": "navigate_to_category", "arguments": { "category": "clothes" } },
{
"unordered": [
{ "ordered": [
{ "functionName": "search_clothes", "arguments": { "query": "black jacket" } },
{ "functionName": "get_product_details", "arguments": { "productId": "JACKET002" } }
]},
{ "ordered": [
{ "functionName": "search_clothes", "arguments": { "query": "jeans" } },
{ "functionName": "get_product_details", "arguments": { "productId": "JEANS001" } }
]}
]
}
]
}Code language: JSON / JSON with Comments (json)
A documentação tem uma frase que resume bem por que isso importa: se um agente não consegue descobrir qual ferramenta chamar para um pedido como “quero uma pizza pequena”, ele não tem a menor chance numa jornada de usuário complexa. Vale também testar pedidos ambíguos (“quero todas as carnes na minha pizza”), não só os pedidos diretos.
Como testar hoje
O WebMCP está disponível como Origin Trial no Chrome 149+. Para experimentar localmente, ative a flag em chrome://flags/#enable-webmcp-testing, marque como Enabled e reinicie o navegador.
E tem novidade no DevTools 149 para quem quer depurar: há suporte experimental à WebMCP no painel Application, que permite inspecionar as ferramentas registradas e seus esquemas, executar ferramentas manualmente com parâmetros personalizados e acompanhar os eventos de invocação.
Para ligar, são duas flags: chrome://flags#devtools-webmcp-support e #enable-webmcp-testing. Há também a extensão Model Context Tool Inspector na Chrome Web Store para inspecionar ferramentas.

Neste novo painel, é possível executar as ferramentas de teste diretamente no Chrome DevTools. Selecionando as ferramentas disponíveis e visualizando os resultados diretamente no navegador.

Limitações que você precisa conhecer
Antes de sair empolgado, é honesto colocar as cartas na mesa. O WebMCP tem fronteiras claras:
- Não funciona em headless. Ele exige que uma aba do navegador esteja aberta. Não há suporte para rodar sem interface, o que faz sentido, já que as tools são efêmeras e vivem presas à aba.
- A descoberta depende da visita do usuário. O agente só vê suas ferramentas quando o usuário estiver no seu site. Não é um catálogo global que qualquer agente consulta a qualquer momento, para isso, o lugar é o MCP do lado do servidor.
- Interfaces complexas podem exigir refatoração. Nem toda UI se mapeia bem para ferramentas estruturadas; às vezes, você terá que repensar os fluxos.
- É uma proposta em discussão ativa. A spec está sujeita a mudanças. Frameworks já começam a se mexer (o Angular, por exemplo, tem suporte experimental), mas nada está cristalizado.
Nada disso invalida a tecnologia — só ajuda a calibrar a expectativa. WebMCP não substitui o MCP nem resolve tudo sozinho; ele cobre muito bem a parte “interação em tempo real com a página que o usuário está vendo”.
Conclusão
O WebMCP representa uma mudança de filosofia sobre a forma como sites e agentes conversam. Em vez do agente espiar a sua UI e torcer pelo melhor, o seu site assume o controle e declara, de forma estruturada e segura, exatamente o que pode ser feito. Para quem vem do front-end, o detalhe mais elegante é poder começar com a API declarativa: anotar um <form> que você já tem e, de repente, ele virou uma ferramenta para agentes.
Vale lembrar que isso é uma proposta em discussão ativa e sujeita a mudanças — não saia reescrevendo a aplicação inteira ainda. Mas vale muito entender o modelo agora, porque a direção está clara: a web está sendo preparada para ser usada não só por humanos, mas também por agentes que atuam em nome deles. E quanto mais cedo você entender como expor ações com segurança, melhor posicionado estará quando isso virar o novo normal.
Repositório oficial para acompanhar a evolução: webmachinelearning/webmcp. A documentação completa está em developer.chrome.com/docs/ai/webmcp.

Deixe um comentário