Fix catalog book links and rewrite PDF destinations to live HTTPS.
Some checks are pending
offline / test (push) Waiting to run

Module and model book cards now point at generated index.html/index.pdf
instead of directory URLs that 404. WeasyPrint file:// annotations are
mapped to https://zapier.georgelambert.org/ paths that exist. Developer
module, architecture, and research snapshot links target published files.
This commit is contained in:
George Lambert 2026-09-11 22:50:00 -04:00
parent 666eca79a1
commit 85b5b53ea9
26 changed files with 2253 additions and 35 deletions

View file

@ -0,0 +1,362 @@
# 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; // 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**
```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(12000), 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
```