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.
12 KiB
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). params → bundle.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; // 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
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:
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