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

# Notifizz MCP Tools Reference

> Every tool the Notifizz MCP server exposes, grouped by intent: set up the data contract, configure channels, build and implement a campaign, test it, migrate email templates.

# MCP tools

The Notifizz **MCP server** — MCP being the *Model Context Protocol*, the open standard an AI assistant uses to call outside tools — exposes 27 tools. This page groups them by what you are trying to do, and says when each one is worth calling.

**This page is for the Dev**, and for anyone who wants to know exactly what an AI assistant can and cannot do to a Notifizz organisation. You rarely call these by hand: you describe the outcome, and the assistant chains them.

## TL;DR

* **Six intents**: set up the data contract · configure the channels · build a campaign · implement it · test and promote it · migrate existing email templates.
* **`campaign_get_status` is the compass.** After any campaign step it reports the phase, what is blocking, which role must act, the open questions and the next tool to call. An assistant that reads it never has to guess.
* **The server ships its own playbook.** The order of operations is sent to the assistant on connection, so you don't have to prompt it into the right sequence.
* **Three human gates**: approving a proposed flow, confirming an archive, and publishing Live — the last one has **no tool at all** and only ever happens in the dashboard.
* **Writes are gated by permissions and recorded.** Reads are not recorded. See [scopes and audit](/docs/ai/scopes-and-audit).
* **Two tools return a plan rather than doing something**: `quickstart` and `email_templates_migration`. They are the entry points; the plan they hand back gates every write behind your confirmation.

## Set up the data contract

The foundation: what your product emits ([events](/docs/concepts/events)), what fetches live data at notification time ([enrichers](/docs/why/enrichers)), where a call to action points ([link routes](/docs/concepts/link-routes)), and the business language all of it is named in.

| Tool                       | What it does                                                                                                                                                                                               | When to call it                                                                                                                                                    |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `quickstart`               | Returns the guided, interactive plan to inventory this codebase and lay down the data contract. Read-only — the plan itself gates every write                                                              | **First**, before any other setup tool, whenever you set Notifizz up or want the tagging plan regenerated from the code                                            |
| `vocabulary_upsert`        | Saves business terms and one-line definitions to the organisation's vocabulary — shared context for every Notifizz AI                                                                                      | At the plan's first gate, once you have confirmed the terms. Never with unconfirmed guesses                                                                        |
| `link_route_upsert`        | Saves a notification's call-to-action destinations (`payInvoiceUrl` → `/invoices/:id`). One relative path per route, applied to every environment                                                          | At the plan's link-route gate, once you have confirmed the routes                                                                                                  |
| `env_variable_upsert`      | Sets the value behind a route's `baseUrlVar` — the root URL a relative path hangs off                                                                                                                      | With `link_route_upsert`, and never after: a route whose base URL has no value fails at send time. The production value is only ever set if you give it explicitly |
| `sandbox_get_config`       | Returns a **non-production** environment's keys and base URL so the assistant can wire the SDK for you                                                                                                     | While wiring the client. Production is excluded on purpose                                                                                                         |
| `sandbox_run_discovery`    | Registers a public discovery endpoint if you have one, then runs discovery so your events and enrichers get ingested                                                                                       | At the **end** of the quickstart, once the endpoint is reachable                                                                                                   |
| `sandbox_verify_tracking`  | Reports whether Notifizz actually received a boot ping and a real `track()` from your sandbox                                                                                                              | Right after firing your first real `track()`. It is the honest answer to *"is it wired?"*                                                                          |
| `sandbox_verify_discovery` | Diagnoses **why** discovery is failing, per service, with the specific cause — authentication blocked, signature mismatch, nothing answering, wrong path, empty response — instead of a flat *unreachable* | Whenever enrichers show as unreachable or removed, or discovery looks stale                                                                                        |

<Note>
  **The gates are the point.** The quickstart is not a script that runs and reports; it stops three times — vocabulary first, then events and enrichers, then link routes — and refuses to name anything before you have settled the language. Vocabulary comes first so nothing gets renamed later.
</Note>

### Several sandboxes

`sandbox_get_config` returns **no keys at all** if your organisation has several non-production environments and none was named — it returns the list of names instead, and the assistant asks you which one. The convention is one personal dev environment per developer: own keys, own local tunnel, no cross-talk between teammates. `campaign_send_test_event` follows the same rule.

## Configure the channels

| Tool                                       | What it does                                                                                                                                                                                                            | When to call it                                                                                                                      |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `channels_upsert_identity`                 | Declares the path that identifies a recipient for a channel — for email, the event property or enricher output that yields the address (`user.email`, `customer.contact_email`)                                         | Once per channel, after the assistant has proposed a path **and you confirmed it**. A wrong path misaddresses every message silently |
| `channels_notification_center_upsert_auth` | Persists the [Notification Center](/docs/sdks/notification-center/overview) widget's authentication setup: the mode (`none`, `backendToken`, `firebase`), the identity field, and the Firebase project id when relevant | During the quickstart, or whenever you change how the widget authenticates users                                                     |
| `channels_webpush_setup`                   | Generates the per-environment [web push](/docs/sdks/web-push/overview) key pair — idempotent, existing pairs are kept and never rotated — and returns each environment's public key                                     | When wiring web push, before the frontend needs `applicationServerKey`                                                               |
| `channels_webpush_verify_setup`            | Reports the web push setup per environment: key configured, the widget's last in-situ service-worker check with its dated reason if it failed, active subscription count, setup state                                   | When push isn't reaching anyone and you need to know which of the three moving parts is wrong                                        |

<Warning>
  Web push itself is in **closed beta** and enabled per organisation. These two tools run regardless, but the push channel only becomes selectable on a campaign once your organisation is switched on — see [web push](/docs/sdks/web-push/overview).
</Warning>

<Note>
  **The identity field has to agree with itself.** The value the widget authenticates with, the field named here, and the property your events and enrichers use to address a recipient must be the same thing. When they diverge, nothing errors — the inbox simply stays empty.
</Note>

## Build a campaign

The business half. The copilot interviews you about intent, audience, tone, key message and timing — and deliberately knows nothing about enrichers or event properties. That conversation belongs to the [campaign](/docs/concepts/campaigns) in `Editing`.

| Tool               | What it does                                                                                                                                                                        | When to call it                                                                                                                                                                                      |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `campaign_create`  | Starts a new campaign from a one-or-two-sentence brief, runs the first interview turn, and returns the campaign id plus a dashboard link to hand to whoever asked                   | To open a campaign from the IDE. If it comes back with `needs_confirmation` and a list of **similar campaigns**, it has not created anything: read the list, decide, and only then confirm a new one |
| `campaign_answer`  | Relays your answers to the open questions. In `Editing` they go to the business copilot; **past that point the same tool routes them to the technical orchestrator** and re-runs it | Each time `campaign_get_status` reports open questions                                                                                                                                               |
| `campaign_approve` | Approves the flow the copilot proposed and materialises it — the notifications get created and their copy designed                                                                  | **Only after a person has explicitly approved.** The proposal object is passed back unchanged; the assistant does not get to edit it on the way through                                              |

<Note>
  **The duplicate check is not a nuisance.** The same event does not mean the same campaign, and only a human can tell which is which — so the tool surfaces what already exists and stops. It also silently reuses a recent empty draft created from an identical brief, so a retry doesn't litter your list.
</Note>

## The compass

| Tool                  | What it does                                                                                                                                                                                                                                      | When to call it                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `campaign_get_status` | The journey snapshot: current phase, `blocked_by` (what is needed **and which role must act**), open questions to relay, the implementation tasks, the notifications designed so far, a review summary, and `next_actions` — the tool to call now | **After every campaign step.** It is the one tool an assistant should never skip |

It also answers two questions nothing else does:

* **Who receives the later sends of a sequence** — recipients resolved at each send, or frozen at the first one.
* **Whether a published campaign has a pending update.** Editing a Live campaign forks a child that carries its own tasks and its own orchestrator thread. Asking the parent would report *"live, nothing to do"* and hide it, so the snapshot folds in the child's id — you drive the child, and publishing the update stays a human step in the dashboard.

## Implement it

The technical half. The AI orchestrator reconciles the campaign's notifications against the events and enrichers that actually exist in your codebase, and raises [implementation tasks](/docs/concepts/orchestrator) for the gaps.

| Tool                  | What it does                                                                                                                                                                                                     | When to call it                                                                                                                                                   |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `campaign_implement`  | Promotes the campaign to the **Implementation** phase and starts the orchestrator. Also the way to **re-run** it after you've done the work                                                                      | When the draft is ready, then again after each round of tasks. If it answers `blocked` with reasons — an empty notification, no bound event — fix those and retry |
| `campaign_list_tasks` | Lists the orchestrator's implementation tasks. Each actionable one carries a ready-to-run prompt your assistant executes **in your codebase**; human-only setup tasks are marked as such and go to the dashboard | Right after `campaign_implement`, and whenever the compass says tasks are open                                                                                    |

The three task types are the ones the orchestrator can raise: a **missing event property**, an **undefined enricher**, a **missing enricher field**. They are not a blocker but a feature — the AI telling you precisely what your data contract is short of, in a form your IDE can execute.

## Test it and promote it

| Tool                         | What it does                                                                                                                                                                                        | When to call it                                                                                                                               |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `campaign_send_to_review`    | Promotes an in-implementation campaign to **Review**, where it can be test-triggered safely: emails land in a non-production inbox, Notification Center messages in the dev center                  | Once the tasks are resolved. Refused with explicit reasons if the orchestrator analysis is missing, errored, or tasks are still open          |
| `campaign_send_test_event`   | Fires the campaign's trigger event as a **test track on a non-production environment**, through the real ingestion pipeline. Pass realistic properties — recipients and enrichers resolve from them | In Review, to trigger the campaign yourself rather than waiting for your app to do it. Your app firing the same event lands in the same place |
| `campaign_get_test_activity` | Observes the run: recent triggers, per-step delivery (**intended versus delivered, and why messages were dropped**) and objective hits                                                              | After a test event, or after asking someone to trigger the real one                                                                           |

<Warning>
  `campaign_send_test_event` is a **Review-phase tool**. On a Live campaign the same event would really send — which is exactly why the tool refuses to fire there.
</Warning>

## Clean up

| Tool               | What it does                                                                     | When to call it                                                                                                                                                                     |
| ------------------ | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `campaign_archive` | Archives a campaign — a reversible soft delete, typically to abandon a duplicate | Called first **without** confirmation, it returns the campaign's name and status and a confirmation prompt. It only archives on a second call, after a person has explicitly agreed |

## Migrate existing email templates

Bring the emails you already own — from your current sending tool, or an export folder — into your Notifizz component library as reusable layouts, sections and assets.

| Tool                        | What it does                                                                                                                                                                                                                   | When to call it                                                                                                                                         |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `email_templates_migration` | Returns the guided migration plan, with your current library already listed inside it. Read-only                                                                                                                               | **First**, before any `library_*` tool, whenever you want to import or recreate existing emails                                                         |
| `library_list`              | The organisation's current library: layouts, sections, assets                                                                                                                                                                  | **Before creating anything.** It is what makes a re-run update instead of duplicating                                                                   |
| `email_templates_analyze`   | Normalises raw template HTML and returns the **deduplicated** plan: assets, layouts, and the section catalogue with placement counts. Deterministic — the parsing pitfalls of machine-generated email HTML are handled for you | For a handful of templates, while iterating. Deduplication only sees the templates analysed **together**, so never feed them one by one                 |
| `library_upload_asset`      | Stores an image and returns its URL. Deduplicated by content, so re-uploading the same bytes returns the existing asset rather than a twin. 5 MB per file                                                                      | While building the catalogue. Rasterise vector sources first, and never invent a replacement for an asset that could not be fetched — report it instead |
| `library_upsert_component`  | Creates or updates the layouts and sections. **Idempotent on the component key**, so a second run updates rather than duplicates. Everything lands as a **draft** for a human to review                                        | Only **after** a person has confirmed the catalogue and its granularity                                                                                 |

<Note>
  **A real corpus never enters the assistant's context.** Tool arguments travel through the model's context window, and a genuine template library is megabytes of HTML. The migration plan therefore hands the assistant a short-lived, read-only way to submit the whole corpus out of band — deduplication still sees every template at once, and the HTML never costs you a single token. `email_templates_analyze` stays for small batches.
</Note>

## Rules the server enforces

These are not conventions the assistant may or may not honour — they are enforced server-side.

* **Your organisation is derived from the credential**, never from a tool argument. There is no parameter through which an assistant could address another organisation.
* **Publishing Live has no tool.** The absence is the design.
* **Content from your organisation is data, not instructions.** Campaign briefs, campaign names, copilot and orchestrator questions come back to the assistant explicitly tagged as content to relay or display — never as instructions to follow, whatever they happen to say. This is what stops a campaign brief from becoming a set of commands.
* **Write tools are permission-gated and recorded**; a refusal names the missing permission rather than failing vaguely. See [scopes and audit](/docs/ai/scopes-and-audit).

## FAQ

<AccordionGroup>
  <Accordion title="The assistant reported ai_credits_exhausted. What now?">
    Copilot turns draw on your organisation's **daily AI-credit pool**, and the turn that hit the limit did not run — nothing was half-done. The pool resets at UTC midnight, and it can be raised. Everything deterministic keeps working in the meantime: `campaign_get_status`, `campaign_approve`, `campaign_list_tasks` and the rest are unaffected.
  </Accordion>

  <Accordion title="Which tools cost AI credits?">
    The copilot conversation — creating a campaign and answering its questions. Approving a proposal materialises the flow deterministically and costs nothing extra. Reads never do.
  </Accordion>

  <Accordion title="Can the assistant publish a campaign for me?">
    No. There is deliberately no tool for it: a campaign goes Live from the dashboard, by a person. The assistant takes it as far as a tested campaign sitting in Review, and hands you the link.
  </Accordion>

  <Accordion title="A tool answered blocked with a list of reasons. Is that an error?">
    No — it is a gate doing its job. Promotion tools return the exact reasons a transition was refused (an empty notification, no bound event, unresolved implementation tasks, a missing orchestrator analysis) so the assistant can fix them and retry, rather than leaving you with a campaign in a state nobody can explain.
  </Accordion>

  <Accordion title="I want the assistant to only read, never write.">
    That is what the permission model is for: a credential can be narrowed so every write tool is refused with `insufficient_scope` while reads keep working. See [scopes and audit](/docs/ai/scopes-and-audit).
  </Accordion>

  <Accordion title="Do these tools exist for editors other than Claude?">
    The server speaks standard MCP over its remote transport, so any client implementing the protocol and its authorisation flow reaches the same tools. Claude Desktop and Claude Code are the two surfaces Notifizz supports and tests today — see [connect your AI tool](/docs/ai/connect-your-ai-tool).
  </Accordion>
</AccordionGroup>

## See also

<CardGroup cols={2}>
  <Card title="Connect your AI tool" icon="plug" href="/docs/ai/connect-your-ai-tool">
    The one-time consent, and what the first connection does.
  </Card>

  <Card title="Scopes & audit" icon="shield-halved" href="/docs/ai/scopes-and-audit">
    Which tools each permission covers, and what is recorded.
  </Card>

  <Card title="Campaigns" icon="diagram-project" href="/docs/concepts/campaigns">
    The statuses these tools move a campaign through.
  </Card>

  <Card title="Orchestrator" icon="robot" href="/docs/concepts/orchestrator">
    Where implementation tasks come from.
  </Card>
</CardGroup>
