v3.0.0 release notes
Release Date: 2026-09-03
Upstream Base: CyberChef v11.4.0 (unchanged)
Licence: GPL-3.0-or-later
Node: >=24 <27
Image: ghcr.io/doublegate/cyberchef-mcp_v3:3.0.0 — the package name changed, see below
Highlights
Section titled “Highlights”Conformance with MCP revision 2026-07-28, and the cleanups conformance forces.
The planned v3.0.0 could not be executed. It was written in December 2025 around six breaking changes, and by the time it came up all six were done, withdrawn, or superseded — the sixth consecutive release to open by measuring its plan and finding it empty. The scope was re-derived by reading the specification changelog against the running server, and what came back was sharper than the plan:
- a missing resource answered “Internal Error”, so a caller could not tell a bad URI from a broken server;
cyberchef_bakecost more than the operations it runs, demanding network authority for recipes that never leave the process;- a tool-list filter had shipped in v2.5.0, been unit-tested ever since, and was never called;
- cache hints were conformant and told every client to cache nothing;
- and
npm publishwas guarded bystartsWith(ref, 'v2.'), so this very tag would have skipped it as a green step.
docs/internal/v3.0.0-findings-log.md has all fourteen findings with the measurements, including
the four that review turned up: a guard fix that quietly broke manual dispatch, two of my own tests
that asserted nothing, and a scope collapse that treated network and write as ordered when they
are not.
Breaking changes
Section titled “Breaking changes”Four. None requires a code change on the caller’s side, which is why there is no migration CLI.
1. The container image is cyberchef-mcp_v3
Section titled “1. The container image is cyberchef-mcp_v3”The GHCR package name carries the major, so a major release renames the image rather than publishing a new tag of the old one:
ghcr.io/doublegate/cyberchef-mcp_v2:2.10.0ghcr.io/doublegate/cyberchef-mcp_v3:3.0.0_v2 stays pullable and is not superseded in place. Docker Hub is a single un-suffixed repository
and is unaffected: doublegate/cyberchef-mcp:latest continues to move.
This was true of every past major too, and nothing in the repository knew it — 40 files pointed at
_v2, including the published Helm chart, which paired an un-bumped repository with a bumped
tag and so resolved to an image that will never exist. npm run check:versions now asserts the
package major alongside the version in docker-compose.yml, values.yaml and server.json.
2. A missing resource is -32602, not -32603
Section titled “2. A missing resource is -32602, not -32603”ErrorCodes in errors.mjs are strings; the SDK dispatcher keeps a thrown error’s code only when
it is a safe integer. So every resources/read failure answered Internal Error with no data:
before recipe://0000… code=-32603 data=undefined file:///etc/passwd code=-32603 data=undefined
after recipe://0000… code=-32602 data={"uri":"recipe://0000…"} file:///etc/passwd code=-32602 data={"supported":"recipe://<id>", …}Two distinct -32602s, told apart by whether data.uri is present — the shape the SDK documents
clients to recognise resource-not-found by. A client matching on -32603 for a missing recipe must
match -32602 now, and gains the ability to distinguish it from a server fault.
3. tools/list is filtered by the caller’s scopes
Section titled “3. tools/list is filtered by the caller’s scopes”Only when authorization is enabled, which is off by default. A read-scoped token is no longer shown write or network tools.
This changes behaviour for deployments that turned auth on and relied — knowingly or not — on seeing the full surface. It is not a tightening: dispatch already refused those calls. What changes is that the model is no longer told about tools it cannot use.
4. cyberchef_bake and cyberchef_batch are priced by their recipe
Section titled “4. cyberchef_bake and cyberchef_batch are priced by their recipe”Both are annotated openWorldHint: true because a recipe may contain HTTP request, and scope
derivation read that hint first — so both demanded cyberchef:network for every call. Measured
across the catalogue:
502 of 504 operation tools require only cyberchef:read 2 of 504 require cyberchef:network (HTTP request, DNS over HTTPS)So cyberchef_to_base64 cost read while cyberchef_bake running that same operation cost
network. Scopes now come from the recipe submitted — the same granularity the offline guard
settled on in v2.8.0 — and strongest wins, so one networked operation still costs network.
cyberchef_recipe_execute is deliberately excluded: it carries only an id, and resolving it would
move the authorization check after a storage read, which is exactly the v2.5.0 bypass shape.
5. List results carry real cache TTLs
Section titled “5. List results carry real cache TTLs”Not breaking in the schema sense, but a client that ignored ttlMs because it was always 0 will
now cache. The SDK already emitted the fields; this release chose honest values:
tools/list 600000 public (300000 private when auth is on)prompts/list 3600000 publicresources/templates/list 3600000 publicresources/list 0 privateresources/read 0 privateserver/discover 600000 publicThe two zeros are the load-bearing ones. Saved recipes change on any caller’s write and are
partitioned by tenant, and this server declares no listChanged capability — so the TTL is the
only invalidation signal a client has, and any non-zero value would serve a stale list with no way
to know.
npm, corrected
Section titled “npm, corrected”npx cyberchef-mcp works, and has since 2.5.0 — seven versions. Four documents said the
package was “publishable, not published”, including server.json’s own comment, which stated the
rule that would have kept it correct: add the record in the same change that publishes it. The
publish happened and nobody applied it. server.json now carries the npm record and is inside
npm run check:versions, where it had never been — it was stale at 2.4.1 for six releases.
Also in this release
Section titled “Also in this release”- Deterministic
tools/listorder. A three-tier stable sort — meta, registry, operations, each by code-unit order — so a client cache and an LLM prompt cache both hit. The spec says SHOULD. - Server spans join the caller’s trace. A
traceparentin_metabecomes the parent of the server span instead of the server starting a root. All-zero trace and span ids are rejected rather than joined. - Tasks and
extensions: assessed and declined, with the reasoning recorded atSERVER_CAPABILITIESrather than only in a log. Tasks need state outliving the request and this server deliberately has none; a negative test is a tripwire so an SDK minor that begins auto-declaring either cannot ship silently. - Deprecation alignment verified, not assumed. Roots, Sampling, Logging and the HTTP+SSE
transport appear in zero files; OAuth DCR does not apply, because
lib/auth.mjsis purely a resource server.
The planning corpus was retired
Section titled “The planning corpus was retired”62 files, ~36,700 lines, written mostly in December 2025 and wrong without saying so. ROADMAP.md
still opened with “Current version: v2.2.0”, dated four shipped releases in 2027, and listed six
v3.0.0 breaking changes none of which existed any more.
26 documents now carry a dated banner naming what replaced them and why. Planning for v3.0.0 onward
lives in docs/planning/v3/, shaped deliberately differently: one deep plan for the release being
executed, a one-page charter each for v3.1.0 through v4.0.0, and RE-MEASURE.md as a mandatory
gate between them. A detailed plan for a release two years out is a hypothesis written at the
point of least information, and six releases in a row is enough evidence.
Nothing moved to docs/planning/archive/. Measuring first showed every one of the 62 documents is
referenced from at least two files outside docs/planning/, so a move would break a published URL
or require rewriting release notes. The archive holds a README recording that.
Upgrading
Section titled “Upgrading”docker pull ghcr.io/doublegate/cyberchef-mcp_v3:3.0.0Or Docker Hub, whose repository is un-suffixed and unchanged:
docker pull parobek/cyberchef-mcp:3.0.0If you followed README’s registry list, you were sent to a repository that does not exist. It
named doublegate/cyberchef-mcp, which returns “object not found” from the Hub API, while every
install snippet in the same file already said parobek — the release workflow pushes to
${{ secrets.DOCKERHUB_USERNAME }}/cyberchef-mcp. Corrected in this release.
Helm and Compose users: the chart’s image.repository and the compose image: line both move to
_v3. If you pinned a digest, resolve a new one against the new package.
Nothing else requires action. If you enabled authorization, expect tools/list to return fewer
tools for restricted tokens, and expect cyberchef_bake to succeed at cyberchef:read for recipes
that do not reach the network.
Verification
Section titled “Verification”npm run lint zero errorsnpm run check:versions every version reference and package major agreesnpm test 241 Node-API + 2,289 operation testsnpm run test:mcp 1,426 tests across 54 filesnpm run test:coverage 95.46 lines / 89.92 branches / 96.40 functions / 96.19 statementsEvery protocol assertion goes through a real MCP client, never hand-rolled JSON-RPC — the rule
three releases paid for by shipping 524 tools with empty inputSchema under a green suite. The
release pipeline fix was proven before the tag by simulating the guard across
v1.9.2 / v2.10.0 / v3.0.0 / v4.0.0, since it is unobservable until a tag exists.
- Plan:
docs/planning/v3/v3.0.0-plan.md - Findings log:
docs/internal/v3.0.0-findings-log.md - Conformance notes:
docs/reference/mcp-2026-07-28-conformance.md - Charters:
docs/planning/v3/charters/