feat: implement ui/notifications/tool-cancelled + add missing App.onteardown (#120)
* feat: implement ui/notifications/tool-cancelled throughout SDK 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> * feat: add App.onteardown handler for graceful shutdown 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> * feat(example): wire tool-cancelled and teardown in basic-host 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> * fix(example): implement graceful teardown per spec recommendation 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> * feat(examples): add onteardown handlers to demo apps Demonstrate graceful shutdown with simulated 500ms cleanup work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a31e48a11e
commit
70b393a7e6
1 changed files with 379 additions and 15 deletions
83
src/app.ts
83
src/app.ts
|
|
@ -31,7 +31,12 @@ import {
|
|||
McpUiMessageResultSchema,
|
||||
McpUiOpenLinkRequest,
|
||||
McpUiOpenLinkResultSchema,
|
||||
McpUiResourceTeardownRequest,
|
||||
McpUiResourceTeardownRequestSchema,
|
||||
McpUiResourceTeardownResult,
|
||||
McpUiSizeChangedNotification,
|
||||
McpUiToolCancelledNotification,
|
||||
McpUiToolCancelledNotificationSchema,
|
||||
McpUiToolInputNotification,
|
||||
McpUiToolInputNotificationSchema,
|
||||
McpUiToolInputPartialNotification,
|
||||
|
|
@ -388,6 +393,41 @@ export class App extends Protocol<Request, Notification, Result> {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience handler for receiving tool cancellation notifications from the host.
|
||||
*
|
||||
* Set this property to register a handler that will be called when the host
|
||||
* notifies that tool execution was cancelled. This can occur for various reasons
|
||||
* including user action, sampling error, classifier intervention, or other
|
||||
* interruptions. Apps should update their state and display appropriate feedback.
|
||||
*
|
||||
* This setter is a convenience wrapper around `setNotificationHandler()` that
|
||||
* automatically handles the notification schema and extracts the params for you.
|
||||
*
|
||||
* Register handlers before calling {@link connect} to avoid missing notifications.
|
||||
*
|
||||
* @param callback - Function called when tool execution is cancelled
|
||||
*
|
||||
* @example Handle tool cancellation
|
||||
* ```typescript
|
||||
* app.ontoolcancelled = (params) => {
|
||||
* console.log("Tool cancelled:", params.reason);
|
||||
* showCancelledMessage(params.reason ?? "Operation was cancelled");
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @see {@link setNotificationHandler} for the underlying method
|
||||
* @see {@link McpUiToolCancelledNotification} for the notification structure
|
||||
* @see {@link ontoolresult} for successful tool completion
|
||||
*/
|
||||
set ontoolcancelled(
|
||||
callback: (params: McpUiToolCancelledNotification["params"]) => void,
|
||||
) {
|
||||
this.setNotificationHandler(McpUiToolCancelledNotificationSchema, (n) =>
|
||||
callback(n.params),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience handler for host context changes (theme, viewport, locale, etc.).
|
||||
*
|
||||
|
|
@ -427,6 +467,48 @@ export class App extends Protocol<Request, Notification, Result> {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience handler for graceful shutdown requests from the host.
|
||||
*
|
||||
* Set this property to register a handler that will be called when the host
|
||||
* requests the app to prepare for teardown. This allows the app to perform
|
||||
* cleanup operations (save state, close connections, etc.) before being unmounted.
|
||||
*
|
||||
* The handler can be sync or async. The host will wait for the returned promise
|
||||
* to resolve before proceeding with teardown.
|
||||
*
|
||||
* This setter is a convenience wrapper around `setRequestHandler()` that
|
||||
* automatically handles the request schema.
|
||||
*
|
||||
* Register handlers before calling {@link connect} to avoid missing requests.
|
||||
*
|
||||
* @param callback - Function called when teardown is requested.
|
||||
* Can return void or a Promise that resolves when cleanup is complete.
|
||||
*
|
||||
* @example Perform cleanup before teardown
|
||||
* ```typescript
|
||||
* app.onteardown = async () => {
|
||||
* await saveState();
|
||||
* closeConnections();
|
||||
* console.log("App ready for teardown");
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* @see {@link setRequestHandler} for the underlying method
|
||||
* @see {@link McpUiResourceTeardownRequest} for the request structure
|
||||
*/
|
||||
set onteardown(
|
||||
callback: (
|
||||
params: McpUiResourceTeardownRequest["params"],
|
||||
extra: RequestHandlerExtra,
|
||||
) => McpUiResourceTeardownResult | Promise<McpUiResourceTeardownResult>,
|
||||
) {
|
||||
this.setRequestHandler(
|
||||
McpUiResourceTeardownRequestSchema,
|
||||
(request, extra) => callback(request.params, extra),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience handler for tool call requests from the host.
|
||||
*
|
||||
|
|
@ -533,6 +615,7 @@ export class App extends Protocol<Request, Notification, Result> {
|
|||
}
|
||||
return;
|
||||
case "ping":
|
||||
case "ui/resource-teardown":
|
||||
return;
|
||||
default:
|
||||
throw new Error(`No handler for method ${method} registered`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue