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>
This commit is contained in:
Radoslav Dimitrov 2025-10-29 15:23:47 +02:00 • committed by GitHub
commit ef4a60505e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 95 additions and 92 deletions

View file

@ -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

View file

@ -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",
},

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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
}

View file

@ -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",
},

View file

@ -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."`

View file

@ -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/<owner>/<repo> --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"`
}