Skip to content

Conversation

@ochafik
Copy link
Collaborator

@ochafik ochafik commented Dec 10, 2025

Summary

  • Implement ui/notifications/tool-cancelled throughout the SDK - hosts MUST send this when tool execution is cancelled (user action, timeout, classifier intervention, etc.)
  • Add App.onteardown handler for guest UIs to handle graceful shutdown requests

Changes

tool-cancelled notification

Component File Change
Type src/spec.types.ts Added McpUiToolCancelledNotification interface
Schema src/generated/schema.ts Auto-generated via ts-to-zod
Host method src/app-bridge.ts Added sendToolCancelled()
Guest handler src/app.ts Added ontoolcancelled setter
Exports src/types.ts Export type and schema
Tests src/app-bridge.test.ts 2 tests (with/without reason)

onteardown handler

Component File Change
Guest handler src/app.ts Added onteardown setter
Capability src/app.ts Allow ui/resource-teardown in request handler
Tests src/app-bridge.test.ts 2 tests (sync/async cleanup)

Usage

tool-cancelled (Host → Guest):

// Host
bridge.sendToolCancelled({ reason: "User cancelled" });

// Guest
app.ontoolcancelled = (params) => {
  console.log("Cancelled:", params.reason);
};

teardown (Host → Guest):

// Host (already existed)
await bridge.sendResourceTeardown({});

// Guest (NEW)
app.onteardown = async () => {
  await saveState();
  return {};
};

Test plan

  • All 19 tests pass
  • Build succeeds
  • Examples build successfully

🤖 Generated with Claude Code

ochafik and others added 2 commits December 10, 2025 03:21
Wire the tool-cancelled notification that hosts MUST send when tool
execution is cancelled (user action, timeout, classifier intervention, etc.):

- Add McpUiToolCancelledNotification type in spec.types.ts
- Generate Zod schema via ts-to-zod
- Add AppBridge.sendToolCancelled() method for hosts
- Add App.ontoolcancelled setter for guest UIs
- Export type and schema from types.ts
- Add tests for notification with/without reason

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Wire the guest UI side of ui/resource-teardown request:

- Add onteardown setter in App class for guest UIs to handle teardown
- Allow ui/resource-teardown in assertRequestHandlerCapability
- Import McpUiResourceTeardownRequest/Result types
- Add tests for sync and async cleanup handlers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 10, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@120

commit: 1076b7d

@ochafik ochafik changed the title feat: wire ui/notifications/tool-cancelled and add App.onteardown handler feat: implement ui/notifications/tool-cancelled + add missing App.onteardown Dec 10, 2025
@ochafik ochafik requested a review from idosal December 10, 2025 02:30
@ochafik ochafik marked this pull request as ready for review December 10, 2025 02:30
Update basic-host example to properly use the new notifications:

- Send sendToolCancelled when tool call promise rejects
- Send sendResourceTeardown when React component unmounts
- Store appBridge ref for cleanup access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ochafik ochafik requested review from antonpk1 and liady December 10, 2025 12:38
return () => {
if (appBridgeRef.current) {
log.info("Sending teardown notification to MCP App");
appBridgeRef.current.sendResourceTeardown({}).catch((err) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ochafik it's worth noting here that this doesn't actually wait for the UI to terminate gracefully before unmounting, which is against against the spec's recommendation (Host SHOULD wait for a response before tearing down the resource (to prevent data loss).)

Copy link
Collaborator Author

@ochafik ochafik Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Fixed in bf3b1b3 - the host now waits for the guest's teardown response before unmounting, per the spec recommendation.

Changes:

  • Added close button (×) to tool call panels
  • Two-phase unmount: clicking close sets isDestroying state which dims the panel and disables pointer events
  • sendResourceTeardown() completes (or errors) before the component is removed
  • Also handles edge case where user closes before bridge is ready

Demo apps now also have onteardown handlers with simulated 500ms cleanup to demonstrate the flow.

ochafik and others added 2 commits December 11, 2025 02:42
Address review feedback: the host now waits for guest's teardown
response before unmounting, following the spec: "Host SHOULD wait
for a response before tearing down the resource (to prevent data loss)."

Changes:
- Add close button to tool call panels
- Two-phase unmount: isDestroying state dims panel and disables events
- sendResourceTeardown() completes before component removal
- Non-app tool results close immediately

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Demonstrate graceful shutdown with simulated 500ms cleanup work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ochafik ochafik merged commit 70b393a into main Dec 11, 2025
8 checks passed
@ochafik ochafik deleted the ochafik/wire-tool-cancelled-notification branch December 13, 2025 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants