Reported issues for ntfy-mcp-server
Pod holds 18 of 23 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.
Back to ntfy-mcp-server.
Most discussed
bug(ntfy-service): upstream ntfy error text never reaches content[], and is discarded on classified failures
Server version
2.1.1
mcp-ts-core version
0.10.6
Runtime
Bun
Runtime version
Bun 1.3.14
Transport
http
Description
ntfy returns a descriptive JSON error body on every 4xx — an error string plus a docs link pointing at the exact parameter that was rejected. None of it reaches the agent through content[], and classified failures drop it from structuredContent too.
Unclassified errors keep the body in structuredContent.error.data.body, but
Read the thread · 2026-07-28 · closed · 3 comments
feat(consent): elicit before high-impact notification actions
ntfy_manage_message is marked destructiveHint: true, but the handler calls NtfyService.manage() directly with no ctx.elicit confirmation. ntfy_publish_message can also trigger high-impact side effects (email, call, broadcast actions, and http action buttons) from model-supplied input.
Proposal
Add an elicitation boundary before side effects where a mistaken or prompt-injected tool call is meaningfully disruptive.
Scope
ntfy_manage_message: ask for confirmation be
Read the thread · 2026-06-28 · closed · 3 comments
feat(ntfy-service): SSRF protection for base_url override
Use case
The base_url override on ntfy_publish_message, ntfy_manage_message, and ntfy_fetch_messages accepts any string passing z.url() — no scheme allowlist, no host filtering. When the server runs publicly (Streamable HTTP transport, MCP_AUTH_MODE=none), unauthenticated callers can supply private/loopback/link-local URLs that the server then dereferences via fetch. This is a server-side request forgery surface.
Reachable from the host running the server:
- IPv4 private (10
Read the thread · 2026-05-10 · closed · 3 comments
feat(ntfy_fetch_messages): limit drops the newest messages instead of the oldest
ntfy_fetch_messages truncates with notifications.slice(0, input.limit), keeping the oldest N of the matching window. The default lookback is since: 10m with limit: 20, so on a busy topic the most common question the tool exists to answer — "did my recent notification land?" — comes back with the start of the window and the recent messages dropped.
Related: #20
Proposal
Keep the newest limit messages (slice(-limit)), matching what the ntfy://{topic} resource does, and stat
Read the thread · 2026-07-30 · closed · 2 comments
feat(schema): replace the priority literal union with an enum so validation errors stay readable
Use case
PrioritySchema is built as z.union([z.literal(1), … z.literal(5)]). It serializes to a five-branch anyOf of const values instead of a plain enum, and a wrong value produces an invalid_union dump listing all five branches — roughly 40 lines of JSON for a one-character mistake.
Calling ntfy_publish_message with priority: 9 returns:
MCP error -32602: Input validation error: Invalid arguments for tool ntfy_publish_message: [
{ "code": "invalid_union", "errors": [
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/21) · 2026-07-28 · closed · 2 comments
### bug(ntfy-topic.resource): description promises the latest 20 messages but returns the oldest 20
### Server version
2.1.1
### mcp-ts-core version
0.10.6
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
http
### Description
The `ntfy://{topic}` resource advertises "latest 20 from the last 1 hour". ntfy returns cached messages oldest-first, and the handler takes `notifications.slice(0, SNAPSHOT_LIMIT)` — the **oldest** 20 in the window. On any topic with more than 20 messages in the hour, the snapshot shows the start of the window and drops everything recent, which is t
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/20) · 2026-07-28 · closed · 2 comments
### bug(ntfy_publish_message): time is documented as accept time but returns delivery time for delayed messages
### Server version
2.1.1
### mcp-ts-core version
0.10.6
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
http
### Description
The `time` field in `ntfy_publish_message`'s output schema is described as "ISO 8601 timestamp when ntfy accepted the message (not delivery time)". For a publish carrying `delay`, ntfy sets `time` to the scheduled **delivery** time, so the description states the opposite of what the field holds.
`format()` compounds it: under a `**Scheduled**` bann
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/19) · 2026-07-28 · closed · 2 comments
### feat(ntfy_search_emoji_tags): add an offset so results past the 200-row cap are reachable
### Use case
The bundled reference holds 1,812 emoji tags. `limit` caps at 200 and there is no `offset` or cursor, so 1,612 rows are unreachable — `truncated: true` is reported with no way to act on it.
Narrowing the query does not close the gap: `query: "a"` matches 1,179 tags and still returns 200. An agent hunting for a tag that sorts late in doc order has to guess ever-shorter substrings with no signal about what it has not seen.
### Proposed behavior
Add `offset: number` (default 0) to
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/18) · 2026-07-28 · closed · 2 comments
## Most recent
### fix(config): pin MCP_SESSION_MODE to stateful — the image ships stateless and breaks the confirmation gate for v1 HTTP clients
`Dockerfile` sets `ENV MCP_SESSION_MODE="stateless"`, but `.env.example` carries a commented `# MCP_SESSION_MODE=stateful`, whose comment documents the value set as `stateful | stateless (default: stateful)`. The container and the same code run via `bunx`, `npm start`, or from source therefore resolve to different session modes. `README.md` disagrees with both, listing the default as `auto` — three surfaces, three answers.
For this server the container is the one that is wrong.
Related: cyanhe
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/31) · 2026-08-22 · open · 0 comments
### feat(config): default MCP_SESSION_MODE to stateful across env, Docker, and src
`Dockerfile` sets `ENV MCP_SESSION_MODE="stateless"`, `.env.example` carries a commented `# MCP_SESSION_MODE=stateful`, and `README.md` documents the default as `auto`. The same code therefore runs stateless in the container and stateful everywhere else — `bunx`, `npm start`, or from source — since the framework schema defaults to `auto` and `auto` resolves to `stateful`.
The `.env.example` comment is also factually wrong. It reads `stateful | stateless (default: stateful)`, omitting `auto`, wh
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/30) · 2026-08-22 · open · 0 comments
### feat(ntfy_publish_message): add structured recovery for invalid delay
### Use case
`ntfy_publish_message` preserves ntfy's invalid-delay explanation on both response surfaces, but the failure has no stable `data.reason` and no recovery hint naming the accepted delay forms. One of ntfy's three delay rejections is also actively misrouted today.
ntfy answers a bad `delay` with one of three errors, all HTTP 400:
| Code | Upstream error | Current classification |
|:---|:---|:---|
| 40004 | `invalid delay parameter: unable to parse delay` | unclassified — bubbles to
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/29) · 2026-08-17 · open · 0 comments
### bug(ntfy_manage_message): idempotentHint conflicts with emitted events
### Server version
2.3.0
### mcp-ts-core version
0.11.0
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
HTTP (Streamable HTTP)
### Description
`ntfy_manage_message` advertises `idempotentHint: true`. `@modelcontextprotocol/sdk` 1.29.0 defines that hint as "calling the tool repeatedly with the same arguments will have no additional effect on its environment", and it is meaningful on this tool because `readOnlyHint` is unset (defaults to `false`).
Clearing and deleting are
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/25) · 2026-08-17 · open · 0 comments
### bug(ntfy_fetch_messages): empty filters silently widen the query
### Server version
2.3.0
### mcp-ts-core version
0.11.0
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
HTTP (Streamable HTTP)
### Description
`since` carries a schema default of `10m`, but a Zod `.default()` only fires on `undefined`. An explicit `""` passes validation, is then dropped from the upstream query by a truthiness check in `NtfyService.fetch()`, and ntfy applies its own poll default of `since=all`. The documented `10m` guardrail is silently replaced by the ent
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/26) · 2026-08-17 · open · 0 comments
### bug(ntfy_fetch_messages): hard cap drops messages without a retrieval path
### Server version
2.3.0
### mcp-ts-core version
0.11.0
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
HTTP (Streamable HTTP)
### Description
`ntfy_fetch_messages` keeps the newest `limit` matches and drops the older head, with `limit` capped at 100. Once more than 100 messages match, the dropped head is unreachable: the tool exposes no offset or cursor, and every path the truncation notice suggests is a dead end at the cap.
ntfy has no upstream lever for this either. I
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/27) · 2026-08-17 · open · 0 comments
### bug(formatting): plain ntfy text is interpreted as Markdown in content[]
### Server version
2.3.0
### mcp-ts-core version
0.11.0
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
HTTP (Streamable HTTP)
### Description
`format()` in `ntfy_publish_message` and `ntfy_fetch_messages` interpolates upstream-controlled strings straight into Markdown `content[]` text, so a message body becomes formatting instructions instead of data. The interpolated values are `title`, `message`, `click` (rendered as `[url](url)`), `attachment.name` / `url` / `type` (r
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/28) · 2026-08-17 · open · 0 comments
### bug(ntfy_fetch_messages): malformed NDJSON is silently omitted
### Server version
2.3.0
### mcp-ts-core version
0.11.0
### Runtime
Bun
### Runtime version
Bun 1.3.14
### Transport
HTTP (Streamable HTTP)
### Description
`parseNdjson()` in `NtfyService` drops every non-empty line that fails `JSON.parse` and returns the surviving lines as a complete success, so a degraded upstream response is indistinguishable from an authoritative one. Two paths reach it:
- A partial or corrupted NDJSON body loses the unparseable lines; the response reports the su
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/24) · 2026-08-17 · open · 0 comments
### docs(design): output blocks type timestamps as Unix seconds and describe format() footers that do not exist
`docs/design.md` describes four things the code does not do. Each is a self-contained line in the `ntfy_fetch_messages` or `ntfy_search_emoji_tags` tool-detail section.
| Claim in `docs/design.md` | Actual |
|:---|:---|
| Fetch output block: `time: number; // Unix seconds when ntfy accepted the message` | `MessageSchema.time` is `z.string()` — an ISO 8601 string (`2026-05-26T06:30:11.000Z`) since the `shapeMessage` normalization |
| Same block: `expires?: number; // Unix seconds when the messag
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/23) · 2026-07-30 · closed · 1 comment
### feat(ntfy_fetch_messages): no way to retrieve message bodies truncated at 500 chars
### Use case
`ntfy_fetch_messages` truncates every message body to 500 characters and reports the dropped count in `messageTruncated`, but exposes no way to read the rest. Replaying a long alert — a stack trace, a CI failure summary, a build log excerpt — returns a body the agent can see is incomplete and cannot complete.
Every other truncation in the tool has an escape hatch: list-level truncation pages via `since=<last message id>`, which works. Body truncation has none.
The `ntfy://{topic}
[Read the thread](https://github.com/cyanheads/ntfy-mcp-server/issues/17) · 2026-07-28 · closed · 2 comments
The remaining reports are on [the project's issue tracker](https://github.com/cyanheads/ntfy-mcp-server/issues).