From 087d8085b7ec15ee9f671620ed10c5fd04725a8d Mon Sep 17 00:00:00 2001 From: Radoslav Dimitrov Date: Tue, 14 Oct 2025 15:26:43 +0300 Subject: [PATCH] Replace / with - for operation IDs (#660) ## Motivation and Context Follow up from #658 addressing the feedback from @tadasant ## How Has This Been Tested? ## Breaking Changes ## Types of changes - [ ] 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 - [ ] 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 Signed-off-by: Radoslav Dimitrov --- docs/guides/consuming/use-rest-api.md | 3 ++- internal/api/handlers/v0/auth/dns.go | 3 ++- internal/api/handlers/v0/auth/github_at.go | 3 ++- internal/api/handlers/v0/auth/github_oidc.go | 3 ++- internal/api/handlers/v0/auth/http.go | 2 +- internal/api/handlers/v0/auth/none.go | 3 ++- internal/api/handlers/v0/auth/oidc.go | 2 +- internal/api/handlers/v0/edit.go | 2 +- internal/api/handlers/v0/health.go | 3 ++- internal/api/handlers/v0/ping.go | 3 ++- internal/api/handlers/v0/publish.go | 2 +- internal/api/handlers/v0/servers.go | 7 ++++--- 12 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/guides/consuming/use-rest-api.md b/docs/guides/consuming/use-rest-api.md index 71942da..024e58d 100644 --- a/docs/guides/consuming/use-rest-api.md +++ b/docs/guides/consuming/use-rest-api.md @@ -9,10 +9,11 @@ Integration patterns and best practices for building applications that consume M **Authentication**: Not required for read-only access **API Versions**: -- `/v0/` - Development version with latest features (may receive additive changes) +- `/v0/` - Development version with latest features (may receive breaking changes) - `/v0.1/` - Stable version (only backward-compatible changes) **Recommendation**: Use `/v0.1/` for production applications requiring API stability. Both versions currently have identical functionality. +We may add breaking changes _only_ to `/v0/` in the future, and we reserve the possibility of deprecating `/v0/` entirely. **Core endpoints:** - **`GET /v0.1/servers`** - List all servers with pagination diff --git a/internal/api/handlers/v0/auth/dns.go b/internal/api/handlers/v0/auth/dns.go index 93a435a..87a812a 100644 --- a/internal/api/handlers/v0/auth/dns.go +++ b/internal/api/handlers/v0/auth/dns.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "net/http" + "strings" "github.com/danielgtaylor/huma/v2" v0 "github.com/modelcontextprotocol/registry/internal/api/handlers/v0" @@ -55,7 +56,7 @@ func RegisterDNSEndpoint(api huma.API, pathPrefix string, cfg *config.Config) { // DNS authentication endpoint huma.Register(api, huma.Operation{ - OperationID: "exchange-dns-token" + pathPrefix, + OperationID: "exchange-dns-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/dns", Summary: "Exchange DNS signature for Registry JWT", diff --git a/internal/api/handlers/v0/auth/github_at.go b/internal/api/handlers/v0/auth/github_at.go index 2f060a1..fbb950c 100644 --- a/internal/api/handlers/v0/auth/github_at.go +++ b/internal/api/handlers/v0/auth/github_at.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "regexp" + "strings" "github.com/danielgtaylor/huma/v2" v0 "github.com/modelcontextprotocol/registry/internal/api/handlers/v0" @@ -48,7 +49,7 @@ func RegisterGitHubATEndpoint(api huma.API, pathPrefix string, cfg *config.Confi // GitHub token exchange endpoint huma.Register(api, huma.Operation{ - OperationID: "exchange-github-token" + pathPrefix, + OperationID: "exchange-github-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/github-at", Summary: "Exchange GitHub OAuth access token for Registry JWT", diff --git a/internal/api/handlers/v0/auth/github_oidc.go b/internal/api/handlers/v0/auth/github_oidc.go index f935b96..e925fb5 100644 --- a/internal/api/handlers/v0/auth/github_oidc.go +++ b/internal/api/handlers/v0/auth/github_oidc.go @@ -9,6 +9,7 @@ import ( "io" "math/big" "net/http" + "strings" "github.com/danielgtaylor/huma/v2" "github.com/golang-jwt/jwt/v5" @@ -231,7 +232,7 @@ func RegisterGitHubOIDCEndpoint(api huma.API, pathPrefix string, cfg *config.Con // GitHub OIDC token exchange endpoint huma.Register(api, huma.Operation{ - OperationID: "exchange-github-oidc-token" + pathPrefix, + OperationID: "exchange-github-oidc-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/github-oidc", Summary: "Exchange GitHub OIDC token for Registry JWT", diff --git a/internal/api/handlers/v0/auth/http.go b/internal/api/handlers/v0/auth/http.go index f397e7d..e917f85 100644 --- a/internal/api/handlers/v0/auth/http.go +++ b/internal/api/handlers/v0/auth/http.go @@ -113,7 +113,7 @@ func RegisterHTTPEndpoint(api huma.API, pathPrefix string, cfg *config.Config) { // HTTP authentication endpoint huma.Register(api, huma.Operation{ - OperationID: "exchange-http-token" + pathPrefix, + OperationID: "exchange-http-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/http", Summary: "Exchange HTTP signature for Registry JWT", diff --git a/internal/api/handlers/v0/auth/none.go b/internal/api/handlers/v0/auth/none.go index b743121..9f373c1 100644 --- a/internal/api/handlers/v0/auth/none.go +++ b/internal/api/handlers/v0/auth/none.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "strings" "github.com/danielgtaylor/huma/v2" v0 "github.com/modelcontextprotocol/registry/internal/api/handlers/v0" @@ -37,7 +38,7 @@ func RegisterNoneEndpoint(api huma.API, pathPrefix string, cfg *config.Config) { // Anonymous token endpoint for development/testing only huma.Register(api, huma.Operation{ - OperationID: "get-anonymous-token", + OperationID: "get-anonymous-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/none", Summary: "Get anonymous Registry JWT (Development/Testing Only)", diff --git a/internal/api/handlers/v0/auth/oidc.go b/internal/api/handlers/v0/auth/oidc.go index 780a13e..0cef699 100644 --- a/internal/api/handlers/v0/auth/oidc.go +++ b/internal/api/handlers/v0/auth/oidc.go @@ -154,7 +154,7 @@ func RegisterOIDCEndpoints(api huma.API, pathPrefix string, cfg *config.Config) // Direct token exchange endpoint huma.Register(api, huma.Operation{ - OperationID: "exchange-oidc-token" + pathPrefix, + OperationID: "exchange-oidc-token" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/auth/oidc", Summary: "Exchange OIDC ID token for Registry JWT", diff --git a/internal/api/handlers/v0/edit.go b/internal/api/handlers/v0/edit.go index 46e048a..9c0286d 100644 --- a/internal/api/handlers/v0/edit.go +++ b/internal/api/handlers/v0/edit.go @@ -31,7 +31,7 @@ func RegisterEditEndpoints(api huma.API, pathPrefix string, registry service.Reg // Edit server endpoint huma.Register(api, huma.Operation{ - OperationID: "edit-server" + pathPrefix, + OperationID: "edit-server" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPut, Path: pathPrefix + "/servers/{serverName}/versions/{version}", Summary: "Edit MCP server", diff --git a/internal/api/handlers/v0/health.go b/internal/api/handlers/v0/health.go index 8fdf0ec..a9e8914 100644 --- a/internal/api/handlers/v0/health.go +++ b/internal/api/handlers/v0/health.go @@ -3,6 +3,7 @@ package v0 import ( "context" "net/http" + "strings" "github.com/danielgtaylor/huma/v2" "go.opentelemetry.io/otel/attribute" @@ -21,7 +22,7 @@ type HealthBody struct { // RegisterHealthEndpoint registers the health check endpoint with a custom path prefix func RegisterHealthEndpoint(api huma.API, pathPrefix string, cfg *config.Config, metrics *telemetry.Metrics) { huma.Register(api, huma.Operation{ - OperationID: "get-health" + pathPrefix, + OperationID: "get-health" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodGet, Path: pathPrefix + "/health", Summary: "Health check", diff --git a/internal/api/handlers/v0/ping.go b/internal/api/handlers/v0/ping.go index 4274609..c03a5f4 100644 --- a/internal/api/handlers/v0/ping.go +++ b/internal/api/handlers/v0/ping.go @@ -3,6 +3,7 @@ package v0 import ( "context" "net/http" + "strings" "github.com/danielgtaylor/huma/v2" ) @@ -15,7 +16,7 @@ type PingBody struct { // RegisterPingEndpoint registers the ping endpoint with a custom path prefix func RegisterPingEndpoint(api huma.API, pathPrefix string) { huma.Register(api, huma.Operation{ - OperationID: "ping" + pathPrefix, + OperationID: "ping" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodGet, Path: pathPrefix + "/ping", Summary: "Ping", diff --git a/internal/api/handlers/v0/publish.go b/internal/api/handlers/v0/publish.go index 97ed122..2bdb198 100644 --- a/internal/api/handlers/v0/publish.go +++ b/internal/api/handlers/v0/publish.go @@ -24,7 +24,7 @@ func RegisterPublishEndpoint(api huma.API, pathPrefix string, registry service.R jwtManager := auth.NewJWTManager(cfg) huma.Register(api, huma.Operation{ - OperationID: "publish-server" + pathPrefix, + OperationID: "publish-server" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodPost, Path: pathPrefix + "/publish", Summary: "Publish MCP server", diff --git a/internal/api/handlers/v0/servers.go b/internal/api/handlers/v0/servers.go index f9c02d7..f9f7ba5 100644 --- a/internal/api/handlers/v0/servers.go +++ b/internal/api/handlers/v0/servers.go @@ -5,6 +5,7 @@ import ( "errors" "net/http" "net/url" + "strings" "time" "github.com/danielgtaylor/huma/v2" @@ -44,7 +45,7 @@ type ServerVersionsInput struct { func RegisterServersEndpoints(api huma.API, pathPrefix string, registry service.RegistryService) { // List servers endpoint huma.Register(api, huma.Operation{ - OperationID: "list-servers" + pathPrefix, + OperationID: "list-servers" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodGet, Path: pathPrefix + "/servers", Summary: "List MCP servers", @@ -106,7 +107,7 @@ func RegisterServersEndpoints(api huma.API, pathPrefix string, registry service. // Get specific server version endpoint (supports "latest" as special version) huma.Register(api, huma.Operation{ - OperationID: "get-server-version" + pathPrefix, + OperationID: "get-server-version" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodGet, Path: pathPrefix + "/servers/{serverName}/versions/{version}", Summary: "Get specific MCP server version", @@ -147,7 +148,7 @@ func RegisterServersEndpoints(api huma.API, pathPrefix string, registry service. // Get server versions endpoint huma.Register(api, huma.Operation{ - OperationID: "get-server-versions" + pathPrefix, + OperationID: "get-server-versions" + strings.ReplaceAll(pathPrefix, "/", "-"), Method: http.MethodGet, Path: pathPrefix + "/servers/{serverName}/versions", Summary: "Get all versions of an MCP server",