# Zapier MCP function reference **Grok start:** `db.platform_reference.findOne({ kind: "guide", key: "build-new-connector" })` or [PLATFORM-REFERENCE.md](PLATFORM-REFERENCE.md). This file is the MCP branch. Mongo: `db.platform_reference.find({ kind: "mcp_function" })` — one document per tool, with JSON Schema, typed inputs, outputs, internals, related tools, and code. Hosted server: `https://mcp.zapier.com/api/v1/connect` (closed source, Streamable HTTP). Plugin repo only: `repos/zapier-mcp` (skills + manifests). Live input schemas captured in `raw/site-extras/zapier-mcp-tools-gumloop.json`. Official docs still list **14** meta-tools. Live servers expose **17**: the 14 plus `list_zapier_connections`, `manage_zapier_connections`, and rolling-out `write_code_action`. --- ## Call graph ``` auto_provision_mcp (also runs on OAuth connect) │ ▼ discover_zapier_actions ──► enable_zapier_action ──► manage_zapier_connections │ │ └──────────────► inspect_zapier_actions ◄── list_zapier_connections (repeat for enums / dynamic fields) ┌───────────────┴───────────────┐ ▼ ▼ execute_zapier_read_action execute_zapier_write_action │ │ └──────── write_code_action ────┘ Skills: list_zapier_skills → get_zapier_skill("zapier:onboarding") create_zapier_skill / update_zapier_skill / delete_zapier_skill Config UI: get_configuration_url Feedback: send_feedback ``` Safety: reads run free; writes need explicit user approval after you show the payload. Billing: each **successful** execute costs **2 Zapier tasks**. Meta-tools do not. Failures are free. Never invent `selected_api` (Gmail is `GoogleMailV2CLIAPI`, not `GmailCLIAPI`) or action keys. Always `inspect_zapier_actions` first. --- ## Action management ### `discover_zapier_actions` Search the 9,000+ app catalog for actions this server *could* enable. Call before saying an app is unavailable. **Internals:** Catalog lookup (same directory as SDK `listApps` / `listActions`). No OAuth, no mutation. Returns `selected_api` that later tools require verbatim. **Input** ```ts type Input = { app?: string; // Search by name. Omit for popular apps. }; ``` **Output (documented):** `{ apps: [{ app, selected_api, actions[] }] }` **Related:** `enable_zapier_action`, `inspect_zapier_actions`, `manage_zapier_connections` **SDK twin:** `zapier.listApps({ search })`, `zapier-sdk list-apps --search` ```ts await client.callTool({ name: "discover_zapier_actions", arguments: { app: "gmail" }, }); ``` --- ### `enable_zapier_action` Add one action (or `*` / omit for all) for a catalog app to this server. **Internals:** Writes mcp.zapier.com server config. If the user has no connection, returns `auth_url`. Does not call the partner API. **Input** ```ts type Input = { selected_api: string; // e.g. "GoogleMailV2CLIAPI" from discover app_display_name?: string; // "Gmail" — for friendly confirmations action?: string; // key, or "*" / omit for all }; ``` **Output:** enabled action list, which execute tool to use (read vs write), optional `auth_url`. **Related:** `discover_zapier_actions`, `inspect_zapier_actions`, `disable_zapier_action`, `manage_zapier_connections` ```ts await client.callTool({ name: "enable_zapier_action", arguments: { selected_api: "GoogleMailV2CLIAPI", app_display_name: "Gmail", action: "find_email", }, }); ``` --- ### `disable_zapier_action` Remove one action, or every action for `selected_api`. Does not revoke the Zapier connection. **Input** ```ts type Input = { selected_api: string; app_display_name?: string; action?: string; // omit = disable the whole app on this server }; ``` **Related:** `inspect_zapier_actions`, `enable_zapier_action` --- ### `inspect_zapier_actions` **Call this first before every execute.** Lists enabled apps/actions and resolves dynamic fields. **Internals:** Reads this server's enabled-action table. With `tool_name` + `enum_property` it hits the same Platform dynamic-dropdown endpoint as the visual builder. With parent `params` it returns `dynamic_properties_schema` for fields that depend on earlier answers (spreadsheet → worksheet). Does not run the partner action. **Input** ```ts type Input = { selected_api?: string; action?: string; tool_name?: string; // collision-safe id from a prior inspect connection_id?: number | string; // only if not using the default account enum_property?: string; // field with is_dynamic_enum: true enum_search?: string; enum_cursor?: string; params?: Record; // parent values for dependent fields }; ``` **Output (documented):** apps → actions with `action`, `tool_name`, execute tool name, parameter schema (`is_dynamic_enum`, `dynamic_properties_depends_on`), `connections.default`, plus `dynamic_enum_values` / `dynamic_properties_schema` on follow-up calls. **Related:** both `execute_*`, `discover_zapier_actions`, `list_zapier_connections` **SDK twin:** `getActionInputFieldsSchema`, `list-action-input-field-choices` ```ts await client.callTool({ name: "inspect_zapier_actions", arguments: {} }); await client.callTool({ name: "inspect_zapier_actions", arguments: { tool_name: "SlackCLIAPI.send_channel_message", enum_property: "channel", enum_search: "launches", }, }); ``` --- ### `auto_provision_mcp` One-shot setup from the user's **own** existing Zapier connections (not shared teammates'). Also runs automatically after OAuth connect. Returns enabled apps plus top Zap titles (skill ideas). No inputs. **Related:** `inspect_zapier_actions`, `enable_zapier_action` --- ## Execution ### `execute_zapier_read_action` Run a search / lookup / get. No confirmation required. **2 tasks** on success. **Internals:** Maps to Zapier Platform search/read `perform` (`runAction({ actionType: "search"|"read" })`) using the user's default connection (or `connection_id`). `params` → `bundle.inputData`. Empty results = not found, not an error. **Input** ```ts type Input = { selected_api: string; action: string; // exact key from inspect — never guess tool_name?: string; // preferred when keys collide across apps connection_id?: number | string; params?: Record; // nest dynamic fields under dynamic_properties }; ``` **Output:** action-specific records (`results[]` or `data[]`). 401 → `manage_zapier_connections`. **Related:** `inspect_zapier_actions`, `discover_zapier_actions`, `enable_zapier_action` **SDK twin:** `repos/sdk/examples/by-app/*/find-*.ts` ```ts await client.callTool({ name: "execute_zapier_read_action", arguments: { selected_api: "GoogleMailV2CLIAPI", action: "find_email", tool_name: "GoogleMailV2CLIAPI.find_email", params: { query: "from:sarah@acme.com newer_than:7d" }, }, }); ``` If the user said only a first name, do **not** take the first hit — list candidates. --- ### `execute_zapier_write_action` Create / update / send. **Show the payload and wait for explicit approval.** **2 tasks** on success. Not rolled back. **Input:** same shape as the read execute. **Related:** `inspect_zapier_actions`, `execute_zapier_read_action` **SDK twin:** `repos/sdk/examples/by-app/gmail/send-email.ts` ```ts // 1) inspect + resolve channel enum 2) confirm with user 3) write await client.callTool({ name: "execute_zapier_write_action", arguments: { selected_api: "SlackCLIAPI", action: "send_channel_message", tool_name: "SlackCLIAPI.send_channel_message", params: { channel: "C01234567", text: "Release shipped, monitoring now" }, }, }); ``` --- ### `write_code_action` (rolling out) Generate a sandboxed custom action when the catalog has no match. Auth is injected from the connected account — **never put secrets in `requirements`**. Same-name call overwrites. **Internals:** Zapier generates code and runs later invokes in a sandbox with the app connection. Closest SDK analog is `zapier.fetch(url, { connection, method })`. **Input** ```ts type Input = { selected_api: string; code_action_name: string; // e.g. "list_channel_users" requirements: string; // natural language; endpoint, filters, pagination }; ``` **Related:** `discover_zapier_actions`, `inspect_zapier_actions` --- ## Connections ### `list_zapier_connections` List OAuth grants for one app. Default = the user's own accounts. Set `include_shared: true` only if they asked. **Input** ```ts type Input = { selected_api: string; include_shared?: boolean; limit?: number; // 1–100, default 20 cursor?: string; }; ``` **Output (documented):** `{ connections: [{ connection_id, title, owner, is_default, expired }], next_cursor? }` **SDK twin:** `zapier.findFirstConnection`, `zapier-sdk find-first-connection` --- ### `manage_zapier_connections` Mint an `auth_url` and/or set `default_connection_id`. An app **cannot execute** until it has a default connection. After the user finishes OAuth, list then optionally set default. **Input** ```ts type Input = { selected_api: string; // verbatim from discover/inspect app_display_name?: string; default_connection_id?: number | string; }; ``` **SDK twin:** `zapier-sdk create-connection` / `get-connection-start-url` --- ## Skills, config, feedback | Tool | Input | What it does | |------|--------|----------------| | `list_zapier_skills` | `{}` | Names + one-line descriptions. Catalog is dynamic. | | `get_zapier_skill` | `{ name }` | Full Markdown. Packaged: `zapier:onboarding`. | | `create_zapier_skill` | `{ name, description, skillDefinition }` | Persist Markdown. Lock IDs with `ZapierAction[app:action](param: "id", runtime)`. Resolve schemas via `inspect_zapier_actions` (tool text still says `list_enabled_zapier_actions`). | | `update_zapier_skill` | `{ name, description?, skillDefinition? }` | Patch. | | `delete_zapier_skill` | `{ name }` | Permanent. | | `get_configuration_url` | `{}` | Dashboard URL for this server. | | `send_feedback` | `{ feedback: string(1–2000), feedback_positive: boolean }` | Product inbox. | Official first-run prompt: ```text Run the Zapier onboarding skill using get_zapier_skill with name "zapier:onboarding" and follow its instructions. ``` --- ## Client connection (TypeScript) ```ts import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( new URL("https://mcp.zapier.com/api/v1/connect"), { requestInit: { headers: { Authorization: `Bearer ${token}` } } }, ); const client = new Client({ name: "app", version: "1.0.0" }); await client.connect(transport); const tools = await client.listTools(); ``` Listed clients use OAuth to that same URL and never see the token. --- ## Plugin skills (not server tools) In `repos/zapier-mcp/plugins/zapier/skills/`: | Skill | When | |-------|------| | `zapier-onboard` | First connect / “what is Zapier MCP” | | `zapier-demo` | One read action, live | | `zapier-explore` | Role-tailored toolkit | | `zapier-status` | Health / audit / diagnose | Lifecycle rules (`zapier-lifecycle.mdc`): prefer native app MCP over Zapier when both exist; never call both. --- ## Reload ```bash # refresh live schemas (optional) # then: source ~/.mcp-env .venv/bin/python scripts/ingest-mcp-reference.py ```