adityamparikh opened a new issue, #261: URL: https://github.com/apache/solr-mcp/issues/261
## Summary `release-publish.yml` has a `publish-mcp-registry` job, but on `main` it cannot publish 1.0.0 to the [official MCP Registry](https://modelcontextprotocol.io/registry/about). This issue is the contributor-side spec: what `server.json` and the workflow must look like, and where the step sits in the [ATR](https://releases.apache.org/) release in [`dev-docs/release-process.md`](https://github.com/apache/solr-mcp/blob/main/dev-docs/release-process.md). The PMC and Infra prerequisites (Docker Hub repo, secrets, GHCR visibility) are tracked in #251 and are not repeated here. ## How the official registry works - **It stores metadata, not artifacts.** A `server.json` lists `packages[]` that point at artifacts hosted elsewhere. The accepted package types are `npm`, `pypi`, `nuget`, `cargo`, `oci` and `mcpb` ([`pkg/model/constants.go`](https://github.com/modelcontextprotocol/registry/blob/main/pkg/model/constants.go)). There is no Maven type, so the JAR cannot be listed; the JVM container images are what get listed. - **OCI images must be on an allowed host and carry an ownership label.** Allowed hosts are `docker.io`, `ghcr.io`, `quay.io`, `*.pkg.dev` and `*.azurecr.io` ([package types](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/package-types.mdx)). At publish time the registry pulls each image's manifest anonymously and requires the label `io.modelcontextprotocol.server.name` to equal the server `name`. The Jib JVM image already sets this label (`build.gradle.kts`). The native images do not, so they stay out of `server.json`. - **OCI packages take the tag in `identifier`, not in `version`.** The registry rejects a package `version` with *"OCI packages must not have 'version' field - include version in 'identifier' instead"* ([`internal/validators/registries/oci.go`](https://github.com/modelcontextprotocol/registry/blob/main/internal/validators/registries/oci.go)). - **The namespace comes from GitHub OIDC.** `mcp-publisher login github-oidc` in a workflow grants `io.github.<repository_owner>/*`, so a run in `apache/solr-mcp` can publish `io.github.apache/solr-mcp` with no stored secret. An interactive `mcp-publisher login github` would need an Owner of the `apache` GitHub org, so publishing is CI-only in practice. - **A published version can't be edited.** Only its `status` can change afterwards (`mcp-publisher status`). A wrong 1.0.0 entry can be deprecated, not fixed. - **`mcp-publisher validate` does not check what `publish` checks.** `validate` checks the schema only. The package checks (allowed host, ownership label, the OCI `version` rule) run only in the publish path (`validateRegistryOwnership`). The current `server.json` on `main` reports *"✅ server.json is valid"* under `validate` while carrying three defects that `publish` rejects. - **Downstream catalogs read from it.** JFrog AI Catalog's public listings, the GitHub MCP Registry (planned) and aggregators such as PulseMCP read from the official registry. The Docker MCP Catalog does not; it needs its own PR to `docker/mcp-registry` (#251). ## What is wrong on `main` `server.json`: 1. `registryType: "docker"`: the type is `oci`. 2. Each package has a `version`, which is not allowed for OCI. 3. `identifier` is `ghcr.io/apache/solr-mcp-server`, an image the workflow never pushes. It pushes `apache/solr-mcp` (Docker Hub) and `ghcr.io/apache/solr-mcp`. 4. `$schema` is `2025-10-17`; the current schema is `2025-12-11`. 5. The `streamable-http` package lists only `PROFILES`. HTTP mode is secured by default and also needs `OAUTH2_ISSUER_URI`, and a client launching the container would have to publish a port. HTTP is for a remote deployment, not for a client-launched package. `release-publish.yml`: 6. Every job checks out `v<version>-<rc>` (e.g. `v1.0.0-rc1`). The release process creates `releases/solr-mcp/1.0.0-rc1`, so `validate-release` fails and nothing publishes. 7. The `jq` step adds `.packages[].version`, which reintroduces defect 2 on every release. 8. Docker Hub credentials are read from `DOCKERHUB_APACHE_USERNAME` / `DOCKERHUB_APACHE_TOKEN`. Infra provisions `DOCKERHUB_USER` / `DOCKERHUB_TOKEN` (#251). 9. Nothing checks that the images are anonymously pullable before publishing. On the first release the new GHCR package is private, and the failure surfaces as a registry error instead of a clear message. 10. The verification step queries `/v0/servers?search=` and never fails, so a missing entry still reports success. ## Design ### `server.json` Two stdio packages, one per JVM image host. The workflow writes the release tag into each `identifier`: ```json { "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", "name": "io.github.apache/solr-mcp", "title": "Apache Solr", "description": "MCP server for Apache Solr providing search, indexing, schema and collection management", "repository": { "url": "https://github.com/apache/solr-mcp", "source": "github" }, "version": "1.0.0-SNAPSHOT", "packages": [ { "registryType": "oci", "identifier": "docker.io/apache/solr-mcp:1.0.0-SNAPSHOT", "transport": { "type": "stdio" }, "environmentVariables": [ "SOLR_URL" ] }, { "registryType": "oci", "identifier": "ghcr.io/apache/solr-mcp:1.0.0-SNAPSHOT", "transport": { "type": "stdio" }, "environmentVariables": [ "SOLR_URL" ] } ] } ``` (`environmentVariables` abbreviated; each is the existing `SOLR_URL` entry.) ### `publish-mcp-registry` job 1. Check out the voted candidate tag `releases/solr-mcp/<version>-<rc>`. 2. Rewrite `.version` and the tag in every `packages[].identifier` to `<version>`; fail if any package has a `version` field or `SNAPSHOT` survives. 3. Check that every `identifier` resolves anonymously (`docker manifest inspect`, no login), with an error that names the GHCR visibility step from #251. 4. Install `mcp-publisher` at a pinned version, verified against the release's checksum file (v1.8.1). 5. `mcp-publisher validate`, then `login github-oidc`, then `publish`. 6. Verify with `GET /v0.1/servers/io.github.apache%2Fsolr-mcp/versions/<version>`, retrying, and fail if it never appears. The other jobs check out the same `releases/solr-mcp/<version>-<rc>` tag, and Docker Hub uses `DOCKERHUB_USER` / `DOCKERHUB_TOKEN`. ## Where this sits in the ATR release ATR stages, votes on and publishes the source archive and JARs. It does not push container images or registry entries: its finish phase leaves third-party distribution to the release manager and only records it ([finish phase](https://releases.apache.org/docs/finish-phase)). So the order is: ``` ATR vote passes ──► release is in ATR's finish phase │ ├─► ATR Publish: artifacts to downloads.apache.org/solr/mcp/<v>/ │ ├─► RM runs release-publish.yml on releases/solr-mcp/<v>-<rc> │ images → Docker Hub + GHCR → MCP Registry entry │ ├─► RM records the Docker Hub distribution on ATR's finish page │ └─► ATR Announce (gated on recorded distributions, if a tagging spec is set) ``` What the ATR process needs for this to work: - **Run `release-publish.yml` after the vote passes and before announcing.** Announcing is ATR's last step, and the optional ATR gate below needs the Docker Hub distribution recorded before it. - **Record the Docker Hub distribution on ATR by hand.** Use the finish page → *Verify a third-party distribution*, platform Docker Hub, namespace `apache`, package `solr-mcp`, version `<v>`, or `POST /api/distribution/record` with a PAT-exchanged JWT. Recording from the workflow with `apache/tooling-actions/record-atr-distribution` is **not** available to Solr today: ATR accepts that OIDC call only from a committee with an Automated Release Signing key ("CI builds: Enabled"), which requires Security-team approval of reproducible builds (`_trusted_project` in ATR's `db/interaction.py`; [Trusted Publishing](https://releases.apache.org/docs/trusted-publishing)). - **Optionally gate the announcement.** Setting a `dockerhub` tag in the project's tagging spec makes ATR refuse to announce until a Docker Hub distribution is recorded. ATR is redesigning tags ([tooling-trusted-releases#1702](https://github.com/apache/tooling-trusted-releases/issues/1702)), so this is optional for 1.0.0. - **Limits in ATR itself today.** ATR can record `MAVEN`, `PYPI`, `NPM`, `NPM_SCOPED`, `DOCKER_HUB` and `ARTIFACT_HUB` only. It has no GHCR/OCI and no MCP Registry platform, and its Docker Hub check confirms the tag exists without comparing digests. The GHCR image and the registry entry therefore can't be recorded on ATR yet; that is an upstream ATR change, under its third-party distribution track ([tooling-trusted-releases#1336](https://github.com/apache/tooling-trusted-releases/issues/1336)). ## Acceptance criteria - [ ] `server.json` publishes cleanly with `mcp-publisher` v1.8.1 once the images exist (the publish-time checks above all pass). - [ ] `release-publish.yml` checks out `releases/solr-mcp/<version>-<rc>` in every job. - [ ] The registry job rewrites identifier tags, fails on a non-public image with a clear message, and fails if the published version can't be read back. - [ ] Docker Hub credentials use `DOCKERHUB_USER` / `DOCKERHUB_TOKEN`. - [ ] `dev-docs` describes the registry publish and its place in the ATR release, and the stale `server.json` examples in `DEPLOYMENT.md` / `DOCKER_PUBLISHING.md` point to it. Related: #251 (PMC/Infra prerequisites), [`dev-docs/release-process.md`](https://github.com/apache/solr-mcp/blob/main/dev-docs/release-process.md). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
