Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Novu

FreeNot checked

Novu MCP Server

GitHubEmbed

About

Novu MCP Server

README


Product Hunt Hacker News npm downloads

Novu MCP Server

The Model Context Protocol (MCP) server for Novu — bring AI assistants directly into your notification workflows. Manage subscribers, trigger workflows, inspect events, and tune preferences from any MCP-compatible client.


Visit our main GitHub Repository »

✨ Features

A single MCP server that unlocks your entire Novu workspace for AI agents:

  • Notifications — fetch and filter events with full execution logs and delivery status
  • Subscribers — search and manage recipients by email, phone, name, or ID
  • Workflows — list, inspect, create, update, and trigger notification workflows
  • Preferences — read and update subscriber channel preferences (email, SMS, in-app, push, chat)
  • Environments — view environments and their configuration
  • Integrations — manage provider integrations across channels
  • Auth & Identitywhoami verifies your credential (OAuth or API key) and reports the active region

🚀 Quick Start

You don't need to host anything — the server is fully managed. Pick the endpoint for your Novu Cloud region and point your MCP client at it:

Region Endpoint Novu API
US https://mcp.novu.co/ api.novu.co
EU https://eu.mcp.novu.co/ eu.api.novu.co

Each host is a dedicated deployment pinned to its region — there is no ?region= query param anymore. (For backward compatibility, a ?region= that doesn't match the host's region returns a 400 pointing you at the correct endpoint.)

Authentication

The server supports two ways to authenticate, and both work identically on either regional endpoint:

1. OAuth (recommended) — No API key to copy/paste. When your MCP client first connects, the server responds with a 401 and an OAuth discovery document (/.well-known/oauth-protected-resource) that points the client at Novu's authorization server (Clerk). Your client opens the Novu sign-in + consent screen, you pick an organization, and the client receives an access token automatically.

Any MCP client that supports remote OAuth (Cursor, Claude, ChatGPT, Windsurf, …) handles this flow for you — just add the server URL with no header.

Note: the client must request the user:org:read scope (advertised in the discovery document) so the Novu API can resolve your organization. If your Novu account belongs to multiple organizations, you'll be asked to select one during consent.

2. API key — Provide your key from the Novu Dashboard as a bearer token:

Authorization: Bearer <your-novu-api-key>

When you present an API key, the server treats the session as API-key mode and will not trigger the OAuth sign-in flow — even on the hosted endpoints. The key is bound to a single environment (and thus region), so no extra configuration is needed; just connect to the endpoint for the region your account lives in.

Self-hosted Novu? OAuth is only available for Novu Cloud (US/EU) — the flow runs against Novu Cloud's authorization server, which a self-hosted deployment has no access to. Self-hosted deployments always authenticate with an API key. See Deploying your own instance and Local Development.

🎯 Environments

How requests map to a Novu environment depends on how you authenticate:

  • API key — the key itself is bound to a single environment; requests always run against that environment.
  • OAuth — the token is bound to your organization, and the Novu API defaults to the Development environment.

For OAuth sessions, every tool accepts an optional environmentId parameter to target a specific environment (forwarded to the Novu API as the Novu-Environment-Id header). Call get_environments first to list your environments, then pass the _id of the one you want — for example, to inspect Production notifications. The Novu API validates that the environment belongs to your organization. With an API key the parameter is ignored — the key already pins the environment.

Local / self-hosted API — to point this MCP server at a Novu API running elsewhere (for example a self-hosted instance on http://localhost:3000), set NOVU_API_URL in .dev.vars and run the server locally (see Local Development). This replaces the old ?region=local query param. Self-hosted always uses an API key — OAuth is Novu Cloud only.

🛠️ Usage

The server speaks the Streamable HTTP MCP transport at https://mcp.novu.co/ (US) and https://eu.mcp.novu.co/ (EU).

Cursor, Windsurf, Claude & other OAuth-capable clients

Any client that supports remote MCP servers with OAuth can connect with no header — the client runs the sign-in flow for you:

  • URL (US): https://mcp.novu.co/
  • URL (EU): https://eu.mcp.novu.co/

On first connection the client opens the Novu sign-in + consent screen. Approve it, select your organization, and the tools appear automatically.

API key (mcp-remote / stdio clients, self-hosted Novu)

For clients that only support stdio transports, if you prefer a static API key, or if you run a self-hosted Novu instance (where OAuth is not available), use the mcp-remote proxy with an Authorization header. Presenting an API key keeps the client from launching the OAuth flow:

{
  "mcpServers": {
    "novu": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://mcp.novu.co/",
        "--header",
        "Authorization:Bearer your-novu-api-key"
      ]
    }
  }
}

For the EU region, swap the URL for https://eu.mcp.novu.co/.

📦 Available Tools

Tool Description
whoami Show who is authenticated (verifies the credential against the Novu API) and the active region
get_environments List all environments with their details and API keys
get_notifications Fetch events with filtering by channel, template, subscriber, date, and more
get_notification Get a specific notification with detailed execution logs
find_subscribers Search subscribers by email, name, phone, or ID
get_subscriber_preferences Get a subscriber's preferences across all channels and workflows
update_subscriber_preferences Update a subscriber's channel preferences globally or per workflow
get_workflows List all workflows with their basic information
get_workflow Get a workflow's full definition, steps, and payload schema
trigger_workflow Trigger a workflow for a subscriber with a custom payload
get_integrations List configured provider integrations across channels

💻 Local Development

Prerequisites: Node.js 20+ and pnpm.

# Clone and install
git clone https://github.com/novuhq/novu-mcp-server.git
cd novu-mcp-server
pnpm install

# Start the local worker
pnpm dev

The server runs at http://localhost:8787. Point your MCP client at it the same way you would the hosted version:

{
  "mcpServers": {
    "novu": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8787/",
        "--header",
        "Authorization:Bearer your-novu-api-key"
      ]
    }
  }
}

Configuration is read from .dev.vars (gitignored) — copy .dev.vars.example to get started. The key variables are:

  • NOVU_API_URL — the Novu API this server proxies to (e.g. http://localhost:3000 for a self-hosted API, or https://api.novu.co / https://eu.api.novu.co for cloud).
  • NOVU_REGION — the display label surfaced by whoami.
  • CLERK_OAUTH_ISSUER — the Clerk authorization server for OAuth. Leave empty to disable OAuth entirely and run API-key-only (the self-hosted mode).

For local development against a self-hosted Novu API on http://localhost:3000, set NOVU_API_URL="http://localhost:3000" in .dev.vars and use your instance's API key (OAuth is Novu Cloud only):

{
  "mcpServers": {
    "novu-local": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8787/",
        "--header",
        "Authorization:Bearer your-local-novu-api-key"
      ]
    }
  }
}

OAuth in local development

To exercise OAuth locally, set CLERK_OAUTH_ISSUER in .dev.vars to a Clerk authorization server your Novu API trusts (e.g. https://clerk.dashboard.novu.co for US). The MCP endpoint origin is derived from the request URL, so run the dev server and point your MCP client at the same URL (e.g. http://localhost:8787/). RFC 9728 requires the PRM resource field to exactly match the MCP endpoint URL; connecting via a different host/port than the server is bound to causes clients like Cursor to discard the metadata and register without the user:org:read scope.

When CLERK_OAUTH_ISSUER is empty, the OAuth discovery endpoints return 404 and 401 responses omit the OAuth metadata, so clients fall back to API-key auth.

Deploying your own instance

The server is a standard Cloudflare Worker. wrangler.jsonc is organized so the top-level config is local-dev-only (no routes, so wrangler dev serves on localhost and OAuth discovery advertises the localhost origin), while real deployments live under named environments:

  • pnpm deploy--env us (binds mcp.novu.co, NOVU_API_URL=https://api.novu.co)
  • pnpm deploy:eu--env eu (binds eu.mcp.novu.co, NOVU_API_URL=https://eu.api.novu.co)

To deploy your own instance, fork the repo and add an environment under env (or edit an existing one) with your own routes, NOVU_API_URL, and NOVU_REGION, then deploy it with wrangler deploy --env <name>. A self-deployed instance works out of the box with API-key authentication against whatever NOVU_API_URL points at — including a self-hosted Novu API. OAuth on your own deployment requires setting the CLERK_OAUTH_ISSUER secret (wrangler secret put CLERK_OAUTH_ISSUER --env <name>) to an authorization server that your Novu API trusts; leave it unset for API-key-only.

Scripts

  • pnpm dev — Run the worker locally via Wrangler (top-level, route-free config)
  • pnpm deploy — Deploy the US worker (mcp.novu.co, --env us)
  • pnpm deploy:eu — Deploy the EU worker (eu.mcp.novu.co, --env eu)
  • pnpm type-check — Run TypeScript type checking
  • pnpm lint:fix — Fix linter issues with Biome
  • pnpm format — Format the codebase with Biome

Project structure

src/
├── index.ts            # Worker entry — auth extraction and routing
├── oauth.ts            # OAuth discovery, 401 bootstrap, initialize-time probe
├── server/NovuMCP.ts   # Durable Object hosting the MCP agent
├── tools/              # One file per tool group (workflows, subscribers, …)
├── utils/              # API client, validation, tool factory
└── types/              # Shared TypeScript types

Add new tools by creating a register*Tools function under src/tools/ and wiring it in src/server/NovuMCP.ts.

🔒 Security

  • The server is a pure OAuth pass-through: it does not mint, exchange, or re-sign tokens. It never validates tokens itself — it advertises Novu's Clerk authorization server and forwards the caller's Authorization header verbatim to the Novu API, which validates it and resolves the org/permissions.
  • OAuth access tokens (Clerk opaque oat_… tokens) are short-lived and revocable from the Novu side, so they are far safer than a long-lived API key.
  • Whether OAuth token or legacy API key, the credential is scoped to your MCP session: it is handed to the session's Durable Object via the runtime's props channel — never placed in URLs, where it would leak into request logs — and is discarded with the session. The server holds no ambient credentials.
  • Never commit API keys or issuer config. Use .dev.vars for local values (already gitignored).
  • Treat your Novu API key like a password — rotate it from the dashboard if you suspect it has been exposed.

🤝 Contributing

  1. Make Changes

    git checkout -b feat/your-change
    pnpm dev           # Test locally
    pnpm type-check    # Verify types
    git commit -m "feat: your change"
    git push origin feat/your-change
    
  2. Open a Pull Request

    • Use a descriptive title with feat:, fix:, docs:, or chore: prefix
    • Include a short description of the change and, where relevant, a sample tool call

Guidelines:

  • Keep tool descriptions concise — they are surfaced verbatim to LLMs
  • Validate inputs with Zod schemas in src/utils/
  • Prefer the ToolFactory helpers for standard CRUD endpoints
  • Something missing? Open a GitHub issue

Need help? Email us at [email protected] or join the Discord.


Thank you for contributing! 🙏

from github.com/novuhq/novu-mcp-server

Installing Novu

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/novuhq/novu-mcp-server

FAQ

Is Novu MCP free?

Yes, Novu MCP is free — one-click install via Unyly at no cost.

Does Novu need an API key?

No, Novu runs without API keys or environment variables.

Is Novu hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Novu in Claude Desktop, Claude Code or Cursor?

Open Novu on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Novu with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs