- 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>
<!-- 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>
## Summary
Fixes a concurrent map access vulnerability in the OIDC handler that
could cause remote unauthenticated DoS.
## Changes
- Removed OIDC authorization flow endpoints ( and )
- Removed the unsynchronized map that caused the data race
- Kept only the OIDC token exchange endpoint ()
- Simplified by removing OAuth2 flow dependencies
The map was being accessed concurrently by the start (write) and
callback (read/delete) endpoints without synchronization, causing
runtime panics. Since the token exchange flow doesn't require session
state, removing the authorization flow eliminates the vulnerability
entirely.
Wielded Claude Code to do this; across many iterations and have reviewed
all the code + largely rewritten the PR commentary here.
This PR implements the server ID consistency changes from
[#396](https://github.com/modelcontextprotocol/registry/issues/396). Our
goal is to:
- Rename `id` to `versionId` to make it clear that it is the ID for a
specific version, not a server
- Introduce `serverId` as a net new concept. This will be 1:1 with
`name`. While not strictly necessary (we could just use name as a PK),
the convention of having a UUID as an ID on our objects is just a
helpful subjective architecture decision. Plus also leaves open the door
to reconsidering the "should we allow renames" question.
## Key Changes
### 🗄️ Database Schema Changes
- **Renamed**: `id` column → `version_id` (unique identifier for each
server version)
### 📋 Metadata Structure Updates
- **JSON Schema**: Updated
`_meta.io.modelcontextprotocol.registry/official` to include:
- `serverId`: Consistent ID across all versions of a server
- `versionId`: Unique ID for this specific version (renamed from `id`)
### 🔧 API Endpoint Updates
- **New endpoint structure**: Changed from version-ID-based to
server-ID-based URLs:
- `GET /v0/servers/{server_id}` - Get latest version of server
- `GET /v0/servers/{server_id}?version=X.X.X` - Get specific version
- `GET /v0/servers/{server_id}/versions` - List all versions of a server
- `PUT /v0/servers/{server_id}?version=X.X.X` - Edit specific version
- **Consistent URL patterns**: All server endpoints now use `server_id`
as the primary identifier
### Database Migration Strategy
The migration (`005_add_server_id_rename_version_id.sql`):
1. Adds new `version_id` column
2. Generates deterministic UUIDs for servers with the same name
3. Updates JSON metadata to add `serverId` and rename `id` to
`versionId`
4. Copies existing `id` values to `version_id` column
5. Drops old `id` column and makes `version_id` the new primary key
## Testing
Besides of course automated tests passing, I:
1. Set up my local db with the pre-005-migration state, imported all the
production data
2. Ran the migration
3. Spot checked some diffs of the data that resulted --
```json
// before
{
"name": "io.github.ruvnet/ruv-swarm",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"id": "0a9cda7f-2b73-4839-844b-6582f335de42",
"is_latest": false,
"updated_at": "2025-09-10T17:21:34.92137012Z",
"published_at": "2025-09-10T17:15:32.69690433Z"
}
},
"version": "1.0.18",
"repository": {
"url": "",
"source": ""
},
"description": "Neural network swarm orchestration with WebAssembly acceleration and MCP integration"
}
// after
{
"name": "io.github.ruvnet/ruv-swarm",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "e8538952-96af-4a33-9e31-7fbed012521e",
"is_latest": false,
"versionId": "0a9cda7f-2b73-4839-844b-6582f335de42",
"updated_at": "2025-09-10T17:21:34.92137012Z",
"published_at": "2025-09-10T17:15:32.69690433Z"
}
},
"version": "1.0.18",
"repository": {
"url": "",
"source": ""
},
"description": "Neural network swarm orchestration with WebAssembly acceleration and MCP integration"
}
```
Servers that have multiple versions stayed consistent in their
`serverId`:
```json
// First version
{
"name": "app.getdialer/dialer",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "80f08bdb-f3e4-4f19-b072-1676ae49b663",
"is_latest": false,
"versionId": "04f25b17-331d-48d7-b08b-37baece208a7",
"updated_at": "2025-09-09T00:16:49.162620072Z",
"published_at": "2025-09-08T23:47:09.452137971Z"
}
},
"status": "active",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"remotes": [
{
"url": "https://getdialer.app/mcp",
"type": "streamable-http"
},
{
"url": "https://getdialer.app/sse",
"type": "sse"
}
],
"version": "1.0.0",
"repository": {
"url": "",
"source": ""
},
"description": "An MCP server that provides your you make outbound phone calls using your own phone number"
}
// Second version
{
"name": "app.getdialer/dialer",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "80f08bdb-f3e4-4f19-b072-1676ae49b663",
"is_latest": true,
"versionId": "faa26cb9-3aad-415e-aece-f715fff5fe5e",
"updated_at": "2025-09-09T00:16:49.107842808Z",
"published_at": "2025-09-09T00:16:49.107842808Z"
}
},
"status": "active",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"remotes": [
{
"url": "https://getdialer.app/mcp",
"type": "streamable-http"
},
{
"url": "https://getdialer.app/sse",
"type": "sse"
}
],
"version": "1.0.1",
"repository": {
"url": "",
"source": ""
},
"description": "An MCP server that provides lets you make outbound phone calls using your own phone number"
}
```
And I also tried publishing a test server anew; looked good:
```bash
⏺ Bash(curl -s "http://localhost:8080/v0/servers/102dc4e4-6ca8-40e6-aa11-cd45763d3352" | jq '.')
⎿ {
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"name": "io.modelcontextprotocol.anonymous/test-claude-migration-server",
"description": "A test server to verify the new migration and API endpoints work correctly",
"status": "active",
"repository": {
"url": "https://github.com/example/test-claude-migration-server",
"source": "github",
"id": "example/test-claude-migration-server"
},
"version": "1.0.0",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "102dc4e4-6ca8-40e6-aa11-cd45763d3352",
"versionId": "48c9cd55-7bc4-4ac2-896e-59e81eb653e4",
"published_at": "2025-09-12T18:33:23.264203-07:00",
"updated_at": "2025-09-12T18:33:23.264203-07:00",
"is_latest": true
}
}
}
⏺ Bash(curl -s "http://localhost:8080/v0/servers/102dc4e4-6ca8-40e6-aa11-cd45763d3352/versions" | jq '.')
⎿ {
"servers": [
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"name": "io.modelcontextprotocol.anonymous/test-claude-migration-server",
"description": "A test server to verify the new migration and API endpoints work correctly",
"status": "active",
"repository": {
"url": "https://github.com/example/test-claude-migration-server",
"source": "github",
"id": "example/test-claude-migration-server"
},
"version": "1.0.0",
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "102dc4e4-6ca8-40e6-aa11-cd45763d3352",
"versionId": "48c9cd55-7bc4-4ac2-896e-59e81eb653e4",
"published_at": "2025-09-12T18:33:23.264203-07:00",
"updated_at": "2025-09-12T18:33:23.264203-07:00",
"is_latest": true
}
}
}
],
"metadata": {
"count": 1
}
}
```
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Preeti Dewani <preetidewani1990@gmail.com>
Co-authored-by: adam jones <adamj+git@anthropic.com>
Co-authored-by: Adam Jones <adamj@anthropic.com>
## Summary
Added validation to reject server names with multiple slashes, ensuring
consistency between JSON schema pattern and API validation.
- Count slashes in parseServerName() and reject if > 1
- Add ErrMultipleSlashesInServerName error constant
- Add unit tests in validators_test.go
- Add integration test in publish_test.go
## Motivation and Context
Fixes#471. The JSON schema regex pattern `^[^/]+/[^/]+$` only allows a
single slash in server names, but the API validation was not enforcing
this constraint. This inconsistency
allowed invalid server names like `com.example/server/path` to be
published.
## How Has This Been Tested?
- Unit tests added to verify slash validation logic
- Integration tests added to verify the publish endpoint rejects
multi-slash names
- Tested various edge cases: trailing slashes, consecutive slashes,
URL-like paths
- All existing tests pass
## Breaking Changes
None. This change only adds validation to reject previously invalid
server names that shouldn't have been accepted.
## Types of changes
- [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
- [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
- The fix ensures server names follow the intended format:
`namespace/name` (e.g., `com.example/my-server`)
- This validation aligns the API behavior with the existing JSON schema
regex pattern
- Test coverage includes edge cases like `com.example//server`,
`com.example/server/`, and `a/b/c/d/e/f`
- The error message clearly indicates the issue: "server name cannot
contain multiple slashes"
Claude wrote this extra test while I was doing some other work
experimenting with stuff, seems useful to have!
Also deleted the unnecessary expectedServers, because we basically never
assert on it.
Resolves#419 where URLs with trailing slashes like `/v0/servers/` would
return empty responses instead of proper data.
**Changes**:
- Added TrailingSlashMiddleware that redirects trailing slash URLs with
301 status
- Preserves root path ('/') without redirecting
- Uses HTTP 301 Moved Permanently to indicate canonical form
- Added comprehensive test coverage for the middleware
This follows REST API best practices and is consistent with how major Go
web frameworks handle trailing slash normalization.
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>
## Summary
The permission error now displays what namespaces the user has
permission to publish and what namespace they attempted to publish. This
helps users debug permission mismatches more easily.
Helps mitigate #398 to enable us to figure out what's going on
## Summary
- Consolidate ServerListResponse and Metadata types into pkg/api/v0
- Remove duplication between handler and API types
- Change metadata from optional pointer to required value
- Remove unused Total field from Metadata
## Summary
Simplified the schema structure by:
- Replacing `version_detail.version` with direct `version` field
- Removing unused `release_date` field from seed data
- Updating all API types, models, and tests to match new structure
- Maintaining backwards compatibility in API responses
This change makes the schema more intuitive and reduces nesting depth.
## Summary
- Adds `updated_since`, `search`, and `version` query parameters to `GET
/v0/servers`
- Enables incremental synchronization via RFC3339 timestamp filtering
- Provides simple substring search on server names
- Supports latest version filtering with `version=latest`
This implementation provides the core filtering capabilities needed for
efficient registry synchronization and improved server discovery.
Fixes#291Fixes#135
## Summary
- Changes the API title from "MCP Registry API" to "Official MCP
Registry"
- Redirects root path to GitHub docs instead of /docs endpoint
- Adds GitHub repo and docs links to API description
Fixes#370
## Summary
Updates the `_meta` field structure to be compliant with the MCP
specification by using proper `prefix/name` format for vendor
extensions.
### Changes
- **Registry metadata**: `io.modelcontextprotocol.registry` →
`io.modelcontextprotocol.registry/official`
- **Publisher metadata**: `publisher` →
`io.modelcontextprotocol.registry/publisher-provided`
- **Database migration**: Updates indexes to use new field paths
- **Updated all code**: Service layer, validators, tests, and seed data
### Format Before
```json
{
"_meta": {
"publisher": { "license": "MIT" },
"io.modelcontextprotocol.registry": { "id": "...", "is_latest": true }
}
}
```
### Format After
```json
{
"_meta": {
"io.modelcontextprotocol.registry/publisher-provided": { "license": "MIT" },
"io.modelcontextprotocol.registry/official": { "id": "...", "is_latest": true }
}
}
```
This resolves the naming collision with the planned top-level
`publisher` field and ensures compliance with MCP specification
requirements.
Fixes#356
## Summary
Implements mandatory file hash validation for MCPB (MCP Bundle) packages
to ensure file integrity and security.
## Changes
- **Validator enforcement**: MCPB packages now require `file_sha256`
field at publish time
- **Test coverage**: Updated all MCPB test cases to include valid
SHA-256 hashes
- **Documentation**: Updated publisher guide and schema to reflect hash
requirement
- **Error handling**: Clear error message when hash is missing
## Security Impact
This ensures the complete security workflow for MCPB packages:
1. Authors generate and provide SHA-256 hashes when publishing
2. Registry validates hash is present (but doesn't verify content)
3. MCP clients validate hash matches downloaded file before installation
Fixes#351
<!-- 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 `transport` type used in Package and Remotes
* Added `docker` to the `runtime_hint` examples
* Added support for templated URLs. It is available for streamable-http
and sse transports for Packages. I didn't thought of reasons to have
this for Remotes, but we can enable it if needed.
* Added validation for templated URLs so we can ensure all referenced
placeholder variables are available.
* For streamable-http and SSE transport types the URL is now a required
property
* Updated the publisher init command to reflect these changes
* Updated the seed.json file
* Added unit tests for the transport type related changes
* Updated the server.json schema and the external pkg structs to reflect
the new transport type
* Updated the examples
Thanks to @kkkarthik for spotting it! 🙏
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Ran the tests locally
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
Yes
## 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)
- [x] 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>
Fixes#96
## Motivation and Context
See #96
## How Has This Been Tested?
Has some unit and integration tests, still needs proper testing of the
different registry types
## Breaking Changes
Yes, new package uploads will need extra verification
## 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)
- [ ] Documentation update
## Motivation and Context
The database logic was getting a bit unwieldy and fragile - especially
because business logic that should really have lived at the registry
service level was being pushed into the persistence level.
This PR tightens the interface, simplifies the code there, as well as
rips out a bunch of mocks etc. we don't need.
## How Has This Been Tested?
Locally everything works
## Breaking Changes
The list endpoint was surprisingly always filtering for isLatest only,
which seems like a bug? I have removed this filter.
Thanks Camila for being a great Go consultant and advising on how to
tidy this up!
(I'm still a lil grumpy about some parts, but it's in much better shape
😄)
- Consolidated publisher extension validation into a single function.
- Updated the `Publish` and `EditServer` methods to directly use
`XPublisher` from the request.
- Removed outdated tests for publisher extension extraction and
validation.
- Introduced new validation functions for server details and remote URL
matching.
- Enhanced error handling for server name format and remote URL
validation.
- Updated existing tests to reflect changes in validation logic and
structure.
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Things were starting to become a bit spaghetti-y after lots of small PRs
and contributions from many people. Camila and I went through and
figured out how we could make this a lot cleaner.
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Tested locally, plus all the integration and unit tests still pass.
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
None
---------
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 eliminates duplicate struct definitions by migrating
the publisher tool to use canonical types from pkg/model, creating a
single source of truth across the codebase. The publisher tool
previously had its own copies of structs that were duplicated, ie.
ServerJSON, Package, Repository, VersionDetail, EnvironmentVariable,
RuntimeArgument and a few others which was not optimal
**Changes in the PR:**
- Refactored the structs to single canonical types located at pkg/model
- Refactor the implementation to use/build canonical structures directly
- Remove all duplicate definitions (5 structs eliminated)
- Publisher now uses model.ServerJSON, model.Package, model.Repository,
etc.
- Renamed some of the structs to better reflect their use case, i.e.
ServerJSON instead of ServerDetail
- Fixes an issue where the Remote property was missing from the previous
publisher copy of the Server
**Benefits:**
- Single source of truth - Schema changes in one place
- Type safety - Compiler catches mismatches
- Enhanced validation - Field constraints and bson tags
- Zero breaking changes - Same CLI interface and JSON output
- Future-proof - New canonical fields automatically available
Supersedes: #217 and #240
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Locally
## 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: -->
- [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>
## Summary
Implements `PUT /v0/servers/{id}` admin edit endpoint to address part of
issue #182, providing an API-based solution for server moderation
without requiring direct database access.
- **New endpoint**: `PUT /v0/servers/{id}` for editing existing servers
- **Security**: Uses existing JWT auth with `PermissionActionEdit`
permissions
- **Anti-undelete protection**: Added `ServerStatusDeleted` status that
cannot be reverted
- **Full implementation**: Database, service, API, and comprehensive
test coverage
## Key Use Cases
- Mark malicious servers as `deleted` for takedown
- Update server metadata for moderation actions
Related to: https://github.com/modelcontextprotocol/registry/issues/182
(but that is not _done_ yet because we need admins to be able to login
(probably with #283), and need to add docs on how to do the takedown,
and probably guidelines on what we will/won't takedown)
## Summary
This PR implements OIDC authentication support for admin users,
specifically configured for Google Cloud Identity. The implementation
includes:
- Configurable OIDC authentication endpoints and validation
- Google Cloud Identity integration for admin access
- JWT token validation and user session management
- Deployment configuration updates for OIDC provider settings
Fixes#283
<!-- Provide a brief summary of your changes -->
The changes are intended to create validators for all the free-form
fields. Please find the details of the validation of different field
below.
- Repository.Source: only github and gitlab is accepted.
- Repository.Url - It should be a valid github or gitlab URL. Created
regex for both.
- Server.Name - Max 200 char can be there. Reverse domain name
verification is part of another PR (not owned by me).
- Package.Name - Max 200 char and no spaces.
- Server.Description - Max 100 char.
- Remote.Url - It should be valid URL.
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
The motivation was to make the code clean and add base code for more
validator for different objects like Repository etc.
https://github.com/modelcontextprotocol/registry/issues/97
## How Has This Been Tested?
It's tested via UTs. Added UT's for all the validations.
## Breaking Changes
Yes
## 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)
- [x] 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)
- [ ] 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-by: Avish Porwal <avishporwal@microsoft.com>
Co-authored-by: Adam Jones <adamj+git@anthropic.com>
## Summary
- Add reverse-DNS namespace format validation for server names
(namespace/name)
- Validate remote URLs match the DNS namespace derived from hostname
- Prevent duplicate remote URLs across different servers
- Support localhost/development URLs without namespace restrictions
- Add comprehensive test coverage for validation logic
- Update database layer to support remote_url filtering
Fixes#180 by ensuring proper namespace governance and preventing URL
conflicts.
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Disable the `ireturn` linter rule in golangci-lint configuration
- Remove all related `nolint:ireturn` comments from the codebase
The `ireturn` rule was flagging factory functions that intentionally
return interfaces for dependency injection, which is a common and valid
Go pattern. Since this pattern is used extensively throughout the
codebase for good architectural reasons, it makes sense to disable this
rule entirely.
It also seems buggy, and seems to conflict with other lint rules -
causing unnecessary toil.See:
https://stackoverflow.com/questions/72385337/golang-linter-always-complains
<!-- Provide a brief summary of your changes -->
This PR serves as a placeholder and brings together all of the changes
related to supporting vendor extensions passed through the API. The idea
is to have a single place to track and review the work as it comes
together (even if it’s still a bit of a work in progress).
**The changes in this PR cover:**
* Updates on the data model
* Updates on both databases (in-memory and postgresql), added a new
table to PSQL for tracking the extensions leaving the server table only
for the clean server.json properties
* Updates the seed.json file (thus the big line change)
* Adds a seed-migrate tool to help migrating an existing seed file to
the new format
* Updates the seed import mechanism to support this
* Updates the existing tests - unit, integration and validation tests
* Adds the publish handler to the OpenAPI spec (it was missing)
* Fixes linting errors
* Updates on the API side on (publish, list, get) to support the new
format of `ServerResponse` -
```
{
"server": {},
"x-io.modelcontextprotocol.registry": {}, /*not available for publish since this gets populated by the registry*/
"x-publisher": {}
}
```
## Motivation and Context
<!-- Why is this change needed? What problem does it solve? -->
Motivated by the discussions in:
https://github.com/modelcontextprotocol/registry/discussions/284
## How Has This Been Tested?
<!-- Have you tested this in a real application? Which scenarios were
tested? -->
Locally and by running all of the tests
## Breaking Changes
<!-- Will users need to update their code or configurations? -->
Yes, it changes both the API and the format of the seed file
## 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)
- [x] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
---
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
Co-authored-by: adam jones <domdomegg+git@gmail.com>
Add HTTP-based authentication to prove domain ownership, similar to
https://github.com/modelcontextprotocol/registry/pull/238's DNS
authentication but using HTTPS well-known URIs instead of DNS TXT
records.
Fixes#280
## Motivation and Context
Some organizations don't have easy access to DNS records, but can easily
deploy web assets. They would therefore prefer to be able to complete a
HTTP challenge rather than a DNS one to authenticate to the registry.
This would in some way mirror ACME challenges: where you can do a DNS-01
or a HTTP-01 challenge.
## How Has This Been Tested?
- Tested locally by stubbing out the HTTP getter
- Added unit tests
## 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
- [x] I have added or updated documentation as needed
## Additional context
I concern I had when building this that it might expose us to SSRF
attacks.
I think on reflection this is not a significant problem:
- We only GET a fixed file `.well-known/mcp-registry-auth` (redirects
disallowed) after sanitizing the domain, and then also don't expose the
response to the user. This means the user shouldn't be able to hit
anything very interesting.
- The information they might get is what domains/servers exist in the
network. Our infrastructure is already all open-source, so attackers
aren't getting any additional real info by prodding at the environment
this way.
Fixes#270Closes#233
Adds support for DNS-based authentication for proving ownership of a
particular domain. E.g. if you can add a TXT record to `anthropic.com`,
you can publish anything at `com.anthropic/*` or `com.anthropic.*`.
Notes:
- Uses Ed25519 signatures with 15-second timestamp windows to prevent
replay attacks
- Supports multiple public keys in DNS TXT records for key rotation
scenarios
- Publisher CLI supports DNS auth via --dns-domain and --dns-private-key
flags
- Includes key generation commands in publisher README for easy setup
## Motivation and Context
This implements DNS-based public/private key authentication to allow
people to actually publish at their own domains. Currently,
authentication requires GitHub accounts which limits publishing to the
io.github.* namespace.
DNS-based auth enables:
- Publishing under your actual domain (e.g., com.anthropic/* for
anthropic.com)
- Independence from GitHub or other external auth providers
- Organizations managing their own keys and access to publishing
## How Has This Been Tested?
- Unit tests cover signature verification, DNS TXT parsing, timestamp
validation, and error cases
- Tested locally by editing my own DNS records
- All existing auth methods covered by passing tests
## 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
- [x] I have added or updated documentation as needed
## Additional context
Will be adding HTTP challenge auth in a similar way as a separate PR,
e.g. for verifying you own `github.com` by hosting a
`github.com/.well-known/mcp-server-challenge` or similar. Just
mentioning this as we discussed HTTP challenges as closely related to
DNS challenges elsewhere, and want to reassure reviewer that this hasn't
been forgotten with this approach. :) Update: tracking the HTTP auth in
https://github.com/modelcontextprotocol/registry/issues/280
## Motivation and Context
- It is important to have basic observability in place so that
availability issues can be figured out easily
## How Has This Been Tested?
- Registration of metrics is tested
- Prometheus endpoint `/metrics` is included in test cases to test the
metrics exposed
- Test locally to understand any regression.
## Breaking Changes
- 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
- [ ] I have added or updated documentation as needed
## Additional context
- Telemetry implementation is currently done by keeping metrics in mind
as of now, other types of telemetry can be added on top of it later.
- Instrumentation takes care of these problems already:
- Cardinality control by limiting latency buckets and not including
labels that grows with throughput.
- Latency buckets are added as per SLA guidelines
- Each metric prefixed with `mcp` to easily identify.
- Pulling mechanism is used since the idea is to scrape metrics via an
agent like vmagent, prometheus agent or otel-collector.
- Metrics follow standard approach of defining counters, histogram and
gauges as per opentelemetry guidelines.
Adds support for auth'ing to the registry via [GitHub Actions
OIDC](https://docs.github.com/en/actions/concepts/security/openid-connect).
Fixes#271
## Motivation and Context
People will probably want to publish to the registry from CI
environments. DNS auth can work here fine
(https://github.com/modelcontextprotocol/registry/issues/270). But for
people who haven't set up DNS, the standard GitHub device flow won't
really work here. We could make this nice by supporting GitHub Actions
OIDC.
## How Has This Been Tested?
Tested locally with a real GitHub OIDC token from a personal repo.
## 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
- [x] I have added or updated documentation as needed
## Motivation and Context
- Adds credentials for the new MCP Registry Login GitHub Apps (local,
staging, prod)
- Adds support for "none" auth to publisher
## How Has This Been Tested?
- Tested publisher workflows locally
- Unit and integration tests passing
## 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
- [x] I have added or updated documentation as needed
---
Merging based on Tadas's approval review, and only making minor docs changes on top of that.
Fixes#264. Adds endpoints:
```
/v0/auth/github # exchange a github token for a registry token that gives you access to namespaces io.github.username and io.github.org for your orgs
/v0/auth/none # get a registry token for namespace io.modelcontextprotocol.anonymous (only for testing/local dev purposes)
```
Updates `/v0/publish` to accept one of these registry tokens.
## Motivation and Context
See #264
## How Has This Been Tested?
- Running locally and getting a token from `/v0/auth/none` and then
publishing to `/v0/publish`
- Updating the integration tests that get a token and then publish, and
them passing
## Breaking Changes
This is a breaking change to the auth API. This is fine for registry
given it's not deployed yet.
## 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
-->
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: adam jones <domdomegg@users.noreply.github.com>
## Motivation and Context
Currently there's a lot of unsafe manual JSON unmarshalling/marshalling,
and we have to manually keep the openapi schema in sync.
This PR migrates the API to
[Huma](https://github.com/danielgtaylor/huma), which appears like a
popular, well-maintained way to build APIs in Golang. I'm not a Golang
expert, but seemed highly recommended by Reddit + Claude and has a
decent star count. It provides automatic openapi spec generation and
docs hosting, JSON parsing, as well as the ability to add auth
middlewares etc.
## How Has This Been Tested?
Running locally, and poking at the endpoints
## Breaking Changes
Docs are served at `/docs` rather than `/v0/swagger/index.html` now
## 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
-->
This PR simplifies the seed data import configuration based on
maintainer feedback by removing command line flags and using a clearer
environment variable name.
## Key Changes
### Configuration Simplification
- **Renamed**: `MCP_REGISTRY_SEED_FILE_PATH` → `MCP_REGISTRY_SEED_FROM`
- **Removed**: `--seed-file-path` command line flag to eliminate
configuration complexity
### Improved User Experience
Users now configure seed data import using a single, clear environment
variable:
```bash
# Before (multiple ways to configure)
MCP_REGISTRY_SEED_FILE_PATH=data/seed.json ./registry
./registry --seed-file-path=data/seed.json
# After (simplified single method)
MCP_REGISTRY_SEED_FROM=data/seed.json ./registry
```
### Registry Composability
The composability workflow is now simplified while maintaining all
functionality:
```bash
# Start first registry with seed data
MCP_REGISTRY_SEED_FROM=data/seed.json ./registry
# Start second registry importing from first via pagination
MCP_REGISTRY_SEED_FROM=http://localhost:8080 ./registry
```
## Technical Implementation
- Maintains full backward compatibility for import functionality
- All existing seed data sources continue to work (local files, HTTP
URLs, registry URLs)
- Automatic pagination through `/v0/servers` endpoint remains unchanged
- Configurable delays between requests preserved
## Benefits
- **Reduced complexity**: Single configuration method instead of
multiple
- **Clearer naming**: `SEED_FROM` better describes the source of seed
data
- **Easier maintenance**: Fewer configuration paths to test and document
- **Consistent patterns**: Aligns with other environment-variable-only
configuration
All existing functionality is preserved while providing a cleaner, more
maintainable configuration interface.
<!-- START COPILOT CODING AGENT TIPS -->
---
💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey.alchemer.com/s3/8343779/Copilot-Coding-agent) to
start the survey.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Avinash Sridhar <sridharavinash@users.noreply.github.com>
Co-authored-by: Toby Padilla <toby@toby.sh>
Co-authored-by: toby <83556+toby@users.noreply.github.com>
## Summary
- Added redirect from `/` to `/v0/swagger/index.html` to help
contributors quickly access API documentation
- Implemented the redirect in router.go after v0 routes registration
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
Migrate golangci-lint from v1 to v2.
## Motivation and Context
The golangci-lint has been upgraded to v2 since March 2025.
The v2 of golangci-lint has simplified the linters management.
## How Has This Been Tested?
Tested locally with golangci-lint@v2.1.6
## Breaking Changes
No.
## Types of changes
- [ ] 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
-->
---------
Co-authored-by: haokunt <haokunt@opera.com>
Co-authored-by: Avinash Sridhar <sridharavinash@users.noreply.github.com>
Co-authored-by: Adam Jones <adamj+git@anthropic.com>
This is a first PR for #159 - adding some validation scripts. I want to
get to a place where we are confident that making schema changes is in
sync with the rest of our code. Step one is making sure the schemas are
in sync with our examples. Step two will be making sure the schemas are
in sync with our actual Registry implementation code.
This is just for the JSON right now; if we're feeling good about this
approach I'll do an analogous change for the OpenAPI schemas as well.
I'll also follow with adding usage of these scripts to our CI pipeline
so we have automated checks on them with every change.
## Summary
- Added CLI validation tools for JSON schemas and examples in
`docs/server-json/`
- Fixed some minor validation errors found in `examples.md`
- Ensures schema consistency and example validity in CI/CD pipelines
## Changes
### New Validation Tools
1. **`tools/validate-schemas`** - Validates that `schema.json` and
`registry-schema.json` are valid JSON Schema documents
2. **`tools/validate-examples`** - Validates all JSON examples in
`examples.md` against both schemas
### Key Features
- ✅ Validates JSON schema syntax and structure
- ✅ Validates all examples against both base and registry schemas
- ✅ Tracks validation counts to prevent silent failures
- ✅ Proper exit codes for CI integration
- ✅ Clear error messages for debugging
### Fixes to examples.md
- Added missing `repository.id` field in NuGet example
- Changed `repository.source` from "gitlab" to "github" in Docker
example
### Usage
```bash
# From repository root
./tools/validate-schemas.sh
./tools/validate-examples.sh
```
## Testing
I ran these scripts locally with minor (breaking) changes, which they
each correctly reported. As submitted, they are both passing.
🤖 Co-authored with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com>
- Added error handling for JSON encoding in ServersHandler and ServersDetailHandler.
- Updated test cases to reflect changes in handler functions and improved mock expectations.
- Refactored server initialization to include ReadHeaderTimeout for better request handling.
- Modified GitHubDeviceAuth to accept context in ValidateToken and checkOrgMembership methods.
- Improved error messages in database import functions for better debugging.
- Updated memory and mongo database list functions to accept context and improved filtering logic.
- Enhanced logging in publisher tool for better visibility during execution.
- Cleaned up code formatting and comments for better readability and maintainability.