Publishing is the easy half. What makes this usable inside an agent loop is that the same server reads the topic back, so "did the alert actually go out" has an answer instead of an assumption. The design choice worth knowing: anything reaching beyond the notification drawer — an email, a phone call, a broadcast or http button, or clearing someone's notification — returns a confirmation request first, and a client that cannot present that prompt gets an error rather than a silent side effect.
A server over ntfy's HTTP API: publish a push notification to a topic, update or clear one already sent, poll a topic's cached messages, and look up the emoji short codes that render on the recipient's device. It works against ntfy.sh or an ntfy server of your own.
- ntfy_publish_message covers ntfy's publish surface — title, priority from 1 to 5, tags, click, attach, icon, filename, markdown, delay, email, call, cache and firebase
- Up to three action buttons per message (view, broadcast, http or copy), so the notification can be acted on straight from the drawer
- Passing the original sequence_id updates or replaces a message already sent instead of stacking a second one underneath it
- ntfy_manage_message clears or deletes a sent notification; the original stays in cache and subscribers receive a message_clear or message_delete event
- ntfy_fetch_messages polls several topics at once, comma-separated, filtered by since — a duration, timestamp, message ID, all or latest — and by priority, tags, id, title, message or scheduled-only
- Fetches default to a 10m window and 20 messages, capped at 100, with long bodies truncated near 500 characters and a count of what was dropped; refetch by message id to read one in full
- ntfy_search_emoji_tags searches the bundled emoji-tag reference and returns tag strings ready to paste into a publish call
- Anything that reaches past the notification drawer asks first: a clear or delete, or a publish carrying email, call or a broadcast/http button, comes back as a confirmation request naming the exact target and goes out only on the reissued, approved call
- An ntfy://{topic} resource gives a snapshot of a topic — its latest 20 messages from the past hour, in the same shape ntfy_fetch_messages returns
Published as ntfy-mcp-server and launched over stdio or run as a Streamable HTTP server. Public ntfy.sh works with no account; protected topics need an access token. NTFY_DEFAULT_TOPIC sets the topic used when a call omits one — treat that name as a secret, because anyone who knows it can publish to it or subscribe to it. A single server is configured with NTFY_BASE_URL plus either NTFY_AUTH_TOKEN or NTFY_AUTH_USERNAME and NTFY_AUTH_PASSWORD; NTFY_SERVERS takes a JSON array to register several, each with its own credentials. Credentials stay bound to the base URL they were registered under, so a per-call base_url override that matches nothing registered goes out unauthenticated rather than leaking them, and NTFY_BLOCK_PRIVATE_HOSTS additionally forces such overrides to resolve to a public address.
One command — bunx ntfy-mcp-server@latest
