diff --git a/internal/api/handlers/v0/servers.go b/internal/api/handlers/v0/servers.go index 12a1bde..da05af7 100644 --- a/internal/api/handlers/v0/servers.go +++ b/internal/api/handlers/v0/servers.go @@ -12,13 +12,6 @@ import ( apiv0 "github.com/modelcontextprotocol/registry/pkg/api/v0" ) -// Metadata contains pagination metadata -type Metadata struct { - NextCursor string `json:"next_cursor,omitempty"` - Count int `json:"count,omitempty"` - Total int `json:"total,omitempty"` -} - // ListServersInput represents the input for listing servers type ListServersInput struct { Cursor string `query:"cursor" doc:"Pagination cursor (UUID)" format:"uuid" required:"false" example:"550e8400-e29b-41d4-a716-446655440000"` @@ -28,12 +21,6 @@ type ListServersInput struct { Version string `query:"version" doc:"Filter by version ('latest' for latest version, or an exact version like '1.2.3')" required:"false" example:"latest"` } -// ListServersBody represents the paginated server list response body -type ListServersBody struct { - Servers []apiv0.ServerJSON `json:"servers" doc:"List of MCP servers with extensions"` - Metadata *Metadata `json:"metadata,omitempty" doc:"Pagination metadata"` -} - // ServerDetailInput represents the input for getting server details type ServerDetailInput struct { ID string `path:"id" doc:"Server ID (UUID)" format:"uuid"` @@ -49,7 +36,7 @@ func RegisterServersEndpoints(api huma.API, registry service.RegistryService) { Summary: "List MCP servers", Description: "Get a paginated list of MCP servers from the registry", Tags: []string{"servers"}, - }, func(_ context.Context, input *ListServersInput) (*Response[ListServersBody], error) { + }, func(_ context.Context, input *ListServersInput) (*Response[apiv0.ServerListResponse], error) { // Validate cursor if provided if input.Cursor != "" { _, err := uuid.Parse(input.Cursor) @@ -94,21 +81,14 @@ func RegisterServersEndpoints(api huma.API, registry service.RegistryService) { return nil, huma.Error500InternalServerError("Failed to get registry list", err) } - // Build response body - body := ListServersBody{ - Servers: servers, - } - - // Add metadata if there's a next cursor - if nextCursor != "" { - body.Metadata = &Metadata{ - NextCursor: nextCursor, - Count: len(servers), - } - } - - return &Response[ListServersBody]{ - Body: body, + return &Response[apiv0.ServerListResponse]{ + Body: apiv0.ServerListResponse{ + Servers: servers, + Metadata: apiv0.Metadata{ + NextCursor: nextCursor, + Count: len(servers), + }, + }, }, nil }) diff --git a/internal/api/handlers/v0/servers_test.go b/internal/api/handlers/v0/servers_test.go index 66fa5f5..76652b7 100644 --- a/internal/api/handlers/v0/servers_test.go +++ b/internal/api/handlers/v0/servers_test.go @@ -26,7 +26,7 @@ func TestServersListEndpoint(t *testing.T) { setupRegistryService func(service.RegistryService) expectedStatus int expectedServers []apiv0.ServerJSON - expectedMeta *v0.Metadata + expectedMeta *apiv0.Metadata expectedError string }{ { @@ -268,10 +268,7 @@ func TestServersListEndpoint(t *testing.T) { assert.Equal(t, "application/json", w.Header().Get("Content-Type")) // Parse response body - var resp struct { - Servers []apiv0.ServerJSON `json:"servers"` - Metadata *v0.Metadata `json:"metadata,omitempty"` - } + var resp apiv0.ServerListResponse err := json.NewDecoder(w.Body).Decode(&resp) assert.NoError(t, err) @@ -297,7 +294,7 @@ func TestServersListEndpoint(t *testing.T) { default: assert.NotEmpty(t, resp.Servers, "Expected at least one server") } - + // General structure validation for _, server := range resp.Servers { assert.NotEmpty(t, server.Name) @@ -311,11 +308,9 @@ func TestServersListEndpoint(t *testing.T) { // Check metadata if expected if tc.expectedMeta != nil { assert.NotNil(t, resp.Metadata, "Expected metadata to be present") - if resp.Metadata != nil { - assert.Equal(t, tc.expectedMeta.Count, resp.Metadata.Count) - if tc.expectedMeta.NextCursor != "" { - assert.NotEmpty(t, resp.Metadata.NextCursor) - } + assert.Equal(t, tc.expectedMeta.Count, resp.Metadata.Count) + if tc.expectedMeta.NextCursor != "" { + assert.NotEmpty(t, resp.Metadata.NextCursor) } } } else if tc.expectedError != "" { @@ -336,7 +331,7 @@ func TestServersDetailEndpoint(t *testing.T) { testServer, err := registryService.Publish(apiv0.ServerJSON{ Name: "com.example/test-server", Description: "A test server", - Version: "1.0.0", + Version: "1.0.0", }) assert.NoError(t, err) @@ -466,9 +461,7 @@ func TestServersEndpointsIntegration(t *testing.T) { assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) // Parse response body - var listResp struct { - Servers []apiv0.ServerJSON `json:"servers"` - } + var listResp apiv0.ServerListResponse err = json.NewDecoder(resp.Body).Decode(&listResp) assert.NoError(t, err) diff --git a/pkg/api/v0/types.go b/pkg/api/v0/types.go index e5101bd..41c7d42 100644 --- a/pkg/api/v0/types.go +++ b/pkg/api/v0/types.go @@ -17,7 +17,7 @@ type RegistryExtensions struct { // ServerListResponse represents the paginated server list response type ServerListResponse struct { Servers []ServerJSON `json:"servers"` - Metadata *Metadata `json:"metadata,omitempty"` + Metadata Metadata `json:"metadata"` } // ServerMeta represents the structured metadata with known extension fields @@ -42,6 +42,5 @@ type ServerJSON struct { // Metadata represents pagination metadata type Metadata struct { NextCursor string `json:"next_cursor,omitempty"` - Count int `json:"count,omitempty"` - Total int `json:"total,omitempty"` + Count int `json:"count"` }