
ntfy
io.github.ni-c由 GitHub 帳號 ni-c 發布v0.3.0更新於 Oct 24, 2026
Publish ntfy notifications, read the message cache, and manage users and topic access
概覽
針對 ntfy 的 MCP 伺服器,讓助理發布推播通知、讀取訊息快取,並在具備管理員帳號時管理使用者與主題權限。
- 可以做什麼
- 發布與修改通知:向一個或多個主題傳送訊息,就地更新通知,讓進度報告始終是一則訊息
- 讀取訊息快取:依條件輪詢主題並取得下一頁游標,檢視單則訊息的按鈕與附件,將訊息標為已讀
- 檢視執行個體與憑證:伺服器健康狀態與能力、帳號身分與額度、某主題是否可讀
- 管理帳號:列出使用者及其授權,建立與刪除使用者,授予或撤銷主題存取權
- 啟動時篩選要註冊哪些工具,包括一組精選的六工具預設集
- 適用情境
- 適合讓助理在長時間工作完成或失敗時推播提醒到手機,或在建置過程中持續更新同一則通知。也適合自架 ntfy 的維運人員,不必使用命令列即可管理帳號與主題授權。
- 執行需求
- 透過 npx 或容器映像以 stdio 在本機執行;npm 套件需要 Node.js 24 以上版本。需要一個可連線的 ntfy 伺服器,由 NTFY_URL 指定(沒有預設值)。選用憑證:NTFY_TOKEN,或 NTFY_USERNAME 搭配 NTFY_PASSWORD。NTFY_TOPICS 限定可操作的主題。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 ntfy,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
ntfy-mcp
[CI]
[OpenSSF Scorecard]
[Socket Badge]
[Glama score]
[npm version]
[container image]
[HTTP via mcp-hub]
[docs]
[sponsor]
A Model Context Protocol (MCP) server for ntfy, the pub-sub notification service that sends push messages to your phone with an HTTP request and nothing else.
Lets MCP clients like Claude Code, Claude Desktop or Codex send you notifications,
read back what was sent, revise a notification in place while a job runs, and — with
an admin account — create accounts and grant or revoke their access to topics, which
otherwise means the ntfy command line on the server.
Thirteen tools is the ceiling, not the floor: NTFY_ALLOW_TOOLS=essential registers
a curated six instead, and a model picks the right tool far more reliably from six
than from thirteen — see choosing which tools load.
What makes it different
A progress report stays one notification. The id publish_message returns is
also the notification's sequence id, and update_message replaces its content in
place — subscribers watch one notification change from "building" to "deployed"
instead of collecting five.
NTFY_TOPICS is the fence. On ntfy a topic name is a bearer credential:
knowing it is often the whole of the access control. One variable names the topics
this server may touch and supplies the default when a tool omits one, so the name
stays out of the tool arguments and out of the model's context.
Requirements
- Node.js ≥ 24
- A reachable ntfy server. Credentials are optional: an instance that allows anonymous access needs none.
Configuration
Setting NTFY_TOKEN together with NTFY_USERNAME/NTFY_PASSWORD is refused at
startup rather than resolved by a precedence rule: which credential is in force must
never be ambiguous.
Use
https://. Over plain http the credentials travel unencrypted — basic auth is base64, not encryption — and the server prints a warning unless the host is local. For self-signed certificates prefer a proper internal CA overNTFY_INSECURE_TLS.
Without configuration the server still starts and lists its tools (so registries and inspectors can introspect it), but every call fails with setup instructions instead of reaching the API.
Writes are on by default
NTFY_READ_ONLY defaults to false. ntfy exists to publish, and a read-only default
would ship a notification server that cannot notify — this is the opposite of
imap-mcp, where the same variable defaults to
true because a mailbox is an irreplaceable archive.
Two consequences worth knowing:
- A typo still fails open.
true,1andyesare all read as read-only, in any case — a protection switch is parsed generously on purpose. ButNTFY_READ_ONLY=tureis not any of them, and because the default is permissive it leaves the write tools enabled, where in imap-mcp it would fail closed. - A client that can publish can publish anywhere on the instance unless you say
otherwise. Confirmation tokens do not help against that — publishing is not a
destructive operation.
NTFY_TOPICSis the control that does.
The recommended shape for anything unattended:
On a self-hosted instance, also give the server its own ntfy account with write-only
access to exactly the topics it needs.
Choosing which tools load
NTFY_ALLOW_TOOLS and NTFY_DENY_TOOLS take comma-separated tool names; a trailing
* matches a whole family. essential is a curated preset — get_server_info,
check_topic_access, publish_message, list_messages, get_message and
update_message — marked as such in the
tool reference. Four of the six are read
tools, so the preset stays useful under NTFY_READ_ONLY=true.
An entry that matches no tool aborts startup and names it, so a typo cannot silently
hide a tool — an absent tool is not something anyone traces back to an environment
variable. A filtered tool is never registered, so it is absent from tools/list and
unknown to tools/call alike, exactly like a write tool under NTFY_READ_ONLY.
If you run several of these servers at once, mcp-hub is
the other answer — its /hub endpoint replaces every server's tools with six
meta-tools.
Installation
Claude Code
Claude Desktop
Codex
Docker
Through mcp-hub
A client that cannot spawn a local process — ChatGPT connectors, Claude on the web,
Cursor, LibreChat — reaches ntfy-mcp through mcp-hub: one
container serves many stdio MCP servers over Streamable HTTP, with an OAuth 2.1 login
behind a single password and long-lived tokens for the clients that cannot do OAuth. Its
/hub endpoint puts every server behind six meta-tools, so one connector reaches all of
them without N×tool schemas in the model's context, and it speaks both protocol revisions
— a question this server asks travels through it to the person at the far end.
Its /config/mcp.json uses Claude Code's format, so the entry is the one you already
have:
allowTools and denyTools there are the hub's own per-server filter, which is not
the same thing as *_ALLOW_TOOLS in env — the difference, and the mistake it invites,
are in the client guide.
Tools
* marks the essential preset.
👤 asks a person through MCP elicitation · falls back to a two-call
confirm_token where the client cannot show a dialog.
Structured output
Every tool declares an outputSchema and answers with structuredContent
alongside the text block, so a client can use the result without parsing prose:
The untrusted marker is a field and not only a sentence in the text, because a
client that reads the structured half and ignores the text would otherwise get a
publisher's prose with no framing at all. It is on the four tools that report
what someone else wrote: list_messages, get_message, get_account and
list_users. get_server_info does not carry it — its sections are the
instance's own configuration and counters.
Fields this server builds are described exactly; documents it merely passes on
from ntfy (/v1/config, /v1/stats, a publisher's attachment metadata) are
declared as objects with no fixed shape. A schema stricter than the data is not
a better contract: the SDK validates every result against it, so an upstream
release that adds a field would take the tool out entirely rather than show you
one field you did not expect.
Two things about ntfy that surprise people
Read and write are granted separately per topic. A write-only publishing token
cannot poll the very topic it publishes to, and that is a correct configuration
rather than a fault. check_topic_access tests the read side only, so a denial
there does not mean publishing will fail — the tool says so in its result.
There is no way to list the topics on a server. A topic exists because someone
published to it, and on an open instance its name is the whole of the access control.
Treat topic names as secrets; get_account and list_users are the only places
existing ones show up.
Not implemented, on purpose
- Sending email or placing a phone call from a published message. ntfy supports
both; an MCP tool that mails an arbitrary address on model output is a spam relay
driven by injectable content, and
callplaces a real, billable call. - Creating, reading or exchanging an access token. Every such endpoint hands back a live credential, which would then live in the conversation transcript.
- Streaming subscriptions (
/sse,/ws,/raw). A tool call is request/response under a timeout;list_messagesreturns the same data, bounded. - Attachment upload. Either base64 through the model's context or a local
filesystem surface this server has no business having.
attachcovers the real case by URL. - Reservations, billing, web push, email and phone verification, and the Matrix
gateway.
GET /v1/accountreturns several of them anyway;get_accountdrops them rather than passing on a payload no tool here uses.
Not exposed, on purpose
No topic enumeration — ntfy has no such API, and neither does anything else. A
topic exists because someone published to it, and on an instance with the default
access rules its name is the whole of the access control, so a list endpoint would
be a list of credentials. get_account names the topics the account is subscribed
to and list_users the per-topic grants; those are the two honest answers.
Safety
- A person is asked, not just told. Where the client supports MCP elicitation,
delete_messages,delete_user,manage_user_access,create_userandupdate_messageraise a real dialog that the model cannot answer on its behalf. Where it does not, they fall back to a short-lived token bound to a fingerprint of the exact target — and say so, rather than implying somebody approved. A confirmation for one target cannot execute another, a longer list, or — formanage_user_access— the same three arguments in a different order. See Asking a person. NTFY_TOPICSbounds the access tools too.manage_user_accessrefuses a pattern that reaches past the list,*included: a grant is permanent access to every topic it covers, and no finite allowlist covers a wildcard.list_usersreports each account's grants against the allowed topics only, because a grant pattern is a topic name and a topic name is a bearer credential.- Confirmation prompts never quote content from ntfy. They name the topic, the
count or the username and nothing else, because that text is read by a model. And
never the password
create_userwas given: it is a live credential, so it is in neither the prompt nor the token's binding. - Returned content is marked as untrusted data, because it is: everything in a notification was written by whoever could publish to the topic.
get_accountanswers from an allowlist, not a denylist. It reports the identity, role, tier, limits, usage and the metadata of each access token, and drops everything else ntfy sends — the token values, which ntfy returns in plaintext, but also the phone numbers, the billing identifiers and the reservation and subscription topic names. A key a future ntfy adds is dropped without an edit here.- Caller-supplied URLs must be
httporhttps.click,icon,attachand action-button URLs are opened by the recipient's device, not by the server, and ntfy stores whatever it is given — including ajavascript:URL. - Every field a publisher controls is bounded. ntfy caps the message body at 4096 bytes but not the title or the tag list, so those are capped here.
NTFY_READ_ONLY=truedoes not register the write tools at all, andNTFY_DENY_TOOLScuts finer along the same line — a filtered tool is never built, not refused at call time.
Documentation
The full guide, tool reference and security notes live at
ntfy-mcp.ni-c.de (source in docs/).
Development
The architecture diagram and the social card are generated: edit
docs/assets/architecture.source.svg or docs/assets/og.json and run
npm run assets, never the rendered copies under docs/public/. CI runs
npm run assets:check and fails if they have drifted.
The documentation site has its own manifest, so its toolchain never lands in the container image or the test matrix:
Releasing
Releases are tag-driven. Bump package.json, move the [Unreleased] notes in
CHANGELOG.md under the new version, commit, then:
The release workflow publishes to npm via Trusted Publishing (OIDC, with provenance), pushes the multi-arch container image to GHCR, creates the GitHub release from the CHANGELOG section, and updates the entry in the official MCP registry.
Contributing
Issues, discussions and pull requests are welcome — see CONTRIBUTING.md. For vulnerabilities please use private reporting rather than a public issue; the policy is in SECURITY.md.
License
MIT © Willi Thiel
來源:README.md,提交 143a502
工具
0版本歷史
1- v0.3.0最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分