* Execute an MCP tool via the server-side MCP endpoint * * @param toolId - MCP tool ID in format "mcp-serverId-toolName" * @param params - Tool parameters * @param executionContext - Execution context * @param requestId - Request ID for logging * @param startTimeISO - Start time for timing
( toolId: string, params: Record<string, any>, executionContext?: ExecutionContext, requestId?: string, startTimeISO?: string, signal?: AbortSignal )
| 1997 | * @param startTimeISO - Start time for timing |
| 1998 | */ |
| 1999 | async function executeMcpTool( |
| 2000 | toolId: string, |
| 2001 | params: Record<string, any>, |
| 2002 | executionContext?: ExecutionContext, |
| 2003 | requestId?: string, |
| 2004 | startTimeISO?: string, |
| 2005 | signal?: AbortSignal |
| 2006 | ): Promise<ToolResponse> { |
| 2007 | const actualRequestId = requestId || generateRequestId() |
| 2008 | const actualStartTime = startTimeISO || new Date().toISOString() |
| 2009 | |
| 2010 | try { |
| 2011 | logger.info(`[${actualRequestId}] Executing MCP tool: ${toolId}`) |
| 2012 | |
| 2013 | const { serverId, toolName } = parseMcpToolId(toolId) |
| 2014 | |
| 2015 | const baseUrl = getInternalApiBaseUrl() |
| 2016 | |
| 2017 | const mcpScope = resolveToolScope(params, executionContext) |
| 2018 | |
| 2019 | const headers: Record<string, string> = { 'Content-Type': 'application/json' } |
| 2020 | |
| 2021 | if (typeof window === 'undefined') { |
| 2022 | try { |
| 2023 | const internalToken = await generateInternalToken(mcpScope.userId) |
| 2024 | headers.Authorization = `Bearer ${internalToken}` |
| 2025 | } catch (error) { |
| 2026 | logger.error(`[${actualRequestId}] Failed to generate internal token:`, error) |
| 2027 | } |
| 2028 | } |
| 2029 | |
| 2030 | // Handle two different parameter structures: |
| 2031 | // 1. Direct MCP blocks: arguments are stored as JSON string in 'arguments' field |
| 2032 | // 2. Agent blocks: arguments are passed directly as top-level parameters |
| 2033 | let toolArguments = {} |
| 2034 | |
| 2035 | // First check if we have the 'arguments' field (direct MCP block usage) |
| 2036 | if (params.arguments) { |
| 2037 | if (typeof params.arguments === 'string') { |
| 2038 | try { |
| 2039 | toolArguments = JSON.parse(params.arguments) |
| 2040 | } catch (error) { |
| 2041 | logger.warn(`[${actualRequestId}] Failed to parse MCP arguments JSON:`, params.arguments) |
| 2042 | toolArguments = {} |
| 2043 | } |
| 2044 | } else { |
| 2045 | toolArguments = params.arguments |
| 2046 | } |
| 2047 | } else { |
| 2048 | // Agent block usage: extract MCP-specific arguments by filtering out system parameters |
| 2049 | toolArguments = Object.fromEntries( |
| 2050 | Object.entries(params).filter(([key]) => !MCP_SYSTEM_PARAMETERS.has(key)) |
| 2051 | ) |
| 2052 | } |
| 2053 | |
| 2054 | if (mcpScope.callChain && mcpScope.callChain.length > 0) { |
| 2055 | headers[SIM_VIA_HEADER] = serializeCallChain(mcpScope.callChain) |
| 2056 | } |
no test coverage detected