# Courier (remote · mcp.courier.com)

Send notifications, manage templates, and configure integrations with Courier.

- Trust score: 69/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `mcp.courier.com`: 69/100 (this document), [markdown](https://verifymcp.io/servers/trycourier-courier/mcp.md), [page](https://verifymcp.io/servers/trycourier-courier/mcp)

## Channel facts

- Endpoint: `https://mcp.courier.com`
- Transports: `streamable-http`
- Auth: `required`
- Version: `1.3.7`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 63/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (delete_audience).
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 73/100
  - AI-judged instruction clarity (good).
  - Tool/resource definitions use about 10121 tokens (~70/item across 144 items; 144 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 99% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http trycourier-courier https://mcp.courier.com/
```

### Codex

```toml
[mcp_servers.trycourier-courier]
url = "https://mcp.courier.com/"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "trycourier-courier": {
      "type": "remote",
      "url": "https://mcp.courier.com/",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add trycourier-courier --url https://mcp.courier.com/ --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  trycourier-courier:
    url: "https://mcp.courier.com/"
```

### Other

```json
{
  "mcpServers": {
    "trycourier-courier": {
      "type": "http",
      "url": "https://mcp.courier.com/"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 69, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-01 (score 68, +1)

No change was recorded against any check on this day. Stability & Change Management went from 17 to 20. That category is still filling its 30-day observation window: 5 days of observed history at the previous scan, 6 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-31 (score 67, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 67, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 66, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-27 (score 65, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 64)

First indexed and scored.

## MCP tools (144)

### `get_audience` (~32 tokens)

Get an audience by its ID, including its filter definition.

Input parameters:

- `audience_id` (string, required): The audience ID

### `list_audience_members` (~37 tokens)

List all members of an audience.

Input parameters:

- `audience_id` (string, required): The audience ID
- `cursor` (string): Pagination cursor

### `list_audiences` (~26 tokens)

List all audiences in the workspace.

Input parameters:

- `cursor` (string): Pagination cursor

### `update_audience` (~59 tokens)

Create or update an audience with a filter definition.

Input parameters:

- `audience_id` (string, required): The audience ID
- `description` (string): Description
- `filter`: Filter definition object (operator, rules)
- `name` (string): Display name

### `delete_audience` (~29 tokens)

Delete an audience by its ID.

Input parameters:

- `audience_id` (string, required): The audience ID to delete

### `get_audit_event` (~32 tokens)

Get a specific audit event by its ID.

Input parameters:

- `audit_event_id` (string, required): The audit event ID

### `list_audit_events` (~34 tokens)

List audit events in the workspace. Useful for tracking API usage and changes.

Input parameters:

- `cursor` (string): Pagination cursor

### `generate_jwt_for_user` (~83 tokens)

Generate a JWT authentication token for a user. Used for client-side SDK auth (Inbox, Preferences, etc.).

Input parameters:

- `expires_in` (string): Token expiry duration (e.g. "1h", "2 days")
- `scopes` (array): Permission scopes for the token
- `user_id` (string, required): The user ID to scope the token to

### `invoke_automation_template` (~128 tokens)

Invoke an automation run from an existing automation template. Call list_automations first to get the template_id. Example: { template_id: "auto-onboarding", recipient: "user-123", data: { plan: "pro" } }.

Input parameters:

- `brand` (string): Brand ID override
- `data` (object): Data to pass to the automation
- `profile` (object): Profile data for the recipient
- `recipient` (string, required): Recipient user ID
- `template` (string): Notification template override
- `template_id` (string, required): The automation template ID

### `invoke_ad_hoc_automation` (~106 tokens)

Invoke an ad-hoc automation with inline steps. Valid step actions: send, send-list, delay, cancel, update-profile, invoke, fetch-data. To cancel a previously started automation, use the cancel_automation tool instead.

Input parameters:

- `automation` (object, required): The automation definition with typed steps
- `brand` (string)
- `data` (object)
- `profile` (object)
- `recipient` (string)
- `template` (string)

### `list_automations` (~59 tokens)

List automation templates in the workspace. Always call this first to discover template_id values before calling invoke_automation_template. Optionally filter by version.

Input parameters:

- `cursor` (string): Pagination cursor
- `version` (string): Filter by version state

### `cancel_automation` (~85 tokens)

Cancel a running automation by its cancelation_token. This invokes a second ad-hoc automation with a single cancel step. The token must match the cancelation_token set when the original automation was started. Note: spelling is "cancelation_token" (single "l").

Input parameters:

- `cancelation_token` (string, required): The cancelation_token that was set when the automation was originally invoked

### `create_brand` (~152 tokens)

Create a new brand. The API requires settings — omitting it returns a 400. If you do not have specific brand colors, omit settings and a safe default will be used automatically (black primary, white secondary). Example: { name: "Acme", settings: { colors: { primary: "#1a73e8", secondary: "#ffffff" } } }.

Input parameters:

- `id` (string): Optional brand ID; auto-generated if omitted
- `name` (string, required): Brand display name
- `settings` (object): Brand appearance settings. If omitted, defaults to { colors: { primary: "#000000", secondary: "#ffffff" } }.
- `snippets` (object): Brand snippets

### `get_brand` (~26 tokens)

Get a brand by its ID.

Input parameters:

- `brand_id` (string, required): The brand ID

### `list_brands` (~25 tokens)

List all brands in the workspace.

Input parameters:

- `cursor` (string): Pagination cursor

### `update_brand` (~64 tokens)

Replace an existing brand with new values.

Input parameters:

- `brand_id` (string, required): The brand ID to update
- `name` (string, required): Brand display name
- `settings` (object): Brand settings (colors, email, inapp)
- `snippets` (object): Brand snippets

### `delete_brand` (~28 tokens)

Delete a brand by its ID.

Input parameters:

- `brand_id` (string, required): The brand ID to delete

### `create_bulk_job` (~50 tokens)

Create a new bulk job for sending messages to multiple recipients. Workflow: create_bulk_job → add_bulk_users → run_bulk_job.

Input parameters:

- `message` (object, required): Bulk message definition with event/template and content

### `add_bulk_users` (~42 tokens)

Add users to an existing bulk job.

Input parameters:

- `job_id` (string, required): The bulk job ID
- `users` (array, required): Array of user objects to add

### `run_bulk_job` (~35 tokens)

Run a bulk job, triggering delivery to all added users.

Input parameters:

- `job_id` (string, required): The bulk job ID to run

### `get_bulk_job` (~29 tokens)

Get the status of a bulk job.

Input parameters:

- `job_id` (string, required): The bulk job ID

### `list_bulk_users` (~38 tokens)

List the users in a bulk job.

Input parameters:

- `cursor` (string): Pagination cursor
- `job_id` (string, required): The bulk job ID

### `courier_installation_guide` (~85 tokens)

Get the Courier SDK installation guide for a specific platform. For client-side SDKs (React, iOS, Android, Flutter, React Native), also generates a sample JWT.

Input parameters:

- `platform` (string, required): The platform to get installation guide for
- `user_id` (string): User ID for JWT generation (client-side SDKs only). Defaults to "example_user".

### `track_inbound_event` (~99 tokens)

Track an inbound event that can trigger automations. Requires event name, messageId (for deduplication), and properties.

Input parameters:

- `event` (string, required): The event name (appears as trigger in Automation Trigger node)
- `messageId` (string, required): Unique ID for deduplication (returns 409 if not unique)
- `properties` (object, required): Event properties payload
- `userId` (string): User ID associated with the event

### `list_lists` (~52 tokens)

Get all lists. Optionally filter by pattern (e.g. 'example.list.*').

Input parameters:

- `cursor` (string): Pagination cursor
- `pattern` (string): Filter pattern (e.g. 'example.list.*')

### `get_list` (~26 tokens)

Get a list by its ID.

Input parameters:

- `list_id` (string, required): The list ID

### `get_list_subscribers` (~37 tokens)

Get all subscribers of a list.

Input parameters:

- `cursor` (string): Pagination cursor
- `list_id` (string, required): The list ID

### `create_list` (~40 tokens)

Create or update a list by list ID.

Input parameters:

- `list_id` (string, required): The list ID
- `name` (string, required): Display name for the list

### `subscribe_user_to_list` (~59 tokens)

Subscribe a user to a list. Creates the list if it doesn't exist.

Input parameters:

- `list_id` (string, required): The list ID
- `preferences` (object): Optional notification preferences
- `user_id` (string, required): The user ID to subscribe

### `unsubscribe_user_from_list` (~42 tokens)

Unsubscribe a user from a list.

Input parameters:

- `list_id` (string, required): The list ID
- `user_id` (string, required): The user ID to unsubscribe

### `delete_list` (~26 tokens)

Delete a list by its ID.

Input parameters:

- `list_id` (string, required): The list ID

### `restore_list` (~25 tokens)

Restore a previously deleted list.

Input parameters:

- `list_id` (string, required): The list ID

### `bulk_subscribe_to_list` (~47 tokens)

Replace all subscribers on a list with the given recipients.

Input parameters:

- `list_id` (string, required): The list ID
- `recipients` (array, required): Recipients to set on the list

### `add_subscribers_to_list` (~46 tokens)

Append subscribers to a list without removing existing subscribers.

Input parameters:

- `list_id` (string, required): The list ID
- `recipients` (array, required): Recipients to set on the list

### `list_messages` (~224 tokens)

List messages you've previously sent. Filter by status, recipient, notification, provider, tags, or tenant.

Input parameters:

- `archived` (boolean): Include archived messages
- `cursor` (string): Pagination cursor for fetching the next page
- `enqueued_after` (string): ISO 8601 timestamp; only return messages enqueued after this time
- `event` (string): Filter by event ID
- `list` (string): Filter by list ID
- `messageId` (string): Filter by message ID
- `notification` (string): Filter by notification ID
- `provider` (array): Filter by provider key (e.g. sendgrid, twilio)
- `recipient` (string): Filter by recipient user ID
- `status` (array): Filter by status (e.g. DELIVERED, UNDELIVERABLE)
- `tag` (array): Filter by metadata tags
- `tags` (string): Comma-delimited list of tags
- `tenant_id` (string): Filter by tenant ID
- `traceId` (string): Filter by trace ID

### `get_message` (~35 tokens)

Get the full details and status of a single message by its ID.

Input parameters:

- `message_id` (string, required): The message ID to retrieve

### `get_message_content` (~37 tokens)

Get the rendered content (HTML, text, subject) of a previously sent message.

Input parameters:

- `message_id` (string, required): The message ID

### `get_message_history` (~56 tokens)

Get the event history for a message, showing each step in the delivery pipeline (enqueued, sent, delivered, etc.).

Input parameters:

- `message_id` (string, required): The message ID
- `type` (string): Filter by event type

### `cancel_message` (~38 tokens)

Cancel a message that is currently being delivered. Returns the message details with updated status.

Input parameters:

- `message_id` (string, required): The message ID to cancel

### `resend_message` (~75 tokens)

Resend a previously sent message. Loads the original send request and enqueues a brand-new send to the same recipient with the same content, producing a new messageId; the original message is unchanged. Rate limited per message (429 on rapid repeats).

Input parameters:

- `message_id` (string, required): The message ID of the original message to resend

### `list_notifications` (~27 tokens)

List notification templates. Optionally filter by cursor.

Input parameters:

- `cursor` (string): Pagination cursor

### `get_notification_content` (~31 tokens)

Get the published content blocks of a notification template.

Input parameters:

- `notification_id` (string, required): The notification template ID

### `get_notification_draft_content` (~37 tokens)

Get the draft (unpublished) content blocks of a notification template.

Input parameters:

- `notification_id` (string, required): The notification template ID

### `create_notification` (~156 tokens)

Create a V2 notification template. name is required. Provide content inline or set it immediately after creation via put_notification_content. To send with this template you must publish it first via publish_notification (or pass state: 'PUBLISHED' on create). Link a routing strategy via notification.routing.strategy_id to control which channels are used. Example: { notification: { name: 'welcome-email', tags: [], brand: null, subscription: null, routing: { strategy_id: 'rs_01abc' }, content: { version: '2022-01-01', elements: [] } } }.

Input parameters:

- `notification` (object, required): Notification template payload
- `state` (string): Template state after creation (defaults to DRAFT)

### `get_notification` (~63 tokens)

Retrieve a notification template by ID. Optionally request draft, published, or a version such as v001.

Input parameters:

- `notification_id` (string, required): The notification template ID
- `version` (string): Version to retrieve: draft, published, or a string like v001

### `replace_notification` (~59 tokens)

Replace a notification template entirely (full document PUT).

Input parameters:

- `notification` (object, required): Full notification template payload
- `notification_id` (string, required): The notification template ID to replace
- `state` (string): Template state after update (defaults to DRAFT)

### `archive_notification` (~29 tokens)

Archive a notification template by ID.

Input parameters:

- `notification_id` (string, required): The notification template ID to archive

### `list_notification_versions` (~61 tokens)

List version history for a notification template.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `limit` (number): Max versions per page (default 10, max 10)
- `notification_id` (string, required): The notification template ID

### `publish_notification` (~106 tokens)

Publish a notification template, making it available for sending. Must be called before send_message_template unless the template was created with state: 'PUBLISHED'. Publishes the current draft by default; pass version (e.g. 'v001') to publish a specific historical version. Returns 204 on success.

Input parameters:

- `notification_id` (string, required): The notification template ID to publish
- `version` (string): Historical version to publish (e.g. v001); omit to publish current draft

### `list_notification_checks` (~43 tokens)

List checks for a notification submission.

Input parameters:

- `notification_id` (string, required): The notification template ID
- `submission_id` (string, required): The submission ID for the checks resource

### `update_notification_checks` (~54 tokens)

Update check statuses for a notification submission.

Input parameters:

- `checks` (array, required): Checks to update
- `notification_id` (string, required): The notification template ID
- `submission_id` (string, required): The submission ID for the checks resource

### `put_notification_content` (~197 tokens)

Replace the elemental content of a V2 notification template. Overwrites all elements. Use channel elements to target specific channels. Multi-channel example: elements: [{ type: "channel", channel: "email", elements: [{ type: "meta", title: "Hello" }, { type: "text", content: "Email body" }] }, { type: "channel", channel: "push", elements: [{ type: "meta", title: "Hello" }, { type: "text", content: "Push body" }] }, { type: "channel", channel: "inbox", elements: [{ type: "text", content: "Inbox plain text only" }] }].

Input parameters:

- `elements` (array, required): Array of elemental content nodes
- `notification_id` (string, required): The notification template ID (nt_ prefix)
- `state` (string): Template state after update
- `version` (string): Content version string

### `put_notification_element` (~137 tokens)

Update a single element within a V2 notification template.

Input parameters:

- `channels` (array): Channels this element applies to
- `data` (object): Element data payload
- `element_id` (string, required): The element ID to update
- `if` (string): Conditional expression for element visibility
- `loop` (string): Loop expression for repeating elements
- `notification_id` (string, required): The notification template ID (nt_ prefix)
- `ref` (string): Reference identifier
- `state` (string): Template state after update
- `type` (string, required): Element type (e.g. text, action, image, divider, meta)

### `put_notification_locale` (~167 tokens)

Set locale-specific content overrides for a V2 notification template. Each element override must reference an existing element by its id. Example for Spanish locale: { notification_id: "nt_01abc", locale_id: "es", elements: [{ id: "elem_meta_1", title: "Restablecer contraseña" }, { id: "elem_text_1", content: "Haga clic en el enlace para restablecer su contraseña." }] }.

Input parameters:

- `elements` (array, required): Array of element overrides with id and locale-specific content
- `locale_id` (string, required): Locale identifier (e.g. es, fr, pt-BR)
- `notification_id` (string, required): The notification template ID (nt_ prefix)
- `state` (string): Template state after update

### `cancel_notification_submission` (~40 tokens)

Cancel a notification template submission.

Input parameters:

- `notification_id` (string, required): The notification template ID
- `submission_id` (string, required): The submission ID to cancel

### `get_user_profile_by_id` (~45 tokens)

Get a user profile by their ID. Returns profile data including email, phone, and custom properties.

Input parameters:

- `user_id` (string, required): The user ID to look up

### `create_or_merge_user` (~71 tokens)

Create a new user profile or merge supplied values into an existing profile (POST). Existing fields not included are preserved.

Input parameters:

- `profile` (object): Profile data to create or merge (e.g. { email: "...", phone_number: "..." })
- `user_id` (string, required): The user ID

### `replace_profile` (~54 tokens)

Fully replace a user profile (PUT). All existing data is overwritten; include every field you want to keep.

Input parameters:

- `profile` (object, required): Complete profile data to replace with
- `user_id` (string, required): The user ID

### `patch_profile` (~62 tokens)

Partially update a user profile via JSON Patch (RFC 6902). Use add/replace/remove operations on specific profile paths.

Input parameters:

- `patch` (array, required): Array of JSON Patch operations to apply to the profile
- `user_id` (string, required): The user ID

### `delete_profile` (~27 tokens)

Delete a user profile permanently.

Input parameters:

- `user_id` (string, required): The user ID to delete

### `get_user_list_subscriptions` (~39 tokens)

Get all list subscriptions for a user.

Input parameters:

- `cursor` (string): Pagination cursor
- `user_id` (string, required): The user ID

### `subscribe_user_to_lists` (~50 tokens)

Subscribe a user to one or more lists. Creates lists that do not exist.

Input parameters:

- `lists` (array, required): Array of lists to subscribe to
- `user_id` (string, required): The user ID

### `delete_user_list_subscriptions` (~30 tokens)

Delete all list subscriptions for a user.

Input parameters:

- `user_id` (string, required): The user ID

### `send_message` (~122 tokens)

Send a message to a user using inline title and body content (no template). Optionally specify routing channels.

Input parameters:

- `body` (string, required): Message body
- `channels` (array): Channel names to route through (e.g. email, sms, push). Omit to use default routing.
- `data` (object): Key-value data to include with the message
- `method` (string): Routing method: deliver to all channels or stop after first success
- `title` (string, required): Message title
- `user_id` (string, required): The recipient user ID

### `send_message_template` (~144 tokens)

Send a message to a user using a published notification template. The template must be published before sending — call publish_notification first if needed. Example: { user_id: "user-123", template: "nt_01abc123", data: { name: "Alex", resetUrl: "https://app.example.com/reset" } }.

Input parameters:

- `channels` (array): Channel names to route through. Omit to use template routing config.
- `data` (object): Key-value data for template variables
- `method` (string): Routing method
- `template` (string, required): Template ID or notification slug
- `user_id` (string, required): The recipient user ID

### `send_message_to_list` (~98 tokens)

Send a message to all subscribers of a list using inline title and body content.

Input parameters:

- `body` (string, required): Message body
- `channels` (array): Channel names to route through. Omit to use default routing.
- `data` (object): Key-value data to include
- `list_id` (string, required): The list ID to send to
- `method` (string): Routing method
- `title` (string, required): Message title

### `send_message_to_list_template` (~93 tokens)

Send a message to all subscribers of a list using a notification template.

Input parameters:

- `channels` (array): Channel names to route through. Omit to use template routing config.
- `data` (object): Key-value data for template variables
- `list_id` (string, required): The list ID to send to
- `method` (string): Routing method
- `template` (string, required): Template ID or notification slug

### `get_tenant` (~27 tokens)

Get a tenant by its ID.

Input parameters:

- `tenant_id` (string, required): The tenant ID

### `create_or_update_tenant` (~124 tokens)

Create or replace a tenant. Tenants represent organizations or groups that users belong to.

Input parameters:

- `brand_id` (string): Brand ID to associate with this tenant
- `default_preferences`: Default notification preferences for users in this tenant
- `name` (string, required): Display name for the tenant
- `parent_tenant_id` (string): Parent tenant ID for hierarchical tenants
- `properties` (object): Custom properties for the tenant
- `tenant_id` (string, required): The tenant ID
- `user_profile` (object): Default profile data for users in this tenant

### `list_tenants` (~36 tokens)

List all tenants in the workspace.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page

### `delete_tenant` (~29 tokens)

Delete a tenant by its ID.

Input parameters:

- `tenant_id` (string, required): The tenant ID to delete

### `list_tenant_users` (~56 tokens)

List users associated with a tenant.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page (default 20, max 100)
- `tenant_id` (string, required): The tenant ID

### `update_tenant_preference` (~216 tokens)

Set the default notification preference for a subscription topic on a tenant. This controls tenant-level defaults — it does NOT set per-user preferences (use the user preferences API for that). The topic_id must already exist as a subscription topic in the workspace; a 404 means the topic has not been created yet. Example: { tenant_id: "acme", topic_id: "marketing-updates", status: "OPTED_IN", has_custom_routing: true, custom_routing: ["email", "push"] }.

Input parameters:

- `custom_routing` (array): Default channels when has_custom_routing is enabled
- `has_custom_routing` (boolean): When true, use custom_routing instead of template defaults
- `status` (string, required): Subscription status for the topic
- `tenant_id` (string, required): The tenant ID
- `topic_id` (string, required): The subscription topic ID — must already exist in the workspace. A 404 response means the topic does not exist; create it in the Preferences Editor first.

### `delete_tenant_preference` (~45 tokens)

Remove default notification preference for a topic from a tenant.

Input parameters:

- `tenant_id` (string, required): The tenant ID
- `topic_id` (string, required): The subscription topic ID

### `list_tenant_templates` (~57 tokens)

List notification templates configured for a tenant.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page (default 20, max 100)
- `tenant_id` (string, required): The tenant ID

### `get_tenant_template` (~42 tokens)

Get a tenant notification template association by template ID.

Input parameters:

- `template_id` (string, required): The template ID
- `tenant_id` (string, required): The tenant ID

### `replace_tenant_template` (~122 tokens)

Create or replace a tenant notification template (draft unless published is true).

Input parameters:

- `channels`: Channel-specific delivery configuration
- `content`: Elemental content object (e.g. elements and version per Courier Elemental schema)
- `providers`: Provider-specific routing configuration
- `published` (boolean): When true, publish immediately after save
- `routing`: Message routing configuration
- `template_id` (string, required): The template ID
- `tenant_id` (string, required): The tenant ID
- `title` (string): Optional title merged into template content when provided

### `publish_tenant_template` (~65 tokens)

Publish a version of a tenant notification template.

Input parameters:

- `template_id` (string, required): The template ID
- `tenant_id` (string, required): The tenant ID
- `version` (string): Version to publish (e.g. v1, latest); defaults to latest if omitted

### `get_tenant_template_version` (~72 tokens)

Get a specific version of a tenant notification template (e.g. latest, published, or v1).

Input parameters:

- `template_id` (string, required): The template ID
- `tenant_id` (string, required): The tenant ID
- `version` (string, required): Version identifier (latest, published, or v-prefixed)

### `delete_tenant_template` (~63 tokens)

Delete a tenant notification template. Returns 204 on success, 404 if the template does not exist for this tenant.

Input parameters:

- `template_id` (string, required): The notification template ID to delete
- `tenant_id` (string, required): The tenant ID that owns the template

### `get_translation` (~62 tokens)

Get a translation for a specific locale (e.g. "en_US", "fr_FR").

Input parameters:

- `domain` (string): Translation domain (only "default" is supported currently)
- `locale` (string, required): Locale code (e.g. en_US, fr_FR)

### `update_translation` (~58 tokens)

Create or update a translation for a specific locale.

Input parameters:

- `body` (string, required): Translation content (PO file format)
- `domain` (string): Translation domain
- `locale` (string, required): Locale code (e.g. en_US, fr_FR)

### `list_user_push_tokens` (~30 tokens)

List all push/device tokens for a user.

Input parameters:

- `user_id` (string, required): The user ID

### `get_user_push_token` (~41 tokens)

Get a specific push/device token for a user.

Input parameters:

- `token` (string, required): The token identifier
- `user_id` (string, required): The user ID

### `create_or_replace_user_push_token` (~63 tokens)

Create or replace a push/device token for a user.

Input parameters:

- `device` (object): Device metadata
- `provider_key` (string, required): Push provider
- `token` (string, required): The token string
- `user_id` (string, required): The user ID

### `bulk_add_user_tokens` (~51 tokens)

Add multiple push/device tokens for a user in one request. Overwrites matching existing tokens.

Input parameters:

- `tokens` (array, required): Token records to upsert
- `user_id` (string, required): The user ID

### `patch_user_token` (~58 tokens)

Apply a JSON Patch (RFC 6902) to a specific push token.

Input parameters:

- `patch` (array, required): Array of JSON Patch operations
- `token` (string, required): The token identifier
- `user_id` (string, required): The user ID

### `delete_user_token` (~41 tokens)

Delete a specific push token for a user.

Input parameters:

- `token` (string, required): The token identifier to delete
- `user_id` (string, required): The user ID

### `get_user_preferences` (~48 tokens)

Get a user's notification preferences (subscriptions, opt-outs, channel preferences).

Input parameters:

- `tenant_id` (string): Scope preferences to a specific tenant
- `user_id` (string, required): The user ID

### `get_user_preference_topic` (~57 tokens)

Get a user's preference for a specific subscription topic.

Input parameters:

- `tenant_id` (string): Scope to a specific tenant
- `topic_id` (string, required): The subscription topic ID
- `user_id` (string, required): The user ID

### `update_user_preference_topic` (~93 tokens)

Update a user's preference for a specific subscription topic (opt in, opt out, or set channel preferences).

Input parameters:

- `custom_routing` (array): Custom channel routing order
- `has_custom_routing` (boolean): Whether custom channel routing is set
- `status` (string, required): Preference status
- `topic_id` (string, required): The subscription topic ID
- `user_id` (string, required): The user ID

### `delete_user_preference_topic` (~53 tokens)

Delete a user's preference for a specific subscription topic, reverting it to the topic's default status.

Input parameters:

- `topic_id` (string, required): The subscription topic ID
- `user_id` (string, required): The user ID

### `list_user_tenants` (~49 tokens)

List all tenants a user belongs to.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page
- `user_id` (string, required): The user ID

### `add_user_to_tenant` (~52 tokens)

Add a user to a tenant.

Input parameters:

- `profile` (object): Tenant-scoped profile overrides
- `tenant_id` (string, required): The tenant ID
- `user_id` (string, required): The user ID

### `remove_user_from_tenant` (~40 tokens)

Remove a user from a tenant.

Input parameters:

- `tenant_id` (string, required): The tenant ID
- `user_id` (string, required): The user ID

### `bulk_add_user_tenants` (~51 tokens)

Add a user to multiple tenants at once. A custom profile can be supplied per tenant.

Input parameters:

- `tenants` (array, required): Array of tenant associations
- `user_id` (string, required): The user ID

### `remove_all_user_tenants` (~29 tokens)

Remove a user from all tenants.

Input parameters:

- `user_id` (string, required): The user ID

### `bulk_update_user_preferences` (~108 tokens)

Additively create or update a user's preferences for one or more topics in a single request. Only the topics in the body are touched; existing overrides for other topics are left untouched. Partial-success: valid topics are written and returned in `items`, unapplicable ones collected in `errors`.

Input parameters:

- `tenant_id` (string): Scope the update to a specific tenant context
- `topics` (array, required): Topics to create or update
- `user_id` (string, required): The user ID

### `bulk_replace_user_preferences` (~122 tokens)

Replace a user's complete set of preference overrides in one request. The topics in the body become the recipient's entire override set: listed topics are created or updated, and every existing override not included is reset to its topic default. An empty `topics` array clears all overrides. Validation-atomic (all-or-nothing).

Input parameters:

- `tenant_id` (string): Scope the replacement to a specific tenant context
- `topics` (array, required): The complete set of topic overrides. An empty array resets every existing override.
- `user_id` (string, required): The user ID

### `archive_request` (~39 tokens)

Archive a send request and all its associated messages by request ID.

Input parameters:

- `request_id` (string, required): The request ID (requestId returned from /send)

### `create_routing_strategy` (~98 tokens)

Create a routing strategy defining how notifications are delivered across channels and providers.

Input parameters:

- `channels` (object): Per-channel delivery configuration
- `description` (string): Description of the routing strategy
- `name` (string, required): Human-readable name for the routing strategy
- `providers` (object): Per-provider delivery configuration
- `routing` (object, required): Routing tree defining channel selection method and order
- `tags` (array): Tags for categorization

### `get_routing_strategy` (~46 tokens)

Retrieve a routing strategy by ID. Returns the full entity including routing, channels, and providers.

Input parameters:

- `routing_strategy_id` (string, required): The routing strategy ID (rs_ prefix)

### `replace_routing_strategy` (~115 tokens)

Replace a routing strategy. Full document replacement; missing optional fields are cleared.

Input parameters:

- `channels` (object): Per-channel delivery configuration. Omit to clear.
- `description` (string): Description. Omit to clear.
- `name` (string, required): Human-readable name
- `providers` (object): Per-provider delivery configuration. Omit to clear.
- `routing` (object, required): Routing tree
- `routing_strategy_id` (string, required): The routing strategy ID
- `tags` (array): Tags. Omit to clear.

### `archive_routing_strategy` (~46 tokens)

Archive a routing strategy. The strategy must not have associated notification templates; unlink all templates before archiving.

Input parameters:

- `routing_strategy_id` (string, required): The routing strategy ID to archive

### `list_routing_strategies` (~57 tokens)

List routing strategies in the workspace. Returns metadata only; use get for full details.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page (default 20, max 100)

### `list_routing_strategy_notifications` (~74 tokens)

List notification templates associated with a routing strategy. Useful for checking linked templates before archiving.

Input parameters:

- `cursor` (string): Pagination cursor
- `limit` (number): Max results per page (default 20, max 100)
- `routing_strategy_id` (string, required): The routing strategy ID (rs_ prefix)

### `list_journeys` (~73 tokens)

List journey templates in the workspace. Call this first to discover journey IDs before calling invoke_journey, get_journey, or replace_journey. Optionally filter by version (published or draft).

Input parameters:

- `cursor` (string): Pagination cursor
- `version` (string): Filter by version state. Defaults to published.

### `invoke_journey` (~129 tokens)

Invoke a journey run from a journey template. Call list_journeys first to find the template_id. Example: { template_id: "j-onboarding", user_id: "user-123", data: { plan: "pro" } }.

Input parameters:

- `data` (object): Data payload passed to the journey for conditions and template variables
- `profile` (object): Profile data for the user (email, phone, custom fields)
- `template_id` (string, required): The journey template ID
- `user_id` (string): Recipient user ID. Can also be resolved from profile or data.

### `create_journey` (~234 tokens)

Create a new journey. Defaults to DRAFT state. Send nodes are not allowed on create — create the shell with a trigger node, then call replace_journey to add send nodes after linking notification templates. Call publish_journey to make it live. Node ids are server-generated; do NOT include an id field. Example: { name: "Welcome Journey", nodes: [{ type: "trigger", trigger_type: "api-invoke" }], enabled: true }.

Input parameters:

- `enabled` (boolean): Whether the journey is active. Defaults to true.
- `name` (string, required): Journey display name
- `nodes` (array, required): Array of journey node objects. Node ids are server-generated — do NOT include an id field. Trigger node example: { type: "trigger", trigger_type: "api-invoke" }. Send node example: { type: "send", te…
- `state` (string): Create as DRAFT (default) or PUBLISHED immediately.

### `get_journey` (~78 tokens)

Get a journey by ID. Pass version=draft to retrieve the working draft, or version=vN for a historical version. Defaults to published.

Input parameters:

- `journey_id` (string, required): The journey template ID
- `version` (string): Version to retrieve: "draft", "published" (default), or a version string like "v001"

### `replace_journey` (~154 tokens)

Replace (update) a journey draft. Full document replacement — include all nodes and properties in the body. Call publish_journey afterwards to make changes live, or pass state: "PUBLISHED" to publish immediately. Send node template IDs must already be scoped to this journey.

Input parameters:

- `enabled` (boolean): Whether the journey is active.
- `journey_id` (string, required): The journey template ID to update
- `name` (string, required): Journey display name
- `nodes` (array, required): Complete array of journey nodes. Use server-assigned node ids from get_journey — do NOT invent new ids. Each node requires type plus type-specific fields.
- `state` (string): Set to PUBLISHED to publish immediately after replace.

### `publish_journey` (~93 tokens)

Publish the current draft of a journey, making it live and invokable. Pass version to roll back to a prior published version instead of publishing the draft. Returns 404 if there is no draft to publish.

Input parameters:

- `journey_id` (string, required): The journey template ID to publish
- `version` (string): Historical version to roll back to (e.g. "v001"). Omit to publish the current draft.

### `archive_journey` (~39 tokens)

Archive a journey. Archived journeys cannot be invoked but existing runs continue to completion.

Input parameters:

- `journey_id` (string, required): The journey template ID to archive

### `list_journey_versions` (~34 tokens)

List published versions of a journey, ordered most recent first.

Input parameters:

- `journey_id` (string, required): The journey template ID

### `list_journey_templates` (~83 tokens)

List notification templates scoped to a journey. Journey-scoped templates can only be used by send nodes within the same journey. Call this to discover template IDs before wiring send nodes in replace_journey.

Input parameters:

- `cursor` (string): Pagination cursor
- `journey_id` (string, required): The journey template ID
- `limit` (number): Page size (1–100)

### `create_journey_template` (~197 tokens)

Create a notification template scoped to a journey. Defaults to DRAFT; pass state: "PUBLISHED" to publish on create. The template can then be referenced in journey send nodes. Example: { journey_id: "j-abc", channel: "email", notification: { name: "Welcome Email", tags: [], brand: null, subscription: null, content: { version: "2022-01-01", elements: [{ type: "text", content: "Hello!" }] } } }.

Input parameters:

- `channel` (string, required): Channel for this template (e.g. "email", "push", "sms", "inbox")
- `journey_id` (string, required): The journey template ID
- `notification` (object, required): Notification template definition
- `provider_key` (string): Specific provider key to target
- `state` (string): Initial state: "DRAFT" (default) or "PUBLISHED"

### `get_journey_template` (~95 tokens)

Get a journey-scoped notification template by notification ID. Pass version=draft to retrieve the working draft (required before the template has been published). Defaults to published.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID
- `version` (string): Version to retrieve: "draft", "published" (default), or "vN"

### `replace_journey_template` (~91 tokens)

Replace the draft of a journey-scoped notification template. Full document replacement. Call publish_journey_template afterwards to make it live.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification` (object, required): Full notification template definition
- `notification_id` (string, required): The notification template ID
- `state` (string): "PUBLISHED" to publish immediately after replace

### `archive_journey_template` (~52 tokens)

Archive a journey-scoped notification template. Archived templates cannot be sent.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID

### `publish_journey_template` (~88 tokens)

Publish the current draft of a journey-scoped notification template. Optionally pass version to roll back to a prior version.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID
- `version` (string): Version to roll back to (e.g. "v1"). Omit to publish current draft.

### `list_journey_template_versions` (~55 tokens)

List published versions of a journey-scoped notification template, ordered most recent first.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID

### `get_journey_template_content` (~100 tokens)

Fetch the elemental content of a journey-scoped notification template. Pass version=draft for the working draft, or vN for a historical version. Defaults to published.

Input parameters:

- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID
- `version` (string): Version to retrieve: "draft", "published" (default), or a version string like "v001"

### `put_journey_template_content` (~116 tokens)

Replace the elemental content of a journey-scoped notification template. Overwrites all elements. Call publish_journey_template afterwards to make it live.

Input parameters:

- `elements` (array, required): Array of elemental content nodes
- `journey_id` (string, required): The journey template ID that owns this notification
- `notification_id` (string, required): The notification template ID
- `state` (string): Template state after update
- `version` (string): Content version string (e.g. "2022-01-01"). Server defaults when omitted.

### `put_journey_template_locale` (~113 tokens)

Set locale-specific content overrides for a journey-scoped notification template. Each element override must reference an existing element by its id.

Input parameters:

- `elements` (array, required): Array of element overrides with id and locale-specific content
- `journey_id` (string, required): The journey template ID that owns this notification
- `locale_id` (string, required): Locale identifier (e.g. es, fr, pt-BR)
- `notification_id` (string, required): The notification template ID
- `state` (string): Template state after update

### `cancel_journey` (~110 tokens)

Cancel journey runs. Supply EXACTLY ONE of cancelation_token (cancels every run associated with the token) or run_id (cancels a single run). Cancelation is idempotent: a run that already finished or was already canceled is left unchanged.

Input parameters:

- `cancelation_token` (string): Cancels every run associated with this token. Mutually exclusive with run_id.
- `run_id` (string): Cancels a single run by id. Mutually exclusive with cancelation_token.

### `list_providers` (~26 tokens)

List configured provider integrations for the workspace.

Input parameters:

- `cursor` (string): Pagination cursor

### `get_provider` (~28 tokens)

Fetch a single provider configuration by ID.

Input parameters:

- `provider_id` (string, required): The provider configuration ID

### `list_provider_catalog` (~68 tokens)

List available provider types from the catalog with their configuration schemas.

Input parameters:

- `channel` (string): Filter by channel type (email, sms, push, etc.)
- `keys` (string): Comma-separated provider keys to filter by
- `name` (string): Substring match on provider name

### `create_provider` (~127 tokens)

Create a new provider (integration) configuration. Once routing strategies or notification templates reference this config, credential or settings mistakes can affect live sends—confirm provider key and settings against list_provider_catalog before saving. The provider field must be a known Courier provider key.

Input parameters:

- `alias` (string): Short alias for referencing this provider
- `provider` (string, required): Provider key from the catalog (e.g. sendgrid, twilio, firebase-fcm)
- `settings` (object): Provider-specific settings (API keys, credentials, etc.)
- `title` (string): Display name for this provider configuration

### `update_provider` (~106 tokens)

Replace an existing provider configuration. Full replacement — retrieve current config with get_provider first; omitted optional fields are cleared. Changing API keys or settings affects live delivery if this integration is in use.

Input parameters:

- `alias` (string): Short alias
- `provider` (string, required): Provider key (must match existing; changing provider type is not supported)
- `provider_id` (string, required): The provider configuration ID
- `settings` (object): Provider-specific settings
- `title` (string): Display name

### `delete_provider` (~41 tokens)

Delete a provider configuration. Returns 409 if the provider is still referenced by routing or notifications.

Input parameters:

- `provider_id` (string, required): The provider configuration ID to delete

### `list_preference_sections` (~23 tokens)

List the workspace's preference sections. Each section embeds its topics.

### `create_preference_section` (~86 tokens)

Create a preference section in your workspace. The section id is generated and returned. Add topics afterwards with create_preference_topic.

Input parameters:

- `has_custom_routing` (boolean): Whether the section defines custom routing for its topics
- `name` (string, required): Human-readable name for the section
- `routing_options` (array): Default channels for the section. Defaults to empty if omitted.

### `get_preference_section` (~34 tokens)

Retrieve a preference section by id, including its topics.

Input parameters:

- `section_id` (string, required): Id of the preference section

### `replace_preference_section` (~96 tokens)

Replace a preference section. Full document replacement; missing optional fields are cleared. Topics attached to the section are unaffected.

Input parameters:

- `has_custom_routing` (boolean): Whether the section defines custom routing for its topics
- `name` (string, required): Human-readable name for the section
- `routing_options` (array): Default channels for the section. Omit to clear.
- `section_id` (string, required): Id of the preference section

### `archive_preference_section` (~49 tokens)

Archive a preference section. The section must be empty: delete its topics first, otherwise the request fails with 409.

Input parameters:

- `section_id` (string, required): Id of the preference section to archive

### `publish_preferences` (~41 tokens)

Publish the workspace's preferences page. Takes a snapshot of every section with its topics under a new published version, making the current state visible on the hosted preferences page.

### `list_preference_topics` (~31 tokens)

List the topics in a preference section.

Input parameters:

- `section_id` (string, required): Id of the preference section

### `create_preference_topic` (~166 tokens)

Create a subscription preference topic inside a section. The topic id is generated and returned. Fails with 404 if the section does not exist.

Input parameters:

- `allowed_preferences` (array): Preference controls a recipient may customize for this topic
- `default_status` (string, required): Default subscription status applied when a recipient has not set their own
- `include_unsubscribe_header` (boolean): Whether to include a list-unsubscribe header on emails for this topic
- `name` (string, required): Human-readable name for the preference topic
- `routing_options` (array): Default channels delivered for this topic. Defaults to empty if omitted.
- `section_id` (string, required): Id of the preference section to create the topic in
- `topic_data` (object): Arbitrary metadata associated with the topic

### `get_preference_topic` (~65 tokens)

Retrieve a topic within a section. Returns 404 if the section or topic does not exist, or the topic belongs to a different section.

Input parameters:

- `section_id` (string, required): Id of the preference section
- `topic_id` (string, required): Id of the subscription preference topic

### `replace_preference_topic` (~169 tokens)

Replace a topic within a section. Full document replacement; missing optional fields are cleared.

Input parameters:

- `allowed_preferences` (array): Preference controls a recipient may customize. Omit to clear.
- `default_status` (string, required): Default subscription status applied when a recipient has not set their own
- `include_unsubscribe_header` (boolean): Whether to include a list-unsubscribe header on emails for this topic
- `name` (string, required): Human-readable name for the preference topic
- `routing_options` (array): Default channels delivered for this topic. Omit to clear.
- `section_id` (string, required): Id of the preference section
- `topic_data` (object): Arbitrary metadata associated with the topic. Omit to clear.
- `topic_id` (string, required): Id of the subscription preference topic

### `archive_preference_topic` (~46 tokens)

Archive a topic within a section.

Input parameters:

- `section_id` (string, required): Id of the preference section
- `topic_id` (string, required): Id of the subscription preference topic to archive

### `release_digest` (~67 tokens)

Release a digest schedule early — send what users have collected so far now instead of waiting for the scheduled time. A 204 is also returned when the schedule has no in-progress instances to release.

Input parameters:

- `schedule_id` (string, required): The digest schedule id, in the form "sch/{uuid}"

### `list_digest_instances` (~93 tokens)

List the digest instances for a schedule. Each instance represents the events accumulated for a single user against the schedule, useful for monitoring accumulation before a digest is released.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `limit` (number): Max instances to return (default 20, max 100)
- `schedule_id` (string, required): The digest schedule id, in the form "sch/{uuid}"

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/trycourier-courier/mcp#diagnostics

## Score history

- 2026-08-03: 69
- 2026-08-02: 68
- 2026-08-01: 68
- 2026-07-31: 67
- 2026-07-30: 67
- 2026-07-29: 66
- 2026-07-28: 65
- 2026-07-27: 65
- 2026-07-26: 64

## Links

- Remote endpoint: https://mcp.courier.com/
- Authorisation metadata: https://mcp.courier.com/.well-known/oauth-protected-resource
- Repository: https://github.com/trycourier/courier-mcp
- Website: https://courier.com/
- Changelog RSS feed: https://verifymcp.io/servers/trycourier-courier/mcp/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/trycourier-courier/mcp/changelog.json
- HTML version of this page: https://verifymcp.io/servers/trycourier-courier/mcp
