# Workflow gallery

> The Whisper MCP workflow gallery: the list_workflows and run_workflow contracts, the business workflows, partial results, and a typosquat sweep.

*Source: https://www.whisper.security/docs/ai/mcp/workflow-gallery*
*Published: 2026-06-27*
*Last updated: 2026-09-27*

---
The workflow **gallery** is a shared library of fifteen business-oriented investigation workflows. It's the same library that powers the [use cases](/products/intelligence/use-cases) on this site and the investigations in the [console](https://console.whisper.security). Over MCP, an agent finds a workflow with `list_workflows` and runs it with `run_workflow`. A single `run_workflow` call can cover a multi-step pivot — resolve DNS to an IP, the IP to its ASN, check threat intel — and every step comes back with the query that produced it.

This is the connector's headline feature. Instead of stitching together five `query` round-trips, an agent runs one named workflow and gets chained, evidence-backed results.

Each of the fifteen workflows is a deep build-out that runs the union of several narrower query patterns in one call — one input in (usually a domain, IP, ASN, or prefix), a full cross-layer answer out. Every one of them is also surfaced as a [use case](/products/intelligence/use-cases) on this site; `list_workflows` is the authoritative, always-current index — the table below is a starting point, not a copy you should hand-maintain.

The gallery was curated down from a larger, more granular catalogue (2026-07): several narrow, single-purpose slugs — a coverage-only verdict check, a standalone WHOIS/BGP history diff, a bulk risk scorecard — were folded into `indicator`, which now runs as one unified deep-dive with no `mode` param: point it at a domain, IP, ASN, or prefix and it returns the verdict, the historical WHOIS/BGP context, and the surrounding infrastructure in a single call.

The gallery holds fifteen workflows and no recipes (measured 2026-10-11). The narrower copy-paste pivots live in [Recipes](/docs/recipes) and are not addressable through `run_workflow`.

> New to the connector? Start with the [Setup guide](/docs/ai/mcp/setup), then the [Reference](/docs/ai/mcp/reference) for the full 7-tool, read-only surface. The two gallery tools are `list_workflows` and `run_workflow`.

## How it works

1. **Discover.** `list_workflows` searches the gallery and returns matching workflows, each with its summary *and its full parameter space* — every dial, with options, ranges, and defaults — so an agent can run any variant, not just the default.
2. **Run.** `run_workflow` takes one or more slugs (with optional `input` / `params`) and runs them in a single call. It returns the chained per-step record and, by default, a ready markdown report the agent can relay verbatim.
3. **Cite.** Every step in that record carries the exact Cypher that ran, its row count and its latency, and the report's `## Evidence` appendix maps each citation back to one of them. The agent can show its work.

## The workflow slugs

Gallery workflows are addressed by slug — a stable, human-readable identifier you pass to `run_workflow`. A few of the most-used:

| Slug | What it answers |
|------|-----------------|
| `typosquat` | Registered typosquats and lookalikes of a domain (14 mutation algorithms), scored and enriched |
| `indicator` | Full-depth investigation of a domain, IP, ASN, or prefix — verdict, historical WHOIS/BGP context, and everything connected to it, single-mode |
| `infrastructure-mapping` | The owned estate behind one indicator — true owner, subdomains, networks, physical footprint, up to the vendor border |
| `supply-chain` | What a domain depends on — every external provider by function, with dependency chains and single-vendor (SPOF) signals |
| `attack-surface` | Everything a domain exposes to the outside world — DNS, mail, IPs, subdomains, CDN-origin candidates — scored for risk |
| `indicator-enrichment` | One domain or IP as a full context card — registrant, hosting, mail, location, and a reputation read |

These six cover the most common one-shot investigations — a brand sweep, a full indicator deep-dive, owned-estate and dependency mapping, an exposure sweep, and single-indicator enrichment.

The other nine round out the catalogue: `anycast-dns-root-sovereignty` (how resilient a country's core DNS is if cut off from the world), `bgp-hijack-exposure` (grade a network's routing security and trace conflicts to affected domains), `build-takedown-evidence-package` (a ready-to-submit takedown dossier for a scam or phishing domain), `email-security-posture` (SPF, DKIM, DMARC, MX and DNSSEC graded on presence and hygiene), `nameserver-hijack-dns-consistency` (the name-server misconfigs that enable DNS hijack), `route-health` (BGP route health — prefixes, peers, MOAS conflicts, RPKI), `subdomain-takeover` (subdomains pointing at abandoned services an attacker could claim), `threat-actor-attribution` (from an indicator to a named actor, or from an actor to their techniques and infrastructure), and `xray` (everything a domain stands on in one read: verdict, web, nameserver and mail strands, networks, subdomains, physical layer and look-alikes).

**Thirteen of the fifteen are also advertised as MCP prompts**, so your client's prompt picker shows them as one-click investigations; the [Reference](/docs/ai/mcp/reference) documents the prompt surface. The two exceptions are `attack-surface` and `indicator`, which are not advertised as prompts yet. Both stay reachable through `run_workflow` by slug: `indicator` has a fixed step count and completes inside the run budget, so it behaves like any other workflow, while `attack-surface` cannot finish inside a single tool call on any input and is refused up front — `notRun: true`, with a `reason` and a `howToNarrow` hint — rather than started.

## Flagship workflows

| Slug | What it answers | Example input |
|------|-----------------|---------------|
| `typosquat` | Registered lookalikes of a brand domain | `paypal.com` |
| `indicator-enrichment` | Registrant, hosting, mail, location and reputation for one indicator, on one card | `github.com` |
| `infrastructure-mapping` | The owned estate behind one indicator, up to the vendor border | `www.cloudflare.com` |
| `supply-chain` | Every external provider a domain depends on, with SPOF signals | `shopify.com` |
| `build-takedown-evidence-package` | A ready-to-submit takedown dossier for a scam or phishing domain | `ickaoex.com` |
| `route-health` | A network's routing and reachability health card | `AS3356` |

The gallery holds fifteen workflows in total — `list_workflows` is the authoritative, always-current index. Treat this table as a starting point, not the whole catalogue.

## When a workflow returns nothing

A partial run is not a clean result, and the response says which it is. Read three fields before you believe an empty answer:

- **`coverage.stepsWithData` below `coverage.stepsTotal`** is a coverage gap and therefore a *finding*. Report it as one.
- **`coverage.stepsSkipped`** means a step did not run — most often because its gate did not apply to your input type (a prefix-only step on an ASN), sometimes because a capability layer is not live on the deployment. `incompleteSteps[]` carries the reason for each, and `readyLayers[]` in the `whisper://server` resource lists the live layers.
- **`truncations[]`** records everything the report's token budget dropped. An untruncated-*looking* report is not complete until this array is empty.

Two known gaps, so you can tell them apart from your own mistake:

- **`route-health` returns `complete: false` on an ASN.** Four of its steps are prefix-scoped (BGP status, MOAS conflicts, RIR allocation, prefix hierarchy) and only run when the input is a prefix, so on an ASN they are reported as skipped — a live run on `AS3356` on 2026-09-02 returned `success: true` in 1.6 s with five of the ten steps carrying data — and `incompleteSteps[]` and `warnings[]` name each gap rather than passing it off as clean. Give it a prefix when the routing status of one block is the question.
- **`attack-surface` is refused up front** (`success: true`, `notRun: true`, plus `reason` and `howToNarrow`) because it cannot finish inside a tool call on any input. That is a successful, actionable refusal, not an error. Any other run that reaches its wall-clock budget comes back as a **successful partial** — `success: true`, `partial: true`, with guidance in `warnings[]` — never a hang.

**If one of these returns nothing, you did not do it wrong.**

## `list_workflows` — the contract

Search the gallery; get back each item's summary *and* its full parameter space. All four filters are optional: `keyword`, `persona`, `task` and `layer`. Called with no arguments it returns the entire catalogue, uncapped.

**Returns**

```json
{
  "workflows": [
    {
      "slug": "typosquat",
      "kind": "workflow",
      "title": "Typosquat & Brand-Impersonation Scanner",
      "summary": "Find registered look-alikes of your brand and check which ones are dangerous.",
      "personas": ["Brand protection", "Threat intelligence"],
      "task": ["detect", "cluster", "enrich", "pivot"],
      "layers": ["DNS", "threat-intel", "BGP", "GeoIP", "WHOIS", "historical"],
      "inputs": [{ "name": "domain", "passAs": "input", "label": "Brand domain", "kind": "domain", "required": false }],
      "params": [],
      "stepCount": 10,
      "docPath": "/docs/workflows/typosquat"
    }
  ],
  "count": 1
}
```

Two keys are optional and appear only where they apply: `outputKind` (what the run produces, for example `"report"` or `"routing"`) and `requiresCapability` (a capability layer the workflow needs, for example `["ct-subdomains"]` on `attack-surface`). The catalogue entry carries no prose description and no icon — the prose is one `read_docs(docPath)` call away, and the icon rides on the `run_workflow` result.

`params[]` is the dial list. Where a workflow has one, each entry is described in full (`name`, `kind`, `label`, `description`, `default`, and `options[]` for a select), so an agent can run a non-default variant without guessing the shape — `attack-surface`, `infrastructure-mapping` and `supply-chain` all take a `level` of `quick` / `standard` / `deep` / `comprehensive` / `exhaustive`, and `anycast-dns-root-sovereignty` takes an `instanceType`. An empty `params: []`, as on `typosquat`, means the workflow has no dials.

Note `stepCount`: it is the workflow's declared step count, and the `coverage.stepsTotal` you get back from `run_workflow` is what *actually ran*. When the two differ, the difference is the story.

> **Read `coverage` before `band`.** Only `known-clean` licenses the word "clean"; `no-data` means
> *unknown*, which is a different thing again; `malicious-evidenced` and `ambiguous` mean there is
> evidence, whatever the band says.
> Full contract: [Coverage — what we looked at](/docs/whisper-graph/procedures/coverage).

## `run_workflow` — the contract

Run one or more workflows by slug in a single call.

**Input**

```json
{
  "runs": [
    { "slug": "typosquat", "input": "paypal.com" },
    { "slug": "indicator-enrichment", "input": "paypal.com" }
  ]
}
```

- `runs[]` — one or more `{ slug, input?, params? }`. Multiple runs execute in the same call.
  **The entity goes in `input`; `params` carries the settings.** `list_workflows` says which is which for every field it describes: each entry in `inputs[]` carries a `name` and a `passAs` of either `"input"` or `"params"`. Read `passAs` and place the value accordingly — a `passAs: "input"` field sent inside `params` is not the same request, and the workflow will run against a default it was not given.
- `profile` — `console` / `website` / `mcp` / `raw` (default `mcp`), a top-level sibling of `output`. The profile is what decides the result shape: on the default `mcp` profile each step returns its `cypher`, `rowCount` and `executionTimeMs`, and the findings arrive as a ready, budgeted markdown report in `results[].markdown`. `steps[]` never carries rows; to get them, run a step's `cypher` through `query`.
- `output` — optional `{ emit, slices }` fine-tuning, applied **on top of** whichever profile resolves. Sending it at all replaces the profile's slice list and overrides its `emit` — it does not merge — so omit it entirely (the default) to keep the profile's markdown.

**Output**

```json expect=skip reason="response envelope read off a live run_workflow call, 2026-09-20 — steps[].cypher echoes the parameterised query the server ran, not a request body a reader posts"
{
  "results": [
    {
      "slug": "typosquat",
      "input": "paypa1.com",
      "paramValues": {},
      "success": true,
      "icon": "Tag",
      "docPath": "/docs/workflows/typosquat",
      "steps": [
        {
          "stepId": "registered",
          "title": "Registered look-alikes",
          "reason": "The candidate set every later arm is scoped to",
          "status": "done",
          "cypher": "CALL whisper.variants($domain) YIELD variant, method, exists, confidence\nWHERE exists AND variant <> $domain\nRETURN variant, method, confidence ORDER BY confidence DESC LIMIT 500",
          "rowCount": 44,
          "executionTimeMs": 136
        },
        { "stepId": "curate", "title": "curate", "status": "done", "cypher": null, "rowCount": 0, "executionTimeMs": 2 }
      ],
      "complete": true,
      "coverage": { "stepsTotal": 11, "stepsWithData": 10, "stepsEmpty": 1, "stepsSkipped": 0, "stepsError": 0 },
      "derived": {},
      "totalLatencyMs": 2712,
      "markdown": "## Findings\n\n- 7 third-party look-alike(s) are listed in a threat feed …\n\n## Evidence\n\n1. 44 registered look-alike(s) found for paypa1.com …",
      "truncations": [
        { "layer": "profile", "kind": "rows", "target": "inactive", "dropped": 10, "of": 30 }
      ],
      "profile": "mcp"
    }
  ],
  "slugsRun": ["typosquat"]
}
```

**`steps[]` is the audit trail.** There is no separate `evidence` array: each step ships the exact parameterised Cypher it ran, its `rowCount` and its `executionTimeMs`, which is what lets an agent cite the query behind a conclusion. The rows themselves do not come back on the default `mcp` profile — the findings arrive already written.

On that profile `markdown` is the piece to hand to the user: a verdict, findings, and a numbered `## Evidence` appendix that each `[n]` citation in the findings resolves against. Relay it verbatim rather than re-summarizing it.

Anything the report's budget dropped is recorded in `truncations[]` (`{layer, kind, target?, dropped, of, guidance?}`) and non-fatal warnings land in `profileWarnings[]` — never silently. `complete` and the `coverage` counters flag any step that was skipped or returned nothing; a coverage gap is a finding, not a clean result (no-data != benign), and `incompleteSteps[]` carries the reason per step when one fires. `coverage` is computed over the workflow's declared step list, so a step that never reported back shows as `skipped` rather than disappearing.

`paramValues` records exactly which dials actually ran — an out-of-range param is clamped or filtered, never rejected, and the effective value is echoed back here. `inputSource` appears when the entity arrived inside `params` under the input's own name (it is still used), and `ignoredParams` lists any key that matched no declared param. `derived` carries rolled-up signals where a workflow projects them and is `{}` where it does not.

The result carries no static documentation links: the schema, Cypher and API references are reached through `read_docs`, and `docPath` on the result points at the workflow's own page.

## Worked example: a typosquat sweep, end to end

A user asks: *"Is anyone squatting on paypal.com, and is any of it dangerous?"*

**1 — discover the workflow.**

```
list_workflows({ keyword: "typosquat brand protection" })
→ { workflows: [{ slug: "typosquat", kind: "workflow", inputs: [{name:"domain", passAs:"input"}], params: [], stepCount: 10, docPath: "/docs/workflows/typosquat" }], count: 1 }
```

**2 — run it.**

```
run_workflow({ runs: [{ slug: "typosquat", input: "paypal.com" }] })
```

**3 — relay the report.** On the default `mcp` profile the answer arrives ready-made: `results[].markdown` is a budgeted report — verdict, findings, and a numbered `## Evidence` appendix — that the agent relays verbatim, not re-summarized.

A live run on 2026-09-20 against `paypa1.com` returned **44 registered look-alikes**, each tagged with the generation method that found it (homoglyph, bitsquatting, TLD-swap, hyphenation, …), of which **7 are listed in a threat feed**. It took 2.7 s across 11 steps, reported `complete: true`, and `coverage` came back `stepsWithData: 10, stepsEmpty: 1`.

Read `exists` carefully: it means **registered or observed, not malicious**. Look-alikes existing at all is normal for a brand of any size; the feed-listed ones and the operator clusters are the finding.

Behind the report, every `[n]` citation maps back to the step that produced it, and each step carries the query it ran:

| Step | Cypher (abridged) | Rows | Latency |
|------|-------------------|------|---------|
| `registered` | `CALL whisper.variants($domain) YIELD variant, method, exists, confidence …` | 44 | 136 ms |
| `whois` | the registrant pivot over the registered set | 200 | 1,077 ms |

**4 — pivot, still in one call.** To go further, chain a second workflow in the same `run_workflow`:

```
run_workflow({ runs: [
  { slug: "typosquat",                       input: "paypal.com" },
  { slug: "build-takedown-evidence-package", input: "paypa1.com" }
]})
```

That returns the lookalikes *and* a ready-to-send takedown dossier on the worst offender — two investigations, one round-trip, each with its own `steps[]` trail and its own report.

> **Live numbers will differ.** WhisperGraph reflects the current state of the internet, not a fixed snapshot — counts, verdicts, and registrants change as feeds and routing refresh. The figures above are what one dated run returned, not a guarantee about the next one.

## Next steps

- [Your first investigation](/docs/ai/mcp/investigation) — one alert worked end to end, with the pivot and the falsification step.
- [MCP Reference](/docs/ai/mcp/reference) — the full 7-tool, read-only surface and the per-step evidence model.
- [Setup guide](/docs/ai/mcp/setup) — connect a client and run your first investigation.
- [Use cases](/products/intelligence/use-cases) — the same fifteen workflows, as guided flows you can run in the browser.
- [Recipes](/docs/recipes) — the narrower pivots the gallery does not carry, as copy-paste Cypher.
