Ship a container image, and list on the MCP Registry - #1
Merged
Conversation
The caveat under "As a Claude Code skill" told readers the skill only walks the Gmail path and has not caught up with `provider: imap` or `mail-muncher init`. Both halves stopped being true at 2944723, which reordered the skill to lead with IMAP; `init` is documented across SKILL.md and references/setup.md as well. Left alone it was actively steering people away from the two-minute route the rest of the README spends its opening arguing for.
The official MCP Registry indexes servers by distributable package and accepts npm, PyPI, NuGet, cargo, OCI and MCPB. A GitHub release of Go binaries is none of those, so mail-muncher could not be listed at all. OCI is the path that fits. MCPB looked closer -- prebuilt binaries off a GitHub release, no toolchain -- but it is one server out of 1200 in the live registry, and it has no way to say which of four os/arch artifacts a client should take. A container manifest resolves the architecture itself, and 51 registry entries already go this way. The image is Alpine rather than scratch or distroless, which is not a size oversight: `imap.password_cmd` is mandatory on the IMAP path and internal/provider/imap runs it as `/bin/sh -c`. Without a shell, IMAP auth cannot work at all. The trade is real and README says so -- inside a container `password_cmd` reaches the container's environment, not the password manager on your host. `dockers_v2` hands the Dockerfile a build context laid out as <os>/<arch>/<binary>, so the COPY resolves through buildx's TARGETOS and TARGETARCH rather than a bare path. CI grows QEMU because the arm64 layer genuinely executes `apk add` and `adduser`. The registry proves ownership by matching an `io.modelcontextprotocol.server.name` annotation on the pushed manifest against `name` in server.json, so those two strings move together. server.json names 0.4.0, not the current 0.3.0: the image it points at does not exist until a release builds it, so publishing to the registry follows the tag rather than leading it. Verified by a snapshot build: image builds for both platforms, runs as non-root with $HOME resolving the default config path, carries the annotation, and answers an MCP initialize + tools/list with all five tools over stdio.
The release dry run builds the container image now, and the linux/arm64 half genuinely runs `apk add` and `adduser` on an amd64 runner. Without binfmt registered that is "exec /bin/sh: exec format error", which is how this job failed the moment the image landed. release.yml got the same two steps when the image was added; this job lives in ci.yml and was missed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an OCI image to the release so mail-muncher can be listed in the official MCP Registry, plus the
server.jsonthat is that listing.Why OCI and not MCPB
The registry indexes servers by distributable package: npm, PyPI, NuGet, cargo, OCI or MCPB. A GitHub release of Go binaries is none of them, so today there is no way to be listed.
MCPB looked like the closer fit — prebuilt binaries off a GitHub release, no toolchain on the user's machine. Two things ruled it out:
packages[]has no platform discriminator, so four os/arch bundles give a client no way to choose.A container manifest resolves architecture itself, and 51 registry entries already take this route.
Alpine, deliberately
imap.password_cmdis mandatory on the IMAP path andinternal/provider/imapruns it as/bin/sh -c. A scratch or distroless image cannot authenticate to IMAP at all — not less conveniently, it fails outright.The cost is honest and documented: inside a container
password_cmdreaches the container's environment (printenv IMAP_PASSWORD,cat /run/secrets/…), not your host password manager. README says so plainly, including that anydest:in the config has to be a path the container can see.Verified, not assumed
A snapshot build caught a real bug first:
dockers_v2lays the context out as<os>/<arch>/<binary>, so a bareCOPY mail-muncherfails. Fixed via buildx'sTARGETOS/TARGETARCH.After the fix:
linux/amd64andlinux/arm64$HOMEresolving the default config pathio.modelcontextprotocol.server.name, which the registry matches againstnameinserver.jsoninitialize+tools/listover stdio with all five toolsgoreleaser check,go test ./...andclaude plugin validateall passSequencing
server.jsonnames 0.4.0, not the current 0.3.0 — the image it points at does not exist until a release builds it. Order is: merge, tagv0.4.0, thenmcp-publisher publish.CI gains QEMU because the arm64 layer genuinely executes
apk addandadduser, andpackages: writeto push to GHCR.