Commit graph registry/internal/api
Author SHA1 Message Date
adam jones
e7de7541c7
improve: Add hint about making GitHub org membership public in error messages (#772)
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>
2025-11-17 13:59:19 +00:00
adam jones
8cf317af68
Add simple web UI for browsing the registry (#757)
## 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.
2025-11-10 12:37:36 +00:00
Radoslav Dimitrov
ef4a60505e
Make Repository field properly optional in server.json (#717)
<!-- 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>
2025-10-29 13:23:47 +00:00
Terry Nederveld
73d2174cec
feat: add CORS support to registry API (#711)
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: *)
2025-10-27 18:07:13 +00:00
Joel Verhagen
6c0f085708
Add support for ECDSA P-384 (#685)
## 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>
2025-10-24 12:02:33 -06:00
adam jones
f870a4c000
Improve golang type documentation and examples (#631)
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>
2025-10-16 21:55:52 +01:00
Radoslav Dimitrov
2a80690063
Introduce a /version API (#667)
<!-- 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>
2025-10-15 17:24:46 +03:00
Radoslav Dimitrov
3592b2cc0c
Add the rest of the tag descriptions (#661)
<!-- 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>
2025-10-14 15:28:10 +03:00
Radoslav Dimitrov
087d8085b7
Replace / with - for operation IDs (#660)
<!-- 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>
2025-10-14 15:26:43 +03:00
Aleksandr Beshkenadze
cce5e5df46
feat: add OpenAPI tags for improved SDK generation and API organization (#655)
## Summary
Adds OpenAPI tags to improve SDK generation and API documentation
organization, as discussed in #644.

## Changes
- **Go Code**: Define tag metadata (name + description) in
`internal/api/router/router.go` using Huma's `api.OpenAPI().Tags`
- **Reference Spec**: Update `docs/reference/api/openapi.yaml` to match
the generated spec
- **Tags Added**: servers, publish, auth, admin, health, ping

## Benefits
- ✅ Improved SDK generation with proper service grouping (e.g.,
`serversService`, `publishService`)
- ✅ Better API documentation organization in Scalar UI, Swagger UI, and
other tools
- ✅ Code-first approach ensures reference spec stays in sync via
compliance tests

## Testing
- ✅ Compliance test passes: `go test -v ./internal/api -run
TestOpenAPIEndpointCompliance`
- ✅ All 4 reference endpoints verified as implemented
- ✅ TypeScript SDK regenerated successfully with proper tag-based
grouping

## Related
Closes #644
2025-10-14 14:30:36 +03:00
Radoslav Dimitrov
1a7cd97099
Introduce v0.1 version of the API (#658)
<!-- 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>
2025-10-14 11:04:48 +03:00
Radoslav Dimitrov
632cbce815
Refactor package types to use dedicated schema types per package type (NPM, PyPI, NuGet, OCI, MCPB) (#634) 2025-10-11 10:53:45 +03:00
adam jones
4f453ff2bd
Drop GET /v0/servers/{serverName} endpoint (#618)
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>
2025-10-07 13:56:45 +03:00
Radoslav Dimitrov
44950c23bb
Enforce schema validation on the publish and edit API level (#598)
<!-- 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>
2025-10-05 13:57:10 +01:00
Tadas Antanavicius
8bd13d5ed7
Apply gofmt formatting to all Go files (#588)
## 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>
2025-09-30 17:32:22 +03:00
tadasant
a0bc09dbe1 Revert "docs: clarify release deployment process and enable manual deploy trigger"
This reverts commit c40374c280.
2025-09-29 18:57:40 -07:00
tadasant
c40374c280 docs: clarify release deployment process and enable manual deploy trigger
- 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>
2025-09-29 18:54:56 -07:00
Joel Verhagen
df018fc43b
Share more code between DNS and HTTP auth flows (#552)
<!-- 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
-->
2025-09-29 23:43:27 +01:00
Radoslav Dimitrov
3762542ddc
Ensure registry API implements the reference openapi schema (#568)
<!-- 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>
2025-09-29 13:53:54 -07:00
Radoslav Dimitrov
b21c6f564d
Changes on the server.json format and the API (#562) 2025-09-29 23:30:35 +03:00
Ville Vesilehto
76365a61e3
fix: use io.LimitReader in key fetcher (#558)
## 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>
2025-09-26 11:24:07 +01:00
Radoslav Dimitrov
ddcc586842
Remove the in-memory database (#537)
<!-- 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>
2025-09-23 16:40:20 +01:00
adam jones
5746e7e99b
Remove OIDC authorization flow to fix data race vulnerability (#526)
## 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.
2025-09-22 13:41:32 +01:00
Tadas Antanavicius
56e8b4879b
Introduce serverId, rename id to versionId (#465)
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>
2025-09-21 15:00:09 +03:00
Ossama Lafhel
63cf08efad
fix: validate server names to allow only single slash (#471) (#476)
## 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"
2025-09-15 12:05:51 +01:00
adam jones
256c730198
Add test for filtered servers (#426)
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.
2025-09-11 07:51:57 +00:00
adam jones
6bb62d160e
fix: add HTTP middleware to redirect trailing slash URLs to canonical form (#420)
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>
2025-09-10 13:14:59 -07:00
adam jones
62f4453f37
feat: Add proper 404 error handling with helpful suggestions (#421)
Fixes #418

This PR addresses the issue where invalid API endpoints (like
`/servers`) were returning blank 200 responses instead of proper 404
errors.

## Changes

- Added catch-all 404 handler for unmatched routes
- Return RFC 7807 compliant JSON error responses
- Provide smart suggestions for common mistakes:
  - `/servers` → suggest `/v0/servers`
  - `/health` → suggest `/v0/health`
  - `/ping` → suggest `/v0/ping`
  - `/v1`, `/v2` → inform only v0 is supported
- Fixes blank 200 responses for invalid endpoints
- Improves API discoverability and debugging experience

## Testing

- ✅ Unit tests pass
- ✅ Integration tests pass
- ✅ Manual testing confirms proper 404 responses with helpful messages

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>
Co-authored-by: Radoslav Dimitrov <radoslav@stacklok.com>
2025-09-10 13:14:49 -07:00
adam jones
1236f3732d
Improve publish permission error message to show available permissions (#417)
## 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
2025-09-10 12:28:22 -07:00
adam jones
0eada9b3b4
refactor: consolidate server list response types (#387)
## 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
2025-09-09 11:47:27 +00:00
adam jones
f975e68cf2
Clean up schema by simplifying version structure (#379)
## 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.
2025-09-08 14:32:59 -07:00
adam jones
a85456a9b9
Add filtering functionality to server list endpoint (#374)
## 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 #291
Fixes #135
2025-09-08 13:55:33 -07:00
adam jones
576b759be4
Fix API title and redirect to external docs (#372)
## 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
2025-09-08 13:37:12 -07:00
adam jones
ef4607720d
Fix _meta field format for MCP spec compliance (#367)
## 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
2025-09-08 11:40:04 -07:00
adam jones
8f5e17d0fe
Enforce and document file hash requirement for MCPB packages (#368)
## 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
2025-09-08 11:38:25 -07:00
Radoslav Dimitrov
e0e51eae37
Reflect the latest registry changes in openapi.yaml (#345)
<!-- 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>
2025-09-05 21:07:08 +01:00
adam jones
694a4d8879
Add registry validators (#350)
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
2025-09-04 22:45:59 +01:00
adam jones
9d9a02c57f
Database implementation cleanup (#335)
## 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.
2025-09-02 13:37:28 +01:00
adam jones
218b0b422d
Implement flattened _meta format for server extensions (#331)
## Summary

This PR implements the flattened `_meta` format for server extensions as
discussed in #284, replacing the confusing wrapper format with a clean
single-file approach.

**Before (wrapper format):**
```json
{
  "server": { "name": "my-server", "description": "..." },
  "x-publisher": { "build_info": "..." },
  "x-io.modelcontextprotocol.registry": { "id": "...", "published_at": "..." }
}
```

**After (flattened format):**
```json
{
  "name": "my-server",
  "description": "...",
  "_meta": {
    "publisher": { "build_info": "..." },
    "io.modelcontextprotocol.registry": { "id": "...", "published_at": "..." }
  }
}
```

## Key Changes

- **Flattened Format**: Single `ServerJSON` file with structured `_meta`
field
- **Better DX**: Publishers maintain one file instead of separate
server.json + extensions.json
- **MCP Compliance**: Uses standard `_meta` mechanism instead of `x-*`
prefixes
- **Simplified Database**: PostgreSQL now uses simple `id, value` table
structure
- **Type Safety**: Structured `ServerMeta` with known extension fields

## Database Migration

Added migration `003_simplify_to_key_value.sql` that drops the complex
relational structure and creates a simple key-value table. This
significantly simplifies database management.

## Testing

- All core tests passing (validators, service layer)
- Schema validation working for all 10 examples
- Seed data successfully migrated (396 entries)
- Publishing functionality verified

Fixes #284
2025-09-01 19:27:23 +01:00
adam jones
654cad4aa7
Clean up publish and edit handler and service logic (#319)
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>
2025-08-28 20:20:43 +01:00
adam jones
c0a94cca8c
Rename api/v1 -> api/v0 to match API paths (#320)
This PR renames the API paths from v1 to v0 to align with the actual API
versioning scheme.
2025-08-28 15:06:00 +01:00
Radoslav Dimitrov
099a2d702e
Deduplicate server JSON structs between publisher and registry (#318)
<!-- 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>
2025-08-28 14:58:15 +01:00
adam jones
6431f23107
feat: add admin edit endpoint for server moderation (#315)
## 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)
2025-08-27 21:28:04 +01:00
adam jones
36fcdff044
feat: implement OIDC authentication for admin users (#316)
## 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
2025-08-27 18:59:49 +01:00
Avish Porwal
c3b72ef3a6
Add more validation for free-form server fields (#272)
<!-- 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>
2025-08-27 01:58:41 +01:00
adam jones
923b2e07b9
feat: implement DNS namespace validation and remote URL uniqueness checks (#306)
## 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>
2025-08-26 23:03:38 +01:00
adam jones
60c75b6591
Disable ireturn linter rule (#307)
## 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
2025-08-26 15:16:43 +01:00
Radoslav Dimitrov
8d7e471fd3
Allow for vendor extensions on servers (#298)
<!-- 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>
2025-08-23 09:59:03 +01:00
adam jones
ee910ca286
auth: Add HTTP-based authentication support to validate domain ownership (#282)
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.
2025-08-21 23:13:09 +01:00
adam jones
316cbb08ee
auth: Add DNS auth (#279)
Fixes #270
Closes #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
2025-08-21 22:43:20 +01:00