fix(api): normalize server $schema to current version on read - #1515
Open
ousamabenyounes wants to merge 1 commit into
Open
fix(api): normalize server $schema to current version on read#1515ousamabenyounes wants to merge 1 commit into
ousamabenyounes wants to merge 1 commit into
Conversation
Registry records are stored as JSONB of the current apiv0.ServerJSON struct and re-serialized into that shape on every read, but the $schema string is carried verbatim from publish time. Entries published under an older schema therefore advertise a stale $schema even though their payload conforms to the current schema (all schema revisions since have been additive/relaxing — no field made newly required). Strict clients such as VSCode fetch the advertised schema and fail validation, so ~7% of live entries break consumers. Normalize $schema to model.CurrentSchemaURL across all read paths (ListServers, GetServerByName, GetServerByNameAndVersion, GetAllVersionsByServerName) so served entries advertise the schema they actually conform to. Fixes modelcontextprotocol#783
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.
Summary
Registry entries published under an older
server.jsonschema are served on the read API with their publish-time$schemavalue, even though the payload itself is re-serialized into the current schema shape. Strict clients (e.g. VS Code'schat.mcp.gallery.serviceUrl) fetch the advertised schema and fail to validate the response, so a non-trivial share of the catalog is unusable to them. A consumer syncing the full/v0/serversfeed measured ~7% of a fresh 100-entry sample advertising a pre-current$schema(four distinct versions served simultaneously).Fixes #783
Root cause
Server records are stored as JSONB of the
apiv0.ServerJSONstruct and, on read, arejson.Unmarshaled back into that current struct shape (internal/database/postgres.go). Every field is therefore normalized to the current format on read — except the$schemastring, which is carried verbatim from publish time. The read path never rewrites it, so old entries keep advertising a schema URL that no longer matches what is actually served.New publishes are already forced to the current schema (publish-time validation rejects non-current schemas), so this only affects entries published while an older schema was current.
Fix
Normalize
$schematomodel.CurrentSchemaURLon every service-layer read path —ListServers,GetServerByName,GetServerByNameAndVersion,GetAllVersionsByServerName(internal/service/registry_service.go). All client-facing reads funnel through these methods.Why this is safe: the served payload is already the current struct shape, and the schema changelog (
docs/reference/server-json/CHANGELOG.md) shows every revision since has been additive or relaxing — no field was ever made newly required. So an entry published under an older schema still conforms to the current one; only its advertised$schemastring was stale. The write path is untouched (edit/statusread-then-write flows re-read through the un-normalized DB layer before persisting, so nothing new is written).Test verification (RED → GREEN)
Added
TestReadNormalizesLegacySchemaVersion, which seeds a server with a legacy$schema(2025-09-16) directly through the database layer (bypassing publish-time validation) and asserts every read path returnsmodel.CurrentSchemaURL.RED — new test against the unmodified base (fix reverted, test present):
GREEN — same test with the fix applied:
Full local run of
golangci-lint,go vet,go build, schema-sync check, and the race-enabled unit suite (./internal/... ./cmd/...) passes with no regressions.