Skip to content

MCPPackage.RegistryBaseURL is a smell — user-settable but validated to a single value #455

@josh-pritchard

Description

@josh-pritchard

Problem

MCPPackage.RegistryBaseURL is exposed as a user-settable field in the v1alpha1 API, but the validators for NPM, NuGet, and PyPI all follow the same pattern:

  1. If the user leaves it empty, default it to the canonical registry URL
  2. If the user sets it to anything other than the canonical URL, reject the request

Example — pkg/api/v1alpha1/registries/npm.go:

```go
// Set default registry base URL if empty
if pkg.RegistryBaseURL == "" {
pkg.RegistryBaseURL = v1alpha1.RegistryURLNPM
}
// ...
// Validate that the registry base URL matches NPM exactly
if pkg.RegistryBaseURL != v1alpha1.RegistryURLNPM {
return fmt.Errorf("registry type and base URL do not match: '%s' is not valid for registry type '%s'. Expected: %s",
pkg.RegistryBaseURL, v1alpha1.RegistryTypeNPM, v1alpha1.RegistryURLNPM)
}
```

Same pattern in nuget.go:23,37 and pypi.go:30,48. Meanwhile oci.go and mcpb.go reject the field entirely.

So RegistryBaseURL is either:

  • Empty (default applied internally)
  • Set to exactly the canonical URL (pointless echo of the default)

Any other value is rejected. There is no override behavior.

Why it's a smell

A field on a user-facing API implies the user has a meaningful choice. RegistryBaseURL does not:

  • If you want it to be an override (alternate NPM mirror, enterprise PyPI proxy, etc.) — then validation should accept alternate URLs, not reject them
  • If you want it to be a discriminator — it's redundant with RegistryType, which already tells us we're dealing with NPM/NuGet/PyPI
  • If you want it internal-only — remove it from the user-facing spec and set it in the validator

Either way, the current shape is wrong. It looks configurable, documents itself as configurable (json:\"registryBaseUrl,omitempty\"), but the validator forces it to a single value.

Proposed fix

Pick one of:

  1. Remove from user API — the validator already knows the canonical URL per RegistryType. Move RegistryBaseURL out of the public spec and set it internally.
  2. Make it a real override — remove the exact-match check and allow alternate URLs per registry type (with appropriate scheme/host validation). Useful for private registries and enterprise mirrors.

Option 1 is simpler. Option 2 enables enterprise use cases (pull-through proxies, private mirrors) but requires thinking through how to validate "this is a reasonable alternate URL for this registry type."

Surfaced while reviewing PR #449.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions