---
summary: "HTTP now refuses to start under a stateless session, since the consent gate needs a live session to complete. Blank and unsubstituted ${…} placeholder NTFY_* values read as unset instead of failing or forwarding the literal text. Development skills move from skills/ to framework-skills/."
breaking: false
security: false
---

# 2.3.4 — 2026-09-16

## Changed

- **HTTP now requires `MCP_SESSION_MODE=stateful`.** `createApp()` declares `sessionMode: { default: 'stateful', require: 'stateful' }` (mcp-ts-core 0.13.1, cyanheads/mcp-ts-core#376) — an HTTP start resolving to `stateless` now fails at boot with a configuration error instead of silently leaving the consent gate on `ntfy_manage_message` and outbound-action publishes unable to complete for a 2025-era client. `.env.example` and the `Dockerfile` `ENV` were already `stateful`, and only their comments changed; `server.json` documented the default as `auto` and now documents `stateful`. Stdio is unaffected.
- **Development skills moved from `skills/` to `framework-skills/`** (mcp-ts-core 0.13.0, cyanheads/mcp-ts-core#428) — installing this server's `.claude-plugin`/`.codex-plugin` no longer hands the server's own development skills to the installing agent. Adds the `release-pr-review` skill and an `audit:fix` script (`bun audit fix`); all framework skills and scripts resynced to 0.13.2.
- **Bun engines floor raised to `>=1.4.0`**, matching the floor mcp-ts-core raised in 0.12.9.
- **README, plugin manifests, and issue templates polished** — the README restructures around an Overview and capability reference and adds an npx install snippet; issue templates route security reports to GitHub advisories and auto-assign `cyanheads`.

## Fixed

- **Blank, whitespace-only, and whole-value `${…}` placeholder `NTFY_*` values now read as unset**, by running the environment through `normalizeEnv` ahead of validation — the rule mcp-ts-core 0.13.0 applies to its own config (cyanheads/mcp-ts-core#427), exported in 0.13.1. Previously a blank `NTFY_MAX_RETRIES` silently became `0`, a blank `NTFY_REQUEST_TIMEOUT_MS` failed startup, a blank `NTFY_BASE_URL` failed instead of defaulting to `https://ntfy.sh`, and an unsubstituted `${NTFY_AUTH_TOKEN}` was sent upstream as the literal bearer token.

## Dependencies

- `@cyanheads/mcp-ts-core` `^0.12.5` → `^0.13.2`
- `zod` `^4.5.4` → `^4.6.4`
- `vitest` `^4.1.11` → `^5.0.0`
- `@biomejs/biome` `^2.5.11` → `^2.5.13`
- `ignore` `^7.0.8` → `^7.0.9`
- `tsc-alias` `^1.9.3` → `^1.9.5`
