Skip to content

v3.7.0 release notes

v3.2.0’s notes say it fixed the operation-count discrepancy: “Three documents said 505 operations where OperationConfig has 504.” Three were corrected. Nine live occurrences still said it, two releases later — and npm run check:versions reported every operation-count location ok the whole time.

The pattern was never the problem. The check was carrying a hand-written list of four files, and the claim appears in eleven.


src/node/mcp-server.mjs "pulls all 505 operation implementations"
src/node/lib/node-api.mjs (twice)
tests/mcp/startup-cost.test.mjs
docs/guides/edge-deployment.md
deploy/grafana/README.md
deploy/grafana/alerts.yaml an alert annotation an operator reads
deploy/grafana/cyberchef-mcp-dashboard.json a panel description an operator reads
deploy/helm/cyberchef-mcp/values.yaml the comment explaining a memory request

This is a sharp version of a mistake already written down in this repository. The check’s own comment reads:

One pattern per file rather than per phrasing. The first version of this matched three hand-written phrases and missed five more occurrences in the same files, which review found — a check that covers some occurrences of a claim reads as covering the claim.

The lesson was learned about phrasings and not applied to files.

The fix is not correcting nine files. It is that the check now discovers the files it checks. Coverage went from 7 locations to 37, and discovery immediately found two that reading the tree by hand had missed — alerts.yaml and values.yaml, both operator-facing.

The file list. Replaced by walking the tree. The exclusion list is short and about history rather than convenience: release notes, findings logs, the CHANGELOG and Release-History.md record what was true when written, and correcting them would falsify the record. docs/reference/cyberchef-upstream.md is excluded for a different reason worth stating — it documents upstream’s tree at v10.19.4, where the count genuinely was 463, so “fixing” it would make it wrong.

The phrasing. With discovery working, node-api.mjs still slipped through: “imports every one of the 505 operation implementations” contains neither all NNN operation nor a barrel.

The anchor was chosen by measurement rather than by adding alternatives until it passed. A deliberately wide pattern was run over the whole tree first, and it catches the nine wrong occurrences plus twenty that are legitimately not 504 — the 100-operation batch limit, upstream’s 463, an external reference’s “over 300”, a generated page’s 214, and HAS-160 operation from a hash name. A wide pattern would have meant a denylist that grows forever.

All nine wrong occurrences share one phrase — “operation implementations” — and none of the twenty false positives does. One anchor added, no exclusions needed.

The pattern was in two places. Adding the anchor to the check and not to the discovery filter meant node-api.mjs was never discovered, so its two wrong counts stayed invisible after the anchor written for them. Two copies of one rule, diverged inside a single edit — the same defect this release adds a guard for elsewhere, committed in the fix for it. CATALOGUE_COUNT is now one constant with two consumers.

The number is not as simple as either figure

Section titled “The number is not as simple as either figure”

Worth recording, because it explains how “505” survived being read hundreds of times: no single count makes every one of those sentences true.

OperationConfig entries 504
operation implementations the bridge imports 494
wrapped operations on the chef object 495
function exports on the chef object 508

Those sentences are about the cost of eagerly importing the bridge, where the exact count was never load-bearing — which is precisely why a wrong one went unnoticed. Corrected to 504, the catalogue figure the gate derives and every user-facing document uses.


mcp-server.mjs holds the meta-tools twice: the META_TOOLS literal tools/list is built from, and the name === "cyberchef_..." chain tools/call dispatches on. The v3.0.0 plan recorded “adding a tool means editing two places” and it was carried, unmeasured, for six releases.

Measured: 23 declared, 23 dispatched, no drift. So this is a guard against a latent hazard, not a fix — and a guard is proportionate. Rewriting the chain into a dispatch table is a large change to the hottest file in the server for a problem that has not yet bitten.

The hazard is credible because it has bitten in the adjacent case: the registry tools carry exactly this tripwire, and it earned its keep in v3.4.0 when ecdsa_recover was added.

Both directions are asserted, and each means something different:

  • declared but not dispatched — a tool in tools/list with a full schema that fails on every call. The shape of the defect that hid ten flow-control tools until v2.1.0.
  • dispatched but not declared — callable and undiscoverable, breaking listing must never be stricter than dispatch.

Verified by injecting a declared-but-undispatched tool; it fails with the offending name.


The carried-forward list, measured item by item

Section titled “The carried-forward list, measured item by item”

Nine standing items were checked against the code rather than against their own descriptions. Two were already done and still being carried — a list nobody re-measures goes stale in both directions.

Item State
cyberchef_search is the last eager help() caller Done — lazy since v2.6.0; the note was stale
“505 operations” discrepancy Not done — nine occurrences, not one. This release
Meta-tool dispatch duplication Real, no drift — guarded this release
Benchmark baseline / tolerance Done across v3.4.0–v3.6.0
What fraction of deployments enable opt-in features Out of reach — needs telemetry this project deliberately does not collect. Recorded as permanently deferred
Task-level scoring Still deferred — needs a model in CI; the charter requires “must not be a flaky gate” answered in writing first, and that document does not exist
Shell-free base image Trigger has not fired — latest-slim is still Node v25.9.0
arm64 performance Needs hardware
cert_chain Still a genuine gap, deliberately deferred

npm run lint zero errors
npm run check:versions 37 operation-count locations, every one correct
npm run check:server-json validates against 2025-12-11
mcp-publisher validate valid, no deprecation warning
npm test 241/241 Node API, 2289/2289 operations
npm run test:mcp 1669/1669 across 70 files
npm run test:coverage exit 0
npm run conformance both eras match the baseline

Nothing breaks. No runtime behaviour, tool or surface changes — corrected comments, a widened gate and a new test.