master-zapier-plan-draft/research/zapier/MCP-REFERENCE.md
George Lambert b4150c8250 Milestone 0: import zappier billing, Verae middleware, and Zapier research
Compose-ready workspace: packages/zappier (rate card, portal, Stripe),
packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier
(CLI app), vendor/zapier-platform, and research/zapier vendor corpus.

Gate 0 structure checks pass. Product code and research are not yet wired.
2026-09-09 02:37:36 -04:00

12 KiB
Raw Permalink Blame History

Zapier MCP function reference

Grok start: db.platform_reference.findOne({ kind: "guide", key: "build-new-connector" })
or 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

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

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

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

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

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

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<string, unknown>;   // 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

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). paramsbundle.inputData. Empty results = not found, not an error.

Input

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<string, unknown>;   // 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

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

// 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

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

type Input = {
  selected_api: string;
  include_shared?: boolean;
  limit?: number;   // 1100, 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

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(12000), feedback_positive: boolean } Product inbox.

Official first-run prompt:

Run the Zapier onboarding skill using get_zapier_skill with name "zapier:onboarding" and follow its instructions.

Client connection (TypeScript)

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

# refresh live schemas (optional)
# then:
source ~/.mcp-env
.venv/bin/python scripts/ingest-mcp-reference.py