## Summary This PR implements the flattened `_meta` format for server extensions as discussed in #284, replacing the confusing wrapper format with a clean single-file approach. **Before (wrapper format):** ```json { "server": { "name": "my-server", "description": "..." }, "x-publisher": { "build_info": "..." }, "x-io.modelcontextprotocol.registry": { "id": "...", "published_at": "..." } } ``` **After (flattened format):** ```json { "name": "my-server", "description": "...", "_meta": { "publisher": { "build_info": "..." }, "io.modelcontextprotocol.registry": { "id": "...", "published_at": "..." } } } ``` ## Key Changes - **Flattened Format**: Single `ServerJSON` file with structured `_meta` field - **Better DX**: Publishers maintain one file instead of separate server.json + extensions.json - **MCP Compliance**: Uses standard `_meta` mechanism instead of `x-*` prefixes - **Simplified Database**: PostgreSQL now uses simple `id, value` table structure - **Type Safety**: Structured `ServerMeta` with known extension fields ## Database Migration Added migration `003_simplify_to_key_value.sql` that drops the complex relational structure and creates a simple key-value table. This significantly simplifies database management. ## Testing - All core tests passing (validators, service layer) - Schema validation working for all 10 examples - Seed data successfully migrated (396 entries) - Publishing functionality verified Fixes #284
59 lines
2.7 KiB
Go
59 lines
2.7 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
apiv0 "github.com/modelcontextprotocol/registry/pkg/api/v0"
|
|
)
|
|
|
|
// Common database errors
|
|
var (
|
|
ErrNotFound = errors.New("record not found")
|
|
ErrAlreadyExists = errors.New("record already exists")
|
|
ErrInvalidInput = errors.New("invalid input")
|
|
ErrDatabase = errors.New("database error")
|
|
ErrInvalidVersion = errors.New("invalid version: cannot publish duplicate version")
|
|
ErrMaxServersReached = errors.New("maximum number of versions for this server reached (10000): please reach out at https://github.com/modelcontextprotocol/registry to explain your use case")
|
|
)
|
|
|
|
// Database defines the interface for database operations with extension wrapper architecture
|
|
type Database interface {
|
|
// List retrieves all ServerRecord entries with optional filtering
|
|
List(ctx context.Context, filter map[string]any, cursor string, limit int) ([]*apiv0.ServerJSON, string, error)
|
|
// GetByID retrieves a single ServerRecord by its ID
|
|
GetByID(ctx context.Context, id string) (*apiv0.ServerJSON, error)
|
|
// Publish adds a new server to the database with separated server.json and extensions
|
|
// The registryMetadata contains metadata determined by the service layer (e.g., is_latest, timestamps)
|
|
Publish(ctx context.Context, serverDetail apiv0.ServerJSON, publisherExtensions map[string]interface{}, registryMetadata apiv0.RegistryExtensions) (*apiv0.ServerJSON, error)
|
|
// UpdateLatestFlag updates the is_latest flag for a specific server record
|
|
UpdateLatestFlag(ctx context.Context, id string, isLatest bool) error
|
|
// UpdateServer updates an existing server record with new server details
|
|
UpdateServer(ctx context.Context, id string, serverDetail apiv0.ServerJSON, publisherExtensions map[string]interface{}) (*apiv0.ServerJSON, error)
|
|
// ImportSeed imports initial data from a seed file
|
|
ImportSeed(ctx context.Context, seedFilePath string) error
|
|
// Close closes the database connection
|
|
Close() error
|
|
}
|
|
|
|
// ConnectionType represents the type of database connection
|
|
type ConnectionType string
|
|
|
|
const (
|
|
// ConnectionTypeMemory represents an in-memory database connection
|
|
ConnectionTypeMemory ConnectionType = "memory"
|
|
// ConnectionTypePostgreSQL represents a PostgreSQL database connection
|
|
ConnectionTypePostgreSQL ConnectionType = "postgresql"
|
|
)
|
|
|
|
// ConnectionInfo provides information about the database connection
|
|
type ConnectionInfo struct {
|
|
// Type indicates the type of database connection
|
|
Type ConnectionType
|
|
// IsConnected indicates whether the database is currently connected
|
|
IsConnected bool
|
|
// Raw provides access to the underlying connection object, which will vary by implementation
|
|
// For PostgreSQL, this will be *pgx.Conn
|
|
// For MemoryDB, this will be map[string]*model.MCPRegistry
|
|
Raw any
|
|
}
|