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
2 changed files with 95 additions and 92 deletions

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