WebMCP on your site|INEMA.CLUB-PRO

Lesson 4 · 15 min

Lifecycle: getTools, toolchange, AbortSignal, and cancellation

A tool is not forever: the page registers it when the function exists and removes it when it leaves the scene. In the 10/16/2026 spec there is no unregisterTool; what removes it is the signal of an AbortController. And the caller can cancel an execution midway. In this lesson you see the whole cycle and the events the browser fires.

Start the lesson
Dark connection panel with a few cables plugged in and a hand pulling one of them out.

In this lesson you will

  1. 1Registering with a signal and the toolchange event
  2. 2Remove with abort(): the place of the old unregisterTool
  3. 3Cancel an execution: signal in execute and in executeTool
  4. 4toolactivated and toolcancel: native fires them, polyfill doesn't

Goal: register, list, remove with AbortSignal, and cancel an execution, knowing which events the browser fires at each step.

01The lifecycle of a tool

Click each step.

Chrome docs: window.ontoolactivated and window.ontoolcancel have not been supported since 156. Listen on document.modelContext.

Measured on 10/19/2026: Chromium 156 fires all three events; polyfill 6.0.3 fires only toolchange.

02The lifecycle in code

Excerpt from kit/scripts/ciclo.mjs (runs inside the page). Two controllers: one for registration, one for the call.

Simplified excerpt · kit/scripts/ciclo.mjs
const registro = new AbortController();
await mc.registerTool({
  name: 'tarefa_lenta', description: 'Leva 2 segundos. Existe só para ensinar cancelamento.',
  async execute(_, { signal }) {
    return new Promise((ok, falha) => {
      const t = setTimeout(() => ok({ terminou: true }), 2000);
      signal.addEventListener('abort', () => { clearTimeout(t); falha(new DOMException('cancelada', 'AbortError')); });
    });
  }
}, { signal: registro.signal });

const t = (await mc.getTools()).find(x => x.name === 'tarefa_lenta');
const chamada = new AbortController();
setTimeout(() => chamada.abort(), 100);
try { await mc.executeTool(t, {}, { signal: chamada.signal }); }
catch (e) { /* AbortError */ }

registro.abort();   // removes the tool: there is no unregisterTool
Terminal · lifecycle in native and in the polyfill
cd ~/projetos/formacao-webmcp-site-v72/kit
node scripts/ciclo.mjs nativo; echo "saída: $?"
node scripts/ciclo.mjs polyfill; echo "saída: $?"
Example from the repository
== Chromium 156.0.8078.4 (Playwright) · modo: nativo
antes: 4 ferramentas
registrou tarefa_lenta: 5 ferramentas
nome repetido: recusado (InvalidStateError)
execução cancelada pelo chamador: AbortError
depois do abort(): 4 ferramentas
eventos: toolchange toolactivated:tarefa_lenta toolcancel:tarefa_lenta toolchange
saída: 0
== Chromium 156.0.8078.4 (Playwright) · modo: polyfill
antes: 4 ferramentas
registrou tarefa_lenta: 5 ferramentas
nome repetido: recusado (InvalidStateError)
execução cancelada pelo chamador: AbortError
depois do abort(): 4 ferramentas
eventos: toolchange toolchange
saída: 0

Same sequence in both. The difference is in the "eventos" line: only native fires toolactivated and toolcancel.

03Where to register and where to abort

Same rule in any framework: register at the start, abort at the end.

1. Page

Register after the rules are ready and abort on pagehide.

This is what iniciarWebMCP does in the kit.

KitaddEventListener('pagehide', () => pagina.abort(), { once: true })

04Practice

Rehearsal in both modes with an API. Each exercise ends with a done when.

E1 · Cycle in native

3 min

Run the cycle block and read it line by line.

Done when: node scripts/ciclo.mjs nativo → nome repetido: recusado (InvalidStateError), execução cancelada pelo chamador: AbortError, depois do abort(): 4 ferramentas and eventos: toolchange toolactivated:tarefa_lenta toolcancel:tarefa_lenta toolchange.

E2 · The polyfill difference

3 min

Run the same in polyfill and note in your status-webmcp.md (lesson 1) what the polyfill doesn't do.

Done when: node scripts/ciclo.mjs polyfill → eventos: toolchange toolchange and saída: 0; the line is in your file.

E3 · All or nothing

5 min

Run the kit's rule tests: one of them simulates the 2nd tool failing at registration.

Done when: node --test 2>&1 | grep -E "^ℹ (pass|fail)" → ℹ pass 4 and ℹ fail 0.

05Lesson quiz

The explanation appears after your answer.

Question 1 of 4

How do you remove a tool in the 10/16/2026 spec?

06In three sentences

RemoveSignal at registration and abort() when the function goes away; there is no unregisterTool.
CancelSignal in executeTool; the execute listens to its own signal and stops.
Eventstoolchange, toolactivated and toolcancel on document.modelContext; the polyfill fires only the first.

To go further

Previous lessonNext lesson