Canonical home of BoJ cartridges. Hosts (boj-server, panll, others) fetch
cartridges from here on demand into a host-local cache; this repository ships
the source tree.
Machine-readable summary: 0-AI-MANIFEST.a2ml.
This repository is the sole source of BoJ cartridges. boj-server retired its
own bundled cartridges/ tree in
boj-server#300 (merged
2026-08-04). There is no longer a second copy anywhere: what lands here is what
every host fetches.
🟢 Manifests. The schema validator runs in strict mode in CI and is green:
142 manifests, 142 passing, 0 failing (just validate). Drift-remediation
campaigns #18 / #19 / #20 are closed.
🟡 Toolchain. .tool-versions pins zig 0.15.1, deno 2.7.14,
idris2 0.8.0. A migration of all 118 FFI trees to Zig 0.16.0 is in flight in
#109 and is
not merged; until it is, 0.15.1 is the pin that CI builds against.
🔴 Adapters. The adapter/ layer does not build, and no CI job compiles it —
zig-test.yml globs ffi/ only. The canonical template’s adapter calls a
function that exists nowhere in the tree, and just mint copies it forward.
Full evidence in docs/known-issues/adapters.adoc.
The ffi/ layer is unaffected and is built and tested in CI.
See the canonical spec: standards/cartridges/CARTRIDGE-FORMAT.adoc and JSON schema: cartridge-v1.json.
A cartridge is a self-contained server unit consumed by a host to extend its tool surface (MCP), language-server reach (LSP), debug-adapter capabilities (DAP), build-tool integration (BSP), or other server-role mode. Cartridges are process-isolated (each backend listens on its own loopback port) and content-addressable.
Hybrid layout ratified in docs/decisions/ADR-001-taxonomy.adoc:
cartridges/
├── domains/ ← cartridges grouped by functional domain
│ ├── cloud/ ← 10 cartridges (umbrella + 9 providers)
│ ├── database/ ← 12 cartridges (umbrella + 11 providers)
│ ├── ci-cd/, languages/, security/, research/, … (31 domains total)
├── cross-cutting/ ← cartridges not bound to a single domain
│ ├── agentic/ ← agent-mcp, claude-ai-mcp, model-router-mcp, …
│ ├── build/ ← bsp-mcp (generic BSP server)
│ ├── debug/ ← dap-mcp (generic DAP server)
│ ├── fleet/ ← fleet-mcp
│ ├── health/ ← boj-health-mcp
│ ├── nesy/ ← nesy-mcp, ml-mcp
│ └── orchestration/ ← stack-orchestrator-mcp
└── templates/ ← canonical scaffolds for new cartridges
└── gossamer-mcp/ ← reference template
A cartridge name ends in a canonical role suffix:
| Suffix | Role |
|---|---|
|
Model Context Protocol |
|
Language Server Protocol |
|
Debug Adapter Protocol |
|
Build Server Protocol |
|
Debugger (when not strictly DAP) |
|
Code formatter |
|
Linter / static analyser |
|
Build orchestration |
|
Neurosymbolic reasoning |
|
Agent harness |
|
Fleet orchestrator |
A single domain may have multiple cartridges across roles, e.g. database-mcp
database-lsp + database-format.
schemas/cartridge-v1.json mirrors the canonical spec at
hyperpolymath/standards.
The mirror is SHA-pinned via schemas/PINNED-SHA (see
also schemas/SCHEMA-MIRROR.md).
The pinned mirror is verified against schemas/PINNED-SHA on every CI run, then
every cartridge.json is checked against schemas/cartridge-v1.json by the
in-tree Deno validator under
tools/validate-cartridges/:
| Task | Behaviour |
|---|---|
|
Walks all manifests, prints a one-line summary per cartridge; exit 0 regardless. |
|
As |
|
Fails the run on any violation. Active in CI as of 2026-06-01. |
CI (.github/workflows/cartridge-schema.yml)
runs the validator in strict mode — any manifest that fails schema validation
blocks the PR. Audit output is still tee’d into the workflow summary for
browsability. The drift-remediation campaigns (#18 missing category, #19
auth.method enum mismatches, #20 canonical-only / missing top-level fields /
name-pattern renames) all closed alongside this gate flip;
audits/cartridge-schema-2026-06-01.md
records the 139/139 baseline as it stood on 2026-06-01. The tree has grown
since: the current baseline is 142/142. Run just validate for the live
figure rather than quoting either number.
Canonical schema home: hyperpolymath/standards.
Each cartridge directory contains its own cartridge.json with version
(semver). Hosts fetch cartridges by name + version; the tray UI
(hyperpolymath/boj-server) exposes "Add cartridge source" to point at this
registry (the canonical default) or any other GitHub URL.
-
142
cartridge.jsonmanifests: 141 cartridges + 1 template scaffold (templates/gossamer-mcp, which is not shippable and is excluded from the public catalogue). -
31 functional domains + 7 cross-cutting categories (
agentic,build,debug,fleet,health,nesy,orchestration) + 1 template. -
Every
cartridge.jsonvalidates strictly againstschemas/cartridge-v1.json. -
12 manifests declare
"available": true— the Foundry Wave-1 "Golden Dozen". The other 130 omit the key entirely rather than setting it tofalse, so the tree records no availability claim for them either way. A count of "canonical-only" cartridges cannot be derived from the manifests; earlier editions of this README asserted 14, which was not verifiable then and is not now.
These figures come from the tree, not from a stored constant. Recount with
just validate (manifest total) and just catalog (catalogue total).
.tool-versions is authoritative:
| Tool | Pin | Used by |
|---|---|---|
|
0.15.1 |
|
|
2.7.14 |
|
|
0.8.0 |
|
The Zig 0.16.0 migration is open in #109 and has not merged. Build against 0.15.1 until it does.
Cartridges with a Zig FFI carry their own cartridge_shim.zig beside
ffi/build.zig. Build configs resolve the shim with
b.path("cartridge_shim.zig") (and b.path("../ffi/cartridge_shim.zig") for
adapter siblings) — the per-cartridge layout is the de facto pattern (#29 / #31).
The canonical shim source is
cartridges/templates/gossamer-mcp/ffi/cartridge_shim.zig.
116 shims are in the tree; 115 are byte-identical to canon. The one exception,
cartridges/domains/gaming/npc-mcp/ffi/cartridge_shim.zig, is a stale copy that
differs only in comments — rewrapped prose and an older heading style. Its API
surface is identical: the same seven RC_* constants and the same three helpers
(invokeArgsNull, toolIs, writeResult). Nothing behavioural turns on it.
(The figure previously printed here, "112 of 114", did not match the tree.)
Shim drift is not currently enforced. Nothing in CI compares a shim against
canon, so a divergent copy would land silently — which is how the npc-mcp one
persisted. A sync script and a shim-drift gate are part of
#109; until that
merges, copy the canonical file verbatim when adding an FFI cartridge and check
it by hand:
find cartridges -name cartridge_shim.zig -exec md5sum {} + \
| awk '{print $1}' | sort -u | wc -l # 1 == no driftThe five-symbol ABI the shim implements is documented in
ADR-0006.
Full guide: docs/cartridge-authoring.adoc.
In short:
-
Mint from the canonical template — write a
minter.toml, thenjust mint path/to/minter.toml. (Don’tcp -rthe template by hand; the minter also does the name substitutions.) -
Update the manifest to reflect your cartridge’s name (role-suffixed), domain, protocols, tools.
-
just validate— new cartridges must validate cleanly againstschemas/cartridge-v1.json. This is the CI gate. -
just catalog— regenerate the public catalogue so the site matches the tree. -
Open a PR; auto-merge is enabled by default for this repo.
Read docs/known-issues/adapters.adoc
before you spend time on the adapter/ directory your mint produces.
In-tree — versions alongside the code:
-
docs/cartridge-authoring.adoc— layer contract, the five-symbol ABI, minting, gates. -
docs/known-issues/adapters.adoc— whyadapter/cannot be trusted. -
docs/decisions/— ADRs, including the ADR-0006 pointer.
On the wiki —
narrative and operational material, kept in a separate git repository
(…/boj-server-cartridges.wiki.git), which is why it is not in this tree:
-
Refresh Discipline — how hosts re-fetch.
-
Schema Validation — working through manifest drift.
MPL-2.0. Cartridges retain their individual SPDX identifiers per
cartridge.json.