Execute Pica Action
execute_pica_actionPerform operations on third-party platforms via Pica by executing predefined actions such as fetching data or creating tasks. Ensure user intent is confirmed and call get_pica_action_knowledge first for accurate execution.
Instructions
Execute a Pica action to perform actual operations on third-party platforms. CRITICAL: Only call this when the user's intent is to EXECUTE an action (e.g., 'read my last Gmail email', 'fetch 5 contacts from HubSpot', 'create a task in Asana'). DO NOT call this when the user wants to BUILD or CREATE code/forms/applications - in those cases, stop after get_pica_action_knowledge and provide implementation guidance instead. REQUIRED WORKFLOW: Must call get_pica_action_knowledge first. If uncertain about execution intent or parameters, ask for confirmation before proceeding.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action object with ID, path, and method | |
| connectionKey | Yes | Key of the connection to use | |
| data | No | Request data (for POST, PUT, etc.) | |
| headers | No | Additional headers | |
| isFormData | No | Whether to send data as multipart/form-data | |
| isFormUrlEncoded | No | Whether to send data as application/x-www-form-urlencoded | |
| pathVariables | No | Variables to replace in the path | |
| platform | Yes | Platform name | |
| queryParams | No | Query parameters |
Implementation Reference
- src/index.ts:262-280 (handler)The main handler function for the execute_pica_action tool. Initializes Pica if needed and delegates to picaClient.executePassthroughRequest to perform the actual API execution, then formats the response.
async function handleExecutePicaAction(args: ExecutePicaActionArgs) { try { const result = await picaClient.executePassthroughRequest(args); return { content: [ { type: "text" as const, text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpError( ErrorCode.InternalError, `Failed to execute Pica action: ${error instanceof Error ? error.message : 'Unknown error'}` ); } } - src/index.ts:114-121 (registration)Registers the execute_pica_action tool with the MCP server, providing the tool config and handler lambda that calls handleExecutePicaAction.
server.registerTool( "execute_pica_action", executePicaActionToolConfig, async (args: z.infer<typeof executePicaActionZodSchema>) => { await initializePica(); return await handleExecutePicaAction(args as ExecutePicaActionArgs); } ); - src/schemas.ts:38-48 (schema)Zod input schema definition for the execute_pica_action tool parameters.
export const executePicaActionInputSchema = { platform: z.string().describe("Platform name"), actionId: z.string().describe("Action ID from search_pica_platform_actions"), connectionKey: z.string().describe("Key of the connection to use"), data: z.any().optional().describe("Request data (for POST, PUT, etc.)"), pathVariables: z.record(z.union([z.string(), z.number(), z.boolean()])).optional().describe("Variables to replace in the path"), queryParams: z.record(z.any()).optional().describe("Query parameters"), headers: z.record(z.string()).optional().describe("Additional headers"), isFormData: z.boolean().optional().describe("Whether to send data as multipart/form-data"), isFormUrlEncoded: z.boolean().optional().describe("Whether to send data as application/x-www-form-urlencoded") }; - src/schemas.ts:109-113 (schema)Tool configuration object including title, description, and reference to input schema.
export const executePicaActionToolConfig = { title: "Execute Pica Action", description: "Execute a Pica action to perform actual operations on third-party platforms. CRITICAL: Only call this when the user's intent is to EXECUTE an action (e.g., 'read my last Gmail email', 'fetch 5 contacts from HubSpot', 'create a task in Asana'). DO NOT call this when the user wants to BUILD or CREATE code/forms/applications - in those cases, stop after get_pica_action_knowledge and provide implementation guidance instead. REQUIRED WORKFLOW: Must call get_pica_action_knowledge first. If uncertain about execution intent or parameters, ask for confirmation before proceeding.", inputSchema: executePicaActionInputSchema }; - src/client.ts:232-339 (helper)Supporting utility in PicaClient that performs the actual HTTP passthrough request to execute the Pica action, handling path variables, form data, headers, etc.
async executePassthroughRequest(args: ExecutePicaActionArgs): Promise<ExecutePassthroughResponse> { const { actionId, connectionKey, data, pathVariables, queryParams, headers, isFormData, isFormUrlEncoded, } = args; // Fetch action details const action = await this.getActionDetails(actionId); const method = action.method; const contentType = isFormData ? 'multipart/form-data' : isFormUrlEncoded ? 'application/x-www-form-urlencoded' : 'application/json'; const requestHeaders = { ...this.generateHeaders(), 'x-pica-connection-key': connectionKey, 'x-pica-action-id': action._id, 'Content-Type': contentType, ...headers }; const finalActionPath = pathVariables ? replacePathVariables(action.path, pathVariables) : action.path; const normalizedPath = finalActionPath.startsWith('/') ? finalActionPath : `/${finalActionPath}`; const url = `${this.baseUrl}/v1/passthrough${normalizedPath}`; // Check if action has "custom" tag and add connectionKey to body if needed const isCustomAction = action.tags?.includes('custom'); let requestData = data; if (isCustomAction && method?.toLowerCase() !== 'get') { requestData = { ...data, connectionKey }; } const requestConfig: RequestConfig = { url, method, headers: requestHeaders, params: queryParams }; if (method?.toLowerCase() !== 'get') { if (isFormData) { const formData = new FormData(); if (requestData && typeof requestData === 'object' && !Array.isArray(requestData)) { Object.entries(requestData).forEach(([key, value]) => { if (typeof value === 'object') { formData.append(key, JSON.stringify(value)); } else { formData.append(key, String(value)); } }); } requestConfig.data = formData; Object.assign(requestConfig.headers, formData.getHeaders()); } else if (isFormUrlEncoded) { const params = new URLSearchParams(); if (requestData && typeof requestData === 'object' && !Array.isArray(requestData)) { Object.entries(requestData).forEach(([key, value]) => { if (typeof value === 'object') { params.append(key, JSON.stringify(value)); } else { params.append(key, String(value)); } }); } requestConfig.data = params; } else { requestConfig.data = requestData; } } const sanitizedConfig = { ...requestConfig, headers: { ...requestConfig.headers, 'x-pica-secret': '***REDACTED***' } }; try { const response: AxiosResponse = await axios(requestConfig); return { requestConfig: sanitizedConfig, responseData: response.data }; } catch (error) { console.error("Error executing passthrough request:", error); if (axios.isAxiosError(error)) { throw new Error(`Failed to execute passthrough request: ${error.response?.status} ${error.response?.statusText}`); } throw new Error("Failed to execute passthrough request"); } }