Current version v0.22.9, 57 servers. 27 releases below, newest first.
Spreadsheet, Expense Tracker and Office Suite use the official SheetJS0.20.3 release. This replaces the older XLSX parser affected by the vendor's prototype-pollution and regular-expression denial-of-service advisories. The update includes the ESM file-writing and legacy-codepage setup required by the new dependency. New immutable archives and their checksum manifest identify the updated bytes; previous releases are retained.
"A dependency version check alone does not establish workflow compatibility."
Duplicate Invoice Check, Three-Way Match and Office Suite have public runtime0.22.8 archives whose downloaded SHA-256 values equal the independently tested bytes. Six official registry names resolve to those three local capabilities. Office discovery measures49 children and447 tools; bounded invoice workflow checks pass. Shared offline licensing reports48 paid products at$19 single/$39 bundle, with unchanged permission checks. Full diagnostics and CSV evidence remain free; Pro removes the saved-report count cap.
"Available completed-history MCP Checkout gross remains$0, so tested products and published install routes do not establish willingness to pay."
R5 indexing sprint shipped four changes and no release doc existed for them, which is why sitemap lastmod stayed at 2026-09-19 while the site changed: (1) IndexNow key verification route added to the billing worker at /e5c1a8f3d2b94c6f8a7d0e3b5c9f1a4d.txt (PR #11 merged, live-verified HTTP 200); (2) all 235 sitemap URLs bulk-submitted to api.indexnow.org (HTTP 200, covers Bing/Yandex/Seznam/Naver — Google does not participate in IndexNow); (3) GSC sitemap resubmitted via Search Console API (sc-domain:zovo.one, URLSearchParams token fetch); (4) GSC URL Inspection audit of 16 URLs found exactly 1 of 235 indexed (homepage), 19 impressions/0 clicks in 28d — the audit that motivated this sprint. tests: billing 173/173 pass before and after. deploys: worker with IndexNow route live on mcp.zovo.one.
"the freshness signal Google schedules by is the release doc, and it had been silent since 2026-09-19 while four shipped changes went live; a dated release doc per sprint is the cheapest crawl-priority lever available and costs one file."
sprint 46 shipped three crawled-visible changes and no release doc existed for them, which is why sitemap lastmod stayed at 2026-09-17 while the pages themselves changed: (1) T13 social meta, twitter:card summary + twitter:title + twitter:description emitted from the shared page() helper so all 193 sitemap URLs carry them, plus Organization and WebSite JSON-LD on the homepage, SearchAction correctly skipped because no real search route exists, live-verified with curl on production (twitter:card present on / and /s/invoice, both JSON-LD blocks present); (2) T15 fix 3, sitewide footer hub links, every page() render now links Home, Guides, Setup, Compare, Changelog so crawlers hitting a deep guide page are one hop from the section hubs; (3) the honesty gate number on the homepage was reconciled with the tests actually on disk (148 unit tests green, verified live). tests: billing test runner reported 158 pass 0 fail before and after; remote 141/141; validation 1192/1192 unchanged. deploys: 71ae9dbd (footer links), 66af2e1c (honesty gate), both live on mcp.zovo.one.
"sitemap lastmod is downstream of the release doc, not of the deploy. three shipped, production-verified changes moved nothing a crawler schedules by because the freshness signal comes from docs/RELEASE_V*.md; a release doc is part of shipping, not bookkeeping after shipping."
registry remotes went from 0 to all 41 hosted endpoints visible in the Official MCP Registry (3 under alias names); GitHub release v0.22.0 with 38 .mcpb assets then 4 more uploaded for the new servers (42 total); fileSha256 placeholders replaced with real digests in 42 manifests and primary server.json switched from npm packages (unpublished, token revoked) to mcpb packages so the registry accepts them; the 2026-09-13 hosted-row waiver for supplier-list, service-agreement, maintenance-log and mileage-log deleted after live initialize probes returned 200; Awesome-MCP PR #52 opened and mergeable with an upstream catalog.yaml conflict fixed as a side effect; 38/38 mirror descriptions patched to carry the hosted endpoint URL; billing 148/148, remote 141/141, validation 1192/1192.
"the official registry was the one index the client pickers read and none of our endpoints were reachable through it; a manifest is not published until its referenced artifact resolves, so the mcpb asset had to exist before the remote entry could stick."
change-order joins as the thirtieth server (added, removed and changed lines against a quote or work-order reference with reason and date; running contract value counting approved deltas only, pending shown separately; approval flow draft, sent, approved, rejected, void; a changed line emitted as a reversal plus a revised item, never one net item; the invoice-ready delta payload in both scales with the 100x quotient re-derived from each payload's own items, 117,012 against 11,701,200; 47 tests at build); SERVER_COUNT 30 in both licence files, bundle saving $531; hosted catalogue round 38 scored 18/18 with the undated question answered from the in_force block both times; D-R97 and D-R98 fixed and deployed (hosted price list tool says HTML, PDF names the booked later row and no longer repeats the issuer); every SPEC.md regenerated without an em dash; checkout for change-order joins work-order and catalogue as a named PENDING_HUMAN gap; wiring round 23 closed 20/20 (guide, GIF, logo, Docker repin to 8f37031, Cline issue 2461, /buy 503 live); hosted on mcp.zovo.one/mcp/change-order as the thirtieth endpoint, re-vendored after the audit and the below-zero refusal verified live; audit 16/18 shipped, 18/18 after D-R99 (a removal cannot take the contract below zero, checked at the line and again at approval) and D-R100 (money in item descriptions formatted with its code, not a bare minor figure); stdio round 39 11/18 with four client-side classes (invented gross value, false nothing-written, hand-built Pro payload, netted changed line) and the server clean on every figure; 32 package.json and 84 ranges at 0.20.0; 114 manifests bumped, 83 reference a bundle; release-check green with three named gaps on 30 servers; npm test 1507 pass, 0 fail, 11 skipped of 1518; 31 bundles, no stale dist; boot-check change-order 11 tools, invoice 13, office-suite 282, all serverInfo 0.20.0; GitHub release with 31 assets; sha256 into 83 manifests, change-order digest equal to the release asset digest; registry publish, mirrors and by-name verify recorded at loop close.
"a change order that nets a changed line into one figure destroys the audit trail the document exists to keep; reversal plus revised line is the only shape both engines and an auditor can read."
catalogue joins as the twenty-ninth server (SKUs with per-currency, per-tier, valid-from price rows; a labour rate card; lines_resolve builds both the invoice and the quote payload itself because the two engines take prices in different scales, a 100x gap asserted exactly by re-deriving the net from each payload's own items; audit 18/18; stdio round 37 14/18, the miss being an undated question answered against the wrong valid-from row; hosted on mcp.zovo.one/mcp/catalogue as the twenty-ninth endpoint with the ladder, the scale and both downloads verified live on one Pro key); checkout for catalogue and work-order both stay named gaps because the keychain Stripe key lacks product write, /buy answers 503 with the bundle link; release-check gained a per-server dist-version check and build-mcpb a stale-dist guard, both after v0.18.0 shipped a kanban bundle from a stale build; work-order hosted round 16/18; intel round 13 found five more empty slots led by change-order; 30 package.json and 80 ranges at 0.19.0; 110 manifests bumped, 80 reference a bundle; release-check green with two named gaps on 29 servers; npm test 1455 pass, 0 fail, 11 skipped of 1466 (data/tests.json); 30 bundles, no stale dist; boot-check catalogue 12 tools, invoice 13, office-suite 273, all serverInfo 0.19.0; GitHub release with 30 assets; sha256 written into 80 manifests, catalogue digest equal to the release asset digest; registry publish, mirrors and by-name verify recorded at loop close.
"two sibling engines that accept the same field name in different units cannot detect a swap; the one place that knows both shapes must emit both payloads and print the scale next to each."
work-order joins as the twenty-eighth server (job orders with parts and labour lines, status flow, completion report, invoice-ready payload; markup applied on the unit cost because the invoice engine rounds unit prices first, gap of exactly one minor unit asserted; audit 17/18; stdio round 35 16/18 in which the client rebuilt nothing from refused output); checkout for work-order is a named gap because the Stripe key in the keychain lost product write, so its price is the literal PENDING_HUMAN, /buy answers 503 with the bundle link and release-check reports the gap without turning green; petty-cash hosted round 16/18; scripts/record-tests.mjs writes data/tests.json for the KPI; 30 package.json and 75 ranges at 0.18.0; 106 manifests bumped, 77 reference a bundle; release-check green with one named gap on 28 servers; npm test, 29 bundles, boot-check, GitHub release, sha256, publish, mirrors and by-name verify recorded at loop close.
"a gap that is named in the checker, the storefront and the validator is safer than a plausible placeholder that turns every cell green and fails for the first time in front of a buyer."
petty-cash joins as the twenty-seventh server (imprest float; replenishment is imprest minus balance, never the voucher sum; a count is a fact that moves the book balance; audit 16/18 with a date-guard fix; stdio round 33 14/18); recoverable free slots across nine servers: a byte-identical record is refused by name before the cap and ten free delete tools recover a slot; every gate text now states that any total or journal composed outside the free tools is an estimate (the earlier imperative wording was read by a client as a prompt injection); amortization hosted round 15/18; intel round 12 found five more empty slots; 29 package.json and 70 ranges at 0.17.0; 102 manifests bumped, 74 reference a bundle; release-check green on 27 servers; npm test, 28 bundles, boot-check, GitHub release, sha256, publish, mirrors and by-name verify recorded at loop close.
"text inside a tool result that reads as a command to the model is treated as hostile; the same protection stated as a fact about the data ("figures outside these tools are estimates") is something a client can act on without being told what to do."
amortization joins as the twenty-sixth server (loan and lease schedules with effective interest, fees, early repayment and balloon; journal lines in the cash-book account names; worked examples asserted to the minor unit; audit 18/18; stdio round 31 15/18 with every server figure relayed exactly and the lost points on client-side totals over refused data); the cash-book free tier is documented and its gate text names the free evidence; cash-book hosted round 17/18; all twelve estate backlinks still serve; the release checker's number-word table extended to thirty-six; 28 package.json and 65 ranges at 0.16.0; 98 manifests bumped, 71 reference a bundle; release-check green on 26 servers; npm test 1207 tests, 1195 pass, 0 fail after the amortization contract stopped pinning the version string; 27 bundles, three boot-checked at 0.16.0; GitHub release, sha256, publish, mirrors and by-name verify recorded at loop close.
"three consecutive first releases broke on a contract that pinned a moment (TBD, a version string) instead of a rule; the rule form (a sha or TBD, a semver shape) is what the newest servers now assert, and the checker table that names counts in English must grow with the server count the same way."
cash-book joins as the twenty-fifth server (one double-entry ledger from six sibling stores, trial balance to zero, bank rows matched as evidence rather than posted because 99.6 percent of bank cash movement is already in the documents; audit 18/18; stdio round 29 17/18); copy buttons on every prompt block on the storefront; statement-of-account hosted round 18/18; findable share re-measured at 50 percent on the tracked 97 tokens and 55 percent on the extended set; 27 package.json and 61 ranges at 0.15.0; 94 manifests bumped, 68 reference a bundle; release-check green on 25 servers; npm test 1242 tests, 1231 pass, 0 fail, 0 cancelled; 26 bundles, three boot-checked at 0.15.0; GitHub release with 26 assets; sha256 into 68 manifests; registry 67 on the first pass and the 68th a confirmed duplicate; mirrors and by-name verify running in the background at loop close.
"a server that only reads other servers' stores is the cheapest kind to add and the most revealing: cash-book found that a hosted endpoint with a missing sibling document produces a ledger that balances perfectly with nothing in it, so the shared-store list is a correctness input, not a convenience."
statement-of-account joins as the twenty-fourth server (per-client statements from the invoice, credit-note and deposit stores, aging as at any date, dunning with the profile bank details, PDF; audit 18/18; stdio round 26 18/18); the month-end guide is generated from a real nine-prompt run through the 224-tool bundle (round 27, 26/27); invoice balances net credit notes and the profile reader accepts vat_rate (D-R95, D-R96); the hosted worker takes a list of shared stores with read-only shares; sync-mirrors retries network drops; release-check enforces the profile-reader list; 26 package.json and 54 ranges at 0.14.0; 90 manifests bumped, 65 reference a bundle; release-check green on 24 servers; npm test 1119 tests, 1107 pass, 0 fail after the asset-register contract was widened to accept a real sha; 25 bundles, three boot-checked at 0.14.0; GitHub release with 25 assets; sha256 into 65 manifests; registry 63 on the first pass, one more on retry and the last a confirmed duplicate; mirrors and by-name verify running in the background at loop close.
"the "fileSha256 must be TBD" contract has now broken two consecutive first releases (per-diem, asset-register); every contract test written for a new server should assert the rule (TBD or a 64-hex sha), which the statement-of-account contract already does."
asset-register joins as the twenty-third server (Polish KST, UK capital allowance and US MACRS tables bundled with provenance; monthly journals; disposals; audit 18/18; stdio round 24 recorded); every cap message on every server ends with the twenty-three-server bundle link at $39 carrying src=<product>.<tool>.bundle, and the instrument recorded the first bundle-sourced click; 25 package.json and 49 ranges at 0.13.0; 86 manifests bumped, 62 reference a bundle; release-check green on 23 servers; npm test 1069 tests, 1056 pass, 0 fail after two fixes (invoice PROFILE_READERS gained asset-register; the per-diem contract now accepts a real sha after its first release); 24 bundles (invoice and office-suite rebuilt after the reader fix), three boot-checked at 0.13.0; GitHub release with 24 assets; sha256 into 62 manifests; registry 61 of 62 on the first pass and the 62nd a confirmed duplicate; registry 62 of 62 verified at 0.13.0 after index lag on one name; the first mirror sync died on a GitHub network drop at mcp-barcode and the last seven mirrors were re-synced by name afterwards.
"two tests broke for the same reason in two consecutive releases: a constant that must grow with the server count (the invoice reader list) and a contract that was true only before the first release (fileSha256 is TBD)."
per-diem joins as the twenty-second server (Polish, UK domestic and US GSA rate tables bundled byte-exact with provenance; UK overseas deliberately not bundled; audit 18/18; stdio round 22 17/18); the invoice profile-reader list gained per-diem (D-R89, caught by the invoice test that greps every server); 24 package.json and 47 ranges at 0.12.0; 82 manifests bumped, 59 reference a bundle; release-check green on 22 servers incl. the new hosted-row check; npm test 1016 tests, 1004 pass, 0 fail after the reader fix; 23 bundles (invoice and office-suite rebuilt after the fix), three boot-checked at 0.12.0; GitHub release with 23 assets; sha256 into 59 manifests; registry 58 of 59 on the first pass and the 59th a confirmed duplicate; mirrors and by-name verify running in the background at loop close.
"a source edit after the bundle build started means two bundles are stale (the server and office-suite, which vendors it); a per-server rebuild needs SERVERS trimmed to that one name because office-suite always follows the loop."
deposits joins as the twenty-first server (security and retainer deposits, applied to invoices through the invoice engine; audit 18/18 no defects; round 20 stdio 16/18); invoice_mark_paid now adds payments and records each one (D-R87, found by the deposits build); 23 package.json and 45 ranges at 0.11.0; 78 manifests bumped, 56 reference a bundle; release-check green on 21 servers; npm test 983 tests, 971 pass, 0 fail after the deposits contract was updated to expect its remote (it was written before hosting); 22 bundles, three boot-checked at 0.11.0 (deposits, invoice, office-suite); GitHub release with 22 assets; sha256 into 56 manifests; registry 55 of 56 on the first pass and the 56th refused as a duplicate (already landed on a timed-out first attempt); mirrors and by-name verification running in the background at loop close.
"a contract test that pins "this server is not hosted" is correct for one day and wrong the next; the check belongs on remotes.json equality (hosted) or absence (stdio-only names), which is what the other servers already assert."
billing-docs joins as the twentieth server (credit notes and purchase orders on the invoice engine; audit 18/18 with no defects; hosted round 19 16/18); 22 package.json and 41 ranges at 0.10.0; 74 manifests bumped (53 reference a bundle); release-check green with 0 gaps on 20 servers; npm test 1011 tests, 1000 pass, 0 fail, 0 cancelled; 21 bundles, three boot-checked at 0.10.0 (billing-docs, office-suite, invoice); GitHub release with 21 assets; sha256 into 53 manifests; registry 53 of 53 published on the first pass (verification by name running in the background at the loop close); mirrors syncing.
"crediting part of a mixed-VAT invoice at one rate is wrong by far more than rounding and invisible downstream because the gross matches; the VAT line on a EUR 177.00 credit of a 23 and 8 percent invoice is out by EUR 6.10."
21 package.json and 38 ranges at 0.9.5; 70 manifests bumped (three new names this loop: letterhead on docx, label on barcode, appointment on calendar); release-check green; npm test 968 tests, 957 pass, 0 fail, 0 cancelled; 20 bundles, three boot-checked at 0.9.5 (calendar, bank-statement, docx); GitHub release with 20 assets; sha256 into 50 manifests; registry 50 of 50 published on the first pass (verification by name ran in the background, see the loop close note); mirrors synced (exit 0).
"the release recipe is now stable enough that every step is a one-line command with a log file; the only variable is the registry's search latency, which decides how long the verification takes, never whether it succeeds."
21 package.json and 38 ranges at 0.9.4; 67 manifests bumped; release-check green; npm test 966 tests, 955 pass, 0 fail, 0 cancelled; 20 bundles, three boot-checked at 0.9.4 (pdf, calendar, clauses); GitHub release with 20 assets; sha256 into 47 manifests; registry 47 of 47 published first pass and verified at 0.9.4 by name; mirrors synced (sync-mirrors exit 0, mcp-zip main at the sha commit).
"the whole release is five bounded steps (bump, build+test+bundles, push+release, sha+publish, mirrors+verify)."
21 package.json and 38 internal ranges at 0.9.3; 67 manifests bumped, 47 identifier URLs moved; release-check green (0 gaps); npm test 881 tests, 869 pass, 0 fail after one date-dependent timezone test was widened to a full week (a Friday-night start left a 3-day window with no weekday); 20 bundles built, three boot-checked at 0.9.3 (zip, barcode, invoice); GitHub release v0.9.3 with 20 assets; sha256 written into the 47 bundle-referencing manifests; registry 47 of 47 verified at 0.9.3 by fully qualified name; mirrors synced (see log note below).
"a "publish failed" line from mcp-publisher is not evidence of a missing entry."
Taken as given, not re-derived: 21 `package.json` files and 67 server manifests bumped to 0.9.2 and pushed (`30e4fdc`), GitHub release `v0.9.2` created with 20 `.mcpb` assets, sha256 of each bundle written into every manifest that references one (`e5575ff`), and registry entries for `zip` and `qr-code` confirmed at 0.9.2.
"The stall left no error to diagnose, which made "verify, don't assume" the only correct approach for both remaining unknowns (registry publish state, mirror sync state) even though the task's own starting assumption ("all 47 manifests are at 0.9.2 locally, so the registry probably is too") turned out to be right for 2 servers and untested for the rest."
19 servers plus `servers/office-suite` and `packages/mcp-license` bumped to 0.9.1 (21 package.json files), and 38 internal `@theluckystrike/*` ranges rewritten to `^0.9.1`.
"v0.9.0 closed with an observation that nothing checked the reverse direction of the wiring: no reader asserted that a server with a `remotes.json` also had a variant name, or that a new server got its second registry name at all. `scripts/release-check.mjs` is that reader, and its first run found nineteen real wiring failures across 456 cells, including the exact defect predicted: `barcode` had one registry name, one server after `zip` had the same problem."
19 servers plus `servers/office-suite` and `packages/mcp-license` bumped to 0.9.0 (21 package.json files), and 38 internal `@theluckystrike/*` ranges rewritten to `^0.9.0`.
"v0.7.0 and v0.8.0 both found a writer with no reader, and both added a one-line check for it."
18 servers plus `servers/office-suite` and `packages/mcp-license` bumped to 0.8.0, and 37 internal `@theluckystrike/*` ranges rewritten to `^0.8.0`.
"The recurring shape in this repo is a writer with no reader. v0.7.0 found three (a version literal, a hand-maintained child list, a description length); v0.8.0 found two more in the same file, both in `servers/barcode/server.mcpb.json`, and both introduced by a commit that added a server without publishing it."
17 servers plus `servers/office-suite` and `packages/mcp-license` bumped to 0.7.0, and every internal `@theluckystrike/*` range rewritten to `^0.7.0`. `servers/quotes` was excluded from the v0.6.1 bump (it was another agent's server at the time) and still carried `^0.6.0` ranges; it is in the bump now.
"`npm test` exiting 1 while every summary line says `fail 0` is the shape to watch for."
`scripts/sync-versions.mjs` writes `servers/<name>/src/version.ts` from that server's own `package.json`:
"The generated-file fix is worth more than the version numbers it corrects: `src/version.ts` is the only shape that survives both build targets."
`scripts`-free node pass over every manifest: 59 files changed to 0.6.0 (16 servers + office-suite `package.json`, `packages/mcp-license/package.json`, and every `server.json`, `server.mcpb.json`, `server.variant.json`). Every internal `@theluckystrike/*` range rewritten to `^0.6.0`, including office-suite's twelve child ranges, `mcp-license` -> `mcp-timezone`, bank-statement -> `mcp-spreadsheet`, calendar -> `mcp-timezone`, clauses/resume -> `mcp-docx`, recurring -> `mcp-invoice`.
"The `serverInfo.version` a server reports over the protocol is a string literal in its `src/index.ts`, not read from `package.json`, so it is not touched by a version bump."