fix(mcp): proxy resource templates and fail closed on app config resolution

The host advertises serverResources, and the ext-apps bridge treats resources/read, resources/list, and resources/templates/list as one proxied set. Only the first two were wired, so an app that sent resources/templates/list received a method-not-found. Register an onlistresourcetemplates handler backed by a new MCPManager.listResourceTemplates and a /api/mcp/resources/templates/list route, mirroring the existing resources/list path. Tool listing is left out deliberately: the App Bridge has no app-to-host tools/list request, and serverTools covers only tool calls.

Make app follow-up requests fail closed when scoped config resolution errors. resolveConfigServers gains an opt-in throwOnError so the app path rejects instead of degrading to an empty set, which previously let a transient failure fall back to the base config for the same server name and proxy the iframe request to the wrong server.
This commit is contained in:
Dustin Healy 2026-06-25 14:42:14 -07:00
parent f31dacac70
commit acc0befd0b
6 changed files with 128 additions and 5 deletions

View file

@ -9,6 +9,7 @@ import {
CallToolResultSchema,
ReadResourceResultSchema,
ListResourcesResultSchema,
ListResourceTemplatesResultSchema,
ErrorCode,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
@ -927,6 +928,56 @@ Please follow these instructions when using tools from the respective MCP server
return result;
}
async listResourceTemplates({
userId,
serverName,
user,
cursor,
configServers,
customUserVars,
flowManager,
tokenMethods,
}: {
userId: string;
serverName: string;
user?: import('@librechat/data-schemas').IUser;
cursor?: string;
configServers?: Record<string, t.ParsedServerConfig>;
customUserVars?: Record<string, string>;
flowManager?: FlowStateManager<MCPOAuthTokens | null>;
tokenMethods?: TokenMethods;
}): Promise<unknown> {
const logPrefix = `[MCP][User: ${userId}][${serverName}]`;
if (userId && user) this.updateUserLastActivity(userId);
const connection = await this.getAppConnection({
serverName,
userId,
user,
configServers,
customUserVars,
flowManager,
tokenMethods,
});
if (!(await connection.isConnected())) {
throw new McpError(
ErrorCode.InternalError,
`${logPrefix} Connection is not active. Cannot list resource templates.`,
);
}
const result = await connection.client.request(
{
method: 'resources/templates/list',
params: cursor != null ? { cursor } : {},
},
ListResourceTemplatesResultSchema,
{ timeout: connection.timeout },
);
return result;
}
/**
* Proxies a tool call from an MCP App iframe to the MCP server.
* Unlike callTool, this is a lightweight proxy without provider formatting.