Fix _meta field format for MCP spec compliance (#367)

## Summary

Updates the `_meta` field structure to be compliant with the MCP
specification by using proper `prefix/name` format for vendor
extensions.

### Changes

- **Registry metadata**: `io.modelcontextprotocol.registry` →
`io.modelcontextprotocol.registry/official`
- **Publisher metadata**: `publisher` →
`io.modelcontextprotocol.registry/publisher-provided`
- **Database migration**: Updates indexes to use new field paths
- **Updated all code**: Service layer, validators, tests, and seed data

### Format Before
```json
{
  "_meta": {
    "publisher": { "license": "MIT" },
    "io.modelcontextprotocol.registry": { "id": "...", "is_latest": true }
  }
}
```

### Format After
```json
{
  "_meta": {
    "io.modelcontextprotocol.registry/publisher-provided": { "license": "MIT" },
    "io.modelcontextprotocol.registry/official": { "id": "...", "is_latest": true }
  }
}
```

This resolves the naming collision with the planned top-level
`publisher` field and ensures compliance with MCP specification
requirements.

Fixes #356
This commit is contained in:
adam jones 2025-09-08 11:40:04 -07:00 • committed by GitHub
commit ef4607720d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -113,8 +113,8 @@ func (s *registryServiceImpl) Publish(req apiv0.ServerJSON) (*apiv0.ServerJSON,
isNewLatest := true
if existingLatest != nil {
var existingPublishedAt time.Time
if existingLatest.Meta != nil && existingLatest.Meta.IOModelContextProtocolRegistry != nil {
existingPublishedAt = existingLatest.Meta.IOModelContextProtocolRegistry.PublishedAt
if existingLatest.Meta != nil && existingLatest.Meta.Official != nil {
existingPublishedAt = existingLatest.Meta.Official.PublishedAt
}
isNewLatest = CompareVersions(
serverJSON.VersionDetail.Version,
@ -133,7 +133,7 @@ func (s *registryServiceImpl) Publish(req apiv0.ServerJSON) (*apiv0.ServerJSON,
}
// Set registry metadata
server.Meta.IOModelContextProtocolRegistry = &apiv0.RegistryExtensions{
server.Meta.Official = &apiv0.RegistryExtensions{
ID: uuid.New().String(),
PublishedAt: publishTime,
UpdatedAt: publishTime,
@ -150,13 +150,13 @@ func (s *registryServiceImpl) Publish(req apiv0.ServerJSON) (*apiv0.ServerJSON,
// Mark previous latest as no longer latest
if isNewLatest && existingLatest != nil {
var existingLatestID string
if existingLatest.Meta != nil && existingLatest.Meta.IOModelContextProtocolRegistry != nil {
existingLatestID = existingLatest.Meta.IOModelContextProtocolRegistry.ID
if existingLatest.Meta != nil && existingLatest.Meta.Official != nil {
existingLatestID = existingLatest.Meta.Official.ID
}
if existingLatestID != "" {
// Update the existing server to set is_latest = false
existingLatest.Meta.IOModelContextProtocolRegistry.IsLatest = false
existingLatest.Meta.IOModelContextProtocolRegistry.UpdatedAt = time.Now()
existingLatest.Meta.Official.IsLatest = false
existingLatest.Meta.Official.UpdatedAt = time.Now()
if _, err := s.db.UpdateServer(ctx, existingLatestID, existingLatest); err != nil {
return nil, err
}
@ -193,8 +193,8 @@ func (s *registryServiceImpl) validateNoDuplicateRemoteURLs(ctx context.Context,
// getCurrentLatestVersion finds the current latest version from existing server versions
func (s *registryServiceImpl) getCurrentLatestVersion(existingServerVersions []*apiv0.ServerJSON) *apiv0.ServerJSON {
for _, server := range existingServerVersions {
if server.Meta != nil && server.Meta.IOModelContextProtocolRegistry != nil &&
server.Meta.IOModelContextProtocolRegistry.IsLatest {
if server.Meta != nil && server.Meta.Official != nil &&
server.Meta.Official.IsLatest {
return server
}
}