From d7b505fdd2932bfcdd53a56eed8ff5c59ea8a648 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 3 Apr 2026 18:55:31 -0700 Subject: [PATCH 1/2] fix(mcp): resolve userId before JWT generation for agent block auth --- apps/sim/tools/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sim/tools/index.ts b/apps/sim/tools/index.ts index 737dfa47bb..e48e05baf2 100644 --- a/apps/sim/tools/index.ts +++ b/apps/sim/tools/index.ts @@ -1552,11 +1552,13 @@ async function executeMcpTool( const baseUrl = getInternalApiBaseUrl() + const mcpScope = resolveToolScope(params, executionContext) + const headers: Record = { 'Content-Type': 'application/json' } if (typeof window === 'undefined') { try { - const internalToken = await generateInternalToken(executionContext?.userId) + const internalToken = await generateInternalToken(mcpScope.userId) headers.Authorization = `Bearer ${internalToken}` } catch (error) { logger.error(`[${actualRequestId}] Failed to generate internal token:`, error) @@ -1587,8 +1589,6 @@ async function executeMcpTool( ) } - const mcpScope = resolveToolScope(params, executionContext) - if (mcpScope.callChain && mcpScope.callChain.length > 0) { headers[SIM_VIA_HEADER] = serializeCallChain(mcpScope.callChain) } From f182eb52f1868787e49d9f211435447808c71698 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 3 Apr 2026 19:01:49 -0700 Subject: [PATCH 2/2] test(mcp): add regression test for agent block JWT userId resolution --- apps/sim/tools/index.test.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/apps/sim/tools/index.test.ts b/apps/sim/tools/index.test.ts index 1c7df7a07c..e3ecf97fae 100644 --- a/apps/sim/tools/index.test.ts +++ b/apps/sim/tools/index.test.ts @@ -25,6 +25,7 @@ const { mockGetCustomToolById, mockListCustomTools, mockGetCustomToolByIdOrTitle, + mockGenerateInternalToken, } = vi.hoisted(() => ({ mockIsHosted: { value: false }, mockEnv: { NEXT_PUBLIC_APP_URL: 'http://localhost:3000' } as Record, @@ -38,6 +39,7 @@ const { mockGetCustomToolById: vi.fn(), mockListCustomTools: vi.fn(), mockGetCustomToolByIdOrTitle: vi.fn(), + mockGenerateInternalToken: vi.fn(), })) // Mock feature flags @@ -65,6 +67,10 @@ vi.mock('@/lib/api-key/byok', () => ({ getBYOKKey: (...args: unknown[]) => mockGetBYOKKey(...args), })) +vi.mock('@/lib/auth/internal', () => ({ + generateInternalToken: (...args: unknown[]) => mockGenerateInternalToken(...args), +})) + vi.mock('@/lib/billing/core/usage-log', () => ({})) vi.mock('@/lib/core/rate-limiter/hosted-key', () => ({ @@ -1154,6 +1160,34 @@ describe('MCP Tool Execution', () => { expect(result.timing).toBeDefined() }) + it('should embed userId in JWT when executionContext is undefined (agent block path)', async () => { + mockGenerateInternalToken.mockResolvedValue('test-token') + + global.fetch = Object.assign( + vi.fn().mockImplementation(async () => ({ + ok: true, + status: 200, + json: () => + Promise.resolve({ + success: true, + data: { output: { content: [{ type: 'text', text: 'OK' }] } }, + }), + })), + { preconnect: vi.fn() } + ) as typeof fetch + + await executeTool('mcp-123-test_tool', { + query: 'test', + _context: { + workspaceId: 'workspace-456', + workflowId: 'workflow-789', + userId: 'user-abc', + }, + }) + + expect(mockGenerateInternalToken).toHaveBeenCalledWith('user-abc') + }) + describe('Tool request retries', () => { function makeJsonResponse( status: number,