Authored by Claude Code Opus 4.5, steered/reviewed by me.
## Summary
- Updated the URL regex pattern in `StreamableHttpTransport` and
`SseTransport` to allow template variables like `{baseUrl}` as an
alternative to requiring the `https://` prefix
- This enables more flexible URL configuration in the `remotes` section
of server.json
## Changes
- Modified the `url` field pattern from `^https?://[^\s]+$` to
`^(https?://[^\s]+|\{[a-zA-Z_][a-zA-Z0-9_]*\}[^\s]*)$`
- Updated both `openapi.yaml` and the derived `server.schema.json`
- Added clarifying documentation that URL must start with `http://`,
`https://`, or a template variable
## Regex breakdown
```
^(https?://[^\s]+|\{[a-zA-Z_][a-zA-Z0-9_]*\}[^\s]*)$
```
| Part | Meaning |
|------|---------|
| `^` | Start of string |
| `(` | Begin alternation group |
| `https?://[^\s]+` | `http://` or `https://` followed by non-whitespace
|
| `\|` | OR |
| `\{[a-zA-Z_][a-zA-Z0-9_]*\}` | Template variable: `{` + valid
identifier + `}` |
| `[^\s]*` | Optional path/query after template variable |
| `)` | End alternation group |
| `$` | End of string |
## Test cases
**Should match ✓**
- `https://api.example.com/mcp`
- `http://localhost:8080/sse`
- `https://example.com/path?query=value`
- `{baseUrl}`
- `{baseUrl}/mcp`
- `{server_url}/api/v1`
- `{API_ENDPOINT}`
**Should NOT match ✗**
- `ftp://example.com` — wrong protocol
- `example.com` — missing protocol or variable
- `/relative/path` — relative paths not allowed
- `{invalid-name}/path` — hyphens not valid in variable names
- `{123invalid}` — variables can't start with numbers
---------
Co-authored-by: Agent Orchestrator <agent@ao.pulsemcp.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
## Motivation and Context
Per discussion with @rdimitrov - all validation now happens in a new
`/validate` endpoint. For details, see below.
## Breaking Changes
None. Validation on /publish only validates schema version and semantic
checks (manual checks) as before. We can add schema validation by
changing a flag in the called to `ValidateJSONSchema` when we're ready.
## Types of changes
- [X] New feature (non-breaking change which adds functionality)
## Checklist
- [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
## API Changes
### 1. New `/validate` Endpoint
A new public endpoint was added for validating `server.json` files
without publishing them.
**Details:**
- **Paths:** `/v0/validate` and `/v0.1/validate`
- **Method:** `POST`
- **Authentication:** None required (public endpoint)
- **Request:** JSON body containing `ServerJSON`
- **Response:** `200 OK` with `ValidationResult` containing:
- `valid` (boolean)
- `issues` (array of validation issues with type, path, message,
severity, reference)
**Implementation:**
- New handler file: `internal/api/handlers/v0/validate.go`
- Performs comprehensive validation using `ValidationAll` option:
- Schema version validation
- Full schema validation
- Semantic validation
- Always returns `200 OK` - validity is indicated in `result.Valid`
field
- Registered in router for both `/v0` and `/v0.1` prefixes
### 2. `/publish` Endpoint Validation Flow Changes
The publish endpoint now validates earlier in the request flow and
provides clearer error responses.
**Before:** Validation was mixed into `ValidatePublishRequest()` (which
also handled publisher extensions and registry ownership).
**After:**
1. Validates `ServerJSON` structure first using `ValidateServerJSON()`
(schema version + semantic validation)
2. Returns `422 Unprocessable Entity` with message: "Failed to publish
server, invalid schema: call /validate for details"
3. Only proceeds to publisher extensions/registry validation if schema
validation passes
4. No longer calls `ValidatePublishRequest()` internally for schema
validation
**Key Changes:**
- Validation happens before `CreateServer()` call
- Returns `422` on schema/semantic validation failures
- Error message directs users to `/validate` endpoint for details
- `ValidatePublishRequest()` no longer performs schema validation (added
note in comments)
### 3. `/edit` Endpoint Validation Flow Changes
Similar validation changes were applied to the edit endpoint.
**Changes:**
- Added `ValidateServerJSON()` call before server update
- Returns `422` with same error message format on validation failure
- Matches the `/publish` endpoint behavior
### 4. Validator Functions Refactoring
Updated validator functions to reflect that schema validation is now
done separately.
**Changes to `ValidatePublishRequest()`:**
- Removed internal `ValidateServerJSON()` call
- Added note: "ValidateServerJSON should be called separately before
this function"
- Now only validates publisher extensions and registry ownership
**Changes to `ValidateUpdateRequest()`:**
- Same change (removed schema validation, added note)
- Now only validates registry ownership
## CLI Changes
### 1. `validate` Command: Now Uses API Endpoint
**Before:** Performed local validation using
`validators.ValidateServerJSON()`.
**After:** Calls the `/v0/validate` endpoint on the registry.
**Details:**
- Reads `server.json` and sends it to the registry API
- Displays validation results returned by the server
- Uses the same error formatting as before
- Registry URL comes from token file (or default)
- No authentication required (public endpoint)
**Implementation:**
- Added `validateViaAPI()` function that POSTs to `/v0/validate`
- Parses `ValidationResult` response from server
- Uses shared `printValidationIssues()` for formatting
### 2. `publish` Command: Validation Only on 422 Errors
**Before:** Performed upfront local schema validation before publishing.
**After:** Attempts publish first, then validates only if server returns
422.
**Details:**
- Attempts publish immediately (no upfront validation)
- If publish returns 422 (Unprocessable Entity):
- Calls `/v0/validate` endpoint to get detailed validation errors
- Formats and displays them using same logic as `validate` command
- Returns error with migration links
- For non-422 errors (401, 403, etc.), returns original error (no
validation call)
**Implementation Changes:**
- Removed upfront `runValidationAndPrintIssues()` call
- Modified `publishToRegistry()` to return HTTP status code alongside
response/error
- Added 422 detection logic that calls `validateViaAPI()`
### 3. Shared Validation Error Formatting
**Before:** `runValidationAndPrintIssues()` function handled both
validation and printing together.
**After:** Refactored to separate printing logic.
**Details:**
- Created `printValidationIssues()` function - just prints validation
issues (no validation logic)
- Removed `runValidationAndPrintIssues()` function (no longer used)
- Both `validate` and `publish` commands use `printValidationIssues()`
for consistent output
**Behavior:**
- Prints schema validation errors with migration guidance
- Prints all other validation issues with formatting
- Returns formatted error message string for schema issues
## Summary
Both CLI commands now use the `/validate` API endpoint for validation
instead of local validation. The `publish` command validates only after
receiving a 422 error response, and both commands share the same error
formatting via `printValidationIssues()`.
### Benefits
- **Centralized validation logic** - All validation happens on the
server
- **Always up-to-date** - CLI always uses current server validation
rules
- **Consistent experience** - Same validation behavior whether using CLI
or API directly
- **Better separation of concerns** - Schema validation separated from
publisher-specific validation
Added schema validation and support for exhaustive and more detailed
validation to existing validators. Added new `mcp-publisher validate`
command. No change to any existing tests or behavior other than the new
command.
## Motivation and Context
Many currently published servers fail schema validation. Of those that
pass, many have semantic/logical errors or other errors that make them
impossible to configure, or their configuration when applied doesn't
generate correct MCP server configuration (per their own documentation).
To address this, we need better tooling to validate servers and to
inform server publishers of errors, issues, and best practices in a way
that is clear and actionable, both during server development and at time
of publishing.
I have started a discussion about the broader topic:
https://github.com/modelcontextprotocol/registry/discussions/635
There is also a fairly detailed document describing the design,
architecture, implementation, future plans, etc. See [Enhanced
Validation Design](docs/explanations/proposed-enhanced-validation.md)
This PR is the first step in the process of improving validation. It
adds schema validation and updates all existing validators to use a new
model that allows them to track context and return rich and exhaustive
results. This has been done in a way that is backward compatible
(ValidateServerJSON is unchanged as are all existing validation unit
tests).
There is a new `mcp-publisher` command called `validate` that is
currenty the only place that schema validation and enhanced
(exhaustive/rich) validation results are exposed.
### Changes
Internal Validation improvements
- Schema validation has been implemented and is available as an option
in validation methods (defaults to off)
- Existing validators track the JSON path (context) of the attribute
they're evaluating, passing it to any child validators
- Existing validators are exhaustive (return all issues, not failing
fast on the first error)
- Existing validators return rich validation results, including:
- type (schema, semantic, linter)
- severity (error, warn, info)
- path (JSON path to server.json element)
- reference (to the schema element or rule that triggered the result)
- message (currently the same as previous error message)
A new `validate` command has been added to `mcp-publisher` so publishers
can evaluate their server.json before publishing
- Includes new schema validation and previous semantic validation
- Shows full details of all issues encountered during validation
### Usage
Given a server.json that looks like this:
```json
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
"name": "io.github.BobDickinson/registry",
"description": "An MCP server that provides [describe what your server does]",
"repository": {
"url": "",
"source": ""
},
"version": "=1.0.0",
"packages": [
{
"registryType": "oci",
"registryBaseUrl": "https://docker.io",
"identifier": "registry",
"version": "1.0.0",
"transport": {
"type": "sse"
},
"packageArguments": [
{
"type": "named",
"name": "--mode",
"description": "Operation mode",
"format": "foo"
}
],
"environmentVariables": [
{
"description": "Your API key for the service",
"isRequired": true,
"format": "string",
"isSecret": true,
"name": "YOUR_API_KEY"
}
]
}
]
}
```
Run the command:
`mcp-publisher validate server.json`
Which will produce the output:
```bash
❌ Validation failed with 5 issue(s):
1. [error] packages.0.packageArguments.0.format (schema)
value must be one of "string", "number", "boolean", "filepath"
Reference: #/definitions/Input/properties/format/enum from: [#/definitions/ServerDetail]/properties/packages/items/[#/definitions/Package]/properties/packageArguments/items/[#/definitions/Argument]/else/[#/definitions/NamedArgument]/allOf/0/[#/definitions/InputWithVariables]/allOf/0/[#/definitions/Input]/properties/format/enum
2. [error] packages.0.transport (schema)
missing required fields: 'url'
Reference: #/definitions/SseTransport/required from: [#/definitions/ServerDetail]/properties/packages/items/[#/definitions/Package]/properties/transport/else/else/[#/definitions/SseTransport]/required
3. [error] repository.url (schema)
'' has invalid format 'uri'
Reference: #/definitions/Repository/properties/url/format from: [#/definitions/ServerDetail]/properties/repository/[#/definitions/Repository]/properties/url/format
4. [error] version (semantic)
version must be a specific version, not a range: "=1.0.0"
Reference: version-looks-like-range
5. [error] packages[0].transport.url (semantic)
url is required for sse transport type
Reference: streamable-transport-url-required
Error: validation failed
```
Note in the results above:
- All errors contain the JSON path of the triggering element from
server.json.
- The first three errors are schema errors detected during schema
validation. The `Reference` provided contains an absolute path to the
schema rule that was violated, followed by the full schema path that
enforced that rule (with $ref redirect values substited and enclosed in
square brackets).
- The error messages provided by the existing semantic validators are
exactly the same as the previous error messages those validators
produced.
In the final solution we would remove semantic validators that are
redundant to schema validation (as in number 5 above). We have the
option to use the structured data produced by schema validation to
replace the generic schema validation message with a more descriptive
message if that is an issue (in particular, if the only argument for an
ad-hoc validator is that is produces a better/cleaner message, we would
just move that message creation code to the schema error result
formatter and special case it as opposed to having a redundant
validator).
### What's Next
If this general direction is supported and this PR is accepted, a fast
follow would include:
- Add new validators (infliuenced by observed issues) for both semantic
errors and best practices
- Require passing schema validation (in addition to improved semantic
validation) in order to publish
- Remove existing validation code that is redundant to schema validation
(ensuring error messages remain intelligible)
- Update validation client code and tests to handle the new rich return
types natively
### Issues
Schema validation requires embedding the `server.schema.json` file into
the validators package via `go:embed`, which is restricted from
embedding files outside of the package. For this reason we copy the
schema file into a schema subdir (via a prep target in the makefile) and
we .gitignore it. I tried cleaning up the copy in the make clean target,
but then the linter would complain about the embed target being missing
if it wasn't there during development. I also considered just checking
in the schema file and assuming a separate workflow for updating the
embedded schema file, but it's not clear what that workflow would be or
how it would be maintained. I'm open to a different approach, but the
schema file does need to be embedded somehow for schema validation to
work.
## How Has This Been Tested?
All existing validation tests pass, new tests implemented and all pass.
## Breaking Changes
No breaking changes, no behavior change except new `validate` command
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 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
---------
Co-authored-by: GitHub Action <action@github.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Follow up on #869
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
Change the UI default to the locally hosted registry.
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Was quite confusing at first :)
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] 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
- [ ] I have added or updated documentation as needed
Co-authored with Claude Code, but I've closely reviewed/modified/vetted
all changes; ready for final review.
## Summary
This PR adds LocalTransport and RemoteTransport separation with URL
template variable support for remote servers, enabling e.g. multi-tenant
deployments with configurable endpoints.
**Key additions:**
- LocalTransport (for Packages) and RemoteTransport (for Remotes)
- URL template variables for remote transports (e.g., `{tenant_id}` in
URLs)
- Pattern validation ensuring URLs are URL-like while allowing templates
- Full test coverage via Go validator tests and documentation examples
## ⚠️ server.json Update
This PR updates the `server.json` schema. A new schema version will be
cut after this lands.
## Problem
The current schema describes URL templating with `{curly_braces}` for
transports but provides no mechanism for Remote contexts to define what
those variables should resolve to, making the feature unusable for
remote servers.
Referenced issue: #394
- Users need multi-tenant remote servers with different endpoints per
deployment
- Each tenant/region has its own URL (e.g., `us-cell1.example.com`,
`emea-cell1.example.com`)
- Current schema doesn't support parameterized remote URLs
## Solution
### Schema Architecture
**LocalTransport** (for Package context):
```typescript
LocalTransport = StdioTransport | StreamableHttpTransport | SseTransport
```
- Used in Package context (non-breaking rename of existing behavior)
- Variables in `{curly_braces}` reference parent Package
arguments/environment variables
- Supports all three transport types including stdio
**RemoteTransport** (for Remote context):
```typescript
RemoteTransport = (StreamableHttpTransport | SseTransport) + { variables: object }
```
- Extends StreamableHttp/Sse via `allOf` composition - no duplication!
- Adds `variables` object for URL templating
- Only supports streamable-http and sse (stdio not valid for remotes)
### Key Changes
**1. Schema Updates** (`openapi.yaml`, `server.schema.json`):
- Added `LocalTransport` union type for Package context
- Added `RemoteTransport` with `allOf` composition extending base
transports
- Updated Package to reference `LocalTransport`
- Updated remotes to reference `RemoteTransport`
- Added URL pattern validation: `^https?://[^\\s]+$` to both
StreamableHttp and SSE
- Removed `format: uri` from SSE (was blocking template variables)
**2. Go Types** (`pkg/model/types.go`):
- Base `Transport` struct unchanged for Package context
- `RemoteTransport` struct for remotes with `Variables` field
- Both work with existing validation infrastructure
**3. Validators** (`internal/validators/`):
- `validateRemoteTransport()` validates Remote-specific constraints
- `collectRemoteTransportVariables()` extracts available variables
- `IsValidTemplatedURL()` validates template variables reference defined
variables
- `IsValidRemoteURL()` handles template variable substitution before
localhost check
- 6 new test cases for remote transport variable validation
**4. Documentation Examples** (`generic-server-json.md`):
- Remote Server with URL Templating (StreamableHttp with `{tenant_id}`)
- SSE Remote with URL Templating (SSE with `{tenant_id}`)
- Local Server with URL Templating (Package with `{port}`)
- All examples validate via existing `validate-examples` tool
## Example: Remote Transport with Variables
```json
{
"remotes": [
{
"type": "streamable-http",
"url": "https://api.example.com/mcp/{tenant_id}/{region}",
"variables": {
"tenant_id": {
"description": "Tenant identifier",
"isRequired": true,
"choices": ["us-cell1", "emea-cell1", "apac-cell1"]
},
"region": {
"description": "Deployment region",
"isRequired": true
}
}
}
]
}
```
Clients configure the variables, and `{tenant_id}` and `{region}` get
replaced to connect to tenant-specific endpoints like
`https://api.example.com/mcp/us-cell1/east`.
## Architecture Details
**Context-based variable resolution:**
- **Package + LocalTransport**: `{port}` references `--port` argument or
`PORT` env var from parent Package
- **Remote + RemoteTransport**: `{tenant_id}` references
`variables.tenant_id` defined in the transport itself
- **Code reuse**: StreamableHttp/Sse definitions shared via `allOf`, not
duplicated
- **Validation**: Template variables validated against available
variables for each context
---
## Follow-on Work
Follow-on work will be done to adopt the feedback in
https://github.com/modelcontextprotocol/registry/pull/570#issuecomment-3367417636
regarding variable naming/prioritzation/scoping conventions, but should
not have any impact on the shape being introduced here (just
validations).
---------
Co-authored-by: yuna0x0 <yuna@yuna0x0.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Connor Peet <connor@peet.io>
The DNS auth endpoint was vulnerable to resource exhaustion if an
attacker controlled a domain with a slow/non-responding authoritative
DNS server. Without a timeout, handler goroutines would block on DNS
resolution indefinitely, allowing an attacker to pile up goroutines
until OOM.
Production is protected by NGINX ingress's default 60s proxy timeout,
but this adds defense-in-depth with a tighter 5s bound.
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
This resolves
https://github.com/modelcontextprotocol/registry/issues/738. There are
two issues with the NuGet.org integration today:
1. Change the `registryBaseUrl` for NuGet to
`https://api.nuget.org/v3/index.json`. `https://api.nuget.org` is not
the entry point for our service and is not specific enough.
`https://api.nuget.org/v3/index.json` is the value that users put into
their tooling to connect to our public registry (it is installed by
default in .NET client tooling).
2. Use the service index API to get the URL pattern for package READMEs.
- This URL is not guaranteed to be stable. The service index URL
(`registryBaseUrl`) is, however.
Additionally, I polished up the error messages so various error modes
are clearer. When packages are published to NuGet.org, they take 2-5
minutes to become available due to validations we run.
Some possible states that are now handled and described more helpfully
are:
- Version exists, but the package has no README
- The ID exists, but the version does not
- The ID does not exist at all
There are only 3 authors (me, another MSFT person, and a community
member) explicitly setting the old value. The DB migration will fix the
issue. A future publish will fail with the validation error but the
error message is clear.
`registry type and base URL do not match: 'https://api.nuget.org' is not
valid for registry type 'nuget'. Expected:
https://api.nuget.org/v3/index.json`
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
- Unit tests, new and existing
- Manual test locally
- Set old data in the DB, `docker compose up`, confirm the migration
updates the specific package
## Breaking Changes
Yes, but minimal impact expected, unless there is a dependency on the
specific `https://api.nuget.org` value downstream. I am not aware of any
such dependency, and the new value is more proper and specific.
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [x] 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
-->
For more information about the NuGet API see:
https://learn.microsoft.com/en-us/nuget/api/overview#service-index (I
wrote most of the docs).
<!-- Provide a brief summary of your changes -->
## Motivation and Context
Microsoft uses `mcr.microsoft.com` to host our public containers. These
are syndicated to Docker Hub but image references use
`mcr.microsoft.com` which is not currently supported by the Official MCP
Registry.
See https://github.com/modelcontextprotocol/registry/issues/753.
Microsoft teams want to use MCR-based images for Microsoft MCP servers.
I believe we should be adding ACR support as well, so that our customers
using Azure Container Registry can use the MCP Registry as well.
In short, MCR is used for Microsoft managed containers. ACR is a
solution for Azure customers to host their own containers.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Unit tests.
Manual test: local push of a server.json with
`mcr.microsoft.com/azure-sdk/azure-mcp:2.0.0-beta.1` and
`azurearcjumpstart.azurecr.io/hello-arc:latest` in it. The error is now
about missing annotation not unsupported OCI registry.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
No.
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 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
-->
When users try to publish to a GitHub organization but don't have
permission, the error message now includes a helpful hint suggesting
they may need to make their organization membership public in GitHub
settings.
This addresses the issue where users couldn't understand why they were
unable to publish servers from organization repositories, even when they
were members of the organization.
Fixes#398
Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: adam jones <domdomegg@users.noreply.github.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Resolve https://github.com/modelcontextprotocol/registry/issues/768 and
https://github.com/modelcontextprotocol/registry/issues/494.
Require HTTPS for remote URLs. Currently all remote URLs on the MCP
Registry are HTTPS.
Also fix a test bug when running on Windows (bad temp path).
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Unit tests.
Published a server.json locally with a website URL not matching the
server name.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 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
- [ ] ~I have added or updated documentation as needed~ N/A
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
## Summary
Adds a clean, minimal web interface at `/` for browsing MCP servers in
the registry. Built as a single self-contained HTML file embedded in the
Go binary.
## Features
- Responsive grid layout (1/2/3 columns based on screen size)
- Search servers by name
- Filter to show only latest versions (default on)
- "Recently Updated" section for servers updated in the last hour
- Expandable cards with full server metadata and JSON viewer
- Debug modal to switch between production/staging/local/custom API
endpoints
- Full URL parameter support and browser history navigation
## Implementation
- Single HTML file (~400 lines) with Tailwind CSS via CDN
- Zero build dependencies
- Embedded using `//go:embed`
- Served directly from router at root path
- Uses stable v0.1 API endpoints
Fixes#99
---
AI disclosure: this is 99% vibed with Claude. It's intended as a v0 to
get something up and working, and then maybe at a later date we can
replace it with something more real.
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The Repository field in ServerJSON was not properly omitting empty
values
when marshaling to JSON. Even when a server had no repository
configured,
the JSON would include `"repository": {"url": "", "source": ""}` due to:
1. Repository struct fields (URL, Source) lacking omitempty tags
2. Repository being a value type instead of pointer in ServerJSON
This caused validation warnings for servers without repository URLs.
Changes:
- Add omitempty tags to Repository.URL and Repository.Source fields
- Change ServerJSON.Repository from model.Repository to
*model.Repository
- Update validateRepository to handle nil pointers
- Update all code creating Repository instances to use pointers
Now, servers without repository information correctly omit the field
entirely from JSON output, eliminating spurious validation warnings.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR:
* Deprecates the existing OCI reference parser
* Deprecates the existing OCI way of authenticating and accessing the
image manifest
* Replaces the above by leveraging go-containerregistry
* Introduces support for Google Artifact Registry
* Enables us to easily add support for other OCI-compliant registries in
the future
* Introduces better error handling
* Introduces custom context timeouts for validation
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Related to #427
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
Fixes#710
This PR adds CORS middleware to enable browser-based clients and web
applications to access the registry API.
## Changes
- Add CORSMiddleware in internal/api/cors.go to handle preflight OPTIONS
requests and inject CORS headers
- Integrate CORS middleware into the server middleware stack
- Add CORS configuration options (CORS_ENABLED and CORS_ALLOWED_ORIGIN)
## Testing
- All existing tests pass
- Manual testing confirms CORS headers are present in responses
- OPTIONS preflight requests now return 204 with proper headers
## Configuration
New environment variables:
- MCP_REGISTRY_CORS_ENABLED (default: true)
- MCP_REGISTRY_CORS_ALLOWED_ORIGIN (default: *)
## Motivation and Context
See
https://github.com/modelcontextprotocol/registry/issues/482#issuecomment-3436993157
for full details.
This adds ECDSA P-384 (a popular NIST approved curve) in addition to
Ed25519.
## How Has This Been Tested?
I have tested with a local deployment against `mcp.joelverhagen.com`.
Also, I have added significant tests.
## Breaking Changes
None. (hopefully)
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] 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
-->
@domdomegg and I spoke a bit about this on Discord:
https://discord.com/channels/1358869848138059966/1369487942862504016/1423710918180606052
---------
Co-authored-by: adam jones <domdomegg+git@gmail.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR:
* Makes mcpb package version property optional
* Bumps the schema and reflects that in the code
* Makes sure the publisher tests are being covered by doing `make check`
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
Enhanced Go struct tags throughout `pkg/api/v0/types.go` and
`pkg/model/types.go` to better align with the OpenAPI specification.
## Changes
- Added comprehensive `doc` tags with detailed field descriptions
matching OpenAPI
- Added `example` tags showing valid values for fields (e.g.,
`"io.github.user/weather"`, `"npx"`)
- Added `format` tags (`uri`, `date-time`) for better type specification
- Added `pattern` and `enum` tags for validation constraints
- Added `placeholder` field to `Input` struct matching OpenAPI spec
- Removed redundant comments in favor of inline struct tags
These changes improve code clarity and make the types more
self-documenting, while maintaining compatibility with the OpenAPI
schema definitions in `docs/reference/api/openapi.yaml`.
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR introduces a `/version` API that serves the build
details along with the version of the API server being served. The
`/version` endpoint allows users to programmatically query which exact
version of the registry is running in production for debugging.
~~auditing, and compatibility checks~~.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR fixes an issue we introduced on September, 30th that
caused some of the migrations to not apply. This PR fixes it. After
merging we'll have to reset staging as this would not work there (this
is expected).
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR addresses the feedback from #634 around:
* Use a proper library - https://github.com/distribution/reference,
instead of the implementing the OCI parsing ourselves (note: left the
tests so we can ensure we are not breaking any existing behavior)
* Updating one of the error messages to now assume MCPB.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Follow up from #658 addressing the feedback from @tadasant
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR adds a new v0.1 API version.
The goal is to mark v0.1 as a "freeze" point while keeping v0 as the
moving target for new features so integrators can start building on top
of something stable(r).
Details:
* This change is quite simple - we re-register the same handlers twice,
once as `v0` and once as `v0.1`
* Going forward, we'll keep v0.1 frozen while we add changes either on
top of both (non-breaking) or we'll have to branch if breaking changes
are necessary
* We all acknowledge this is not exactly best-practice, but it gives us
a way to gather feedback and allow clients to start integrating with the
API without breaking them (**note** this implies a follow up PR that
would branch the handlers used in v0.1).
* For integrators/clients: please provide your feedback - what works
well, what doesn't so we can take this into account going towards GA.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
No, this just adds a new API version alongside the existing one.
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Fixes: #649
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
Implements icon support based on the Model Context Protocol
specification, allowing servers to specify display icons with optional
size, MIME type, and theme variants.
## Changes
- Add `Icon` type to `pkg/model/types.go` with struct tags for automatic
API validation
- Add `icons` field to `ServerJSON` in `pkg/api/v0/types.go`
- Add icon validation in `internal/validators/validators.go`:
- Only HTTPS URLs allowed (no HTTP or data URIs)
- Maximum URL length of 255 characters
- Validates absolute URLs with proper scheme
- Update JSON schema and OpenAPI documentation with Icon definitions
- Add comprehensive test cases for icon validation
- Add example icon to seed.json (Airtable server)
- Change `websiteUrl` validation to HTTPS-only for consistency
## Implementation Details
The implementation uses a two-layer validation architecture:
1. **Huma framework** validates struct tags (`required`, `maxLength`,
`enum`, `pattern`) and returns 422 for violations
2. **Custom validators** handle business logic (HTTPS scheme
requirement, absolute URL requirement) and return 400 for violations
This approach leverages Huma's automatic validation while keeping
business-specific rules in the validator layer.
## Icon Field Specification
- `src` (required): HTTPS URL to icon resource, max 255 characters
- `mimeType` (optional): One of `image/png`, `image/jpeg`, `image/jpg`,
`image/svg+xml`, `image/webp`
- `sizes` (optional): Array of size strings in "WxH" format or "any" for
scalable formats
- `theme` (optional): Either "light" or "dark" to indicate intended
background
Multiple icons can be provided (e.g., for different themes or sizes).
Remove redundant endpoint as suggested in #617. Clients should now use
`GET /v0/servers/{serverName}/versions/latest` instead (using `latest`
as a special version value in the existing endpoint).
This simplifies the API surface and reduces implementation burden for
subregistries, while maintaining a clear migration path for consumers.
## Changes
- Removed `GET /v0/servers/{serverName}` endpoint
- Updated `GET /v0/servers/{serverName}/versions/{version}` to accept
`latest` as special version
- Updated all tests to use new endpoint pattern
- Updated documentation and OpenAPI spec
- Added breaking change notice to CHANGELOG
Fixes#617
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Introduces a new optional `title` field for MCP servers to provide a
clean, human-readable display name that clients and subregistries can
use for display purposes.
Fixes#606
## Changes
- Added `title` field to `ServerJSON` type (optional, max 100 chars)
- Added validation to reject titles ending with 'MCP Server', 'MCP
server', or 'MCP' suffixes
- Updated JSON schema and OpenAPI specification
- Added comprehensive test coverage for title validation
- Updated all documentation examples to demonstrate the new field
## Validation
The title field:
- Is optional (can be omitted)
- Must not be only whitespace if provided
- Must not end with MCP-related suffixes (case-insensitive)
- Can contain 'MCP' in the middle (e.g., "MCP Weather API" is valid)
Examples:
- ✅ Valid: "GitHub", "Weather API", "Slack Integration"
- ❌ Invalid: "GitHub MCP", "Weather MCP Server", "Slack-MCP"
---------
Co-authored-by: Claude <noreply@anthropic.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR:
* Enforces schema validation on the API level (requests without schema
or older schema will fail)
* Updates the unit tests and examples to match that
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
**Note this can be considered breaking if clients have not included it
before.**
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
## Summary
Fixes staging deployment by renumbering migrations to match what staging
has already applied.
## Problem
Staging already applied migration 008 (metadata separation) before we
inserted the new cleanup migration. When we added the cleanup as 008 and
renumbered metadata to 009, staging tried to apply 009 again and failed
with "column already exists".
## Current State
- **Staging**: Has run original 008 (metadata separation), marked as
complete. Failed trying to run 009 (which is the same migration
renumbered).
- **Production**: Has not run either 008 or 009 yet.
## Solution
- Rename `008_clean_invalid_data.sql` → `007a_clean_invalid_data.sql`
- Rename `009_separate_official_metadata.sql` →
`008_separate_official_metadata.sql` (back to original)
## How This Fixes It
With this renumbering:
1. **Staging behavior**:
- Sees 008 is already complete (the metadata migration it already ran)
- Sees 007a as new and runs it, but it will be a no-op (skips because
staging doesn't have the problematic production data)
- Continues normally
2. **Production behavior**:
- Runs 007a (cleanup migration) - removes invalid data
- Runs 008 (metadata separation) - applies successfully because data is
now clean
- Both migrations run in the correct order as intended
## Testing
- Verified migration order works correctly
- Tested on empty database (test environment) - 007a skips as expected
- Tested with production data snapshot - 007a cleans data, 008 applies
successfully
This is a critical fix to unblock staging deployment.
## Summary
This PR adds two important improvements to ensure data integrity:
1. **Adds server name format validation at the API layer** to match the
database constraint from migration 008
2. **Includes migration 008 to clean up invalid data** before applying
strict constraints in migration 009
## Changes
### Server Name Validation
- Enforces validation at the API layer matching the database constraint
- **Namespace pattern**: `[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]`
- Must start and end with alphanumeric characters
- Can contain dots and hyphens in the middle
- **Name pattern**: `[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]`
- Must start and end with alphanumeric characters
- Can contain dots, underscores, and hyphens in the middle
- Provides clear, user-friendly error messages indicating which part is
invalid
- Uses DRY approach with composed regex patterns
### Migration 008: Data Cleanup
- Removes servers with invalid names or empty versions (5 servers
affected in production)
- Fixes invalid status values by setting them to 'active' (1 server
affected)
- Removes duplicate name+version combinations
- Includes comprehensive safety checks to prevent accidental data loss
- Must run before migration 009 which adds strict constraints
## Testing
- All validator tests pass
- Migration includes safety checks that match production data
- CI verification included
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Applied `gofmt -s -w` across the entire codebase to ensure consistent
Go formatting
- This will trigger a deployment with minimal code changes
## Test plan
- [x] Pre-commit hooks pass
- [x] No functional changes, formatting only
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Fixes migration 008 failing with "column contains null values" error
- Adds COALESCE protection to handle 126 servers without status fields
- Includes test utilities to reproduce and verify fixes with production
data
## Problem
Migration 008 was failing in production because:
- 126 out of 781 servers have no `status` field in their JSON
- When extracting `rec.value->>'status'`, these became NULL values
- The `ALTER TABLE servers ALTER COLUMN status SET NOT NULL` constraint
then failed
## Solution
1. **Prevent NULLs during migration**: Use COALESCE to provide 'active'
default when status is NULL/empty
2. **Enhanced debugging**: Added RAISE NOTICE statements to log
problematic values
3. **Safety check**: Double-check that throws exception if any NULLs
remain
4. **Test utilities**: Created mirror_data tools to test migrations with
real production data
## Testing
Created and used `scripts/mirror_data/` tools to:
- Fetch all 781 servers from production API
- Load them into a test database
- Verify the migration fix works correctly
### Results:
- **Before fix**: 126 NULL status values created during migration
- **After fix**: 0 NULL status values, all servers have valid status
- Migration completes successfully with NOT NULL constraint
## Test plan
- [x] Tested locally with production data using mirror_data tools
- [x] Verified 0 NULL values after migration (vs 126 before)
- [x] Confirmed NOT NULL constraint adds successfully
- [ ] Deploy to staging and verify migration succeeds
- [ ] Monitor production deployment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR tries to ensure sane defaults for entries that for one
reason or another have NULL values for some of their properties.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
## Problem
Production deployment is failing with CrashLoopBackOff. Migration 008
fails with:
```
ERROR: column "status" of relation "servers" contains null values (SQLSTATE 23502)
```
## Root Cause
The migration extracts the `status` field from an unexpected location in
the data structure.
### Actual Data Structure (Before Migration)
In the current format, `status` is at the **top level** of the JSON, not
nested in official metadata:
```json
{
"name": "com.example/server",
"version": "1.0.0",
"status": "active", ← STATUS IS HERE (top level)
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "uuid",
"publishedAt": "2025-09-01T00:00:00Z",
"isLatest": true
// NO STATUS FIELD HERE
}
}
}
```
For 120 out of 765 servers, the status field is **missing entirely**:
```json
{
"name": "com.biodnd/agent-ip",
"version": "0.1.2",
// ← NO STATUS FIELD AT ALL
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "uuid",
"publishedAt": "2025-09-23T09:47:07Z",
"isLatest": true
// STILL NO STATUS FIELD HERE
}
}
}
```
### Original Migration Logic
```sql
IF official_meta IS NOT NULL THEN
UPDATE servers
SET
status = (official_meta->>'status'), -- Extracts NULL for all servers
```
**Result:**
- All 765 servers would have NULL status extracted
- Because `official_meta->>'status'` returns NULL (field doesn't exist
there)
- The migration tries to add `NOT NULL` constraint → fails
### Fixed Migration Logic
```sql
IF official_meta IS NOT NULL THEN
UPDATE servers
SET
status = COALESCE(NULLIF(rec.value->>'status', 'null'), 'active'),
```
**Result:**
- Extracts from top-level JSON where status actually exists
- `NULLIF(rec.value->>'status', 'null')` handles edge case of literal
string "null"
- `COALESCE(..., 'active')` provides fallback when status is missing
- All servers get valid status value
### Impact Breakdown
**645 servers with `"status": "active"`:**
- Before fix: Would extract NULL → migration fails
- After fix: Extracts "active" correctly
**120 servers with missing status field:**
- Before fix: Would extract NULL → migration fails
- After fix: Defaults to 'active' via COALESCE
## Example Servers with Missing Status
(First 9 discovered during investigation)
- com.biodnd/agent-ip
- io.github.jkakar/cookwith-mcp
- com.joelverhagen.mcp/Knapcode.SampleMcpServer
- io.github.Lyellr88/marm-mcp-server
- com.biodnd/agent-press
- io.github.timheuer/sampledotnetmcpserver
- io.github.CodeCraftersLLC/local-voice-mcp
- com.biodnd/agent-fin
- io.github.ruvnet/ruv-swarm
## Testing
Verified against production data (765 total servers):
- ✅ All servers have official metadata
- ✅ None have status in official metadata (expected)
- ✅ 645 have "status": "active" at top level
- ✅ 120 have missing status field (no field present)
- ✅ Fix extracts from correct location for all cases
## Impact
This unblocks production deployment. Once merged and released as v1.2.1,
the migration will:
1. Extract status from the correct location (top-level JSON)
2. Handle missing status fields with sensible defaults
3. Successfully add NOT NULL constraint
4. Allow pods to start normally
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add workflow_dispatch to deploy.yml for manual deployment triggers
- Document that releases don't auto-deploy to production
- Add instructions for deploying releases to production
- Add verification steps for deployment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
Currently the `dns` and `http` based auth flows share code well in the
publisher tool. However there is a lot of duplication in the auth
endpoint. This on it's own is not a problem but it does make
enhancements to the proof record (the `v=MCPv1; ...` string) harder to
keep in sync.
This PR adds a `common.go` file to share logic between the two.
This supports work I am prototyping for
https://github.com/modelcontextprotocol/registry/issues/482.
## How Has This Been Tested?
Added new test cases for the permissions. Ran them before and after the
refactoring to ensure no behavior change.
Ran existing UTs.
Ran the integration tests.
Manually exercised the flows locally.
## Breaking Changes
None.
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 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
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The following PR adds a simple unit test to ensure the served API
handlers are a superset of the reference OpenAPI schema.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Fixes: https://github.com/modelcontextprotocol/registry/issues/567
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
## Motivation and Context
Replace server-only `http.MaxBytesReader(nil, ...)` with
`io.LimitReader` to cap the fetched body to 4KB in key fetcher. This
avoids passing a `nil` ResponseWriter and aligns with Go idioms. If more
than 4KB is received, return a clear error. Previously `MaxBytesReader`
returned a misleading `http: request body too large` error, which is
server-oriented. With this change the error becomes `HTTP auth key
response too large`.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Add tests covering success, oversized bodies, connection failure,
non-200 status, and read failures. This covers almost all lines of
`FetchKey` method of `DefaultHTTPKeyFetcher`. For tests, I also added a
new initialiser `NewDefaultHTTPKeyFetcherWithClient` so that the HTTP
client could be modified for test use.
Tests use `httptest.NewTLSServer` plus a helper to construct a client
pinned to the test server.
`auth` package test coverage increased from 56.8% to 59.3%.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
None.
## 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)
- [ ] 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
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
## Summary
Fixes a race condition where a server could have no version marked as
`isLatest` if the database operations failed independently.
## Changes
- **CreateServer signature**: Now accepts `oldLatestVersionID` parameter
to atomically unmark previous latest version
- **PostgreSQL implementation**: Uses a transaction to ensure UPDATE
(unmark old latest) and INSERT (create new version) happen atomically
- **Service layer**: Maintains `WithPublishLock` for concurrent
operation serialization
- **Two-level protection**: Advisory lock prevents races, transaction
ensures atomicity
## Test plan
- [x] Existing race condition tests pass
- [x] Integration tests pass
- [x] Unit tests pass
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Housekeeping on leftover psql references
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
<!-- Provide a brief summary of your changes -->
Package identifier and version are required for some of the registries
else we won't be able to pull the meta data to validate the packages.
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
This is in continuation to
https://github.com/modelcontextprotocol/registry/pull/424
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Unit test.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
No
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
Co-authored-by: Avish Porwal <avishporwal@microsoft.com>
<!-- Provide a brief summary of your changes -->
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The follow PR removes the in-memory database option from the registry.
We had a chat about this with @domdomegg and although it is supposed to
be convenient, it isn't that useful in reality. We want to test and
develop the registry in a setup that is closer to the environment it is
supposed to be run. One of the main reasons are:
* We don't use it anywhere else besides unit testing and potentially
local development. Instead we should use postgresql for reliable results
(in-memory was actually giving false positive results)
* We have to keep maintaining it and make sure it mimics the behaviour
we have for postgresql which is not yielding a lot of value
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Yes, I've updated the test unit make target to run in the postgresql
environment and now we can see the race condition issue happening.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
No
## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] 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)
- [ ] Documentation update
## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed
## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
---------
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>