vercel/ai · error · Error
No tools/call handler configured
Error message
No tools/call handler configured
What it means
The iframe app sent a `tools/call` request, but the host bridge was constructed without a `callTool` handler in its `handlers` object. The bridge refuses to proxy the request since there is no host callback to execute it. This is a host configuration error surfaced as a JSON-RPC error to the iframe and to `onError`.
Source
Thrown at packages/react/src/mcp-apps/bridge.ts:358
): Promise<unknown> {
switch (request.method) {
case 'ui/initialize':
return {
protocolVersion: MCP_APP_PROTOCOL_VERSION,
hostCapabilities: {
...(this.handlers.callTool != null ? { serverTools: {} } : {}),
...(this.handlers.readResource != null
? { serverResources: {} }
: {}),
...(this.handlers.onLog != null ? { logging: {} } : {}),
},
hostInfo: this.hostInfo,
hostContext: this.hostContext,
};
case 'tools/call': {
if (this.handlers.callTool == null) {
throw new Error('No tools/call handler configured');
}
const params = assertToolCallParams(request.params);
// Deny-by-default: the (untrusted) MCP App may only invoke tools the
// host has explicitly allow-listed. Omitting `allowedTools` exposes no
// tools, rather than forwarding every requested tool to `callTool`.
if (
this.handlers.allowedTools == null ||
!this.handlers.allowedTools.includes(params.name)
) {
throw new Error(`Tool is not app-visible: ${params.name}`);
}
return this.handlers.callTool(params);
}
case 'resources/read':
if (this.handlers.readResource == null) {
throw new Error('No resources/read handler configured');
}View on GitHub (pinned to 69428b1f8b)
Solutions
- Add a `callTool` handler (and `allowedTools` allow-list) when constructing MCPAppBridge if the app should invoke tools.
- If tools should remain unavailable, configure the app to not call tools — the host will never accept them.
- Verify handlers were not spread/overridden after bridge construction.
- Check `ui/initialize`'s reported capabilities: serverTools is only advertised when `callTool` exists.
Example fix
// before
const bridge = new MCPAppBridge({ targetWindow, handlers: { onError: console.error } })
// after
const bridge = new MCPAppBridge({
targetWindow,
handlers: {
allowedTools: ['search'],
callTool: params => client.callTool(params),
onError: console.error,
},
}) Defensive patterns
Strategy: validation
Validate before calling
// host-side, at construction time:
const bridge = new MCPAppBridge({
targetWindow,
handlers: {
...(appNeedsTools
? { allowedTools: ['search'], callTool: p => client.callTool(p) }
: {}),
onError: e => console.error('MCP App bridge error:', e),
},
});
if (appNeedsTools) console.assert('callTool' in bridgeHandlers, 'callTool handler required'); Type guard
function hasCallToolHandler(h: unknown): h is { callTool: (p: any) => unknown } {
return typeof h === 'object' && h !== null && 'callTool' in h &&
typeof (h as any).callTool === 'function';
} Try / catch
try {
await appRequest;
} catch (error) {
if (error instanceof Error && error.message === 'No tools/call handler configured') {
console.error('Bridge was built without a callTool handler; add one or stop the app from calling tools');
}
} Prevention
- Always configure callTool (plus allowedTools) when embedding apps that invoke tools.
- Wire handlers.onError to catch and log bridge errors during development.
- Keep handler wiring in one place and assert required keys at startup.
- Remember serverTools capability is only advertised when callTool exists — align app expectations with it.
When it happens
Trigger: `new MCPAppBridge({ handlers: { ... } })` was called without `callTool`, then the app called `tools/call` (the app may attempt this because `ui/initialize` reports serverTools capability based on handler presence).
Common situations: Host intentionally disabled tool access but the app still calls tools; copy-pasted bridge setup omitted `callTool`; conditional handler wiring where the flag was false at mount time.
Related errors
- No resources/read handler configured
- Invalid tools/call params
- Invalid resources/read params
- resources/read is limited to ui:// resources: ${params.uri}
- Invalid ui/open-link params
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/3a9252ef74f0c3ca.
Report an issue: GitHub.