WebMCP lifecycle in SPAs: register, scope, abort, and re-register
Treat tool registration as route- and component-owned state so stale tools never outlive the interface that gives them meaning.
The short version: Registration lifetime should match the shortest UI context required to interpret and execute the tool safely.
Choose the owner of each registration
A global navigation tool can belong to the application shell. A tool that edits the current invoice belongs to the invoice route. A tool that acts on a selected comparison belongs to the component or mode that owns that selection. Scope prevents an agent from discovering actions that no longer match the screen.
Use one AbortController per registration scope
Create the controller when the scope becomes active and pass its signal in the registration options. Abort it during cleanup. Group tools with the same lifetime under one controller; give independently changing tools separate scopes.
useEffect(() => {
if (!document.modelContext?.registerTool) return;
const scope = new AbortController();
void document.modelContext.registerTool(tool, { signal: scope.signal });
return () => scope.abort();
}, [routeId, mode]);Handle in-flight execution and navigation races
The execution callback also receives a signal. Pass cancellation into fetches and long-running application services, then check whether the relevant route or record still exists before committing visible state. Cleanup should stop both discovery of stale tools and work that no longer has a valid owner.
Avoid duplicate names and stale schemas
Hot reload, rapid navigation, and concurrent rendering can briefly overlap effects. Make cleanup deterministic, keep names unique within the active document context, and do not assume a rejected duplicate registration means WebMCP is unavailable. Log lifecycle diagnostics without exposing them as user-facing success.
Test the lifecycle, not just the callback
Enter the route, verify the expected tool inventory, invoke a read action, leave the route, and verify the tool is gone. Repeat across refresh, back/forward navigation, mode switches, and rapid transitions. A callback unit test cannot detect a tool that remains callable after its data and controls have disappeared.
Primary references
Read the sources
Put it to work
Use the guide on a real product surface.