Primera tool: registerTool con inputSchema y execute
Una tool de WebMCP es un objeto con nombre, descripción, esquema de entrada y una función execute. La página la registra; el agente las lista con getTools y la llama con executeTool. En esta clase lees la tool de búsqueda del kit, la llamas como la llamaría un agente y registras la tuya.
1Los campos de una tool y las reglas de nombre y descripción
2inputSchema en JSON Schema, cerrado y descrito
3executeTool: entra un objeto, sale texto JSON
4Tu primera tool en extras.mjs
Objetivo: registrar una tool con nombre, descripción, inputSchema y execute, y llamarla como la llamaría un agente, viendo el resultado y la pantalla.
01 · De la definición al resultado
Haz clic en cada paso.
Haz clic en cada bloque del diagrama para ver qué hace.
Spec del 16/10/2026 y Chromium 156.0.8078.4. Si cambia, la clase 1 avisa: confirma la fecha antes.
02 · La tool de búsqueda del kit
Fragmento de kit/pagina/ferramentas.mjs. La misma agenda.buscar atiende el formulario y la tool.
Fragmento · kit/pagina/ferramentas.mjs
{
name: 'buscar_oficinas',
title: 'Buscar oficinas',
description: 'Lista as oficinas da agenda por tema. Só lê: não reserva nada. Use apenasComVaga=true para ver só as que ainda têm vaga.',
inputSchema: {
type: 'object',
properties: {
tema: { type: 'string', enum: TEMAS, description: 'Tema da oficina.' },
apenasComVaga: { type: 'boolean', description: 'true = só oficinas com vaga.' }
},
additionalProperties: false
},
annotations: { readOnlyHint: true },
execute: comErroUtil(async input => {
const lista = agenda.buscar(input);
ui.mostrarResultados(lista, input); // a pessoa vê o mesmo que o agente recebeu
return { total: lista.length, oficinas: lista };
})
}
Fragmento · registrar con detección (ferramentas.mjs)
const mc = document.modelContext; // nombre actual (16/10/2026)
if (!mc || typeof mc.registerTool !== 'function') {
aviso?.('Este navegador não expõe WebMCP. Tudo funciona pelo formulário.');
return { modo: 'sem', registradas: 0 };
}
const pagina = new AbortController();
addEventListener('pagehide', () => pagina.abort(), { once: true });
await registrar(mc, defs, pagina.signal);
03 · Llamar como lo llamaría un agente
listar.mjs hace getTools; executar.mjs hace executeTool con el objeto que le pasas y muestra la pantalla después.
"resultado (string)": el navegador devuelve texto JSON, como manda la spec. La lista de la pantalla también quedó con 1 taller.
== Chromium 156.0.8078.4 (Playwright) · modo: nativo
navigator.modelContext (nome antigo): undefined
entrada em texto JSON em vez de objeto: TypeError
execute que lança: UnknownError: Tool was executed but the invocation failed. For example, the script function threw an error
== Chromium 156.0.8078.4 (Playwright) · modo: polyfill
navigator.modelContext (nome antigo): undefined
entrada em texto JSON em vez de objeto: TypeError
execute que lança: UnknownError: Tool execution failed
Los ejemplos antiguos pasaban JSON.stringify(input) para esquivar una implementación de septiembre: hoy da TypeError en los dos. Y el motivo de un throw no le llega al agente (UnknownError genérico). Por eso el kit devuelve { erro } como dato (clase 7).
04 · Tu primera herramienta
El bloque copia la página a un ensayo, escribe un extras.mjs con contar_vagas y lo verifica. Para que valga en el kit, pega la misma lista en kit/pagina/extras.mjs.
Terminal · ensayo con contar_vagas
cd ~/projetos/formacao-webmcp-site-v72/kit
E=${TMPDIR:-/tmp}/ensaio-webmcp-site/a3; rm -rf $E; mkdir -p $E; cp -r pagina/. $E/
cat > $E/extras.mjs <<'FIM'
export function extras(agenda) {
return [{
name: 'contar_vagas',
description: 'Soma as vagas livres das oficinas de um tema. Só lê: não reserva nada.',
inputSchema: {
type: 'object',
properties: { tema: { type: 'string', enum: ['html', 'javascript', 'webmcp', 'mcp'], description: 'Tema da oficina.' } },
required: ['tema'],
additionalProperties: false
},
annotations: { readOnlyHint: true },
async execute({ tema }) {
const lista = agenda.buscar({ tema });
return { tema, vagas: lista.reduce((soma, o) => soma + o.vagas, 0) };
}
}];
}
FIM
PAGINA=$E node scripts/listar.mjs nativo | tail -1
PAGINA=$E node scripts/executar.mjs nativo contar_vagas '{"tema":"html"}'; echo "saída: $?"
Escribe otra herramienta de solo lectura en extras.mjs, por ejemplo proxima_oficina (la de fecha más cercana). Nombre con _, descripción que diga lo que no hace, schema cerrado.
Listo cuando:node scripts/executar.mjs nativo [nome] '{}' → resultado (string): con el JSON esperado y saída: 0.
06 · Prueba de la clase
La explicación aparece después de la respuesta.
Pregunta 1 de 4
¿Qué devuelve executeTool en la spec del 16/10/2026?
Correcto
executeTool devuelve Promise: el navegador serializa el retorno del execute en JSON. Quien llama hace JSON.parse, como el testar.mjs.
No es esa
executeTool devuelve Promise: el navegador serializa el retorno del execute en JSON. Quien llama hace JSON.parse, como el testar.mjs.Repasar: La tool de búsqueda del kit
Pregunta 2 de 4
¿Qué nombre de herramienta rechaza registerTool?
Correcto
El nombre acepta de 1 a 128 caracteres: letras y números ASCII, _ - y punto. El espacio no entra, y el registro lo rechaza con InvalidStateError.
No es esa
El nombre acepta de 1 a 128 caracteres: letras y números ASCII, _ - y punto. El espacio no entra, y el registro lo rechaza con InvalidStateError.Repasar: De la definición al resultado
Pregunta 3 de 4
¿Por qué la búsqueda del kit llama a ui.mostrarResultados dentro del execute?
Correcto
Agente y persona trabajan en la misma página. Si el agente busca y la pantalla no cambia, la persona pierde el hilo. La spec no lo obliga; es una decisión de diseño del kit.
No es esa
Agente y persona trabajan en la misma página. Si el agente busca y la pantalla no cambia, la persona pierde el hilo. La spec no lo obliga; es una decisión de diseño del kit.Repasar: La tool de búsqueda del kit
Pregunta 4 de 4
Un tutorial manda llamar executeTool(t, JSON.stringify(entrada)). ¿Qué pasa en Chromium 156?
Correcto
La entrada es object en la spec. El rodeo con texto era de una implementación de septiembre y hoy da TypeError en el nativo y en el polyfill (medido el 19/10/2026).
No es esa
La entrada es object en la spec. El rodeo con texto era de una implementación de septiembre y hoy da TypeError en el nativo y en el polyfill (medido el 19/10/2026).Repasar: La tool de búsqueda del kit
Prueba completada
Acertaste {a} de {n}. Si aciertas todas, la clase se marca como completada.
Elige una alternativa. La explicación aparece después de tu intento.
07 · En tres frases
Definiciónname con regla, description clara, inputSchema cerrado y execute que devuelve un objeto.
LlamadagetTools lista; executeTool recibe un objeto y devuelve texto JSON.
En la pantallaEl execute usa la misma regla del formulario y le muestra a la persona lo que recibió el agente.