/************************************************************************* * Copyright 2026 Adobe * All Rights Reserved. * * NOTICE: Adobe permits you to use, modify, and distribute this file in * accordance with the terms of the Adobe license agreement accompanying * it. If you have received this file from a source other than Adobe, * then your use, modification, or distribution of it requires the prior * written permission of Adobe. **************************************************************************/ /** Property definition within a JSON Schema. */ export interface InputSchemaProperty { description?: string; enum?: string[]; items?: InputSchemaProperty; properties?: Record; required?: string[]; type: string; } /** JSON Schema for a tool's input parameters. */ export interface InputSchema { properties?: Record; required?: string[]; type: 'object'; } export declare const TOOLS_CHANGE_EVENT = "change:tools"; /** * Describes a tool that AO2's LLM can invoke. The serializable fields are sent * as A2A metadata alongside each user message; the LLM uses `description` and * `inputSchema` to decide when and how to call the tool. * * `execute` runs only in the APP iframe and must not cross postMessage. */ export interface ToolDefinition { /** * Tool name. Unique within `(component, frame)`. When `component` is set, * Core composes the LLM-visible identifier as `${component}_${name}`; * otherwise the AO2-visible name is just `name`. */ name: string; /** Component registering the tool. Used for additional context and tool name deduplication. */ component?: string; /** Human-readable description. The LLM uses this to decide when to call the tool. */ description: string; /** Invoked locally when the tool runs; stripped before postMessage to Core. */ execute: (parameters: Record) => Promise; /** JSON Schema describing the tool's input parameters. */ inputSchema: InputSchema; } /** * Serializable subset of {@link ToolDefinition}: everything except `execute`, * which is stripped before the definition is sent across postMessage. */ export type SerializableToolDefinition = Omit; /** * Alias for {@link ToolDefinition.execute}. Handlers stay in the APP iframe * and are never sent across postMessage. */ export type ToolHandler = ToolDefinition['execute']; /** * Handler for the `change:tools` event. Receives the full, deduped list * of tools currently registered across every frame. */ export type ToolsChangedHandler = (tools: SerializableToolDefinition[]) => void; /** * Solution-facing API for registering browser-side tools * that AO2 can invoke via the WebMCP protocol. */ export interface WebMcpApi { /** * Execute a registered tool by name. * * If the tool is registered in the current frame, its handler is * called directly with no postMessage overhead. Otherwise the call * is routed through Core to whichever frame owns the tool. * * ***Example:*** * * ```typescript * const result = await webmcp.executeTool('lookupUI', { type: 'button' }); * ``` * * @param name - The tool name to execute * @param parameters - Parameters to pass to the tool handler * @returns The tool handler's return value */ executeTool: (name: string, parameters?: Record) => Promise; /** * Get all tools registered across all frames (fetched from Core's registry). * * Returns a promise that resolves with tool definitions in flat format * (`{ name, description, inputSchema }`), ready to forward to AO2 via `tools/list`. * * ***Example:*** * * ```typescript * const tools = await webmcp.getTools(); * // [{ name, description, inputSchema }, ...] * console.log(tools); * ``` * * @returns A promise resolving to an array of serializable tool definitions */ getTools: () => Promise; /** * Unsubscribe a previously registered event handler. * Pass the same handler reference that was passed to `on`. * * @param event - Event name to remove the handler from * @param handler - The handler reference to remove */ off: (event: typeof TOOLS_CHANGE_EVENT, handler: ToolsChangedHandler) => void; /** * Subscribe to WebMCP events. * * Currently supported events: * - `change:tools`: fires whenever the tool registry changes (a tool is * registered or unregistered in any frame, or a frame unloads). The * handler receives the full, deduped list of tools currently registered * across every frame. * * The event fires for every change, including those triggered by the * current frame's own `registerTool` / `unregisterTool` calls. * * ***Example:*** * * ```typescript * const onChange = (tools) => console.log('tools now:', tools); * webmcp.on('change:tools', onChange); * // ...later * webmcp.off('change:tools', onChange); * ``` * * @param event - Event name to listen for * @param handler - Callback invoked when the event fires */ on: (event: typeof TOOLS_CHANGE_EVENT, handler: ToolsChangedHandler) => void; /** * Register a tool: serializable fields are sent to Core for A2A metadata; * `execute` is kept local and stripped from the postMessage payload. * * ***Example:*** * * ```typescript * webmcp.registerTool({ * name: 'getPageInfo', * description: 'Returns information about the current page', * inputSchema: { type: 'object', properties: {} }, * execute: async () => ({ title: document.title, url: window.location.href }) * }); * ``` * * @param definition - Tool definition including `execute` */ registerTool: (definition: ToolDefinition) => void; /** * Remove a previously registered tool. * * Removes the handler locally and notifies Core to remove * the definition from the A2A metadata. Pass the same `component` * value that was used during registration (if any). * * ***Example:*** * * ```typescript * webmcp.unregisterTool('getPageInfo'); * webmcp.unregisterTool('getContext', 'damPanel'); * ``` * * @param name - The tool name to unregister * @param component - Optional component the tool was registered under */ unregisterTool: (name: string, component?: string) => void; } declare const webmcp: WebMcpApi; export default webmcp;