---
summary: "Recognizes retry-exhausted upstream 5xx failures again under mcp-ts-core 0.12.4's reclassified error codes, and reports a cancelled ntfy request as cancelled instead of a retryable upstream fault"
breaking: false
security: false
---

# 2.3.3 — 2026-09-04

## Fixed

- **`isUpstreamUnreachable` recognizes retry-exhausted upstream failures again.** mcp-ts-core 0.12.4 classifies a retry-exhausted 5xx as `ServiceUnavailable` or `Timeout` rather than folding it into `InternalError`, so the classifier — which only recognized the `InternalError` shape — stopped reporting a genuinely unreachable ntfy server as one. It now also accepts `ServiceUnavailable` and `Timeout`, while still requiring the retry-exhausted suffix and excluding `RateLimited` (its own `rate_limited` reason) and `RequestCancelled`.
- **A cancelled `ntfy_publish_message`/`ntfy_manage_message` request now reports `RequestCancelled` instead of a retryable upstream error.** `timedFetch` shared one `AbortController` between the request deadline and the caller's own abort signal, so a client disconnecting mid-request surfaced as the same fetch failure as an unreachable ntfy server. It now tracks which side aborted and throws `requestCancelled` when the caller is the one who left.

## Changed

- **Ten framework skills resynced** to the mcp-ts-core template.
- **`Dockerfile`** build stage carries a comment recording why it's pinned to `$BUILDPLATFORM`.

## Dependencies

- `@cyanheads/mcp-ts-core` `^0.12.3` → `^0.12.5`
- `zod` `^4.4.3` → `^4.5.4`
- `@biomejs/biome` `^2.5.9` → `^2.5.11`
- `@types/node` `^26.2.0` → `^26.4.0`
- `ignore` `^7.0.6` → `^7.0.8`
- `tsc-alias` `^1.9.2` → `^1.9.3`
