ntfy-mcp-server
Enables sending notifications to any device with ntfy integration, supporting rich message formatting with titles, tags, priorities, action buttons, and attachments for real-time notifications to phones, desktops, and other devices.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ntfy-mcp-serversend me a notification when the deployment finishes"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overview
Push notifications over the ntfy pub/sub HTTP API. Publish, update, and manage notifications, poll cached topic history, and look up emoji short codes for tags from any MCP client. Runs as a stdio process or a local Streamable HTTP server.
Tools
Tool | Description |
| Send or update a push notification on an ntfy topic. |
| Clear or delete a previously-sent notification by |
| Poll cached messages from one or more topics with optional filters. |
| Look up ntfy emoji tag short codes for use in |
Resources
Resource | Description |
| Snapshot of a topic — latest 20 messages from the past hour, plus the topic's browser URL. |
ntfy_fetch_messages covers the same topic data with custom windows and filters when the resource's fixed defaults aren't enough.
Related MCP server: ntfy-me-mcp
Capability reference
ntfy_publish_message tool
Topics are created on first publish — treat the topic name as a secret; anyone who knows it can publish or subscribe
Full publish-parameter coverage —
title,priority(1–5),tags,click,attach,icon,filename,markdown,delay,email,call,cache,firebase; message body capped at 4096 bytes (non-ASCII characters cost more), empty body defaults server-side totriggeredUp to three discriminated action buttons (
view,broadcast,http,copy) per messageUpdate or replace a previously-sent message by passing the original
sequence_idPer-call
base_urloverride forwards credentials only when it matches a registered server (NTFY_BASE_URLor anNTFY_SERVERSentry); otherwise the request goes out unauthenticatedPublishes carrying
email,call, or abroadcast/httpaction button ask the user to confirm the specific target first — the call returns a confirmation request, and sends only once reissued with the answer
ntfy_manage_message tool
operation:clearmarks the notification read & dismisses it (subscribers seemessage_clear);deleteremoves it from the drawer (subscribers seemessage_delete)Append-only — the original message stays in cache; re-issuing the same operation is safe, though a fresh event fires each call
Every call asks the user to confirm the topic,
sequence_id, and operation before the event fires — the first call returns that confirmation request, and declining fails withconsent_declinedntfy.sh accepts an unknown
sequence_idwithout error; stricter ntfy deployments return anot_foundfailure instead
ntfy_fetch_messages tool
Returns a snapshot, not a live stream — use it to confirm delivery, replay missed alerts, or audit topic activity
Comma-separated multi-topic queries (e.g.
alerts,backups,phil_alerts)Filter by
since(duration / timestamp / message ID /all/latest),priority,tags,id,title,message, scheduled-onlyDefault window
10m, default limit 20 messages per response, hard cap 100 — over-limit windows keep the newestlimitmessages, listed oldest-firstLong bodies truncated to ~500 chars with
messageTruncatedreporting the dropped count; refetch with a messageidto read that one in full
ntfy_search_emoji_tags tool
Substring match against tag names, case-insensitive; omit
queryto list the reference from the start in its documented orderlimitdefault 25, max 200;offsetpages past the cap using the returnedtotalCountReturned
tagstrings plug directly intontfy_publish_message'stagsfield
ntfy://{topic} resource
Fixed snapshot — latest 20 messages from the past 1 hour, plus the topic's browser URL; same normalized message shape as
ntfy_fetch_messages(ISO 8601 timestamps, ~500-char body truncation)For custom windows, filters, or replay, use
ntfy_fetch_messagesinstead
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
ntfy-specific:
Wraps ntfy's HTTP API with a retry-aware client (
withRetry+ per-request timeout)Per-server scoped auth — credentials bind to each registered base URL (
NTFY_BASE_URLor anNTFY_SERVERSentry); mutually-exclusive bearer-token / basic-auth modes validated at config load; a per-callbase_urloverride forwards auth only when it matches a registered serverUser confirmation before side effects that leave the notification drawer — a clear/delete, or a publish carrying
email,call, or abroadcast/httpaction button — enforced on both stdio and Streamable HTTPOptional SSRF guard on
base_urloverrides (NTFY_BLOCK_PRIVATE_HOSTS) — blocks loopback, RFC 1918, RFC 6598 mesh, link-local, and IPv6 equivalents, then refuses redirects; registered servers are exemptBundled emoji-tag reference, regenerated from upstream
docs/ntfy/emojis.mdviascripts/build-emoji-tags.ts
Agent-friendly output:
Provenance —
ntfy_publish_messageandntfy_manage_messageecho back the resolved topic, ID, and timestamp;ntfy_fetch_messagesalso echoes the resolvedsinceand applied filtersDiscriminated outputs — typed
reasoncodes (consent_declined,forbidden_topic,rate_limited,not_found,payload_too_large, and more) on every tool's error contract let callers branch on failure mode instead of parsing error textTruncation and paging guidance —
ntfy_fetch_messagesandntfy_search_emoji_tagsreport atruncatedflag plus anoticenaming the exact next step (widensince, raiselimit, advanceoffset) instead of silently dropping results
Getting started
Add the following to your MCP client configuration file. Public ntfy.sh works out of the box without an account; for protected topics, generate an access token at https://ntfy.sh/account.
{
"mcpServers": {
"ntfy-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["ntfy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"NTFY_DEFAULT_TOPIC": "your-topic-name"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"ntfy-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "ntfy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"NTFY_DEFAULT_TOPIC": "your-topic-name"
}
}
}
}Or with Docker:
{
"mcpServers": {
"ntfy-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "NTFY_DEFAULT_TOPIC=your-topic-name",
"ghcr.io/cyanheads/ntfy-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 NTFY_DEFAULT_TOPIC=your-topic bun run start:http
# Server listens at http://127.0.0.1:3010/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
A topic name on an ntfy server. Public
ntfy.shrequires no account; self-hosted instances and protected topics may need a bearer token or basic-auth credentials.
Installation
Clone the repository:
git clone https://github.com/cyanheads/ntfy-mcp-server.gitNavigate into the directory:
cd ntfy-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env and set NTFY_DEFAULT_TOPIC (and auth, if needed)Configuration
Variable | Description | Default |
| JSON array of | — |
| Single-server shorthand — base URL of the ntfy server (no trailing slash). Used when |
|
| Topic used when a tool call omits | — |
| Bearer access token ( | — |
| Basic-auth username for the single-server shorthand — required together with | — |
| Basic-auth password for the single-server shorthand — required together with | — |
| Per-request HTTP timeout in milliseconds. |
|
| Max retry attempts for transient upstream failures (5xx, network, 429). |
|
| When |
|
| Transport: |
|
| HTTP session model: |
|
| HTTP host. |
|
| HTTP port. |
|
| HTTP endpoint path. |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for file-based logs (Node only; ignored on Workers). |
|
| Enable OpenTelemetry instrumentation (spans, metrics, completion logs). |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security, changelog sync bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t ntfy-mcp-server .
docker run --rm -e NTFY_DEFAULT_TOPIC=your-topic -p 3010:3010 ntfy-mcp-serverThe Dockerfile defaults to HTTP transport, stateful session mode, and logs to /var/log/ntfy-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing ( |
| Tool definitions ( |
| Resource definitions ( |
| ntfy HTTP client, types, and error classifier. |
| Bundled emoji short-code reference and lookup service. |
| Mirrored upstream ntfy API docs (pinned commit in |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Per-tool
errors[]contracts stay inline — repetition is intended for locality
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
Push notifications for AI agents - send instant iPhone notifications from any MCP client.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Real-time planetary signal engine and Model Context Protocol (MCP) server for autonomous AI agents.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceA Model Context Protocol server that allows LLMs to execute shell commands with explicit user permission through desktop notifications.226 npm1MIT
- AlicenseAqualityCmaintenanceA streamlined MCP server that enables AI assistants to send real-time notifications to your devices through the ntfy service, allowing you to receive alerts when tasks complete or important events occur.2163 npm74GPL 3.0
- AlicenseBqualityCmaintenanceA Model Context Protocol server that allows AI agents to play notification sounds when tasks are completed.146 npm14Apache 2.0
- FlicenseBqualityDmaintenanceA Model Context Protocol server that allows displaying messages via polybar status bar and sending desktop notifications via notify-send/dunst.2-