Skip to content

Commit e90d6cf

Browse files
committed
fix: add elicitation forwarding helper to AppBridge
1 parent beb0a36 commit e90d6cf

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

examples/basic-host/src/implementation.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNo
22
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
33
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
44
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5-
import { ElicitRequestSchema, ElicitResultSchema, type CallToolResult, type Resource, type Tool } from "@modelcontextprotocol/sdk/types.js";
5+
import type { CallToolResult, Resource, Tool } from "@modelcontextprotocol/sdk/types.js";
66
import { getTheme, onThemeChange } from "./theme";
77
import { HOST_STYLE_VARIABLES } from "./host-styles";
88

@@ -45,25 +45,7 @@ export async function connectToServer(serverUrl: URL): Promise<ServerInfo> {
4545
const resources = new Map(resourcesList.resources.map((r) => [r.uri, r]));
4646
log.info("Server resources:", Array.from(resources.keys()));
4747

48-
// Buffer elicitation/create requests until the AppBridge is ready.
49-
// The promise is reset after each setBridge() call so it works across
50-
// multiple sequential tool invocations.
51-
let resolveBridge!: (bridge: AppBridge) => void;
52-
let bridgePromise = new Promise<AppBridge>((resolve) => { resolveBridge = resolve; });
53-
54-
const setBridge = (bridge: AppBridge) => {
55-
resolveBridge(bridge);
56-
bridgePromise = new Promise<AppBridge>((resolve) => { resolveBridge = resolve; });
57-
};
58-
59-
client.setRequestHandler(ElicitRequestSchema, async (request, extra) => {
60-
const bridge = await bridgePromise;
61-
return bridge.request(
62-
{ method: "elicitation/create", params: request.params },
63-
ElicitResultSchema,
64-
{ signal: extra.signal },
65-
);
66-
});
48+
const setBridge = AppBridge.setupElicitationForwarding(client);
6749

6850
return { name, client, tools, resources, appHtmlCache: new Map(), setBridge };
6951
}

src/app-bridge.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
CallToolRequestSchema,
66
CallToolResult,
77
CallToolResultSchema,
8+
ElicitRequestSchema,
9+
ElicitResultSchema,
810
EmptyResult,
911
Implementation,
1012
ListPromptsRequest,
@@ -1548,6 +1550,45 @@ export class AppBridge extends Protocol<
15481550

15491551
return super.connect(transport);
15501552
}
1553+
1554+
/**
1555+
* Set up automatic forwarding of `elicitation/create` requests from the MCP
1556+
* server through a bridge to the app.
1557+
*
1558+
* Registers a handler on the given {@link Client} that buffers incoming
1559+
* elicitation requests until a bridge is available, then forwards them.
1560+
* The returned callback must be called with the active {@link AppBridge}
1561+
* once it is initialized (typically right after `ui/initialize` completes).
1562+
* It can be called multiple times for sequential tool invocations.
1563+
*
1564+
* @returns A `setBridge` callback to resolve the current buffered request
1565+
* and prepare for the next one.
1566+
*
1567+
* @example
1568+
* ```ts
1569+
* const setBridge = AppBridge.setupElicitationForwarding(client);
1570+
* // ... later, after the bridge + app are initialized:
1571+
* setBridge(appBridge);
1572+
* ```
1573+
*/
1574+
static setupElicitationForwarding(client: Client): (bridge: AppBridge) => void {
1575+
let resolveBridge!: (bridge: AppBridge) => void;
1576+
let bridgePromise = new Promise<AppBridge>((resolve) => { resolveBridge = resolve; });
1577+
1578+
client.setRequestHandler(ElicitRequestSchema, async (request, extra) => {
1579+
const bridge = await bridgePromise;
1580+
return bridge.request(
1581+
{ method: "elicitation/create", params: request.params },
1582+
ElicitResultSchema,
1583+
{ signal: extra.signal },
1584+
);
1585+
});
1586+
1587+
return (bridge: AppBridge) => {
1588+
resolveBridge(bridge);
1589+
bridgePromise = new Promise<AppBridge>((resolve) => { resolveBridge = resolve; });
1590+
};
1591+
}
15511592
}
15521593

15531594
function deepEqual(a: any, b: any): boolean {

0 commit comments

Comments
 (0)