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>
This commit is contained in:
parent
6d2001b831
commit
4f453ff2bd
3 changed files with 37 additions and 78 deletions
|
|
@ -41,8 +41,6 @@ type ServerVersionsInput struct {
|
|||
}
|
||||
|
||||
// RegisterServersEndpoints registers all server-related endpoints
|
||||
//
|
||||
//nolint:cyclop // Multiple endpoint registrations are inherently complex
|
||||
func RegisterServersEndpoints(api huma.API, registry service.RegistryService) {
|
||||
// List servers endpoint
|
||||
huma.Register(api, huma.Operation{
|
||||
|
|
@ -106,42 +104,13 @@ func RegisterServersEndpoints(api huma.API, registry service.RegistryService) {
|
|||
}, nil
|
||||
})
|
||||
|
||||
// Get server details endpoint (latest version)
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "get-server",
|
||||
Method: http.MethodGet,
|
||||
Path: "/v0/servers/{serverName}",
|
||||
Summary: "Get MCP server details",
|
||||
Description: "Get detailed information about the latest version of a specific MCP server.",
|
||||
Tags: []string{"servers"},
|
||||
}, func(ctx context.Context, input *ServerDetailInput) (*Response[apiv0.ServerResponse], error) {
|
||||
// URL-decode the server name
|
||||
serverName, err := url.PathUnescape(input.ServerName)
|
||||
if err != nil {
|
||||
return nil, huma.Error400BadRequest("Invalid server name encoding", err)
|
||||
}
|
||||
|
||||
// Get latest version by server name
|
||||
serverResponse, err := registry.GetServerByName(ctx, serverName)
|
||||
if err != nil {
|
||||
if err.Error() == errRecordNotFound || errors.Is(err, database.ErrNotFound) {
|
||||
return nil, huma.Error404NotFound("Server not found")
|
||||
}
|
||||
return nil, huma.Error500InternalServerError("Failed to get server details", err)
|
||||
}
|
||||
|
||||
return &Response[apiv0.ServerResponse]{
|
||||
Body: *serverResponse,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Get specific server version endpoint
|
||||
// Get specific server version endpoint (supports "latest" as special version)
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "get-server-version",
|
||||
Method: http.MethodGet,
|
||||
Path: "/v0/servers/{serverName}/versions/{version}",
|
||||
Summary: "Get specific MCP server version",
|
||||
Description: "Get detailed information about a specific version of an MCP server.",
|
||||
Description: "Get detailed information about a specific version of an MCP server. Use the special version 'latest' to get the latest version.",
|
||||
Tags: []string{"servers"},
|
||||
}, func(ctx context.Context, input *ServerVersionDetailInput) (*Response[apiv0.ServerResponse], error) {
|
||||
// URL-decode the server name
|
||||
|
|
@ -156,8 +125,14 @@ func RegisterServersEndpoints(api huma.API, registry service.RegistryService) {
|
|||
return nil, huma.Error400BadRequest("Invalid version encoding", err)
|
||||
}
|
||||
|
||||
// Get specific version by server name and version
|
||||
serverResponse, err := registry.GetServerByNameAndVersion(ctx, serverName, version)
|
||||
var serverResponse *apiv0.ServerResponse
|
||||
// Handle "latest" as a special version
|
||||
if version == "latest" {
|
||||
serverResponse, err = registry.GetServerByName(ctx, serverName)
|
||||
} else {
|
||||
serverResponse, err = registry.GetServerByNameAndVersion(ctx, serverName, version)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err.Error() == errRecordNotFound || errors.Is(err, database.ErrNotFound) {
|
||||
return nil, huma.Error404NotFound("Server not found")
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func TestListServersEndpoint(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetServerByNameEndpoint(t *testing.T) {
|
||||
func TestGetLatestServerVersionEndpoint(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
registryService := service.NewRegistryService(database.NewTestDB(t), config.NewConfig())
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ func TestGetServerByNameEndpoint(t *testing.T) {
|
|||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "get existing server",
|
||||
name: "get existing server latest version",
|
||||
serverName: "com.example/detail-server",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
|
|
@ -155,7 +155,7 @@ func TestGetServerByNameEndpoint(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
// URL encode the server name
|
||||
encodedName := url.PathEscape(tt.serverName)
|
||||
req := httptest.NewRequest(http.MethodGet, "/v0/servers/"+encodedName, nil)
|
||||
req := httptest.NewRequest(http.MethodGet, "/v0/servers/"+encodedName+"/versions/latest", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
mux.ServeHTTP(w, req)
|
||||
|
|
@ -434,9 +434,9 @@ func TestServersEndpointEdgeCases(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Test server detail endpoint
|
||||
// Test latest version endpoint
|
||||
encodedName := url.PathEscape(tt.serverName)
|
||||
req := httptest.NewRequest(http.MethodGet, "/v0/servers/"+encodedName, nil)
|
||||
req := httptest.NewRequest(http.MethodGet, "/v0/servers/"+encodedName+"/versions/latest", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
mux.ServeHTTP(w, req)
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ func TestPrometheusHandler(t *testing.T) {
|
|||
// Add /metrics for Prometheus metrics using promhttp
|
||||
mux.Handle("/metrics", metrics.PrometheusHandler())
|
||||
|
||||
// Create request - using new name-based API
|
||||
url := "/v0/servers/" + url.PathEscape(server.Server.Name)
|
||||
// Create request - using latest version endpoint
|
||||
url := "/v0/servers/" + url.PathEscape(server.Server.Name) + "/versions/latest"
|
||||
req := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
|
|
@ -78,5 +78,5 @@ func TestPrometheusHandler(t *testing.T) {
|
|||
// Check if the response body contains expected metrics
|
||||
assert.Contains(t, body, "mcp_registry_http_request_duration_bucket")
|
||||
assert.Contains(t, body, "mcp_registry_http_requests_total")
|
||||
assert.Contains(t, body, "path=\"/v0/servers/{serverName}\"")
|
||||
assert.Contains(t, body, "path=\"/v0/servers/{serverName}/versions/{version}\"")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue