Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions catalog/internal/catalog/mcpcatalog/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ type yamlMCPServer struct {
PublishedDate *string `yaml:"publishedDate,omitempty"`
Transports []string `yaml:"transports,omitempty"`
Tools []*yamlMCPTool `yaml:"tools,omitempty"`
Artifacts []*yamlMCPArtifact `yaml:"artifacts,omitempty"`
Artifacts []apimodels.MCPArtifact `yaml:"artifacts,omitempty"`
DeploymentMode *string `yaml:"deploymentMode,omitempty"`
Endpoints *yamlMCPEndpoints `yaml:"endpoints,omitempty"`
RuntimeMetadata *apimodels.MCPRuntimeMetadata `yaml:"runtimeMetadata,omitempty"`
Expand All @@ -138,13 +138,6 @@ type yamlMCPTool struct {
Parameters []yamlMCPParameter `yaml:"parameters,omitempty"`
}

// yamlMCPArtifact represents an MCP artifact (e.g., container image)
type yamlMCPArtifact struct {
Name string `yaml:"name"`
URI string `yaml:"uri"`
Type string `yaml:"type"`
}

// yamlMCPEndpoints represents MCP server endpoints
type yamlMCPEndpoints struct {
HTTP *string `yaml:"http,omitempty" json:"http,omitempty"`
Expand Down Expand Up @@ -360,7 +353,7 @@ func (ys *yamlMCPServer) ToMCPServerProviderRecord() MCPServerProviderRecord {
// Validate and convert artifacts to JSON
if len(ys.Artifacts) > 0 {
for i, artifact := range ys.Artifacts {
if err := basecatalog.ValidateArtifactURI(artifact.URI); err != nil {
if err := basecatalog.ValidateArtifactURI(artifact.Uri); err != nil {
return MCPServerProviderRecord{Error: fmt.Errorf("server %q artifact %d: %w", ys.Name, i, err)}
}
}
Expand Down
64 changes: 49 additions & 15 deletions catalog/internal/catalog/mcpcatalog/providers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,35 +438,35 @@ func TestYamlMCPArtifactURIValidation(t *testing.T) {
name: "artifact with valid oci URI passes",
server: &yamlMCPServer{
Name: "server-oci-artifact",
Artifacts: []*yamlMCPArtifact{
{Name: "container", URI: "oci://registry.example.com/image:v1", Type: "container"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "oci://registry.example.com/image:v1"},
},
},
},
{
name: "artifact with valid https URI passes",
server: &yamlMCPServer{
Name: "server-https-artifact",
Artifacts: []*yamlMCPArtifact{
{Name: "model", URI: "https://example.com/model.bin", Type: "model"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "https://example.com/model.bin"},
},
},
},
{
name: "artifact with valid s3 URI passes",
server: &yamlMCPServer{
Name: "server-s3-artifact",
Artifacts: []*yamlMCPArtifact{
{Name: "weights", URI: "s3://bucket/path/to/weights", Type: "weights"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "s3://bucket/path/to/weights"},
},
},
},
{
name: "artifact with invalid URI (no scheme) is rejected",
server: &yamlMCPServer{
Name: "server-invalid-uri",
Artifacts: []*yamlMCPArtifact{
{Name: "bad", URI: "not-a-valid-uri", Type: "model"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "not-a-valid-uri"},
},
},
wantErr: true,
Expand All @@ -476,8 +476,8 @@ func TestYamlMCPArtifactURIValidation(t *testing.T) {
name: "artifact with unsupported scheme is rejected",
server: &yamlMCPServer{
Name: "server-ftp-artifact",
Artifacts: []*yamlMCPArtifact{
{Name: "bad", URI: "ftp://example.com/model.bin", Type: "model"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "ftp://example.com/model.bin"},
},
},
wantErr: true,
Expand All @@ -487,8 +487,8 @@ func TestYamlMCPArtifactURIValidation(t *testing.T) {
name: "artifact with empty URI is rejected",
server: &yamlMCPServer{
Name: "server-empty-uri",
Artifacts: []*yamlMCPArtifact{
{Name: "empty", URI: "", Type: "model"},
Artifacts: []apimodels.MCPArtifact{
{Uri: ""},
},
},
wantErr: true,
Expand All @@ -498,9 +498,9 @@ func TestYamlMCPArtifactURIValidation(t *testing.T) {
name: "multiple artifacts with one invalid URI is rejected",
server: &yamlMCPServer{
Name: "server-mixed-artifacts",
Artifacts: []*yamlMCPArtifact{
{Name: "good", URI: "s3://bucket/valid", Type: "model"},
{Name: "bad", URI: "invalid-uri", Type: "model"},
Artifacts: []apimodels.MCPArtifact{
{Uri: "s3://bucket/valid"},
{Uri: "invalid-uri"},
},
},
wantErr: true,
Expand Down Expand Up @@ -530,6 +530,40 @@ func TestYamlMCPArtifactURIValidation(t *testing.T) {
}
}

func TestYamlMCPArtifactTimestampRoundTrip(t *testing.T) {
createTime := "1753292581000"
updateTime := "1774534350000"
server := &yamlMCPServer{
Name: "server-with-timestamps",
Artifacts: []apimodels.MCPArtifact{
{Uri: "oci://registry.example.com/image:v1", CreateTimeSinceEpoch: &createTime, LastUpdateTimeSinceEpoch: &updateTime},
},
}

record := server.ToMCPServerProviderRecord()
require.Nil(t, record.Error)
require.NotNil(t, record.Server.Properties)

var artifactsJSON string
for _, prop := range *record.Server.Properties {
if prop.Name == "artifacts" && prop.StringValue != nil {
artifactsJSON = *prop.StringValue
}
}
require.NotEmpty(t, artifactsJSON, "artifacts property should be set")

var artifacts []apimodels.MCPArtifact
err := json.Unmarshal([]byte(artifactsJSON), &artifacts)
require.NoError(t, err)
require.Len(t, artifacts, 1)

assert.Equal(t, "oci://registry.example.com/image:v1", artifacts[0].Uri)
require.NotNil(t, artifacts[0].CreateTimeSinceEpoch, "createTimeSinceEpoch should survive round-trip")
assert.Equal(t, "1753292581000", *artifacts[0].CreateTimeSinceEpoch)
require.NotNil(t, artifacts[0].LastUpdateTimeSinceEpoch, "lastUpdateTimeSinceEpoch should survive round-trip")
assert.Equal(t, "1774534350000", *artifacts[0].LastUpdateTimeSinceEpoch)
}

func TestYamlMCPServerLicenseTransformation(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading