> ## Documentation Index
> Fetch the complete documentation index at: https://www.plungeai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool reference

> Every tool the server exposes, in the order tools/list returns them. You rarely call these by name: your client reads the list when it connects and picks the tool from your request. This chapter is the exact contract behind that choice. The server is https://mcp.plungeai.com/v1; …


Source: `orchestration/mcp-gateway/server.ts` (`TOOL_DEFS`, `StatusOutputSchema`, `validateToolArgs`), `orchestration/mcp-gateway/tools.ts` (zod schemas and handlers), `orchestration/mcp-gateway/tool-exec.ts` (`GetToolContractSchema`, `ExecuteToolSchema`), `orchestration/mcp-gateway/extras.ts` (`TemplatesSchema`, `ScheduleSchema`, `WhoamiSchema`), `orchestration/mcp-gateway/tools-bots.ts` and `tools-triggers.ts` (the bot, execution-steer and trigger actions), `orchestration/mcp-gateway/user-context-arg.ts` (`user_context`), `orchestration/mcp-gateway/shared.ts` (`formatArg`, `userRequest`, length bounds), `orchestration/mcp-gateway/tool-outcome.ts` (`ToolOutcomeSchema`, `renderAs`), `orchestration/mcp-gateway/chat.ts`, `orchestration/mcp-gateway/conversation.ts`, `orchestration/mcp-gateway/index.ts` (argument pre-screen, fenced tools).

Every tool the server exposes, in the order `tools/list` returns them. You rarely call these by name: your client reads the list when it connects and picks the tool from your request. This chapter is the exact contract behind that choice. The server is `https://mcp.plungeai.com/v1`; `https://api.plungeai.com/v1/mcp` is the same server and returns the same list.

**How to read the tables.**

- **Type** is the JSON type with the server's bound: `string (max 256)` is at most 256 characters, `integer 1–100` an integer in that range. An enum lists every accepted value.
- **Required** is what the input schema enforces: "yes" or "no". "For `<action>`" or "one of" means the schema accepts the call without the key, but that action, or the call, refuses to run without it.
- **Default** is what happens when you leave the key out: the schema default, or the default the handler applies. "—" means no default.
- A call whose arguments do not match the schema is not run. It comes back as a 📝 NEEDS INPUT outcome naming each bad or missing field, with `isError: false` ([Errors, feedback & limits](/mcp/errors-limits)).

**Two parameters recur.**

- `user_request`, on every tool: a string (max 4,000), optional. It carries the user's request verbatim, in their own words, before the client turned it into arguments. The server instructions ask clients to always send it: the platform uses it for request context, routing and support diagnostics. Some tools also show it as the run's title.
- `format`, on nine tools: `markdown` (the default) or `json`. `json` returns the same answer as a JSON document in the text and the same object as `structuredContent` ([Protocol & transport](/mcp/protocol)).

**Annotations.** Six tools carry `readOnlyHint: true`: `plungeai_get_tool_contract`, `plungeai_list_agents`, `plungeai_list_workflows`, `plungeai_get_result`, `plungeai_get_workflow_status` and `plungeai_whoami`. Several other tools have read-only actions (for example `plungeai_executions` `list`), but the flag is per tool. Seven tools declare an `outputSchema`: `plungeai_execute_workflow`, `plungeai_execute_agent`, `plungeai_get_tool_contract`, `plungeai_execute_tool`, `plungeai_run_mission` and `plungeai_learn` declare the outcome envelope ([Tools](/mcp/tools)), and `plungeai_get_workflow_status` declares its status object.

**Keys can be fenced.** A key limited to some tools does not see the others in `tools/list`, and a call to one answers JSON-RPC `-32602` `Tool not permitted for this key: <name>` ([Authentication & keys](/mcp/authentication)).

| # | Tool | Read-only | Output schema | Chapter |
|---|---|---|---|---|
| 14.1 | `plungeai_execute_workflow` | no | outcome | [8](/mcp/workflows) |
| 14.2 | `plungeai_execute_agent` | no | outcome | [7](/mcp/agents-missions) |
| 14.3 | `plungeai_get_tool_contract` | yes | outcome | [5.4](/mcp/discovery#54-the-invocation-contract--plungeai_get_tool_contract) |
| 14.4 | `plungeai_execute_tool` | no | outcome | [6](/mcp/tools) |
| 14.5 | `plungeai_run_mission` | no | outcome | [7](/mcp/agents-missions) |
| 14.6 | `plungeai_learn` | no | outcome | [10](/mcp/chat-memory-skills) |
| 14.7 | `plungeai_list_agents` | yes | — | [5](/mcp/discovery) |
| 14.8 | `plungeai_list_workflows` | yes | — | [8.1](/mcp/workflows#81-find-your-workflows--plungeai_list_workflows) |
| 14.9 | `plungeai_get_result` | yes | — | [9](/mcp/runs-results) |
| 14.10 | `plungeai_get_workflow_status` | yes | status | [9](/mcp/runs-results) |
| 14.11 | `plungeai_workflow` | no | — | [8](/mcp/workflows) |
| 14.12 | `plungeai_executions` | no | — | [9](/mcp/runs-results) |
| 14.13 | `plungeai_followup` | no | — | [9](/mcp/runs-results) |
| 14.14 | `plungeai_continue` | no | — | [9](/mcp/runs-results) |
| 14.15 | `plungeai_chat` | no | — | [10](/mcp/chat-memory-skills) |
| 14.16 | `plungeai_build_workflow` | no | — | [8](/mcp/workflows) |
| 14.17 | `plungeai_memory` | no | — | [10](/mcp/chat-memory-skills) |
| 14.18 | `plungeai_templates` | no | — | [5.5](/mcp/discovery#55-workflow-templates--plungeai_templates-list-and-get), [8.9](/mcp/workflows#89-start-from-a-template--plungeai_templates-use) |
| 14.19 | `plungeai_schedule` | no | — | [11](/mcp/scheduling) |
| 14.20 | `plungeai_whoami` | yes | — | [2](/mcp/authentication) |
| 14.21 | `plungeai_companies` | no | — | [16](/mcp/companies) |
| 14.22 | `plungeai_connections` | no | — | [17](/mcp/connections) |

## 14.1 plungeai_execute_workflow

Execute a CNL workflow: a saved one (`workflow_id`) or ad-hoc YAML (`workflow_yaml`). Streams progress. Use `mode:"async"` for long runs (over 3 minutes): it returns an execution id to poll with `plungeai_get_workflow_status`. In ad-hoc YAML, write long strings as block scalars (`prompt: |`) and never hard-wrap a value; structured tool-agents take their card's parameters as task fields next to `agent:`. Always answers with a structured outcome, never a raw error: follow the remediation instead of retrying the identical call.

- **Read-only:** no. **Output schema:** the outcome envelope. **Creates an execution:** yes.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words; also the run's title when the question lives inside the YAML |
| `workflow_yaml` | string (max 262,144) | one of `workflow_yaml` / `workflow_id` | — | ad-hoc CNL. The `workflow:` wrapper is optional: bare top-level `name` / `tasks` is wrapped for you |
| `workflow_id` | string (max 256) | one of `workflow_yaml` / `workflow_id` | — | the id of one of your saved workflows. Wins if both are passed |
| `input` | string (max 65,536) | no | — | the run's input, used where the workflow references `{input}` |
| `inputs` | object, string keys (max 128) → string values (max 8,192) | no | — | named inputs |
| `mode` | enum `sync`, `async` | no | `sync` | `async` starts a background run and returns at once |
| `user_context` | object: `time_zone`, `locale`, `place`, `latitude`, `longitude`, `accuracy_m`, `source` (`device` or `network`, default `device`) | no | the request's network location | where and when the user is: the agent's local time and its default schedule zone. Wins over the network guess; a value that does not validate (an unknown zone, a malformed locale) is dropped |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** `ok` with the run's output and the execution-id footer. `ok` with only the execution id for `mode:"async"`. `needs_input` when neither YAML nor id is given, when the saved id is not on your account (``No saved workflow with id `<id>` on this account.``), or when the YAML does not parse. `unavailable` when ad-hoc YAML names an agent that does not exist or is not active, before anything runs. `needs_approval` / `needs_input` when the run pauses for you. A failed run is classified into an outcome; an invalid-YAML failure adds a tip on quoting and block scalars.

Runs a model and costs credits (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_execute_workflow","arguments":{"user_request":"run a one-task pong workflow","workflow_yaml":"name: pong-demo\ntasks:\n  - type: task\n    id: t1\n    agent: one-agent\n    prompt: \"Reply with only the word: pong\"\n"}}}'
```

## 14.2 plungeai_execute_agent

Execute a single prompt-driven agent, for example `one-agent` (call mode; add a `persona` for a specialist answer). Pass `session_id` to start or continue a conversational agent. Structured tool-agents (cards with a Parameters table, such as `markitdown` or `weather-agent`) take typed fields, not prose: use `plungeai_get_tool_contract` and `plungeai_execute_tool` for those. Always answers with a structured outcome, never a raw error: follow the remediation instead of retrying the identical call.

- **Read-only:** no. **Output schema:** the outcome envelope. **Creates an execution:** yes (not for a refusal).

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `agent` | string (max 256) | yes | — | a registry agent id; must be `status:active` |
| `prompt` | string (max 65,536) | yes | — | the prompt |
| `persona` | string (max 256) | no | — | a persona id; `one-agent` answers in that voice |
| `model` | string (max 256) | no | the agent's default | checked against the live model catalog before anything runs. Dated variants match their catalog id by prefix. The catalog entry also sets the provider |
| `provider` | string (max 256) | no | the model's catalog provider | overrides the provider |
| `maxTokens` | integer 1–64,000 | no | — | maximum output tokens |
| `max_tokens` | integer 1–64,000 | no | — | alias of `maxTokens`; `maxTokens` wins if both are passed |
| `temperature` | number 0–2 | no | — | sampling temperature |
| `top_p` | number 0–1 | no | — | nucleus sampling |
| `reasoning_effort` | enum `low`, `medium`, `high`, `xhigh` | no | — | reasoning effort for models that support it |
| `thinking_level` | string (max 256) | no | — | passed through to the agent |
| `streaming` | boolean | no | `true` | `false` opts this call out of forced streaming |
| `session_id` | string (max 256) | no | — | starts or continues a conversation with the agent |
| `user_context` | object: `time_zone`, `locale`, `place`, `latitude`, `longitude`, `accuracy_m`, `source` (`device` or `network`, default `device`) | no | the request's network location | where and when the user is: the agent's local time and its default schedule zone. Wins over the network guess; a value that does not validate (an unknown zone, a malformed locale) is dropped |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** `ok` with the agent's output and the execution-id footer. `unavailable` for an unknown or inactive agent, with live alternatives and no run created. `needs_input` for a model that is not in the catalog (``Unknown model `<id>` … Nothing was executed.``) with up to five near matches. `needs_approval` / `needs_input` when the agent pauses. Failures are classified into an outcome.

Runs a model and costs credits (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_execute_agent","arguments":{"user_request":"ask one-agent what a Durable Object is","agent":"one-agent","prompt":"In one sentence: what is a Cloudflare Durable Object?","model":"claude-sonnet-4-5","max_tokens":80}}}'
```

## 14.3 plungeai_get_tool_contract

The exact invocation contract for one registry agent: the JSON Schema of its parameters, its operations (with approval gates), worked YAML examples, its output shape, and your live credential status (platform-managed, or "connect Google first"). Fetch it before the first `plungeai_execute_tool` call to an unfamiliar agent: the contract is the API docs.

- **Read-only:** yes. **Output schema:** the outcome envelope. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `agent_id` | string (max 256) | yes | — | a registry agent id |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** `ok`, whose `contract` holds `agent_id`, `name`, `description`, `operations[]` (`{name, description?, required_params?}`), `inputSchema` (JSON Schema for `params`), `examples[]` (`{title, cnl}`), `output_type`, `soleRequiredParam` (when exactly one string parameter is required) and `credentials[]` (per provider: `provider`, `tier` = `platform` / `oauth_connector` / `byok_api_key`, `required`, optional `operations`, `connected`, `status`, `accountEmail`). The Markdown adds a **Credentials** section (platform-managed, ✅ connected as …, ⚠️ NOT connected or expired, with where to connect) and a ready `plungeai_execute_tool` line. `unavailable` for an unknown or inactive agent, with alternatives. `error` if the registry did not answer.

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_get_tool_contract","arguments":{"user_request":"what does the weather agent need from me?","agent_id":"weather-agent"}}}'
```

## 14.4 plungeai_execute_tool

Execute one structured tool-agent directly with typed params: `{agent_id, operation?, params}`. Runs through the engine with full observability; use `mode:"async"` for long runs. Always answers with a structured outcome, never a raw error: `ok` → the result; `needs_input` → the missing fields and the schema; `needs_connection` / `needs_api_key` → tell the user exactly what to connect in our apps, then retry; `needs_approval` → relay the ⏸ block and use `plungeai_continue` after the user decides; `unavailable` → real alternatives. Follow the remediation; do not retry the identical call blind.

- **Read-only:** no. **Output schema:** the outcome envelope. **Creates an execution:** yes (not for a refusal).

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words; also shown as the run's input |
| `agent_id` | string (max 256) | yes | — | a registry agent id; must be `status:active` |
| `operation` | string (max 128) | no | the card's default operation | one of the contract's `operations[].name`. Also fills the card's `action` / `op` / `operationType` selector parameter when you did not set it |
| `params` | object, string keys (max 128) → any value | no | `{}` | typed parameters, validated against the contract. Names that collide with task-envelope fields are refused |
| `prompt` | string (max 65,536) | no | — | free text. Satisfies missing requireds on prompt-capable agents; mapped (with a warning) onto a card's only free-text required parameter when you send no `params` |
| `mode` | enum `sync`, `async` | no | `sync` | `async` starts a background run and returns at once |
| `user_context` | object: `time_zone`, `locale`, `place`, `latitude`, `longitude`, `accuracy_m`, `source` (`device` or `network`, default `device`) | no | the request's network location | where and when the user is: the agent's local time and its default schedule zone. Wins over the network guess; a value that does not validate (an unknown zone, a malformed locale) is dropped |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** Checks run in this order, and every refusal happens before a run exists: the active-only card check (`unavailable`), contract validation (`needs_input` with `missing` and the contract), the credential pre-flight (`needs_connection` / `needs_api_key`). Then the engine runs the task: `ok` with the result, any `warnings`, and the execution-id footer; `needs_approval` when an outward, irreversible operation (send, pay, transfer, buy, withdraw) is stopped by the trust fence, with nothing run, no remediation actions and no paused session: despite the description's `plungeai_continue` hint, `plungeai_continue` cannot resume it, and it runs only from Ocean Studio ([6.6](/mcp/tools#66-the-trust-fence--needs-approval)); `needs_approval` / `needs_input` when the agent pauses (`⏸ AWAITING USER APPROVAL` / `⏸ AWAITING USER`), which `plungeai_continue` does resume; a classified outcome on failure.

Runs a tool agent and creates an execution (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_execute_tool","arguments":{"user_request":"current weather in Sun Valley, Idaho","agent_id":"weather-agent","operation":"current","params":{"location":"Sun Valley, Idaho"}}}}'
```

## 14.5 plungeai_run_mission

Run a bounded autonomous agent mission (a loop agent): a goal, an optional tool fence and an iteration cap. Recalls and writes long-term memory automatically. Defaults to async: poll `plungeai_get_workflow_status`. Always answers with a structured outcome, never a raw error: follow the remediation instead of retrying the identical call.

- **Read-only:** no. **Output schema:** the outcome envelope. **Creates an execution:** yes. There is no `format` parameter.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `goal` | string (max 65,536) | yes | — | what the mission must achieve |
| `agent` | string (max 256) | no | `one-agent` | the loop runtime that runs the mission; omitted, the gateway sends `agent: one-agent` explicitly. A named agent passes the active-only fence |
| `mission` | string (max 65,536) | no | `You are a capable autonomous agent. Achieve the goal thoroughly and cite sources.` | the mission's standing instructions |
| `allowed_tools` | array of string (max 256 each), at most 50 | no | `["web_search", "web_fetch", "task_complete"]` | the tool fence |
| `max_iterations` | integer 1–50 | no | `8` | the iteration cap |
| `success_criteria` | array of string (max 2,000 each), at most 20 | no | — | what counts as done |
| `persona` | string (max 256) | no | — | a persona id |
| `skills` | array of string (max 256 each), at most 20 | no | — | skill ids to inject, including your learned skills |
| `mode` | enum `sync`, `async` | no | `async` | `sync` waits for the result |
| `user_context` | object: `time_zone`, `locale`, `place`, `latitude`, `longitude`, `accuracy_m`, `source` (`device` or `network`, default `device`) | no | the request's network location | where and when the user is: the agent's local time and its default schedule zone. Wins over the network guess; a value that does not validate (an unknown zone, a malformed locale) is dropped |

**Returns.** Async: `ok` with ``Started mission `<id>` (async). …`` and the execution id. Sync: `ok` with the mission's output (also when it stopped at `max_iterations`: a sync mission never reports `incomplete`, [7.7](/mcp/agents-missions#77-mission-bounds)), `needs_approval` / `needs_input` when it pauses, or a classified outcome on failure.

Runs an agent loop and costs credits (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_run_mission","arguments":{"user_request":"what is notable about Sun Valley, Idaho?","goal":"Three sourced bullets on what is notable about Sun Valley, Idaho.","max_iterations":6,"success_criteria":["three bullets","a source URL per bullet"]}}}'
```

## 14.6 plungeai_learn

Manage your private skill library. `action: learn` (the default) distills a URL, PDF text or a past workflow into a reusable skill with the `learn` pre-built agent (needs `source`; defaults to async, poll `plungeai_get_workflow_status`). `action: list` returns your learned skills (id and summary). `action: forget` deletes one by `name` (the id from `list`). Always answers with a structured outcome, never a raw error: follow the remediation instead of retrying the identical call.

- **Read-only:** no. **Output schema:** the outcome envelope. **Creates an execution:** `learn` only.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `learn`, `list`, `forget` | no | `learn` | `learn`: distill `source` into a skill · `list`: your learned skills · `forget`: delete one |
| `source` | string (1–65,536) | for `learn` | — | a URL, text or Markdown to distill, or a description of what you just did. Checked before the tool runs |
| `name` | string (max 256) | for `forget` | picked automatically on `learn` | the skill id, kebab-case |
| `mode` | enum `sync`, `async` | no | `async` | for `learn` |

**Returns.** `learn`: `ok` with the execution id to poll (async), or the run's result (sync). `list`: `ok` with `N learned skill(s).` and one line per skill, or `No learned skills yet.`. `forget`: `ok` ``Forgot skill `<name>`.``, or `needs_input` (no `name`), `error` (no such skill), `unavailable` (not yours). See [Skills](/mcp/chat-memory-skills#103-skills-plungeai_learn).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_learn","arguments":{"user_request":"what skills have I learned?","action":"list"}}}'
```

## 14.7 plungeai_list_agents

Discover platform building-block agents in the live registry, the capability catalog. These are registry agents, not the user's own agents: for "show me my agents / workflows" use `plungeai_list_workflows`. `search` is a hybrid semantic and keyword query: describe the capability in natural language (for example "web search", "pdf to markdown"). Prefer `search` / `category` filters; an unfiltered list returns the whole catalog (about 90 agents, large). The catalog is active-only and execution refuses any id that is not active, so take ids from here, not from memory. Fetch one full card with `agent_id`. With `format:"json"` the result is `{content: <markdown>}`: its source is rendered registry markdown, and typed rows are a follow-up.

- **Read-only:** yes. **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `search` | string (max 2,000) | no | — | a natural-language capability description |
| `category` | string (max 256) | no | — | a registry category (for example `financials`, not `finance`) |
| `agent_id` | string (max 256) | no | — | returns that one agent's full card |
| `kind` | enum `agents`, `personas`, `experts`, `skills`, `models`, `workflows`, `connectors` | no | `agents` | which card set to search. `workflows` means registry workflow cards, not your saved workflows |
| `limit` | integer 1–100 | no | 25 with `search` or `category`, 100 without | how many cards |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** Registry Markdown: the matching cards, or one full card for `agent_id`. The active-only filter applies to `kind: "agents"`. An `agent_id` that does not exist, or is not active, gets an explanation and the closest live matches instead of the card. `Registry unavailable — try again shortly.` (`isError: true`) when the registry does not answer.

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_list_agents","arguments":{"user_request":"which agents can search the web?","search":"web search"}}}'
```

## 14.8 plungeai_list_workflows

List your saved workflows, which is what users usually mean by "my agents". With no filters it shows your folders (rubrics) and your most recent workflows; filter with `folder`, `search` and/or `kind`.

- **Read-only:** yes. **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `search` | string (max 2,000) | no | — | matches workflow names, case-insensitive substring |
| `folder` | string (max 2,000) | no | — | matches folder names, case-insensitive substring |
| `kind` | enum `workflow`, `agent`, `bot`, `campaign` | no | — | only that kind |
| `limit` | integer 1–100 | no | `50` | how many workflows |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** Without filters: `# Your Workflows (N most recent)`, a **Folders:** line with every non-empty folder and its count, and a table: Name, Kind, Folder, ID, Description. With filters: `# Your Workflows (N)` and the same table. `No workflows found. …` / `No workflows matched. …` when empty. JSON: `{"workflows": [{id, name, description, kind, folder}]}`.

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_list_workflows","arguments":{"user_request":"show me my workflows in the Finance folder","folder":"Finance","format":"json"}}}'
```

## 14.9 plungeai_get_result

Retrieve the result of one of your executions by `execution_id`. For conversational runs it includes the full conversation thread (all follow-up turns), as Studio shows it. Pass `task_id` to read one task's output (for example one branch of a workflow) instead of the final result. The output is final, user-ready Markdown: show it verbatim and complete, never summarize or re-type it. With `format:"json"` the result is the `GET /v1/executions/{id}/output` body (`execution_id`, `status`, `content`, `final_task_id`, `steps`, `continuation`), not the rendered thread; with `task_id` it is `{execution_id, task_id, result}`.

- **Read-only:** yes. **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `execution_id` | string (max 256) | one of `execution_id` / `workflow_id` | — | the execution id (preferred). The engine's `exec-…` id is also accepted |
| `workflow_id` | string (max 256) | one of `execution_id` / `workflow_id` | — | older alias of `execution_id`; it still takes an execution id, not a workflow id |
| `task_id` | string (max 256) | no | the final task | one task's output instead of the full result |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** The full result: an identity line, the final output, a **Steps in this run** index for multi-step runs, the **Conversation thread** when there are follow-up turns, and a ⏸ block when the run is paused. When there is no output it says why: failed, still running, or no longer stored. An unknown or foreign id is `needs_input`. Details: [9.2](/mcp/runs-results#92-get-a-result-plungeai_get_result).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_get_result","arguments":{"user_request":"show me the result of that last run","execution_id":"<execution_id>"}}}'
```

## 14.10 plungeai_get_workflow_status

Check the status of one of your executions (it self-heals stuck runs). It also returns structured content, including `continuation` when the run is paused awaiting the user's approval or answer: relay that to the user and use `plungeai_continue`.

- **Read-only:** yes. **Output schema:** the status object. **Creates an execution:** no. There is no `format` parameter; `structuredContent` is always present.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `execution_id` | string (max 256) | yes | — | the execution id, or the engine's `exec-…` id |

**Returns.** A Markdown status block and `structuredContent` with `execution_id`, `status` (`running`, `completed`, `incomplete`, `failed`, `cancelled`; `incomplete` only for async runs, since a sync call stamps its run `ok`, which then reads `completed`), `error_message`, `workflow_name`, `started_at`, `duration_ms`, `final_task_id` and `continuation` (`{status, agent, question, pending_action}` or null). A `running` row with a stored result is healed to `completed`; one with no heartbeat for more than 960 seconds is marked `failed` (`Interrupted (run did not complete)`; the reason shows from the next read on). Details: [9.3](/mcp/runs-results#93-check-status-plungeai_get_workflow_status).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_get_workflow_status","arguments":{"user_request":"is that still running?","execution_id":"<execution_id>"}}}'
```

## 14.11 plungeai_workflow

Manage your saved workflows: `action` `create`, `get`, `update`, `delete`, `save_version`, `list_versions`, `get_version`, `restore_version` or `a2a_door`. Create, update and delete sync live to Studio, iMini and the other apps. `a2a_door` manages the workflow's Agent2Agent door (see [8.6](/mcp/workflows#86-manage-saved-workflows--plungeai_workflow)). The bot actions work on a saved bot you own: `permissions_get` / `permissions_set` (class presets, admin locks, spend caps), `files` / `file` (its persistent workspace), `inbox`, `bindings` / `bind` / `unbind` (paired chats) and, by group name, `groups` / `group_set` / `group_delete` / `group_thread`.

- **Read-only:** no (`get`, `list_versions` and `get_version` only read). **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `create`, `get`, `update`, `delete`, `list_versions`, `get_version`, `save_version`, `restore_version`, `a2a_door`, `permissions_get`, `permissions_set`, `files`, `file`, `inbox`, `bindings`, `bind`, `unbind`, `groups`, `group_set`, `group_delete`, `group_thread` | yes | — | what to do |
| `workflow_id` | string (max 256) | for every action except `create` and the group actions | — | the workflow (for the bot actions, the saved bot) |
| `name` | string (max 512) | for `create` | — | the workflow's name; `update` renames |
| `yaml` | string (max 262,144) | for `create` | — | the CNL YAML. Validated before it is saved, on `create` and `update` |
| `description` | string (max 2,000) | no | — | `create` / `update` |
| `folder` | string (max 2,000) | no | — | `create`: file into this folder. `update`: move into it; `none` or `""` takes it out of its folder. Matched case-insensitively: the exact name first, else a single partial match |
| `kind` | enum `workflow`, `agent`, `bot`, `campaign` | no | `workflow` on create | the sidebar section: Flows, Agents, Bot agents or Campaigns |
| `campaign_config` | object, string keys (max 64) → any value | no | — | `create` with `kind: campaign`: the ledger and schedule, `{list: {inline, table, agent or csv}, cycle, max_attempts, schedule?, deliver?, …}`. Refused before anything is saved when it is malformed; without it the campaign is saved with a warning and no ledger |
| `version_id` | string (max 256) | for `get_version`, `restore_version` | — | a version id from `list_versions` |
| `version_description` | string (max 2,000) | no | — | a note for `save_version` |
| `door_action` | enum `mint`, `get`, `pause`, `resume`, `revoke` | for `a2a_door` | — | `mint` creates the door (or rotates its token), `get` shows it, `pause`/`resume` close and reopen it, `revoke` deletes it |
| `handle` | string (max 64) | no | the workflow's name as a slug | `a2a_door` `mint`: the door's URL handle, 3–63 lowercase letters, digits or dashes |
| `classes` | object, string keys (max 16) → string (max 16) | no | — | `permissions_set`: class → preset, `send` / `write` / `pay` / `delete` → `allow` / `ask` / `deny` / `hand_off`. A field present replaces the stored one |
| `locks` | array of string (max 16 each), at most 8 | no | — | `permissions_set`: the classes an admin locks. Only a team admin over the workflow may set them (`lock_admin_required`); a refused call writes nothing |
| `budget_usd_run` | number ≥ 0 or null | no | — | `permissions_set`: the spend cap per run in USD; `null` clears it |
| `budget_usd_month` | number ≥ 0 or null | no | — | `permissions_set`: the spend cap per month in USD; `null` clears it |
| `path` | string (max 512) | for `file` | — | a workspace path as `files` lists it. The file comes back as base64, at most 5 MB |
| `channel` | string (max 20) | for `bind`, `unbind` | — | the paired channel: `telegram`, `whatsapp`, `discord` or `teams` |
| `sender_id` | string (max 128) | for `bind`, `unbind` | — | the paired chat's sender id |
| `group` | string (max 40) | for `group_set`, `group_delete`, `group_thread` | — | the bot group's name |
| `members` | array of string (max 256 each), at most 6 | for `group_set` | — | the group's 2 to 6 member bot ids; `group_set` creates the group or replaces its members |

**Returns.** `create`: ``Created workflow **<name>** (`<id>`). … Synced to all apps.``, with ``Filed under **<folder>**.`` or a ⚠️ note when the folder did not match (then it is created without a folder). `get`: the name, description and YAML, or `needs_input` when not found. `update`: ``Updated workflow `<id>`. Synced to all apps.`` with folder and kind notes; an unknown folder refuses the whole update. `delete`: ``Deleted workflow `<id>`. …``; a bot's memory namespace `<you>:bot:<id>` and scheduler jobs, or a campaign's jobs and ledger, are cleaned up after the row is gone (best effort; `update` with a `kind` that leaves `bot` or `campaign` does the same for the old kind). `save_version`: ``Saved version V<n> (`<version id>`).``. `list_versions`: a table of Version, ID, When, Note. `get_version`: that version's YAML. `restore_version`: `Restored — new version V<n>.`. `a2a_door` `mint`: ``A2A door **<url>** minted for **<name>**.`` with the token (shown once; minting again rotates it), the agent-card URL and a `curl` SendMessage recipe; `get`: the door's URL, status and kind, or `No A2A door for **<name>** yet.`; `pause`/`resume`: ``A2A door of **<name>** is now paused|active.``; `revoke`: ``A2A door of **<name>** revoked — …``. `permissions_get` / `permissions_set`: the classes, locks and caps as a list and a JSON block; `permissions_get` also lists `effective`, the preset each of the four classes runs under (the stored one, else `allow`). `files`: a table of path, size, type and update time; `file`: the file name, type and size and the bytes as a base64 block (a file over 5 MB is refused `file_too_large` with its One API download path). `inbox` and `group_thread`: a table of the queued messages. `bindings`: the chats bound to the bot, or a note when channel bindings are not enabled yet; `bind` / `unbind`: a confirmation. `groups`, `group_set`, `group_delete`: the groups and the change. Every bot refusal is ``Error: <message> (<code>)`` with the same codes as the One API (`workflow_not_found`, `lock_admin_required`, `invalid_params`, `file_not_found`, `not_paired`, `name_taken`, …). A workflow you do not own answers `Workflow not found.` on `update` / `delete` and the version actions (`get` returns a `needs_input` outcome), but ``Error: no saved workflow with that id for this account (workflow_not_found)`` on the bot actions above (and a group you do not own, addressed by name, answers `Group "<name>" not found.`). CNL validation and kind-lint warnings are appended; a validation or kind-lint error (for example `memory_owner` in the YAML) refuses the save (`Workflow YAML failed CNL validation: …`). A missing required field answers `Error: <field> is required for action "<action>"`.

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_workflow","arguments":{"user_request":"show me my Acquisition Scanner workflow","action":"get","workflow_id":"<workflow_id>"}}}'
```

## 14.12 plungeai_executions

Browse your execution history: `action` `list`, `get`, `output`, `conversation`, `files`, `delete`, `cancel` or `steer`. `cancel` stops a running execution cooperatively: it stops at its next turn or tool boundary. `steer` queues a `message` for a running execution, delivered at its next turn; `files` lists the files the run wrote. Outputs are final, user-ready Markdown (tables, threads): show them verbatim and complete, never summarize or re-type them.

- **Read-only:** no (`delete` and `cancel` change state). **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `list`, `get`, `output`, `conversation`, `delete`, `cancel`, `steer`, `files` | yes | — | what to do |
| `execution_id` | string (max 256) | for every action except `list` | — | the execution |
| `workflow_id` | string (max 256) | no | — | `list`: only runs of this workflow |
| `message` | string (max 65,536) | for `steer` | — | `steer`: the message queued for the running execution |
| `limit` | integer 1–100 | no | `20` | `list`: page size |
| `offset` | integer 0–100,000 | no | `0` | `list`: rows to skip |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** `list`: `# Executions (N)`, newest first (ID, Question, Workflow, Status, Source, When); JSON `{"executions": [{id, input, workflow_name, status, start_time, duration, source}]}`. `get`: the status answer of `plungeai_get_workflow_status`. `output`: the full result of `plungeai_get_result`. `conversation`: the follow-up thread; JSON `{execution_id, messages}`. `cancel`: ``Cancelling execution `<id>` — …`` (running runs only). `steer`: ``Queued your message to running execution `<id>` …``, or an error when the run already finished (use `plungeai_followup`). `files`: a table of the files the run wrote. `delete`: ``Deleted execution `<id>`.``; this cannot be undone. Details: [9.4](/mcp/runs-results#94-run-history-plungeai_executions).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_executions","arguments":{"user_request":"show me my last 5 executions","action":"list","limit":5,"format":"json"}}}'
```

## 14.13 plungeai_followup

Ask a follow-up about a completed execution: it continues the run's agent session, or researches with the prior context. If the execution is still running, the message is queued and injected at its next turn (steering); if it has finished, the conversation continues.

- **Read-only:** no. **Output schema:** none. **Creates an execution:** no; the turn is added to the run's conversation thread.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `execution_id` | string (max 256) | yes | — | the run to follow up on |
| `prompt` | string (max 65,536) | yes | — | the follow-up message |

**Returns.** Running: ``Queued your message to running execution `<id>` (delivered at its next turn).`` Finished: the answer as Markdown, plus a ⏸ block if the agent pauses again. Errors (`isError: true`): `Execution not found.`, `Followup agent call failed`, `Failed to retrieve follow-up response`. Details: [9.5](/mcp/runs-results#95-follow-ups-plungeai_followup).

Runs a model and costs credits (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_followup","arguments":{"user_request":"now focus on the competitive landscape","execution_id":"<execution_id>","prompt":"Do the same analysis, but focus on the competitive landscape."}}}'
```

## 14.14 plungeai_continue

Continue a paused conversation: answer a question (`message`) or approve a pending action (`approve: true`). Pass `approve: true` only after the user explicitly confirmed; never approve on your own. To deny or change course, pass the user's words as `message`.

- **Read-only:** no. **Output schema:** none. **Creates an execution:** no; the agent runs again inside the paused run.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `execution_id` | string (max 256) | yes | — | the paused run |
| `message` | string (max 65,536) | one of `message` / `approve: true` | — | the user's answer, denial or change of course |
| `approve` | boolean | one of `message` / `approve: true` | — | `true` approves the staged action. Wins over `message` if both are passed; `false` alone is refused |

**Returns.** The agent's reply, then either a new ⏸ block or `✅ Conversation resolved (no further input needed).` It resumes an agent pause (`⏸ AWAITING USER APPROVAL` / `⏸ AWAITING USER`); a trust-fence `⏸ NEEDS APPROVAL` with no actions has no session and answers `No conversation session…` ([6.6](/mcp/tools#66-the-trust-fence--needs-approval)). Errors (`isError: true`): `` Provide `message` or `approve: true` ``, `Execution not found`, `No conversation session for this execution (expired or not a conversational agent)`, `This run isn't paused — it already completed. Use plungeai_followup …`, `Agent continuation failed`. Details: [9.6](/mcp/runs-results#96-paused-runs-plungeai_continue).

Runs the held action, which may spend money; send it only after the user said yes (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_continue","arguments":{"user_request":"yes, go ahead","execution_id":"<execution_id>","approve":true}}}'
```

## 14.15 plungeai_chat

Persistent chat with the PlungeAI assistant (platform tools and web search): `action` `send`, `new`, `list_sessions` or `history`. Conversations appear in Studio and the CLI.

- **Read-only:** no (`list_sessions` and `history` only read). **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `send`, `list_sessions`, `history`, `new` | yes | — | what to do |
| `message` | string (max 65,536) | for `send` | — | `send`: the turn. `new`: only the title (first 50 characters) |
| `conversation_id` | string (max 256) | for `history` | a new conversation (`send`) | the conversation to continue or read |
| `user_context` | object: `time_zone`, `locale`, `place`, `latitude`, `longitude`, `accuracy_m`, `source` (`device` or `network`, default `device`) | no | the request's network location | where and when the user is: the agent's local time and its default schedule zone. Wins over the network guess; a value that does not validate (an unknown zone, a malformed locale) is dropped |

**Returns.** `send`: the assistant's reply and ``_(conversation: `<id>`)_``. `new`: ``Created conversation `<id>`. …``. `list_sessions`: `# Your conversations (N)` (Title, ID, Messages) for the 20 most recent, or `No conversations yet.`. `history`: `# <title>` and every turn. Details: [10.1](/mcp/chat-memory-skills#101-chat-plungeai_chat).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_chat","arguments":{"user_request":"list my conversations","action":"list_sessions"}}}'
```

## 14.16 plungeai_build_workflow

Generate a new workflow from a goal, or refine an existing one (`workflow_id` + `instruction`), with the platform builder. The result is saved, so it appears everywhere (live sync).

- **Read-only:** no. **Output schema:** none. **Creates an execution:** no; it creates or updates a saved workflow.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `goal` | string (max 65,536) | for a new workflow | — | what the workflow should do, in plain language |
| `workflow_id` | string (max 256) | for a refine | — | the workflow to change |
| `instruction` | string (max 65,536) | for a refine | — | the change to apply. With `workflow_id`, a refine wins over `goal` |

**Returns.** New: ``Created workflow **<name>** (`<id>`). Synced to all apps. Run it with plungeai_execute_workflow.`` and the YAML. The name is the builder's own generated name, or the first 60 characters of the goal when the YAML has no plain `name:` line. Refine: ``Updated workflow **<name>** (`<id>`). Synced to all apps.`` and the YAML; the YAML is replaced in place, so save a version first if you may want to roll back. A generated workflow that fails CNL validation is not saved; the answer shows the errors and the YAML. Other errors (`isError: true`): ``Provide either `goal` (new) or `workflow_id` + `instruction` (refine).``, `Workflow not found: <id>`, `Workflow builder did not return a workflow section.` It reports generating, validating and saving on the progress channel while it works (30–60 seconds).

Runs a model, costs credits and saves a workflow (not verified here):

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_build_workflow","arguments":{"user_request":"build me a workflow that scans a company for acquisition news and writes a briefing","goal":"Scan a company for acquisition news and write a one-page briefing with sources."}}}'
```

## 14.17 plungeai_memory

Long-term memory scoped to you: `action` `recall`, `remember`, `search_runs`, `get_run` or `forget`. `remember` writes the durable store that `recall` reads (`target` `user` or `memory`, `operation` `add`, `replace`, `remove` or `read`); use it when the user asks to remember something. Past-run history is separate: `search_runs` / `get_run` read the run journal, which `recall` deliberately does not include.

- **Read-only:** no (`remember` writes, except `operation: "read"`; `forget` deletes). **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `recall`, `remember`, `search_runs`, `get_run`, `forget` | yes | — | what to do |
| `query` | string (max 2,000) | for `search_runs` | — | keywords matched against run goals |
| `run_id` | string (max 256) | for `get_run` | — | a run id from `search_runs` |
| `entry_id` | string (max 256) | for `forget`, one of `entry_id` / `content` | — | `forget`: one entry's id (`mem_…`, as `GET /v1/memory` lists it) |
| `target` | enum `user`, `memory` | no | `memory` | `remember`: which store |
| `operation` | enum `add`, `replace`, `remove`, `read` | no | `add` | `remember`: what to do |
| `content` | string (max 65,536) | for `add`, `replace`; for `forget`, one of `entry_id` / `content` | — | the entry to store; `forget`: every entry containing it is removed from both stores |
| `old_text` | string (max 2,000) | for `replace`, `remove` | — | a substring that identifies exactly one existing entry |
| `limit` | integer 1–100 | no | `10` | `search_runs`: how many runs |

**Returns.** `recall`: both stores (memory, then the user profile), or `No memory recorded yet.`. `remember`: ``Saved to memory (<usage>). recall will see it immediately.``, or for `read` the entries under `# Memory (<target>)`; a write over the budget is refused with the current entries. `search_runs`: `# Matching runs` with `` `<run id>` — <goal> `` lines. `get_run`: the stored run, or `Run not found.`. `forget`: ``Forgot <n> memory entries.``, or `Memory entry not found.` for an id your stores do not hold. Details: [10.2](/mcp/chat-memory-skills#102-memory-plungeai_memory).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_memory","arguments":{"user_request":"what do you remember about our fiscal year?","action":"recall"}}}'
```

## 14.18 plungeai_templates

Workflow templates: `action` `list`, `get` or `use`. `use` creates a workflow in your account from the template (optional `name` and `folder`).

- **Read-only:** no (`list` and `get` only read; `use` creates a workflow). **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `list`, `get`, `use` | yes | — | what to do |
| `template_id` | string (max 256) | for `get`, `use` | — | a template id from `list` |
| `category` | string (max 256) | no | — | `list`: exact category |
| `name` | string (max 512) | no | `<template name> (copy)`; a bot template keeps its own name | `use`: the new workflow's name |
| `folder` | string (max 2,000) | no | — | `use`: file the new workflow into this folder |
| `limit` | integer 1–100 | no | `50` | `list`: how many templates |

**Returns.** `list`: `# Workflow Templates (N)` with Name, Kind, Category, Difficulty, Used, ID and Description, featured templates first, or `No active workflow templates.`. `get`: the template's name, description, category, difficulty, use count and YAML. `use`: ``Created workflow **<name>** (`<id>`) from template **<template>**. … Run it with plungeai_execute_workflow.``; the template's use count goes up by one. Errors (`isError: true`): `template_id is required for this action.`, `Template not found: <id>`, `Template content missing from storage.`.

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_templates","arguments":{"user_request":"what workflow templates are available?","action":"list","limit":10}}}'
```

## 14.19 plungeai_schedule

Scheduled (cron) jobs: `action` `stats`, `list`, `get`, `create`, `update`, `pause`, `resume`, `delete`, `run_now`, `runs` or `wake`. `create` needs `name`, `job_type` (`agent`, `query`, `workflow` or `heartbeat`), `target` and `schedule`; `create` also takes `mission_ref` to schedule a pre-built agent card, `ends_at` to stop the job at a time, and `schedule: "@once"` with `run_at` for a one-time run. `wake` fires the job's saved workflow once with a `note`. The triggers of a job are the actions `webhook_mint` / `webhook_list` / `webhook_delete` / `webhook_rotate`, `email_mint` / `email_list` / `email_delete` / `email_rotate` and `hooks_mint` / `hooks_list` / `hooks_delete`. A rotate mints a successor with the same settings, then revokes the old trigger.

- **Read-only:** no (`stats`, `list`, `get` and `runs` only read). **Output schema:** none. **Creates an execution:** `run_now` and every scheduled tick do, except for heartbeat jobs ([11.3](/mcp/scheduling#113-create-a-job)).

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `stats`, `list`, `get`, `create`, `update`, `pause`, `resume`, `delete`, `run_now`, `runs`, `wake`, `webhook_mint`, `webhook_list`, `webhook_delete`, `webhook_rotate`, `email_mint`, `email_list`, `email_delete`, `email_rotate`, `hooks_mint`, `hooks_list`, `hooks_delete` | yes | — | what to do |
| `job_id` | string (max 256) | for `get`, `update`, `pause`, `resume`, `delete`, `run_now`, `wake` and every trigger action | — | a job id (`job_…`); `runs` takes it as a filter |
| `name` | string (max 512) | for `create` | — | the job's name; for agent, query and `mission_ref` jobs it also names the wrapper workflow `Scheduled: <name>` |
| `description` | string (max 2,000) | no | — | free text |
| `job_type` | enum `agent`, `query`, `workflow`, `heartbeat` | for a plain `create` | — | not needed with `mission_ref` |
| `target` | string (max 262,144) | for a plain `create` | — | `agent`: an agent id. `query`: JSON `{"agent", "query"}`. `workflow`: one of your workflow ids |
| `schedule` | string (max 128) | for `create` | — | a five-field cron expression |
| `timezone` | string (max 64) | no | UTC | the IANA zone the cron is read in |
| `run_at` | string (max 64) | for `create` with `schedule: "@once"` | — | the one-time run: an ISO-8601 time with a UTC offset, e.g. `2026-10-06T09:00:00Z`. Missing, `create` answers `run_at required` and saves nothing |
| `ends_at` | string (max 64) | no | — | `create` / `update`: the job stops after this ISO-8601 time |
| `parameters` | object, string keys (max 128) → any value | no | — | job extras: `prompt` (the per-run goal), `inputs`, and `deliver`: an array of `{channel, chat_id?, to?}` with `channel` one of `inapp`, `email`, `slack`, `telegram`, `whatsapp`, `discord`, `teams`. A bare `{channel:"slack"}` DMs the owner, a bare `{channel:"email"}` mails the owner's registered address, other email addresses must be confirmed recipients |
| `limit` | integer 1–100 | no | `50` for `list`, `20` for `runs` | how many rows |
| `mission_ref` | string (max 256) | no | — | a pre-built agent card id; schedules the card as a one-task harness workflow |
| `check_agent` | string (max 256) | for a heartbeat, unless `check_workflow` | — | the active agent that checks the condition |
| `check_workflow` | string (max 256) | no | — | a saved workflow id run as the check instead of `check_agent`; its last task answers YES or NO |
| `condition_prompt` | string (max 4,096) | for a heartbeat | — | the condition, answered YES or NO each tick |
| `trigger_workflow` | string (max 256) | no | — | heartbeat: the workflow id to run when the condition is met |
| `notify_channel` | enum `telegram`, `whatsapp`, `discord`, `slack`, `teams`, `email` | no | — | heartbeat: where to notify (WhatsApp sends nothing today) |
| `notify_chat_id` | string (max 128) | no | — | heartbeat: the chat or address to notify; needed together with `notify_channel` |
| `note` | string (max 512) | no | — | `wake`: the note the woken run receives as its input |
| `trigger_id` | string (max 256) | for `webhook_delete`, `webhook_rotate`, `email_delete`, `email_rotate`, `hooks_delete` | — | the token (webhook, email) or id (hooks) the list shows |
| `prompt_template` | string (max 16,384) | no | — | `webhook_mint`: the run's prompt, filled from the payload |
| `scheme` | string (max 64) | no | `generic` | `webhook_mint`: the provider signature scheme |
| `filters` | object, string keys (max 64) → any value | no | — | `webhook_mint`: payload filters `{all?: Rule[], any?: Rule[]}`; a payload that does not match does not fire |
| `allowed_from` | string (max 16,384) | no | anyone | `email_mint`: comma-separated senders allowed to trigger the run |
| `url` | string (max 512) | for `hooks_mint` | — | `hooks_mint`: the https URL called, signed, on the listed run events |
| `events` | array of string (max 64 each), at most 16 | for `hooks_mint` | — | `hooks_mint`: the run events that call the URL |

**Returns.** Markdown text per action: tables for `list` and `runs`, the job as JSON for `get`, a one-line confirmation for the writes, and for `run_now` the execution id to poll. `wake`: the time the woken run starts. The trigger actions answer with the scheduler's JSON in a block: a mint or a rotate shows its secret once and never again. Errors are `isError: true` text that names the cause. Details: [Scheduling](/mcp/scheduling).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"what do I have scheduled?","action":"stats"}}}'
```

## 14.20 plungeai_whoami

Show the authenticated identity: user id, tier, key label and rate-limit window.

- **Read-only:** yes. **Output schema:** none. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `format` | enum `markdown`, `json` | no | `markdown` | answer format |

**Returns.** `# Who am I` with User, Auth (type and tier), Key (label and key id), Rate window (`<n>/min used · <n>/day used`, left out when the counter cannot be read) and Server. JSON: `{"user", "auth_type", "tier", "key_label", "key_id", "rate_window": {"minute_used", "day_used"} or null, "server"}`. Details: [Authentication & keys](/mcp/authentication).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_whoami","arguments":{"user_request":"who am I?"}}}'
```

## 14.21 plungeai_companies

Your companies, action for action the One API's `/v1/companies`: a campus compiled from your saved campus, building and office documents (`kind: campus` / `building` workflows), its items, the gates at its door, its mode and its clock. Every rule lives in company-service; the tool calls it as you. A campus you do not own is the same `not_found` as one that does not exist.

- **Read-only:** no (`list`, `layout`, `snapshot`, `events`, `slice` and `approvals` only read). **Output schema:** none; every answer also carries `structuredContent`. **Creates an execution:** `decide` with `approve` on a tool permission continues the paused execution once; the company's clock starts office runs after `start`.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `list`, `apply`, `layout`, `snapshot`, `events`, `ingest`, `slice`, `item_create`, `item_pause`, `item_resume`, `item_retry`, `item_cancel`, `item_steer`, `approvals`, `decide`, `mode`, `start`, `stop`, `delete` | yes | — | what to do |
| `campus` | string (max 64) | for every action but `list` | — | the campus slug |
| `building` | string (max 64) | for `slice`, `item_create` | — | a building slug of the campus |
| `since` | integer ≥ 0 | no | `0` | `events`: the seq to read after |
| `limit` | integer 1–1,000 | no | `200` | `events`: how many |
| `events` | array (at most 200) of `{building, type, item_id?, office?, data?, at?}` | for `ingest` | — | `ingest`: a local building's events |
| `item_id` | string (max 256) | for `item_pause`, `item_resume`, `item_retry`, `item_cancel`, `item_steer` | — | the item |
| `title` | string (max 300) | for `item_create` | — | the item's title |
| `body` | string (max 65,536) | no | — | `item_create`: the item's text |
| `kind` | enum `feature`, `bugfix`, `docs`, `research`, `content`, `task` | no | — | `item_create`: the item's kind |
| `priority` | integer | no | — | `item_create`: higher goes first |
| `tier` | string (max 32) | no | — | `item_create`: the item's tier word |
| `text` | string (max 65,536) | for `item_steer` | — | the message for the item's running office |
| `status` | enum `pending`, `approved`, `rejected`, `expired` | no | all | `approvals`: only gates in this state |
| `approval_id` | string (max 256) | for `decide` | — | the gate |
| `decision` | enum `approve`, `reject` | for `decide` | — | only after the user decided |
| `note` | string (max 65,536) | no | — | `decide`: kept with the decision |
| `mode` | enum `supervised`, `tiered`, `autonomous` | for `mode` | — | who decides the gates |

**Returns.** A heading line and the One API's response body as a JSON block, the same body as `structuredContent`. A refusal is `isError: true` text `<word>: <message> (<code>)` with `structuredContent.error = {status, code, message}`, the word standing for the REST status: `invalid` (400/422), `forbidden` (401/403), `not_found` (404), `conflict` (409), `unavailable` (5xx). `delete` of a running campus is `conflict` (stop it first). Details: [Companies](/mcp/companies).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_companies","arguments":{"user_request":"which companies do I have?","action":"list"}}}'
```

## 14.22 plungeai_connections

Your connected accounts, action for action the One API's `/v1/connections`: `list`, `add` (an API key for a key-based provider), `remove`, `link` (a signed single-use Studio link to connect a provider). `on_behalf_of` acts on one of your customers instead of you.

- **Read-only:** no (`list` only reads; every list is written to the secrets audit log). **Output schema:** none; every answer also carries `structuredContent`. **Creates an execution:** no.

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `user_request` | string (max 4,000) | no | — | the user's words |
| `action` | enum `list`, `add`, `remove`, `link` | yes | — | what to do |
| `provider` | string (max 64) | for `add`, `remove`, `link` | — | the provider id, e.g. `stripe`, `github`, `google-gmail` |
| `on_behalf_of` | string (max 128) | no | you | one of your customers: 1–128 characters of `A-Z a-z 0-9 _ . -`, no `..` |
| `api_key` | string (max 4,096) | for `add` | — | the provider's key; checked with the provider where the platform has a probe |
| `api_secret` | string (max 4,096) | no | — | `add`: the secret of a key pair |
| `return_url` | string (max 2,048) | no | — | `link`: the https URL the customer returns to |

**Returns.** A heading line and the One API's response body as a JSON block, the same body as `structuredContent`: `list` `{connections: [{provider, on_behalf_of, method, status, connected_at}]}` (never key material), `add` `{provider, on_behalf_of, status: "connected"}`, `remove` `{…, status: "disconnected"}`, `link` `{url, expires_at}` (15 minutes, single use). Refusals use the same `<word>: <message> (<code>)` shape as `plungeai_companies`: `not_found` `unknown_provider` / `connection_not_found`, `invalid` `missing_api_key` / `credential_rejected` / `invalid_on_behalf_of` / `invalid_return_url`, `forbidden` `owner_not_found`, `unavailable` `connections_unavailable`. Details: [Connections](/mcp/connections).

```bash
curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_connections","arguments":{"user_request":"what accounts have I connected?","action":"list"}}}'
```
