From ef4a60505e2e545d9df61667e5025c6c9df8511d Mon Sep 17 00:00:00 2001 From: Radoslav Dimitrov Date: Wed, 29 Oct 2025 15:23:47 +0200 Subject: [PATCH] Make Repository field properly optional in server.json (#717) ## Motivation and Context 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? ## 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 --- cmd/publisher/commands/init.go | 17 +-- cmd/publisher/commands/publish_test.go | 2 +- internal/api/handlers/v0/edit_test.go | 12 +- .../handlers/v0/publish_integration_test.go | 6 +- internal/api/handlers/v0/publish_test.go | 14 +-- internal/api/handlers/v0/telemetry_test.go | 2 +- internal/importer/importer_test.go | 4 +- internal/validators/validators.go | 6 +- internal/validators/validators_test.go | 118 +++++++++--------- pkg/api/v0/types.go | 2 +- pkg/model/types.go | 4 +- 11 files changed, 95 insertions(+), 92 deletions(-) diff --git a/cmd/publisher/commands/init.go b/cmd/publisher/commands/init.go index 42fd182..dc4ec87 100644 --- a/cmd/publisher/commands/init.go +++ b/cmd/publisher/commands/init.go @@ -387,14 +387,17 @@ func createServerJSON( } // Create repository with optional subfolder - repo := model.Repository{ - URL: repoURL, - Source: repoSource, - } + var repo *model.Repository + if repoURL != "" && repoSource != "" { + repo = &model.Repository{ + URL: repoURL, + Source: repoSource, + } - // Only set subfolder if we're actually in a subdirectory - if subfolder != "" { - repo.Subfolder = subfolder + // Only set subfolder if we're actually in a subdirectory + if subfolder != "" { + repo.Subfolder = subfolder + } } // Create server structure diff --git a/cmd/publisher/commands/publish_test.go b/cmd/publisher/commands/publish_test.go index a7e5618..8527020 100644 --- a/cmd/publisher/commands/publish_test.go +++ b/cmd/publisher/commands/publish_test.go @@ -69,7 +69,7 @@ func TestPublishCommand_DeprecatedSchema(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test", Source: "github", }, diff --git a/internal/api/handlers/v0/edit_test.go b/internal/api/handlers/v0/edit_test.go index 87e82eb..66089db 100644 --- a/internal/api/handlers/v0/edit_test.go +++ b/internal/api/handlers/v0/edit_test.go @@ -46,7 +46,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.testuser/editable-server", Description: "Server that can be edited", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/editable-server", Source: "github", ID: "testuser/editable-server", @@ -57,7 +57,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.otheruser/other-server", Description: "Server owned by another user", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/otheruser/other-server", Source: "github", ID: "otheruser/other-server", @@ -77,7 +77,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.testuser/deleted-server", Description: "Server that was deleted", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/deleted-server", Source: "github", ID: "testuser/deleted-server", @@ -96,7 +96,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.testuser/build-metadata-server", Description: "Server with build metadata version", Version: "1.0.0+20130313144700", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/build-metadata-server", Source: "github", ID: "testuser/build-metadata-server", @@ -133,7 +133,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.testuser/editable-server", Description: "Updated server description", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/editable-server", Source: "github", ID: "testuser/editable-server", @@ -347,7 +347,7 @@ func TestEditServerEndpoint(t *testing.T) { Name: "io.github.testuser/build-metadata-server", Description: "Updated server with build metadata", Version: "1.0.0+20130313144700", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/build-metadata-server", Source: "github", ID: "testuser/build-metadata-server", diff --git a/internal/api/handlers/v0/publish_integration_test.go b/internal/api/handlers/v0/publish_integration_test.go index 540d211..3b06a69 100644 --- a/internal/api/handlers/v0/publish_integration_test.go +++ b/internal/api/handlers/v0/publish_integration_test.go @@ -60,7 +60,7 @@ func TestPublishIntegration(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "io.github.testuser/test-mcp-server", Description: "A test MCP server for integration testing", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/testuser/test-mcp-server", Source: "github", ID: "testuser/test-mcp-server", @@ -105,7 +105,7 @@ func TestPublishIntegration(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-mcp-server-no-auth", Description: "A test MCP server without authentication", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -191,7 +191,7 @@ func TestPublishIntegration(t *testing.T) { Name: "io.github.other/test-server", Description: "A test server", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", diff --git a/internal/api/handlers/v0/publish_test.go b/internal/api/handlers/v0/publish_test.go index b70cdac..0a00659 100644 --- a/internal/api/handlers/v0/publish_test.go +++ b/internal/api/handlers/v0/publish_test.go @@ -59,7 +59,7 @@ func TestPublishEndpoint(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "io.github.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -84,7 +84,7 @@ func TestPublishEndpoint(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "example/test-server", Description: "A test server without auth", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -149,7 +149,7 @@ func TestPublishEndpoint(t *testing.T) { Name: "io.github.other/test-server", Description: "A test server", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -174,7 +174,7 @@ func TestPublishEndpoint(t *testing.T) { Name: "example/test-server", Description: "A test server", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -193,7 +193,7 @@ func TestPublishEndpoint(t *testing.T) { Name: "example/test-server", Description: "Existing test server", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server-existing", Source: "github", ID: "example/test-server-existing", @@ -239,7 +239,7 @@ func TestPublishEndpoint(t *testing.T) { Name: "com.example/server/path", Description: "Server with multiple slashes in name", Version: "1.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", @@ -334,7 +334,7 @@ func TestPublishEndpoint(t *testing.T) { Name: "com.example/test/server/v2", Description: "Complex server with invalid name", Version: "2.0.0", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", diff --git a/internal/api/handlers/v0/telemetry_test.go b/internal/api/handlers/v0/telemetry_test.go index 4951b9e..54b4ad5 100644 --- a/internal/api/handlers/v0/telemetry_test.go +++ b/internal/api/handlers/v0/telemetry_test.go @@ -27,7 +27,7 @@ func TestPrometheusHandler(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "io.github.example/test-server", Description: "Test server detail", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/example/test-server", Source: "github", ID: "example/test-server", diff --git a/internal/importer/importer_test.go b/internal/importer/importer_test.go index 0a4f7b6..8337e93 100644 --- a/internal/importer/importer_test.go +++ b/internal/importer/importer_test.go @@ -26,7 +26,7 @@ func TestImportService_LocalFile(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "io.github.test/test-server-1", Description: "Test server 1", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/test/repo1", Source: "github", ID: "123", @@ -69,7 +69,7 @@ func TestImportService_HTTPFile(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "io.github.test/http-test-server", Description: "HTTP test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/test/http-repo", Source: "github", ID: "456", diff --git a/internal/validators/validators.go b/internal/validators/validators.go index dc70ff1..ffdb4a8 100644 --- a/internal/validators/validators.go +++ b/internal/validators/validators.go @@ -74,7 +74,7 @@ func ValidateServerJSON(serverJSON *apiv0.ServerJSON) error { } // Validate repository - if err := validateRepository(&serverJSON.Repository); err != nil { + if err := validateRepository(serverJSON.Repository); err != nil { return err } @@ -122,8 +122,8 @@ func ValidateServerJSON(serverJSON *apiv0.ServerJSON) error { } func validateRepository(obj *model.Repository) error { - // Skip validation for empty repository (optional field) - if obj.URL == "" && obj.Source == "" { + // Skip validation if repository is nil or empty (optional field) + if obj == nil || (obj.URL == "" && obj.Source == "") { return nil } diff --git a/internal/validators/validators_test.go b/internal/validators/validators_test.go index 57d044c..1b08c9b 100644 --- a/internal/validators/validators_test.go +++ b/internal/validators/validators_test.go @@ -24,7 +24,7 @@ func TestValidate(t *testing.T) { serverDetail: apiv0.ServerJSON{ Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -38,7 +38,7 @@ func TestValidate(t *testing.T) { Schema: "https://static.modelcontextprotocol.io/schemas/2025-01-27/server.schema.json", Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -52,7 +52,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -66,7 +66,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -80,7 +80,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -102,7 +102,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -124,7 +124,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -146,7 +146,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -160,7 +160,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -174,7 +174,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -188,7 +188,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -202,7 +202,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -216,7 +216,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -251,7 +251,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", ID: "owner/repo", @@ -283,7 +283,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://bitbucket.org/owner/repo", Source: "bitbucket", // Not in validSources }, @@ -297,7 +297,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner", // Missing repo name Source: "github", }, @@ -311,7 +311,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://gitlab.com", // Missing owner and repo Source: "gitlab", }, @@ -325,7 +325,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "servers/my-server", @@ -340,7 +340,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "../parent/folder", @@ -355,7 +355,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "/absolute/path", @@ -370,7 +370,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "servers/my-server/", @@ -385,7 +385,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "servers/my server", @@ -400,7 +400,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", Subfolder: "servers//my-server", @@ -415,7 +415,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -430,7 +430,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -445,7 +445,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -460,7 +460,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -475,7 +475,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -490,7 +490,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -505,7 +505,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -520,7 +520,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -544,7 +544,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -569,7 +569,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -601,7 +601,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -621,7 +621,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -641,7 +641,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -661,7 +661,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -681,7 +681,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -705,7 +705,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -721,7 +721,7 @@ func TestValidate(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1645,7 +1645,7 @@ func TestValidate_RegistryTypesAndUrls(t *testing.T) { Schema: model.CurrentSchemaURL, Name: tc.name, Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", ID: "owner/repo", @@ -1682,7 +1682,7 @@ func createValidServerWithArgument(arg model.Argument) apiv0.ServerJSON { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", ID: "owner/repo", @@ -1721,7 +1721,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "GitHub", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1736,7 +1736,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "Weather API", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1751,7 +1751,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1766,7 +1766,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "GitHub MCP Server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1781,7 +1781,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "GitHub MCP", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1796,7 +1796,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "GitHub mcp server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1811,7 +1811,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "GitHub-MCP", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1826,7 +1826,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: "MCP Weather API", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1841,7 +1841,7 @@ func TestValidateTitle(t *testing.T) { Name: "com.example/test-server", Description: "A test server", Title: " ", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1856,7 +1856,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1875,7 +1875,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1897,7 +1897,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1918,7 +1918,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1938,7 +1938,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1962,7 +1962,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -1981,7 +1981,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, @@ -2000,7 +2000,7 @@ func TestValidateTitle(t *testing.T) { Schema: model.CurrentSchemaURL, Name: "com.example/test-server", Description: "A test server", - Repository: model.Repository{ + Repository: &model.Repository{ URL: "https://github.com/owner/repo", Source: "github", }, diff --git a/pkg/api/v0/types.go b/pkg/api/v0/types.go index 1bfbe63..b6eab37 100644 --- a/pkg/api/v0/types.go +++ b/pkg/api/v0/types.go @@ -36,7 +36,7 @@ type ServerJSON struct { Name string `json:"name" minLength:"3" maxLength:"200" pattern:"^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$" doc:"Server name in reverse-DNS format. Must contain exactly one forward slash separating namespace from server name." example:"io.github.user/weather"` Description string `json:"description" minLength:"1" maxLength:"100" doc:"Clear human-readable explanation of server functionality." example:"MCP server providing weather data and forecasts via OpenWeatherMap API"` Title string `json:"title,omitempty" minLength:"1" maxLength:"100" doc:"Optional human-readable title or display name for the MCP server." example:"Weather API"` - Repository model.Repository `json:"repository,omitempty" doc:"Optional repository metadata for the MCP server source code."` + Repository *model.Repository `json:"repository,omitempty" doc:"Optional repository metadata for the MCP server source code."` Version string `json:"version" doc:"Version string for this server. SHOULD follow semantic versioning." example:"1.0.2"` WebsiteURL string `json:"websiteUrl,omitempty" format:"uri" doc:"Optional URL to the server's homepage, documentation, or project website." example:"https://modelcontextprotocol.io/examples"` Icons []model.Icon `json:"icons,omitempty" doc:"Optional set of sized icons that the client can display in a user interface."` diff --git a/pkg/model/types.go b/pkg/model/types.go index fe85f5a..454e225 100644 --- a/pkg/model/types.go +++ b/pkg/model/types.go @@ -48,8 +48,8 @@ type Package struct { } type Repository struct { - URL string `json:"url" format:"uri" doc:"Repository URL for browsing source code. Should support both web browsing and git clone operations." example:"https://github.com/modelcontextprotocol/servers"` - Source string `json:"source" doc:"Repository hosting service identifier. Used by registries to determine validation and API access methods." example:"github"` + URL string `json:"url,omitempty" format:"uri" doc:"Repository URL for browsing source code. Should support both web browsing and git clone operations." example:"https://github.com/modelcontextprotocol/servers"` + Source string `json:"source,omitempty" doc:"Repository hosting service identifier. Used by registries to determine validation and API access methods." example:"github"` ID string `json:"id,omitempty" doc:"Repository identifier from the hosting service (e.g., GitHub repo ID). Owned and determined by the source forge. Should remain stable across repository renames and may be used to detect repository resurrection attacks - if a repository is deleted and recreated, the ID should change. For GitHub, use: gh api repos// --jq '.id'" example:"b94b5f7e-c7c6-d760-2c78-a5e9b8a5b8c9"` Subfolder string `json:"subfolder,omitempty" doc:"Optional relative path from repository root to the server location within a monorepo or nested package structure. Must be a clean relative path." example:"src/everything"` }