Ban 'latest' as a reserved version string (#413)

## Summary
- Adds validation to prevent servers from being published with version
string "latest"
- "latest" is now a reserved keyword that cannot be used as a version
string

## Implementation
- Added `ErrReservedVersionString` error constant
- Created `validateVersion` function to check for reserved version
strings
- Integrated validation into the package field validation flow
- Added comprehensive test coverage

---

This is so we can potentially support things like
https://github.com/modelcontextprotocol/registry/discussions/333 in
future more easily, as I imagine we might want to.
This commit is contained in:
adam jones 2025-09-10 10:52:08 -07:00 • committed by GitHub
commit 41aacc1846
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 5 deletions

View file

@ -10,6 +10,7 @@ var (
// Package validation errors // Package validation errors
ErrPackageNameHasSpaces = errors.New("package name cannot contain spaces") ErrPackageNameHasSpaces = errors.New("package name cannot contain spaces")
ErrReservedVersionString = errors.New("version string 'latest' is reserved and cannot be used")
// Remote validation errors // Remote validation errors
ErrInvalidRemoteURL = errors.New("invalid remote URL") ErrInvalidRemoteURL = errors.New("invalid remote URL")

View file

@ -72,6 +72,11 @@ func validatePackageField(obj *model.Package) error {
return ErrPackageNameHasSpaces return ErrPackageNameHasSpaces
} }
// Validate version string
if err := validateVersion(obj.Version); err != nil {
return err
}
// Validate runtime arguments // Validate runtime arguments
for _, arg := range obj.RuntimeArguments { for _, arg := range obj.RuntimeArguments {
if err := validateArgument(&arg); err != nil { if err := validateArgument(&arg); err != nil {
@ -95,6 +100,16 @@ func validatePackageField(obj *model.Package) error {
return nil return nil
} }
// validateVersion validates the version string
// NB: we decided that we would not enforce strict semver for version strings
func validateVersion(version string) error {
if version == "latest" {
return ErrReservedVersionString
}
return nil
}
// validateArgument validates argument details // validateArgument validates argument details
func validateArgument(obj *model.Argument) error { func validateArgument(obj *model.Argument) error {
if obj.Type == model.ArgumentTypeNamed { if obj.Type == model.ArgumentTypeNamed {

View file

@ -193,6 +193,30 @@ func TestValidate(t *testing.T) {
}, },
expectedError: validators.ErrPackageNameHasSpaces.Error(), expectedError: validators.ErrPackageNameHasSpaces.Error(),
}, },
{
name: "package with reserved version 'latest'",
serverDetail: apiv0.ServerJSON{
Name: "com.example/test-server",
Description: "A test server",
Repository: model.Repository{
URL: "https://github.com/owner/repo",
Source: "github",
},
Version: "1.0.0",
Packages: []model.Package{
{
Identifier: "test-package",
RegistryType: "npm",
RegistryBaseURL: "https://registry.npmjs.org",
Version: "latest",
Transport: model.Transport{
Type: "stdio",
},
},
},
},
expectedError: validators.ErrReservedVersionString.Error(),
},
{ {
name: "multiple packages with one invalid", name: "multiple packages with one invalid",
serverDetail: apiv0.ServerJSON{ serverDetail: apiv0.ServerJSON{