diff --git a/client/src/components/Chat/Messages/Content/ToolCall.tsx b/client/src/components/Chat/Messages/Content/ToolCall.tsx
index f8e83978aa..3325a34b05 100644
--- a/client/src/components/Chat/Messages/Content/ToolCall.tsx
+++ b/client/src/components/Chat/Messages/Content/ToolCall.tsx
@@ -70,6 +70,19 @@ const MCPAppView = React.memo(function MCPAppView({
useAppBridge(iframeRef, app, toolArgs, toolResult, handleSizeChanged);
+ if (app.text && (app.mimeType ?? 'text/html').includes('html')) {
+ return (
+
+
+
+ );
+ }
+
return (
{!loaded && !timedOut && (
diff --git a/client/src/components/Chat/Messages/Content/UIResourceCarousel.tsx b/client/src/components/Chat/Messages/Content/UIResourceCarousel.tsx
index afa1a0468b..1e67b52c12 100644
--- a/client/src/components/Chat/Messages/Content/UIResourceCarousel.tsx
+++ b/client/src/components/Chat/Messages/Content/UIResourceCarousel.tsx
@@ -50,7 +50,7 @@ function MCPAppCard({
handleSizeChanged,
);
- if (resource.toolName && resource.serverName) {
+ if (resource.toolName && resource.serverName && !resource.text) {
return (
<>
{!loaded && (
diff --git a/client/src/utils/mcpApps.ts b/client/src/utils/mcpApps.ts
index b0e884c8f9..6c354f2472 100644
--- a/client/src/utils/mcpApps.ts
+++ b/client/src/utils/mcpApps.ts
@@ -11,7 +11,7 @@ export async function callMCPAppTool(
toolName: string,
args: Record,
) {
- return request.post('/api/mcp/app-tool-call', {
+ return request.post(`${apiBaseUrl()}/api/mcp/app-tool-call`, {
serverName,
toolName,
arguments: args,
@@ -40,7 +40,7 @@ export async function readMCPResource(serverName: string, uri: string, userId?:
}
}
- const promise = request.post('/api/mcp/resources/read', { serverName, uri });
+ const promise = request.post(`${apiBaseUrl()}/api/mcp/resources/read`, { serverName, uri });
resourceCache.set(key, { promise, ts: now });
promise.catch(() => resourceCache.delete(key));
return promise;
diff --git a/packages/api/src/mcp/MCPManager.ts b/packages/api/src/mcp/MCPManager.ts
index 61914d8647..da8341b3a8 100644
--- a/packages/api/src/mcp/MCPManager.ts
+++ b/packages/api/src/mcp/MCPManager.ts
@@ -747,14 +747,19 @@ Please follow these instructions when using tools from the respective MCP server
`${logPrefix} Server "${serverName}" requires Graph API token resolution which is not supported for app tool calls.`,
);
}
- const currentOptions = processMCPEnv({
- user,
- dbSourced: isDbSourced,
- options: rawConfig as t.MCPOptions,
- });
- const resolvedHeaders: Record =
- 'headers' in currentOptions ? { ...(currentOptions.headers || {}) } : {};
- connection.setRequestHeaders(resolvedHeaders);
+ // DB-sourced servers have their customUserVars (e.g. {{MCP_API_KEY}}) resolved during
+ // the original callTool setup. Re-processing without customUserVars would overwrite
+ // those resolved headers with unresolved placeholders, so skip for DB-sourced servers.
+ if (!isDbSourced) {
+ const currentOptions = processMCPEnv({
+ user,
+ dbSourced: false,
+ options: rawConfig as t.MCPOptions,
+ });
+ const resolvedHeaders: Record =
+ 'headers' in currentOptions ? { ...(currentOptions.headers || {}) } : {};
+ connection.setRequestHeaders(resolvedHeaders);
+ }
}
const result = await connection.client.request(
diff --git a/packages/api/src/mcp/registry/MCPServerInspector.ts b/packages/api/src/mcp/registry/MCPServerInspector.ts
index 4e0b9438e4..03f7e49a97 100644
--- a/packages/api/src/mcp/registry/MCPServerInspector.ts
+++ b/packages/api/src/mcp/registry/MCPServerInspector.ts
@@ -175,6 +175,17 @@ export class MCPServerInspector {
const toolFunctions: t.LCAvailableTools = {};
tools.forEach((tool) => {
+ const uiMeta = (tool._meta as Record)?.ui as
+ | Record
+ | undefined;
+ const visibility = uiMeta?.visibility as string[] | undefined;
+ if (
+ Array.isArray(visibility) &&
+ visibility.includes('app') &&
+ !visibility.includes('model')
+ ) {
+ return;
+ }
const name = `${tool.name}${Constants.mcp_delimiter}${serverName}`;
toolFunctions[name] = {
type: 'function',