Modern Angular
WebMCP no Angular: como expor tools ao agente de IA do browser (e quando esperar)
O WebMCP deixa sua aplicação Angular entregar tools tipadas para um agente de IA do browser, em vez de deixar o agente clicar pelo DOM. O Angular já traz um suporte experimental atrás de provideExperimentalWebMcpTools. Desde 2026-06-01 o ponto de entrada saiu de navigator para document.modelContext, então o guia que vale agora está em next.angular.dev/ai/webmcp, e não na doc estável.
O que o WebMCP muda de verdade
Um agente de IA que automatiza seu app costuma operar a UI: ele lê o DOM, acha um botão, clica, preenche um campo e torce para o layout não ter mudado. O WebMCP inverte isso. A spec descreve a ideia como deixar o desenvolvedor expor funcionalidades da aplicação web, sejam funções JavaScript ou elementos HTML <form>, como tools com descrições em linguagem natural e schemas estruturados para o agente consumir. Seu app declara uma tool findOrder com um schema de entrada; o agente chama pelo nome e recebe dados estruturados de volta. Sem adivinhar seletor, sem clique sintético.
Leia o status antes de ler a API. O WebMCP é um draft de Community Group do W3C, do Web Machine Learning CG. Isso é um relatório em rascunho, não um W3C Standard e nem está na Standards Track. O formato ainda pode mudar debaixo de você.
Essa é uma camada diferente do Angular CLI MCP server, que entrega contexto do projeto para um assistente enquanto você escreve Angular na sua máquina. Aquele ajuda a gerar código. O WebMCP é runtime: é o seu app publicado expondo capacidades para qualquer agente que o usuário final esteja rodando. O raio de impacto é a aplicação em produção, não o editor, e é exatamente por isso que o resto importa.
Como o Angular liga isso
São quatro lugares para registrar uma tool, e eles correspondem a quanto tempo a tool deve viver. Escolha o escopo mais estreito que cobre a capacidade.
No bootstrap, o provideExperimentalWebMcpTools registra tools para o app inteiro. Cada tool carrega um name, uma description, um inputSchema em JSON Schema e um callback execute que roda dentro de um injection context, então consegue dar inject em services direto.
No nível da rota você passa o mesmo provider no providers da rota, e a tool só existe enquanto aquela rota estiver ativa. Para isso valer, você precisa do withExperimentalAutoCleanupInjectors no provideRouter; sem ele, as tools da rota seguem registradas depois que você navega para fora. Um aviso honesto: essa configuração recomendada tem hoje um bug aberto. Providers de rota com withExperimentalAutoCleanupInjectors podem lançar InvalidStateError: Duplicate tool name quando você volta para a rota várias vezes (issue #68899, aberta em 2026-06-02). Se você fizer um spike no caminho da rota, entre e saia algumas vezes e fique de olho.
Dentro de um service, o declareExperimentalWebMcpTool registra uma tool a partir de um injection context e a remove sozinho quando esse contexto é destruído. Esse é o lugar natural quando a tool pertence a um service de feature, e não a uma rota.
Para formulários, o provideExperimentalWebMcpForms com a opção experimentalWebMcpTool no form() transforma um Signal Form em tool. O Angular infere o JSON schema a partir dos valores iniciais do modelo do formulário e liga a validação e o submit, então o agente enxerga os erros de campo e consegue se corrigir em vez de mandar lixo. Três restrições vêm junto com essa inferência: o modelo precisa de valores iniciais concretos ('', 0, false, nunca null ou undefined), arrays precisam de pelo menos um elemento para o formato do item ser conhecido, e validadores assíncronos não rodam durante o submit do agente. Aprofundo forms como tools em Transformando Signal Forms em tools de agente de IA.
import { Service, inject, provideExperimentalWebMcpTools } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppRoot } from './app-root';
import { Orders } from './orders';
bootstrapApplication(AppRoot, {
providers: [
provideExperimentalWebMcpTools([
{
name: 'findOrder',
description: 'Looks up an order by its number.',
inputSchema: {
type: 'object',
properties: { orderId: { type: 'string' } },
required: ['orderId'],
},
execute: ({ orderId }) => {
const orders = inject(Orders);
return { content: [{ type: 'text', text: orders.summary(orderId) }] };
},
},
]),
],
});// routes.ts
export const routes: Routes = [{
path: 'dashboard',
loadComponent: () => import('./dashboard').then((m) => m.Dashboard),
providers: [
provideExperimentalWebMcpTools([{
name: 'exportDashboardReports',
description: 'Exports the current dashboard analytics.',
inputSchema: { type: 'object', properties: {} },
execute: () => ({ content: [{ type: 'text', text: 'Export triggered.' }] }),
}]),
],
}];
// app.config.ts: sem isto, as tools da rota seguem ativas depois de navegar
provideRouter(routes, withExperimentalAutoCleanupInjectors());// provideExperimentalWebMcpForms() precisa estar nos seus providers
readonly model = signal({ firstName: '', lastName: '' });
readonly userForm = form(this.model,
(f) => {
required(f.firstName, { message: 'First name is mandatory.' });
required(f.lastName, { message: 'Last name is mandatory.' });
},
{
experimentalWebMcpTool: { name: 'registerUser', description: 'Registers a new user.' },
submission: { action: async (formValue) => { /* ... */ } },
},
);Dá para rodar isso hoje?
Antes de desenhar tools, veja em que status você está construindo. O suporte a WebMCP chegou com o v22, mas ainda é uma API experimental, e é por isso que o guia dele mora em next.angular.dev e não na doc estável do angular.dev.
O ponto de entrada também acabou de mudar. Ele ficava pendurado no navigator; desde 2026-06-01 é o document.modelContext, depois que a issue #68947 foi concluída e o PR #68961 entrou. Até isso assentar entre os consumidores, faça feature detection nos dois: const modelContext = document.modelContext || navigator.modelContext;.
Do lado do consumidor, desconfie das demos. O WebMCP é um draft de CG, e eu não consigo te apontar um browser ou agente publicado que consuma document.modelContext a partir de uma fonte primária que eu citaria. Então você testa o registro sem esperar por isso: o guia sugere o pacote @mcp-b/webmcp-polyfill como mock para testes unitários, o que deixa você afirmar que suas tools registram e que o execute devolve o que você espera.
O time do Angular é direto sobre tudo isso. Nas palavras deles: "The WebMCP spec is very early in its lifecycle and is undergoing frequent changes. As such, WebMCP support in Angular is currently experimental. APIs are subject to change even outside of major versions." Leia isso assim: um bump de minor pode renomear aquilo que você publicou.
A superfície que você está expondo
Cada tool que você registra é mais uma coisa que um agente consegue disparar no seu app sem um humano clicar. Essa frase é o modelo de ameaça inteiro. Trate a lista de tools do jeito que você trata endpoints de API pública, porque na prática é o que ela é.
A spec atual registra tools por document.modelContext.registerTool(tool, { signal, exposedTo }). A opção exposedTo limita quais origens podem chamar uma tool, e um AbortSignal deixa você derrubar uma tool. Use por padrão o exposedTo mais estreito que você consiga justificar, o mesmo instinto que você levaria para o CORS.
Não confie na entrada. A doc do Angular é explícita: "Angular does not provide any implicit validation that the inputs provided by an agent actually match the defined JSON schema. Consider explicitly validating arguments to the execute function before using them to ensure reliability." O schema documenta a tool; ele não impõe nada. Um agente sob prompt injection pode entregar ao seu execute o que uma página maliciosa convenceu ele a passar, então valide os argumentos logo no topo do execute e aborte em qualquer coisa que você não esperava.
Nomes de tool são um namespace, e um registro duplicado lança erro. Esse também é o mecanismo por trás do bug de autocleanup lá de cima: uma tool de rota antiga que nunca foi removida colide com a nova na próxima visita.
Onde eu fico: eu me recusaria a registrar uma tool que altera dado real sem confirmação nenhuma, e exigiria que todo execute que mexe em dinheiro, identidade ou ações destrutivas validasse as próprias entradas e reverificasse a autorização no servidor, exatamente como se a chamada viesse de um cliente não confiável. Porque vem.
Onde eu faria um spike e onde eu esperaria
Eu faria um spike de WebMCP numa ferramenta interna ou numa rota de baixo risco, atrás de uma flag, para aprender o desenho de tools e os schemas de entrada. Esse investimento sobrevive mesmo que a API mude de nome.
Eu esperaria em qualquer coisa voltada ao usuário em produção, em qualquer fluxo crítico ou regulado, e em qualquer ponto onde uma quebra no meio do ciclo seja cara de perseguir. Com o ponto de entrada ainda saindo de navigator para document.modelContext e a configuração de rota recomendada carregando um bug aberto de tool duplicada, o custo de tratar isso como estável é real, e ele é independente de a ideia ser boa. A ideia é boa. A superfície é que ainda não assentou.
| Cenário | Spike ou esperar | Por quê |
|---|---|---|
| Ferramenta interna de admin, com flag | Spike | Aprenda desenho de tool e schema onde a quebra é barata. |
| Lookup só-leitura numa rota menor | Spike | Raio de impacto pequeno, fácil de remover se a API mudar. |
| Tools com escopo de rota hoje | Spike, com cuidado | Fique de olho na race de tool duplicada da issue #68899 ao navegar repetidamente. |
| Ação voltada ao usuário em produção | Esperar | Mudanças na spec fora de major podem quebrar fluxos publicados. |
| Fluxo regulado ou de pagamento | Esperar | Tools expostas ampliam a superfície que um agente consegue disparar. |
Artefato para reaproveitar
Gate de spike para WebMCP
- Limite o spike a uma rota interna ou de baixo risco, atrás de uma flag.
- Faça feature detection do ponto de entrada:
document.modelContext || navigator.modelContext. - Se você der escopo de rota às tools, conte com a race de tool duplicada do
withExperimentalAutoCleanupInjectors(issue #68899) e teste navegação repetida. - Ajuste o
exposedTopara o conjunto mais estreito de origens de que a tool precisa. - Valide toda entrada do
executeem runtime; o JSON schema é documentação, não imposição. - Anote o que cada tool exposta deixa o agente disparar, e reverifique a autorização no servidor para qualquer coisa que altere dado.
- Recheque status e nomes de API a cada minor do Angular, não só nos majors.
Perguntas frequentes
O WebMCP é estável no Angular?
Não. O suporte do Angular é experimental e o time avisa que as APIs "are subject to change even outside of major versions." A spec por baixo é um draft de Community Group do W3C, não um padrão.
É `navigator.modelContext` ou `document.modelContext`?
Desde 2026-06-01 o ponto de entrada passou para document.modelContext (PR #68961). Faça feature detection dos dois com const modelContext = document.modelContext || navigator.modelContext; até a mudança assentar entre os consumidores.
Qual a diferença entre o WebMCP e o Angular CLI MCP server?
O Angular CLI MCP server é uma ferramenta de tempo de desenvolvimento: entrega contexto do projeto para um assistente enquanto você escreve código. O WebMCP é runtime: o seu app publicado expõe tools para o agente que roda no browser do usuário final. Camada diferente, superfície bem maior. Eu comparo as duas de frente em WebMCP vs Angular CLI MCP server.
Eu mesmo preciso validar as entradas do agente?
Sim. A doc afirma que o Angular "not provide any implicit validation that the inputs provided by an agent actually match the defined JSON schema." Valide os argumentos no início de todo execute, e reverifique a autorização no servidor para qualquer coisa que altere dado.
De qual versão do Angular eu preciso?
O suporte a WebMCP chegou com o v22, mas ainda é uma API experimental. É por isso que o guia mora hoje em next.angular.dev/ai/webmcp.
Dá para testar tools WebMCP sem um browser que suporte isso?
Dá. O guia sugere o pacote @mcp-b/webmcp-polyfill como mock para testes unitários, então você consegue afirmar que as tools registram e que o execute devolve o que você espera.
Fontes consultadas
- https://next.angular.dev/ai/webmcp
- https://next.angular.dev/api/core/provideExperimentalWebMcpTools
- https://webmachinelearning.github.io/webmcp/
- https://github.com/webmachinelearning/webmcp
- https://angular.dev/ai/mcp
- https://angular.dev/guide/forms/signals/overview
- https://angular.dev/reference/releases
- https://github.com/angular/angular/issues/68899
- https://github.com/angular/angular/issues/68947
- https://github.com/angular/angular/pull/68961
Modern Angular Playbook
Este artigo é um play.
O Playbook do Angular Moderno reúne o diagnóstico, a matriz de adoção, onze jogadas e o plano de 30 dias. Grátis, em inglês e português.
Você recebe os dois PDFs por email, pela lista do Dojo IA.
André Ramosdisponível para vagas remotas, UTC−3Entre em contato →