feat(validation): probe repository URL reachability at publish (#395)#1266
Open
rhinocap wants to merge 1 commit intomodelcontextprotocol:mainfrom
Open
feat(validation): probe repository URL reachability at publish (#395)#1266rhinocap wants to merge 1 commit intomodelcontextprotocol:mainfrom
rhinocap wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
…contextprotocol#395) Issue modelcontextprotocol#395 surfaced a published server (com.pga/pga-golf) whose repository.url was a 404 — the registry had accepted it because semantic validation only verifies URL shape, not reachability. Add a publish-time HTTP HEAD probe that follows up to 5 redirects and rejects 4xx/5xx responses with the URL and status code in the error message. Reuses the prior-art HEAD-probe pattern from internal/validators/registries/mcpb.go. The probe is gated behind a new MCP_REGISTRY_ENABLE_REPOSITORY_REACHABILITY_CHECK config flag (default true; set to false for offline dev), kept independent of MCP_REGISTRY_ENABLE_REGISTRY_VALIDATION so operators can disable just this check. Tests cover 200, 301→200, 404, 410, 5xx, timeout, redirect-chain limit, malformed URL, and unreachable host using net/http/httptest.
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.
Closes #395.
The PGA-golf submission (
com.pga/pga-golf→https://github.com/pgahq/mcp-pga-com) is currently live on the production registry with a repository URL that 404s, because semantic validation only checks URL shape, not whether the repo actually resolves. This PR adds a publish-time HTTP HEAD probe that catches that class of bug.Summary
ProbeRepositoryReachable(ctx, repoURL)ininternal/validators/repository_reachability.goissues aHEADwith a 10s timeout, follows up to 5 redirects, and rejects 4xx/5xx with a clear error including the URL + status code. Mirrors the existing prior-art HEAD probe ininternal/validators/registries/mcpb.go.ValidatePublishRequestso it runs before package-registry ownership checks. No-ops whenrepositoryis unset (preserves the field's optionality) or when the new flag is off.MCP_REGISTRY_ENABLE_REPOSITORY_REACHABILITY_CHECKconfig flag (defaulttrue). Kept independent ofMCP_REGISTRY_ENABLE_REGISTRY_VALIDATIONso operators can flip just this check without disabling npm/PyPI/OCI ownership validation. Threaded throughdocker-compose.yml,tests/integration/docker-compose.integration-test.yml, and the README's offline-dev quick-start.net/http/httptest) cover: 200, 301→200 follow, 404, 410, 5xx (500/502/503), client-side timeout, redirect-chain cap, malformed URL, and unreachable host.Community alignment (re: 8 comments on #395)
This PR implements the minimum check the maintainers converged on, not the larger ownership-binding follow-on:
nameto theserver.jsonatrepository.url(with optionalsubfolder), to disambiguate canonical-vs-platform-republished entries.pgahq/mcp-pga-comis a private repo — agreed offline with @tadasant to omitrepository.urlfor private repos. This PR's behavior matches: private/404 repos must drop the field.repository.urlfor private repos. Documentation of that convention is intentionally not in this PR — happy to follow up in a docs-only patch, or defer to @Avish34 if she's already drafting the larger ownership-binding work.The ownership-binding (matching
nameagainst the repo's hostedserver.json) is a meaningful design effort with subfolder-search semantics still being debated in-thread; this PR does not block it. It just stops the simplest 404 case that surfaced #395 in the first place.Notes for reviewers
net/httpHEAD only.Test plan
go test ./internal/validators/...— all probe tests pass (200, 301→200, 404, 410, 500/502/503, timeout, redirect-chain cap, malformed URL, unreachable host).go vet ./...clean.golangci-lint runclean against new files (internal/validators/repository_reachability*.go,internal/config/config.go,internal/validators/validators.go).