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:
Dustin Healy 2026-06-23 17:07:16 -07:00
parent b1fa8221ef
commit 4da55e8178
3 changed files with 17 additions and 5 deletions

View file

@ -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 ?? '';