feat(validators): Validate that Server versions are not ranges (#435)

<!-- Provide a brief summary of your changes -->

Validates that server versions are not ranges.


**NB:** This also introduces `validateVersion` as a check on the
top-level `ValidateServerJSON`, as previously we were only checking
version ranges of packages via `validatePackageField` (i.e. `latest`
would have still been a valid top level server version), despite #413's
wording suggesting otherwise.

## Motivation and Context
Solves https://github.com/modelcontextprotocol/registry/issues/415

## How Has This Been Tested?

Tests added in `internal/validators/validators_test.go`

`make check` is clean.

## Breaking Changes
As per @domdomegg's comment, we should
> check nobody has done this in the existing registry data (if they
have, we should explore and understand why people have done this / if
it's valid etc.).

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [x] New and existing tests pass locally
- [x] I have added appropriate error handling
- [x] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
This commit is contained in:
Frenchie 2025-09-12 10:14:59 +10:00 • committed by GitHub
commit 78c482b8d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 265 additions and 26 deletions

View file

@ -98,8 +98,22 @@ Registry clients SHOULD:
```javascript
"v1.0" // Version with prefix
"2021.03.15" // Date-based versioning
"snapshot" // Development snapshots
"latest" // Custom versioning scheme
```
### Not Allowed: Version Ranges
The registry requires specific versions for both the top-level `version` and any `packages[].version`. Version ranges or wildcard versions are rejected during publish, including but not limited to:
```javascript
"^1.2.3"
"~1.2.3"
">=1.2.3"
"<=1.2.3"
">1.2.3"
"<1.2.3"
"1.x"
"1.2.*"
"1 - 2"
"1.2 || 1.3"
```
### Alignment Examples

View file

@ -80,7 +80,7 @@ The registry accepts any version string up to 255 characters, but we recommend:
- **SHOULD align with package versions** to reduce confusion
- **MAY use prerelease labels** (e.g., "1.0.0-1") for registry-specific versions
The registry attempts to parse versions as semantic versions for proper ordering. Non-semantic versions are allowed but will be ordered by publication timestamp. See the [versioning guide](../explanations/versioning.md) for detailed guidance.
The registry attempts to parse versions as semantic versions for proper ordering. Non-semantic versions are allowed but will be ordered by publication timestamp. Version ranges (e.g., `^1.2.3`, `~1.2.3`, `>=1.2.3`, `1.x`, `1.*`) are rejected; publish a specific version instead. See the [versioning guide](../explanations/versioning.md) for detailed guidance.
### Can I add custom metadata when publishing?

View file

@ -72,7 +72,7 @@
"type": "string",
"maxLength": 255,
"example": "1.0.2",
"description": "Version string for this server. SHOULD follow semantic versioning (e.g., '1.0.2', '2.1.0-alpha'). Equivalent of Implementation.version in MCP specification. Non-semantic versions are allowed but may not sort predictably."
"description": "Version string for this server. SHOULD follow semantic versioning (e.g., '1.0.2', '2.1.0-alpha'). Equivalent of Implementation.version in MCP specification. Non-semantic versions are allowed but may not sort predictably. Version ranges are rejected (e.g., '^1.2.3', '~1.2.3', '>=1.2.3', '1.x', '1.*')."
},
"website_url": {
"type": "string",
@ -105,7 +105,8 @@
"type": "string",
"description": "Package version",
"example": "1.0.2",
"minLength": 1
"minLength": 1,
"remarks": "Must be a specific version. Version ranges are rejected (e.g., '^1.2.3', '~1.2.3', '>=1.2.3', '1.x', '1.*')."
},
"file_sha256": {
"type": "string",