Skip to content

feat: adopt useApp() hook or fix App.close() cleanup in Echo widget #54

Description

@nickytonline

Background

@modelcontextprotocol/ext-apps 1.7.0 introduced the useApp() React hook and fixed a React StrictMode bug where the App instance was not closed on unmount, leaving a zombie PostMessageTransport listener receiving every host message alongside the live instance.

The fix was applied inside useApp() — it now calls app.close() in the effect cleanup.

Current state

Echo.tsx manually wires App in a useEffect:

useEffect(() => {
  let isMounted = true;
  activeApp.ontoolresult = ...
  activeApp.onhostcontextchanged = ...

  const connect = async () => { await activeApp.connect(); ... };
  connect();

  return () => {
    isMounted = false; // only guards callbacks, doesn't close the transport
  };
}, [activeApp]);

The cleanup never calls activeApp.close(), so under React StrictMode's dev-mode double-invoke the first App instance becomes a zombie listener.

Proposed change

Either:

  1. Keep the manual useEffect pattern but add activeApp.close() to the cleanup (only when activeApp is the internally-created defaultApp, not the injected app prop used in tests/Storybook), or
  2. Refactor Echo.tsx to use the useApp() hook from @modelcontextprotocol/ext-apps/react, which handles the connect/close lifecycle correctly and would serve as a better reference implementation for template users.

Also update CLAUDE.md / AGENTS.md and skill docs to document the correct cleanup pattern (or useApp()) as the preferred approach.

References

  • ext-apps 1.7.0 release notes: useApp effect cleanup now closes the App, so React StrictMode's dev double-invoke doesn't leave a zombie PostMessageTransport listener (modelcontextprotocol/ext-apps#631)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions