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
3 changed files with 379 additions and 15 deletions
|
|
@ -1732,6 +1732,28 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"McpUiToolCancelledNotification": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"method": {
|
||||
"type": "string",
|
||||
"const": "ui/notifications/tool-cancelled"
|
||||
},
|
||||
"params": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reason": {
|
||||
"description": "Optional reason for the cancellation (e.g., \"user action\", \"timeout\").",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["method", "params"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"McpUiToolInputNotification": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer<
|
|||
typeof generated.McpUiToolInputPartialNotificationSchema
|
||||
>;
|
||||
|
||||
export type McpUiToolCancelledNotificationSchemaInferredType = z.infer<
|
||||
typeof generated.McpUiToolCancelledNotificationSchema
|
||||
>;
|
||||
|
||||
export type McpUiResourceTeardownRequestSchemaInferredType = z.infer<
|
||||
typeof generated.McpUiResourceTeardownRequestSchema
|
||||
>;
|
||||
|
|
@ -151,6 +155,12 @@ expectType<spec.McpUiToolInputPartialNotification>(
|
|||
expectType<McpUiToolInputPartialNotificationSchemaInferredType>(
|
||||
{} as spec.McpUiToolInputPartialNotification,
|
||||
);
|
||||
expectType<spec.McpUiToolCancelledNotification>(
|
||||
{} as McpUiToolCancelledNotificationSchemaInferredType,
|
||||
);
|
||||
expectType<McpUiToolCancelledNotificationSchemaInferredType>(
|
||||
{} as spec.McpUiToolCancelledNotification,
|
||||
);
|
||||
expectType<spec.McpUiResourceTeardownRequest>(
|
||||
{} as McpUiResourceTeardownRequestSchemaInferredType,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -160,6 +160,24 @@ export const McpUiToolInputPartialNotificationSchema = z.object({
|
|||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* @description Notification that tool execution was cancelled (Host -> Guest UI).
|
||||
* Host MUST send this if tool execution was cancelled for any reason (user action,
|
||||
* sampling error, classifier intervention, etc.).
|
||||
*/
|
||||
export const McpUiToolCancelledNotificationSchema = z.object({
|
||||
method: z.literal("ui/notifications/tool-cancelled"),
|
||||
params: z.object({
|
||||
/** @description Optional reason for the cancellation (e.g., "user action", "timeout"). */
|
||||
reason: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Optional reason for the cancellation (e.g., "user action", "timeout").',
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* @description Request for graceful shutdown of the Guest UI (Host -> Guest UI).
|
||||
* @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this
|
||||
|
|
|
|||
Loading…
Reference in a new issue