vercel/ai · error · Error
Tool is not app-visible: ${params.name}
Error message
Tool is not app-visible: ${params.name} What it means
The MCP Apps bridge is deny-by-default: an app iframe may only invoke tools explicitly listed in the host's `allowedTools` array. This error is thrown when the app requests a tool that either is not in `allowedTools` or when `allowedTools` was omitted entirely (which exposes no tools). It prevents untrusted frames from invoking arbitrary server tools.
Source
Thrown at packages/react/src/mcp-apps/bridge.ts:368
...(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');
}
return this.handlers.readResource(
assertResourceReadParams(request.params),
);
case 'resources/list':
if (this.handlers.listResources == null) {
throw new Error('No resources/list handler configured');
}
return this.handlers.listResources(request.params);
View on GitHub (pinned to 69428b1f8b)
Solutions
- Add the requested tool's exact name to `handlers.allowedTools` in the MCPAppBridge configuration.
- Remember that omitting `allowedTools` exposes zero tools — you must opt in explicitly.
- Verify the tool name string matches exactly (case, spacing) between app and allow-list.
- If the tool should not be app-visible, fix the app to use an allow-listed tool instead.
Example fix
// before
handlers: { allowedTools: ['search'], callTool: p => client.callTool(p) }
// after
handlers: { allowedTools: ['search', 'refreshDashboardData'], callTool: p => client.callTool(p) } Defensive patterns
Strategy: validation
Validate before calling
// host-side, before constructing the bridge, keep allow-list in sync with the app:
const APP_VISIBLE_TOOLS = ['search', 'refreshDashboardData'] as const;
const handlers = {
allowedTools: [...APP_VISIBLE_TOOLS],
callTool: (params: { name: string }) => {
if (!(APP_VISIBLE_TOOLS as readonly string[]).includes(params.name)) {
throw new Error(`Tool ${params.name} not exposed to apps`);
}
return client.callTool(params);
},
}; Type guard
function isAllowedTool(name: string, allowedTools: string[] | undefined): boolean {
return allowedTools != null && allowedTools.includes(name);
} Try / catch
try {
await callTool({ name: toolName, arguments });
} catch (error) {
if (error instanceof Error && error.message.startsWith('Tool is not app-visible:')) {
const tool = error.message.split(': ')[1];
console.warn(`Tool "${tool}" is not in handlers.allowedTools; add it to expose it to the app`);
}
} Prevention
- Every tool the app should invoke must appear verbatim in handlers.allowedTools — omitting allowedTools exposes none.
- Keep the allow-list in a shared constant synced with the app's tool manifest.
- Update the allow-list whenever tools are added or renamed.
- Watch tool-name casing and whitespace; matches are exact.
When it happens
Trigger: The iframe calls `tools/call` with `name: 'deleteUser'` but the host configured `allowedTools: ['search']`; or the host never set `allowedTools`, so every tool call is rejected.
Common situations: New tool added to the app but not added to the host allow-list; tool renamed in the app while the allow-list kept the old name; developer assumed tools were exposed by default and omitted `allowedTools`; case-sensitivity mismatch between tool names.
Related errors
- resources/read is limited to ui:// resources: ${params.uri}
- Disallowed ui/open-link scheme: ${scheme}
- Invalid tools/call params
- Invalid resources/read params
- Invalid ui/open-link params
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/118b71a3667ce01f.
Report an issue: GitHub.