Skip to content

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.0the package name changed, see below

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_bake cost 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 publish was guarded by startsWith(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.

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.0
ghcr.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.

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 public
resources/templates/list 3600000 public
resources/list 0 private
resources/read 0 private
server/discover 600000 public

The 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.

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.

  • Deterministic tools/list order. 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 traceparent in _meta becomes 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 at SERVER_CAPABILITIES rather 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.mjs is purely a resource server.

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.

Terminal window
docker pull ghcr.io/doublegate/cyberchef-mcp_v3:3.0.0

Or Docker Hub, whose repository is un-suffixed and unchanged:

Terminal window
docker pull parobek/cyberchef-mcp:3.0.0

If 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.

npm run lint zero errors
npm run check:versions every version reference and package major agrees
npm test 241 Node-API + 2,289 operation tests
npm run test:mcp 1,426 tests across 54 files
npm run test:coverage 95.46 lines / 89.92 branches / 96.40 functions / 96.19 statements

Every 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.