mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-07-10 00:03:03 +00:00
fix(mcp): refresh user activity on app tool calls; scope resource cache by user
appToolCall was missing the updateUserLastActivity call that callTool includes, so app interactions from an iframe would not reset the idle timer on user-scoped MCP connections. The client-side resourceCache in mcpApps.ts was keyed only on serverName:uri, meaning a second user logging in within the 5-minute TTL could receive cached HTML from the previous user's session. The key now includes the userId, threaded from the Recoil user atom via useAppBridge.
This commit is contained in:
parent
b1fa8221ef
commit
4da55e8178
3 changed files with 17 additions and 5 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { useEffect, useRef } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import {
|
||||
AppBridge,
|
||||
PostMessageTransport,
|
||||
|
|
@ -7,6 +8,7 @@ import {
|
|||
import type { UIResource } from 'librechat-data-provider';
|
||||
import { callMCPAppTool, fetchMCPResourceHtml } from '~/utils/mcpApps';
|
||||
import { logger } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
type SizeParams = { width?: number; height?: number };
|
||||
|
||||
|
|
@ -17,6 +19,7 @@ export function useAppBridge(
|
|||
toolResult: { content: []; structuredContent?: Record<string, unknown> } | undefined,
|
||||
onSizeChanged: (params: SizeParams) => void,
|
||||
) {
|
||||
const user = useRecoilValue(store.user);
|
||||
const bridgeRef = useRef<AppBridge | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -63,7 +66,11 @@ export function useAppBridge(
|
|||
|
||||
bridge.addEventListener('sandboxready', async () => {
|
||||
try {
|
||||
const html = await fetchMCPResourceHtml(resource.serverName as string, resource.uri);
|
||||
const html = await fetchMCPResourceHtml(
|
||||
resource.serverName as string,
|
||||
resource.uri,
|
||||
user?.id,
|
||||
);
|
||||
await bridge!.sendSandboxResourceReady({
|
||||
html,
|
||||
csp: resource.csp as never,
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ const CACHE_TTL_MS = 5 * 60 * 1000;
|
|||
type CacheEntry = { promise: Promise<unknown>; ts: number };
|
||||
const resourceCache = new Map<string, CacheEntry>();
|
||||
|
||||
export async function readMCPResource(serverName: string, uri: string) {
|
||||
const key = `${serverName}:${uri}`;
|
||||
export async function readMCPResource(serverName: string, uri: string, userId?: string) {
|
||||
const key = `${userId ?? ''}:${serverName}:${uri}`;
|
||||
const now = Date.now();
|
||||
|
||||
const existing = resourceCache.get(key);
|
||||
|
|
@ -46,8 +46,12 @@ export async function readMCPResource(serverName: string, uri: string) {
|
|||
return promise;
|
||||
}
|
||||
|
||||
export async function fetchMCPResourceHtml(serverName: string, uri: string): Promise<string> {
|
||||
const result = (await readMCPResource(serverName, uri)) as {
|
||||
export async function fetchMCPResourceHtml(
|
||||
serverName: string,
|
||||
uri: string,
|
||||
userId?: string,
|
||||
): Promise<string> {
|
||||
const result = (await readMCPResource(serverName, uri, userId)) as {
|
||||
contents?: Array<{ text?: string }>;
|
||||
};
|
||||
return result?.contents?.[0]?.text ?? '';
|
||||
|
|
|
|||
|
|
@ -676,6 +676,7 @@ Please follow these instructions when using tools from the respective MCP server
|
|||
user?: import('@librechat/data-schemas').IUser;
|
||||
}): Promise<unknown> {
|
||||
const logPrefix = `[MCP][User: ${userId}][${serverName}]`;
|
||||
if (userId && user) this.updateUserLastActivity(userId);
|
||||
const connection = await this.getConnection({ serverName, user });
|
||||
|
||||
if (!(await connection.isConnected())) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue