> ## 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.

# Discovery

> Before you run anything, find it. Discovery is three steps. Each one is a read-only tool call that costs no credits:


Source: `orchestration/mcp-gateway/server.ts` (`TOOL_DEFS`, `SERVER_INSTRUCTIONS`), `orchestration/mcp-gateway/tools.ts` (`ListAgentsSchema`, `listAgents`), `orchestration/mcp-gateway/tool-exec.ts` (`getToolContract`), `orchestration/mcp-gateway/credential-preflight.ts`, `orchestration/mcp-gateway/registry-cards.ts`, `orchestration/mcp-gateway/extras.ts` (`TemplatesSchema`, `plungeaiTemplates`), `core/core-base/tool-contract.ts`, `orchestration/registry/registry.ts` (search markdown, `KIND_GROUPS`); registry reads live-verified 2026-09-24.

Before you run anything, find it. Discovery is three steps. Each one is a read-only tool call that costs no credits:

```
Find      ──►  plungeai_list_agents         search the live registry (active agents only)
Inspect   ──►  plungeai_get_tool_contract   typed params, operations, approval gates, YOUR credential status
Execute   ──►  plungeai_execute_tool · plungeai_execute_agent · an agent: task in a workflow
```

`plungeai_templates` (`list` / `get`) is the fourth discovery tool. It lists ready-made workflows. All examples use `https://mcp.plungeai.com/v1`. `https://api.plungeai.com/v1/mcp` is the same server behind the One API ([Overview](/mcp)). Every tool accepts `user_request`, the user's words verbatim. Always send it ([Protocol & transport](/mcp/protocol)). Full parameter tables are in the [Tool reference](/mcp/tool-reference).

## 5.1 Registry agents vs your workflows

Two different things are both called "agents". The server's `initialize` instructions teach every client the difference (`SERVER_INSTRUCTIONS` in `server.ts`):

| Term | What it is | Tool | The user says |
|---|---|---|---|
| **registry agent** | A platform building block in the catalog (`brave-agent`, `sec-agent`, `markitdown`, …). Workflows are built from them. | `plungeai_list_agents` | "agents in the registry", "what can the platform do", "which agent should I use for…" |
| **your workflows** | Your saved CNL workflows. Users call these "my agents". | `plungeai_list_workflows` ([8.1](/mcp/workflows#81-find-your-workflows--plungeai_list_workflows)) | "show me my agents", "my workflows", "what's in my Finance folder" |

An unqualified "show me my agents" means **your workflows**. `plungeai_list_agents` is only for the registry: when the user says registry, discovery or platform agents, or when the client itself is choosing building blocks for a workflow.

`plungeai_list_agents` with `kind: "workflows"` searches the registry's public workflow cards. Those are not your workflows.

## 5.2 Search the registry — `plungeai_list_agents`

One tool, five modes. The mode is picked from the arguments you send:

| You send | Mode | What comes back |
|---|---|---|
| `search` | Hybrid semantic + keyword search over live cards | The top matches (default **25**) with *Good at* and *Not for → use X instead* for each |
| `category` | Filter by registry category | Every active agent in that category (default 25) |
| `search` + `category` | Both | Matches inside that category |
| `agent_id` | One full card | The complete card markdown ([5.3](#53-read-one-full-card--agent_id)) |
| nothing (or only `kind`) | Unfiltered listing | The whole catalog (default **100**), headed `# PlungeAI Agents (live registry)` plus a refine hint |

Other arguments:

- `kind`: which card set to search. `agents` is the default. See the table below.
- `limit`: 1 to 100. It overrides the defaults above.
- `format`: `"json"` returns `{"content": "<the same markdown>"}` as text and as `structuredContent`. The source is rendered registry markdown; there are no typed rows yet (tool description, `server.ts`).

`search` is semantic, so describe the **capability**, not a name: "web search", "convert pdf to markdown", "post to slack". The registry ranks the results. Trust the ranking.

**The catalog is active-only.** For `kind: "agents"` the gateway always adds `status=active` to the registry query (`listAgents` in `tools.ts`). Every agent it lists is deployed and callable. The execution tools refuse any id that is not `status:active` ([Tools](/mcp/tools), [Agents & missions](/mcp/agents-missions)). So take agent ids from a live search, never from memory, another platform, or a guess.

### Try asking

- *"What agents do you have for financial analysis and SEC filings?"*
- *"Which agent should I use to turn a PDF into markdown?"* The search is semantic. For this one you get `pdf-worker`, `markitdown` and `ms-office-worker`, and each card says what it is *not* for (`pdf-worker` → "Extracting text from existing PDFs → use `doc-converter`"). Live-verified 2026-09-24.
- *"What connectors are available?"* Also try personas, experts, skills and models.
- *"What agents are in the registry for web search?"*

```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 agent should I use to turn a PDF into markdown?","search":"convert pdf to markdown","limit":3}}}'
```

The result `text` is the registry's own markdown, passed through unchanged. An abridged excerpt (live registry, 2026-09-24):

```markdown
# Registry search — q="convert pdf to markdown"

*3 results*

## PDF Worker (`pdf-worker`)
*agent · tools · status:active*

Generates PDF documents from Markdown content. …

**Good at:**
- Converting meeting notes in Markdown to a shareable PDF document (exportToPdf)
…

**Not for:**
- Extracting text from existing PDFs → use `doc-converter` (pdf-worker generates PDFs; it does not parse or extract content from existing PDF files)
…

## markitdown (`markitdown`)
*agent · tools · status:active*
…
```

Each result has a heading with the name and id, a line with type, category and status, the description, **Good at:** and **Not for:**. The `*N results*` line counts the results on this page, not the catalog total.

> **Not-for redirects come from the card as written.** A redirect target is not checked against the active catalog. On 2026-09-24, `sec-agent`'s card said "Real-time stock quotes → use `alpha-vantage`", and `alpha-vantage` is `status:testing`, so execution refuses it. Before you use a redirect target, check it with `search` or `agent_id`.

### Kinds

`kind` picks the card set (`KIND_GROUPS` in `orchestration/registry/registry.ts`):

| `kind` | Searches | Active-only filter |
|---|---|---|
| `agents` (default) | Callable agents, the ids that go into a workflow's `agent:` | **supported**. Always applied |
| `personas` | Digital twins (the `persona` of a `one-agent` call, see [Agents & missions](/mcp/agents-missions)) | not applied (these cards carry no `status:active` tag) |
| `experts` | Expert / specialist cards for mission capability injection | not applied |
| `skills` | Skill cards (`skills:` on a harness task) | not applied |
| `models` | Model cards (ids like `anthropic:claude-haiku-4-5-20251001`) | not applied |
| `connectors` | Connector cards | not applied |
| `workflows` | Public registry workflow cards, **not your workflows** | not applied |

The status filter applies only to agents on purpose. Almost no card in the other sets carries `status:active` (personas, experts and workflows none, skills 1 of 1,053 when the rule was written), so filtering would empty the list (comment in `listAgents`).

### Categories

On 2026-09-24 the live catalog held **92 active agents in 14 categories**: `ai`, `blockchain`, `coding-agents`, `communication`, `ecommerce-agents`, `entertainment`, `financials`, `google-workspace`, `media`, `microsoft-365`, `payment`, `search`, `shopping`, `tools`. Category values must match exactly. The finance category is `financials`: `category: "finance"` returns `*0 results*` (live-verified 2026-09-24). If you are unsure, use `search` ("agents for financial analysis") and let the ranking work. For counts per category, read the `plungeai://agents/categories` resource ([Prompts & resources](/mcp/prompts-resources)).

> **Don't ask for "all agents".** An unfiltered listing is large. On 2026-09-24 the full active catalog in markdown was about **150 KB**, all of it going into your client's context in one call. Always filter by `search`, `category` or `kind`.

### When the registry does not answer

| Answer | Meaning | `isError` |
|---|---|---|
| `Registry search failed (<status>).` | The registry answered with a non-OK status | true |
| `Registry unavailable — try again shortly.` | The call threw (timeout 10 s) | true |
| `Registry service not available.` | The gateway has no registry binding | true |

These are plain text errors, not outcome envelopes. `plungeai_list_agents` has no `outputSchema`. Retry after a few seconds.

## 5.3 Read one full card — `agent_id`

`agent_id` returns the agent's complete card as markdown (`GET /api/cards/agent/<id>?fields=full` on the registry). It includes the description, *Best for*, the *Not for* table, the prompt format, operations, parameters, examples, output, credentials, demonstrations and tags. Fetch it before the first use of an unfamiliar agent. Cards are several KB each (`weather-agent`: about 12.7 KB, live 2026-09-24).

`agent_id` takes precedence: `search`, `category` and `kind` are **ignored** when `agent_id` is set. It always reads an **agent** card.

*Try asking: "Show me the full card for sec-agent — what operations does it support?"*

```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":"Show me the full card for the weather agent","agent_id":"weather-agent"}}}'
```

A wrong or inactive id is not an error. The answer is guidance with live near-matches, and `isError` stays false:

| Case | Answer (from `listAgents`) |
|---|---|
| No card with that id | "No registry card with id `<id>` exists — ids cannot be guessed or carried over from other platforms (this one may be stale). Nothing failed; pick a live id below or refine with `search`." Then `## Closest live matches` (the top 3 active cards) |
| Card exists but is not `status:active` | "`<id>` is not available over MCP — only `status:active` agents are listed and callable here. Nothing failed; pick a live agent below or refine with `search`." Then `## Closest live matches` |

The MCP server never shows a non-active card, not even when you ask for it by id.

## 5.4 The invocation contract — `plungeai_get_tool_contract`

Structured agents are *forms, not chats*. A card with a Parameters table (`markitdown`, `weather-agent`, the Gmail agent, …) takes typed fields, not a sentence. `plungeai_get_tool_contract` gives your client the exact form. It lists every typed field, the operations and which of them need approval, worked examples, and the **live credential status for your account**. Then the client fills the form and calls [`plungeai_execute_tool`](/mcp/tools). The contract *is* the API documentation for that agent.

You can also just ask about an agent in plain language. The answer comes from its card (what it is good at, what to use instead) and its contract (the exact fields, and whether you are set up):

- *"Before I use the Gmail agent — what exactly does it need from me, and am I connected?"*
- *"What is the x402 broker for?"*
- *"Can I search Amazon and pay with x402? What information do you need from me?"*

```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"}}}'
```

### What comes back

The `text` is Markdown in this order (`renderContractMarkdown` in `tool-contract.ts`, then `getToolContract` in `tool-exec.ts`):

1. ``# <Name> (`<id>`)`` and the description.
2. `## Operations`: one line per operation, with its purpose, `(requires: …)` for fields that only that operation needs, and `⚠️ GATED: requires explicit user approval` on gated operations.
3. `## Parameters`: one line per field, with its type, `required`, `one of: …` (enums read from the card), `default: …` and the description.
4. `## Examples`: up to three worked CNL snippets from the card's demonstrations.
5. `**Returns:**`: the card's output description.
6. `## Credentials`: your live status (table below).
7. A closing line: `Run it: plungeai_execute_tool {agent_id: "<id>", operation: "<one of the operations above>", params: {<the parameters above>}}. Gated operations pause for user approval — relay the ⏸ block and continue with plungeai_continue.`
   The hint is the server's own text. A gated floor operation run through `plungeai_execute_tool` comes back as a trust-fence refusal that `plungeai_continue` cannot resume; it runs only from Ocean Studio ([6.6](/mcp/tools#66-the-trust-fence--needs-approval)).

An excerpt for `weather-agent` (rendered from the live card, 2026-09-24):

```markdown
# Weather Agent (`weather-agent`)

Complete OpenWeatherMap client: current conditions, 5-day/3-hour forecast, … EVERY location-based operation accepts either lat/lon coordinates OR a `location` city name …

## Operations

- `current` — Real-time weather conditions
- `forecast` — 5-day forecast with 3-hour intervals
- `air-quality` — Current AQI (OWM 1-5 scale) + pollutant components
- `air-quality-history` — Historical AQI between start and end (requires: start, end)
- `one-call-timemachine` — Weather at a past/future moment (requires: dt)
…

## Parameters

- `lat` (number): Latitude - optional when `location` is given (auto-geocoded)
- `location` (string): City name auto-geocoded to coordinates, e.g. "Hamburg,DE" or "Sun Valley,ID,US" …
- `units` (string): `standard` (Kelvin) | `metric` (Celsius, default) | `imperial` (Fahrenheit)
- `start` (number): Unix start time — (operation: air-quality-history, required there)
…

## Credentials
- 🔐 Platform-managed — nothing for the user to connect.
```

`structuredContent` is the outcome envelope ([6.4](/mcp/tools#64-the-outcome-vocabulary)) with the contract attached:

```json
{
  "status": "ok",
  "agent_id": "weather-agent",
  "summary": "Contract for weather-agent",
  "contract": {
    "agent_id": "weather-agent",
    "name": "Weather Agent",
    "description": "…",
    "operations": [{ "name": "air-quality-history", "purpose": "…", "gated": false, "required_params": ["start", "end"] }],
    "inputSchema": { "type": "object", "properties": { "location": { "type": "string", "description": "…" } }, "required": [], "additionalProperties": true },
    "examples": [{ "title": "Current weather by city name (no coordinates)", "cnl": "agent: weather-agent\noperation: current\n…" }],
    "output_type": "…",
    "credentials": []
  }
}
```

With `format: "json"` the text becomes this same object as a JSON document. The Markdown `## Credentials` lines are then not in the text, but `contract.credentials` carries the same data.

### Contract fields

| Field | Meaning |
|---|---|
| `agent_id`, `name`, `description` | The card's identity |
| `operations[]` | `{ name, purpose?, gated, required_params? }`. The values for `operation` on `plungeai_execute_tool`. Built from the card's Operations table, its per-operation parameters and its demonstrations. An empty list means no operation selector is known, not "refuse" |
| `inputSchema` | JSON Schema for `params`: `type: object`, `properties`, `required`, `additionalProperties: true` (fields not on the card are legal and pass through) |
| `examples[]` | `{ title, cnl }`: up to three copy-paste CNL tasks |
| `output_type` | What the agent returns, in prose |
| `soleRequiredParam` | Present when exactly one string field is required. A prose `prompt` can be mapped onto it ([6.3](/mcp/tools#63-typed-params-prose-and-operations)) |
| `credentials[]` | `{ provider, tier, required, connected, status, accountEmail }` per requirement. `connected: null` means the status could not be checked |

### How the contract is built

The card's parameter types are free text written by people. The generator never throws: an unknown type becomes `string`, and the raw type is kept in the description (`buildToolContract` in `tool-contract.ts`). These rules shape what your client sees:

- **Envelope names are skipped.** `agent`, `type`, `id`, `operation`, `depth`, `user_id`, `executor_user_id`, `workflow`, `execution_id` belong to the task envelope. They never appear as params. The operation goes in `plungeai_execute_tool`'s own `operation` argument.
- **Credential fields are never required.** `access_token`, `api_key`, `apikey`, `bearer_token`, `oauth_token`, `refresh_token` are shown with "(platform-injected from your connected account at runtime — do NOT supply)".
- **Operation-specific requireds** live on `operations[].required_params` and are enforced only when you run that operation.
- **`prompt` as an alias.** When a card marks `prompt` and another text field required together (for example `query` + `prompt`), `prompt` is made optional.
- **Old multi-operation cards.** On a card with two or more operations and no per-operation attribution, the fields it marks required are moved into the description as "(required by some operations — see the examples)". Otherwise every call would be refused for fields that belong to other operations.
- **Gated operations** are the platform floor list (`buy`, `purchase`, `fetch_paid`, `send`, `transfer`, `pay`, `send_payment`, `withdraw`, `shop`) plus any `gated:<op>` tag on the card. See [The trust fence](/mcp/tools#66-the-trust-fence--needs-approval).

### Credentials section

The `## Credentials` lines come from the agent's credential requirements ([6.7](/mcp/tools#67-connected-accounts-and-your-own-keys)) and a live status lookup for the calling user:

| Line | Meaning |
|---|---|
| `🔐 Platform-managed — nothing for the user to connect.` | The agent runs on platform keys |
| `` `<provider>`: 🔐 platform-managed. `` | This requirement is served by the platform |
| `` `<provider>` (private connector): ✅ connected as you@… `` | Your OAuth account is connected. The email is shown when known |
| `` `<provider>` (bring-your-own key): ⚠️ NOT connected — required; execution will stop with connect instructions until the user connects it at https://studio.plungeai.com → Connectors. `` | Missing. `expired — reconnect` replaces `NOT connected` for an expired connection; `(optional)` replaces `— required; …` for an optional one |
| `` `<provider>` (<tier>): status could not be checked — execution will verify. `` | The lookup failed. It fails open, and the execution checks again |

### Outcomes

| `status` | When | `isError` |
|---|---|---|
| `ok` | The contract was built | false |
| `unavailable` | No card with that id (``No registry card with id `<id>` exists — … Nothing was executed.``), or the card is not `status:active`. Up to three live alternatives are included as `use_alternative` actions | false |
| `error` | The registry did not answer: `The registry did not answer — the contract cannot be fetched right now.` with "Retry in a few seconds." | true |

The tool is read-only (`readOnlyHint: true`). Card lookups are cached for 60 seconds per gateway isolate (`registry-cards.ts`), so an agent that was just deactivated can still look active for up to a minute.

## 5.5 Workflow templates — `plungeai_templates` `list` and `get`

Templates are a platform-wide library of ready-made workflows. They are the same rows Studio's gallery shows (`templates` / `template_versions` in D1, content in KV). Three actions:

| `action` | Needs | Returns |
|---|---|---|
| `list` | optional `category`, `limit` (1–100, default 50) | `# Workflow Templates (N)`: a table with Name, Kind, Category, Difficulty, Used, ID, Description (first 90 chars). Only `status = 'active'` workflow templates, featured first, then display order, then most used |
| `get` | `template_id` | The name, description, `**Category:** … · **Difficulty:** … · **Used:** N×` and the full YAML in a code block |
| `use` | `template_id`, optional `name`, `folder` | Copies the template into your account as a new workflow. See [8.9](/mcp/workflows#89-start-from-a-template--plungeai_templates-use) |

*Try asking: "What workflow templates are available? Start one from the due-diligence template."* The client lists the templates, finds the due-diligence one, then calls `use` ([Workflows](/mcp/workflows)).

```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}}}'
```

To read one template's YAML, pass its id from the list:

```bash
# get needs a real template id from the list above
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":2,"method":"tools/call","params":{"name":"plungeai_templates","arguments":{"user_request":"Show me the due-diligence template","action":"get","template_id":"<template id>"}}}'
```

| Answer | Meaning | `isError` |
|---|---|---|
| `No active workflow templates.` | `list` matched nothing (for example an unknown `category`) | false |
| `template_id is required for this action.` | `get` or `use` without an id | true |
| `Template not found: <id>` | No active template with that id | true |
| `Template content missing from storage.` | The row exists but its YAML is gone | true |

`plungeai_templates` is not marked read-only, because `use` writes a workflow. `list` and `get` change nothing. The tool has no `format` argument; its output is always Markdown.

## 5.6 Other discovery surfaces

- **Resources.** `plungeai://agents/list`, `plungeai://agents/categories`, `plungeai://personas/list` and the `plungeai://agents/{category}` template read the same live registry (agents active-only). `plungeai://docs/workflow-authoring` is the full CNL authoring guide. See [Prompts & resources](/mcp/prompts-resources).
- **The `/plungeai` prompt** gives the client the whole discover → inspect → execute routine in one message ([Prompts & resources](/mcp/prompts-resources)).
- **Over HTTP.** The One API has the same catalog as REST routes: `GET /v1/discovery/search` and `GET /v1/tools/{id}` (https://api.plungeai.com/docs#8-discovery, https://api.plungeai.com/docs#6-tools-plane).
- **Skills for your client.** https://skills.plungeai.com has installable skills that teach Claude Code, Cursor and other clients these same patterns ([Connecting clients](/mcp/connecting-clients)).
