feat(catalog): register sean/ex-mcp as a native Elixir library project #263

Merged
binjovi-bot merged 1 commit from feat/ex-mcp-catalog into trunk 2026-09-12 15:06:18 +00:00
Owner

Why

Binjovi builds its own MCP server from sean/ex-mcp, and the fork was not a Binjovi project at all — no CI on its pull requests, and until this morning no off-cluster backup either.

It could not become one before today: schema 21 pins the project to four names, so a library needed a Binjovi change first. Binjovi v0.1.681 shipped schema 29 — the first open native-library generation, validating a DNS-form name and repo == sean/<project> instead of an allowlist. That release is deployed to production, so the decoder is in the running image and this record can activate.

Verified against the running decoder

Not "it looks right" — the exact record from this bundle.json fed through ProjectRegistry.from_map/2:

DECODED OK
  project  ex-mcp        repo     sean/ex-mcp
  version  29            taxonomy nil
  executor :native       artifact :git/:semver_patch
  targets  []

No taxonomy, deliberately. Taxonomy names a delivery shape, and a library delivers nothing. bytey and libseanfarm-operator are the same.

The checks come from the fork, not from me

recipes/ex-mcp/Dockerfile runs FORK.md's own Checks list:

mix deps.get · mix deps.compile · mix compile --warnings-as-errors
mix test --exclude compliance

plus two the fork's purpose demands:

mix hex.audit
! mix deps.tree | grep -Ei '(cowboy|cowlib|plug_cowboy|ranch)'

That absence is the reason the fork exists — upstream ExMCP 1.3.0 pulls Cowlib 2.20.0 through a mandatory Plug.Cowboy and fails hex.audit on three EEF CVEs with no upstream fix. FORK.md: "No advisory exceptions are configured in this fork." So it is asserted, not assumed.

Left out on purpose: the three tests/consumer-contract.sh lanes need jq, rg, OpenSSL and an HTTP/2 curl and build three separate consumer releases — wider than a library tag build.

Two things worth flagging

  • cache: buildkit-layer. The closed set is buildkit-c-and-layer, buildkit-go-and-layer, buildkit-layer, gitops, kernel-ccache. There is no Elixir profile; the generic layer cache is the honest fit rather than inventing one.
  • build.dockerfile is inert here. A native recipe build passes filename=recipes/<project>/Dockerfile (agent/command.ex), so the recipe's own Dockerfile runs and this field is never read. The schema still requires the key, so it is set to ci.Dockerfile to match the fleet — but it names a file the fork does not have. A schema requiring a key its own lane ignores is a wart; worth removing when the bindings are collapsed.

Verification

scripts/check          exit 0
scripts/check-recipes  PASS
projects: 31, sorted, ex-mcp decodes at version 29

Still to come: the Forgejo binding lists, so ex-mcp gets the webhook that triggers CI and Binjovi-owned branch protection.

https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6

## Why Binjovi builds its own MCP server from `sean/ex-mcp`, and the fork was not a Binjovi project at all — no CI on its pull requests, and until this morning no off-cluster backup either. It could not become one before today: **schema 21 pins the project to four names**, so a library needed a Binjovi change first. Binjovi **v0.1.681** shipped schema **29** — the first open native-library generation, validating a DNS-form name and `repo == sean/<project>` instead of an allowlist. That release is deployed to production, so the decoder is in the running image and this record can activate. ## Verified against the running decoder Not "it looks right" — the exact record from this `bundle.json` fed through `ProjectRegistry.from_map/2`: ``` DECODED OK project ex-mcp repo sean/ex-mcp version 29 taxonomy nil executor :native artifact :git/:semver_patch targets [] ``` **No taxonomy, deliberately.** Taxonomy names a *delivery* shape, and a library delivers nothing. `bytey` and `libseanfarm-operator` are the same. ## The checks come from the fork, not from me `recipes/ex-mcp/Dockerfile` runs FORK.md's own **Checks** list: ``` mix deps.get · mix deps.compile · mix compile --warnings-as-errors mix test --exclude compliance ``` plus two the fork's purpose demands: ``` mix hex.audit ! mix deps.tree | grep -Ei '(cowboy|cowlib|plug_cowboy|ranch)' ``` That absence **is** the reason the fork exists — upstream ExMCP 1.3.0 pulls Cowlib 2.20.0 through a mandatory `Plug.Cowboy` and fails `hex.audit` on three EEF CVEs with no upstream fix. FORK.md: *"No advisory exceptions are configured in this fork."* So it is asserted, not assumed. Left out on purpose: the three `tests/consumer-contract.sh` lanes need jq, rg, OpenSSL and an HTTP/2 curl and build three separate consumer releases — wider than a library tag build. ## Two things worth flagging - **`cache: buildkit-layer`.** The closed set is `buildkit-c-and-layer`, `buildkit-go-and-layer`, `buildkit-layer`, `gitops`, `kernel-ccache`. There is no Elixir profile; the generic layer cache is the honest fit rather than inventing one. - **`build.dockerfile` is inert here.** A native recipe build passes `filename=recipes/<project>/Dockerfile` (`agent/command.ex`), so the recipe's own Dockerfile runs and this field is never read. The schema still *requires* the key, so it is set to `ci.Dockerfile` to match the fleet — but it names a file the fork does not have. A schema requiring a key its own lane ignores is a wart; worth removing when the bindings are collapsed. ## Verification ``` scripts/check exit 0 scripts/check-recipes PASS projects: 31, sorted, ex-mcp decodes at version 29 ``` Still to come: the Forgejo binding lists, so `ex-mcp` gets the webhook that triggers CI and Binjovi-owned branch protection. https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6
feat(catalog): register sean/ex-mcp as a native Elixir library project
All checks were successful
binjovi/ci Binjovi completed the frozen plan
38d4cfdb75
Binjovi builds its own MCP server from this fork, and until today the fork was
not a Binjovi project at all -- no CI on its pull requests, and until this
morning no off-cluster backup either.

SCHEMA 29. Version 21 pins the project to four names, so a library could not be
added here without a Binjovi change first. Binjovi v0.1.681 shipped 29, the
first open native-library generation: a DNS-form name and repo == sean/<project>
instead of an allowlist. That release is deployed to production, so the decoder
exists in the running image and this record can activate. Verified by decoding
this exact record through ProjectRegistry.from_map/2: version 29, taxonomy nil,
executor native, git/semver_patch, no deployment targets.

NO TAXONOMY, deliberately. Taxonomy names a delivery shape, and a library
delivers nothing. bytey and libseanfarm-operator are the same.

THE CHECKS COME FROM THE FORK. recipes/ex-mcp/Dockerfile runs FORK.md's own
"Checks" list: deps.get, deps.compile, compile --warnings-as-errors, and
test --exclude compliance. It also runs `mix hex.audit` and refutes cowboy,
cowlib, plug_cowboy and ranch in the dependency tree -- that absence is the
entire reason the fork exists, so it is asserted rather than assumed. The three
tests/consumer-contract.sh lanes are left out: they need jq, rg, OpenSSL and an
HTTP/2 curl and build three separate consumer releases, which is wider than a
library tag build.

cache is buildkit-layer. The closed set is buildkit-c-and-layer,
buildkit-go-and-layer, buildkit-layer, gitops and kernel-ccache; there is no
Elixir profile, and the generic layer cache is the honest fit.

build.dockerfile is "ci.Dockerfile" to match the fleet, and it is INERT for
this lane: a native recipe build passes filename=recipes/<project>/Dockerfile
(agent/command.ex), so the recipe's own Dockerfile is what runs. The schema
still requires the key. Worth removing when the bindings are collapsed.

scripts/check and scripts/check-recipes both pass.

Claude-Session: https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6
binjovi-bot deleted branch feat/ex-mcp-catalog 2026-09-12 15:06:19 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
sean/binjovi-plans!263
No description provided.