Skip to content

feat(validators): expose config-free validators as an importable pkg/validators library#1451

Open
itguruhaseeb wants to merge 1 commit into
modelcontextprotocol:mainfrom
itguruhaseeb:feat/validators-importable-library
Open

feat(validators): expose config-free validators as an importable pkg/validators library#1451
itguruhaseeb wants to merge 1 commit into
modelcontextprotocol:mainfrom
itguruhaseeb:feat/validators-importable-library

Conversation

@itguruhaseeb

Copy link
Copy Markdown

Addresses #1394 (phase 1).

What this does

Adds a thin pkg/validators facade over the existing internal/validators package so the config-free validation logic can be imported and used as a library, without running a full registry. This covers the two common cases from the issue:

  • ValidateServerJSON(serverJSON, opts) for schema/semantic validation of a server.json, plus the Validation* option presets and the ValidationResult/ValidationIssue types.
  • ValidatePackage(ctx, pkg, serverName), the per-registry ownership dispatcher (npm / PyPI / NuGet / OCI / MCPB / Cargo) that already lives in internal/validators/package.go.

This lets tools such as a private sub-registry, or a preflight check that runs in CI before a release tag is cut, validate locally instead of calling a deployed /validate endpoint.

The re-exported sentinel errors (e.g. ErrVersionLooksLikeRange) are aliases of the internal values, so consumers can use errors.Is rather than matching on error strings.

Scope (phase 1 only)

Per the issue and the discussion, this intentionally exposes only the config-free surface. It uses a thin re-export facade to keep the diff small and leave all internal call sites compiling unchanged:

  • pkg/validators/validators.go: the facade (doc-commented package + re-exports).
  • pkg/validators/validators_test.go: a test that imports pkg/validators and validates a known-good and a known-bad server.json through the public API.

No existing files are modified.

Deferred to follow-up phases (noted for reviewers, not done here):

  • ValidatePublishRequest / ValidateUpdateRequest take a *config.Config and gate on EnableRegistryValidation, so they need a config-decoupling design before they can live in pkg/.
  • The authentication checks are currently embedded in the API auth handlers (e.g. github_oidc.go) and would be a broader refactor, as the issue notes.

On typed outcomes

@sronix raised a good point in the thread about library consumers wanting typed outcomes (package missing vs ownership mismatch vs transient upstream error) rather than matching on error strings. This PR takes a first step by re-exporting the sentinel errors for errors.Is, but the per-registry validators still largely return formatted strings. Happy to iterate on a richer typed-error surface in this PR or a follow-up if maintainers prefer that direction. I didn't want to expand the blast radius here.

Verification

Run with Go 1.26 on darwin/arm64:

  • go build ./...: passes
  • go vet ./...: clean
  • gofmt -l pkg/validators/: no diffs
  • go test ./pkg/validators/... ./internal/validators/...: passes

The DB-backed test packages (internal/database, internal/service, etc.) were not run in my environment because they require a local PostgreSQL/Docker; this change doesn't touch them.

Happy to adjust naming, scope, or the exported surface to match maintainer preferences.

…rary

Add a thin pkg/validators facade over the internal validators so external
tools can validate a server.json locally without running a full registry.

This is phase 1 of modelcontextprotocol#1394: it re-exports only the config-free surface
(ValidateServerJSON, the ValidatePackage registries dispatcher, the
Validation* result/option types and presets, and the sentinel errors),
leaving the config-dependent ValidatePublishRequest/ValidateUpdateRequest
and the auth-handler checks in internal/ for follow-up phases. Internal
call sites are unaffected. Includes a test covering the public API.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant