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.
362 lines
12 KiB
Markdown
362 lines
12 KiB
Markdown
# 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<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`
|
||
|
||
```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<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`
|
||
|
||
```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
|
||
```
|