Blog
AIENGINEERING

The Courier MCP Server Is Open Source. Here's How It Actually Works.

Mike Miller

February 06, 2026

Courier MCP is open source

Table of contents

TLDR

Try it now

What's in the repo

How the tools register

What you can do

What it won't do

How to contribute

TLDR

Courier's MCP server is open source on GitHub. It's a TypeScript project that extends the official @modelcontextprotocol/sdk and registers 16 tool classes covering send, docs, automations, profiles, lists, and more. Two design decisions are worth stealing: the SdkContextTools class that reads your package.json to detect which Courier SDK version you're running (and provides the correct usage rules to the LLM), and the DocsTools class that pulls installation guides from GitHub at runtime and generates live JWTs in the same response. (Note: SdkContextTools exists in the repo but isn't wired into the server entrypoint yet.) This post walks through the actual code.

Try it now

Grab an API key from app.courier.com/settings/api-keys and pick your client:

Cursor

add to .cursor/mcp.json:

Copied!

Claude Code

Copied!

Codex

— add to ~/.codex/config.toml:

Copied!

All three connect to the same hosted server. Once connected, try something like:

"Send an email to user test_user_123 with the subject 'Hello' and body 'Testing Courier MCP'"

The agent calls send_message, Courier routes it, and you get a requestId back. That's the full loop — no SDK install, no Postman, no curl.

For the full list of available tools, see the MCP docs. For the underlying REST API these tools wrap, see the API Reference. And if you're new to Courier entirely, the Quickstart walks through setting up your first notification channel.

Now here's what's behind it.

claude code prompt strategy notifications

What's in the repo

github.com/trycourier/courier-mcp. TypeScript, two contributors (me and xehl). The structure:

Copied!

The MCP server runs as a hosted HTTP service at https://mcp.courier.com, but you can run it locally with sh dev.sh for development.

How the tools register

The entry point is CourierMcp, which extends the MCP SDK's McpServer:

Copied!

Every tool module extends CourierMcpTools, which has one method worth noting:

Copied!

The availableTools config is the gatekeeper for most tools. Not every user needs all 16 tool classes' worth of tools exposed to their LLM. If you're only using the MCP server to send messages and check docs, you configure it to register just those tools. The LLM never sees the rest. (There is one exception today: send_message_to_list_template is registered directly, not through the gate.)

This matters because MCP clients (especially Cursor) start to degrade when they have 40+ tools loaded. We have enough tools across all modules that this would happen without the filter.

What you can do

Send messages

SendTools registers four tools:

Copied!

Two axes: individual user vs. list, and inline content vs. template. This split exists because LLMs are better at picking the right tool when the name tells them what it does. A single send tool with a use_template: boolean flag would require the LLM to read the schema and reason about the flag. Four named tools let it match on the name alone.

The send_message tool takes a channels array and a method (all or single). all sends to every channel in the array. single sends to the first one that works and stops. This is Courier's routing model exposed directly to the LLM:

Copied!

When a developer prompts "send an email and push notification to user X," the LLM calls send_message with method: 'all' and channels: ['email', 'push']. When they say "try email first, fall back to push," it uses method: 'single' with channels: ['email', 'push']. The schema encodes the routing logic.

SDK version detection

This is the tool I'm most proud of. SdkContextTools has three tools (currently not registered in the server entrypoint):

Copied!

get_courier_sdk_context reads the developer's package.json from disk and detects which Courier React SDK they're running. v7 is the old multi-package setup (@trycourier/react-inbox, @trycourier/react-provider, @trycourier/react-hooks). v8 is the consolidated @trycourier/courier-react (and @trycourier/courier-react-17).

Here's why this matters: if you prompt Cursor to "add a notification inbox to my React app" and you're on v7, the correct code is:

Copied!

But if you're on v8, that code is wrong. v8 removed CourierProvider, switched from clientKey to JWT auth, and renamed the component:

Copied!

Without the SDK context tool, the LLM guesses based on training data, which is a mix of v7 and v8 examples. With it, the LLM knows which version is installed and gets the correct rules, usage example, and migration hints in one call.

scan_courier_imports goes a step further. It walks your src/ directory, reads every .ts, .tsx, .js, and .jsx file, and checks for mixed imports or deprecated API calls:

Copied!

If you have both v7 and v8 imports in the same project (happens more than you'd think during migrations), the tool flags it. If you're using useInbox() (deprecated) or addTag() (removed), it tells the LLM exactly which files have the problem.

The LLM uses this to generate correct migration code instead of making things worse.

Reference Installation Guides

DocsTools has one tool: courier_installation_guide. It takes a platform enum:

Copied!

The guides themselves are Markdown files stored in the repo's /docs directory. The tool fetches them at runtime from GitHub raw content:

Copied!

This means when we update a guide, every MCP user gets the update immediately. No package version bump, no "please update your MCP server" email. Push to main, done.

For client-side platforms (React, iOS, Android, Flutter, React Native), the tool does something extra: it generates a live JWT alongside the docs.

Copied!

So when a developer prompts "set up Courier in my React app," the LLM gets:

  1. Current installation instructions (pulled from GitHub, always up to date)
  2. A working JWT token for the user ID they specify (or a default example_user)

The generated code actually runs. Not placeholder tokens, not YOUR_JWT_HERE, a real token scoped to user_id:example_user with inbox read/write, preferences, and brands permissions. Valid for one hour.

Invoke Automations

AutomationsTools wraps Courier's automation templates in a single tool:

Copied!

This lets you say "trigger the welcome sequence for user abc123" and the LLM calls:

Copied!

Workflow

The template contains the multi-step logic (send email, wait 24 hours, check if user logged in, send push if not). The MCP tool just triggers it. The LLM doesn't need to understand the automation's internal steps.

What it won't do

We don't expose delete operations for core resources like users, templates, or lists. There are delete-style tools for list subscriptions (unsubscribe_user_from_list and delete_user_list_subscriptions), but no delete endpoints for the primary objects themselves. The MCP server is for building and testing, not for teardown. An LLM misinterpreting a prompt and deleting production data is a failure mode we'd rather not ship.

We also limited administrative updates. You can create and read, but bulk modifications to workspace settings aren't exposed. The principle: the MCP server should be safe to hand to an AI agent without worrying about what it might do to your account.

How to contribute

The repo is at github.com/trycourier/courier-mcp. If you find a bug, want to add a tool, or think the SDK context detection should finally be wired in, open an issue or PR. We're two contributors and we review everything that comes in.

Similar resources

Lifecycle marketing from Fable 5
AICustomer JourneysGuide

Your Entire Lifecycle Marketing Department, Run from Claude Fable 5

With the rollout of Claude' Fable model, one thing is becoming increasingly clear. Marketing execution (especially the long-tail work), will be done in an AI editor. In Courier, connect your agent to the MCP server or CLI, install Courier Skills, and keep a small folder of markdown context files. From there, one person with a coding agent covers the work that used to require a lifecycle marketer, an email designer, a marketing ops hire, and an engineer: building journeys, shipping templates, auditing every notification, and debugging delivery without opening a dashboard.

By Kyle Seyler

June 09, 2026

Human-in-the-loop for AI payment agents
AIGuideEngineering

Human-in-the-loop for AI payment agents: building approval notifications that work

AI agents need human approval before taking consequential actions: financial commitments, irreversible changes, decisions that affect other people. This post covers how to design those checkpoints and build the notification infrastructure: multi-channel delivery, live context, escalation, and a back-and-forth question loop between reviewers and the agent.

By Eric Lee

May 26, 2026

product updates May 2026
Product NewsCourier UpdatesAI

What we shipped this month: May 2026 Edition

Courier shipped five launches in May 2026: AI Agent in Journeys (GA), the new Journeys API for code-driven flows, Custom Environments, Design Studio styling controls, and Courier Console v3. Each one closes a gap between writing software and shipping the messages that go with it.

By Kyle Seyler

May 20, 2026

Multichannel Notifications Platform for SaaS

Products

Platform

Integrations

Customers

Blog

API Status

Subprocessors


© 2026 Courier. All rights reserved.