service

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package service provides shared service utilities for the registry server.

Package service provides the business logic for the MCP registry API

Package service defines skill-related types returned by the service layer and mapping from sqlc (database) row types.

Package service provides the business logic for the MCP registry API

Package service provides the business logic for the MCP registry API

Index

Constants

View Source
const (
	// DefaultPageSize is the default number of items per page when no limit is specified.
	// This matches the upstream MCP Registry API default of 30.
	DefaultPageSize = 30
	// MaxPageSize is the maximum allowed items per page to prevent potential DoS.
	MaxPageSize = 1000

	// SkillPackageTypeOCI is the type for OCI packages
	SkillPackageTypeOCI = "oci"
	// SkillPackageTypeGit is the type for Git packages
	SkillPackageTypeGit = "git"
)

Pagination constants used by all RegistryService implementations. These values are aligned with the upstream MCP Registry API specification.

View Source
const CursorSeparator = ","

CursorSeparator is the delimiter used to separate fields in the cursor. We use comma because it does not appear in:

  • server names: [a-zA-Z][a-zA-Z0-9_-]*
  • ISO timestamps: contains colons and hyphens but not commas
  • semver versions: digits, dots, hyphens, plus signs

Variables

View Source
var (
	// ErrNotFound is returned when a server is not found
	ErrNotFound = errors.New("not found")
	// ErrNotImplemented is returned when a feature is not implemented
	ErrNotImplemented = errors.New("not implemented")
	// ErrRegistryNotFound is returned when a registry is not found
	ErrRegistryNotFound = errors.New("registry not found")
	// ErrVersionAlreadyExists is returned when attempting to publish a version that already exists
	ErrVersionAlreadyExists = errors.New("version already exists")
	// ErrConfigSource is returned when attempting to modify a CONFIG-created source via API
	ErrConfigSource = errors.New("cannot modify config-created source via API")
	// ErrInvalidSourceConfig is returned when source configuration is invalid
	ErrInvalidSourceConfig = errors.New("invalid source configuration")
	// ErrSourceAlreadyExists is returned when attempting to create a source that already exists
	ErrSourceAlreadyExists = errors.New("source already exists")
	// ErrSourceTypeChangeNotAllowed is returned when attempting to change a source's type
	ErrSourceTypeChangeNotAllowed = errors.New("changing source type is not allowed")
	// ErrSourceNotFound is returned when a source is not found
	ErrSourceNotFound = errors.New("source not found")
	// ErrNoManagedSource is returned when no managed source is found
	ErrNoManagedSource = errors.New("no managed source found")
	// ErrRegistryAlreadyExists is returned when attempting to create a registry that already exists
	ErrRegistryAlreadyExists = errors.New("registry already exists")
	// ErrConfigRegistry is returned when attempting to modify a CONFIG-created registry via API
	ErrConfigRegistry = errors.New("cannot modify config-created registry via API")
	// ErrInvalidRegistryConfig is returned when registry configuration is invalid
	ErrInvalidRegistryConfig = errors.New("invalid registry configuration")
	// ErrSourceInUse is returned when attempting to delete a source that is linked to registries
	ErrSourceInUse = errors.New("source is referenced by one or more registries")
	// ErrClaimsMismatch is returned when publish claims do not match the existing entry's claims
	ErrClaimsMismatch = errors.New("claims mismatch")
	// ErrClaimsInsufficient is returned when the caller's JWT claims do not cover a resource's claims
	ErrClaimsInsufficient = errors.New("insufficient claims")
)

Functions

func DecodeCursor added in v0.5.1

func DecodeCursor(cursor string) (name, version string, err error)

DecodeCursor decodes a base64-encoded cursor string into name and version components. The cursor format is: base64(name,version) Returns empty strings if the cursor is empty.

func EncodeCursor added in v0.5.1

func EncodeCursor(name, version string) string

EncodeCursor encodes a name and version into a base64 cursor string. The cursor format is: base64(name,version)

func ValidateInlineDataBasic added in v0.4.7

func ValidateInlineDataBasic(data string) error

ValidateInlineDataBasic performs basic validation on inline registry data. It uses the existing registry data validator to parse and validate both toolhive and upstream formats.

func ValidateInlineDataWithFormat added in v0.4.7

func ValidateInlineDataWithFormat(data string, format string) error

ValidateInlineDataWithFormat validates inline registry data with a specific format. If format is empty, it tries upstream format first, then falls back to toolhive.

func ValidateRegistryConfig added in v0.4.7

func ValidateRegistryConfig(req *RegistryCreateRequest) error

ValidateRegistryConfig validates a RegistryCreateRequest

func ValidateSourceConfig added in v1.0.0

func ValidateSourceConfig(req *SourceCreateRequest) error

ValidateSourceConfig validates a SourceCreateRequest

Types

type CreationType added in v0.4.7

type CreationType string

CreationType indicates how the registry was created

const (
	// CreationTypeAPI indicates the registry was created via API
	CreationTypeAPI CreationType = "API"
	// CreationTypeCONFIG indicates the registry was created from config file
	CreationTypeCONFIG CreationType = "CONFIG"
)

type DeleteServerVersionOptions added in v0.3.0

type DeleteServerVersionOptions struct {
	ServerName string
	Version    string
	JWTClaims  map[string]any
}

DeleteServerVersionOptions is the options for the DeleteServerVersion operation

type DeleteSkillVersionOptions added in v0.6.3

type DeleteSkillVersionOptions struct {
	Namespace string
	Name      string
	Version   string
	JWTClaims map[string]any
}

DeleteSkillVersionOptions is the options for the DeleteSkillVersion operation

type DeployedServer

type DeployedServer struct {
	Name        string `json:"name"`
	Namespace   string `json:"namespace"`
	Status      string `json:"status"`
	Image       string `json:"image"`
	Transport   string `json:"transport"`
	Ready       bool   `json:"ready"`
	EndpointURL string `json:"endpoint_url,omitempty"`
}

DeployedServer represents a deployed MCP server in Kubernetes

type EntryVersionInfo added in v1.0.0

type EntryVersionInfo struct {
	Version     string    `json:"version"`
	Title       string    `json:"title,omitempty"`
	Description string    `json:"description,omitempty"`
	CreatedAt   time.Time `json:"createdAt"`
	UpdatedAt   time.Time `json:"updatedAt"`
}

EntryVersionInfo represents a single version of an entry.

type GetServerVersionOptions added in v0.3.0

type GetServerVersionOptions struct {
	RegistryName string
	SourceName   string
	Name         string
	Version      string
	Claims       map[string]any
}

GetServerVersionOptions is the options for the GetServerVersion operation

type GetSkillVersionOptions added in v0.6.3

type GetSkillVersionOptions struct {
	RegistryName string
	SourceName   string
	Namespace    string
	Name         string
	Version      string
	Claims       map[string]any
}

GetSkillVersionOptions is the options for the GetSkillVersion operation.

type ListServerVersionsOptions added in v0.3.0

type ListServerVersionsOptions struct {
	RegistryName string
	Name         string
	Limit        int
	Claims       map[string]any
}

ListServerVersionsOptions is the options for the ListServerVersions operation

type ListServersOptions added in v0.3.0

type ListServersOptions struct {
	RegistryName string
	Cursor       string
	Limit        int
	Search       string
	UpdatedSince time.Time
	Version      string
	Claims       map[string]any
}

ListServersOptions is the options for the ListServers operation

type ListServersResult added in v0.5.1

type ListServersResult struct {
	// Servers is the list of servers matching the query
	Servers []*upstreamv0.ServerJSON
	// NextCursor is the cursor to use for fetching the next page of results.
	// Empty string indicates no more results are available.
	NextCursor string
}

ListServersResult contains the result of a ListServers operation with pagination info. It wraps the server list with cursor-based pagination metadata.

type ListSkillsOptions added in v0.6.3

type ListSkillsOptions struct {
	RegistryName string
	Namespace    string
	Name         *string
	Version      *string
	Search       *string
	Limit        int
	Cursor       *string
	Claims       map[string]any
}

ListSkillsOptions is the options for the ListSkills and ListSkillVersions operations.

type ListSkillsResult added in v0.6.3

type ListSkillsResult struct {
	Skills     []*Skill `json:"skills"`
	NextCursor string   `json:"-"`
}

ListSkillsResult contains the result of a ListSkills operation with pagination.

type Option

type Option func(T any) error

Option is a function that sets an option for service operations

func WithClaims added in v1.0.0

func WithClaims(claims map[string]any) Option

WithClaims sets the claims for the PublishServerVersion or PublishSkill operation

func WithCursor added in v0.3.0

func WithCursor(cursor string) Option

WithCursor sets the cursor for the ListServers operation

func WithJWTClaims added in v1.0.0

func WithJWTClaims(claims map[string]any) Option

WithJWTClaims sets the caller's JWT claims for authorization checks (e.g., verifying published claims are a subset of the publisher's JWT).

func WithLimit added in v0.3.0

func WithLimit(limit int) Option

WithLimit sets the limit for the ListServers or ListServerVersions operation

func WithName added in v0.3.0

func WithName(name string) Option

WithName sets the name for the ListServerVersions, GetServerVersion, or DeleteServerVersion operation

func WithNamespace added in v0.6.3

func WithNamespace(namespace string) Option

WithNamespace sets the namespace for the ListSkills, GetLatestSkillVersion, or DeleteSkillVersion operation

func WithRegistryName added in v0.3.0

func WithRegistryName(registryName string) Option

WithRegistryName sets the registry name for the ListServers, ListServerVersions, GetServerVersion, or DeleteServerVersion operation

func WithSearch added in v0.3.0

func WithSearch(search string) Option

WithSearch sets the search for the ListServers operation

func WithServerData added in v0.3.0

func WithServerData(serverData *upstreamv0.ServerJSON) Option

WithServerData sets the server data for the PublishServerVersion operation

func WithUpdatedSince added in v0.3.0

func WithUpdatedSince(updatedSince time.Time) Option

WithUpdatedSince sets the updated since for the ListServers operation

func WithVersion added in v0.3.0

func WithVersion(version string) Option

WithVersion sets the version for the ListServers, GetServerVersion, or DeleteServerVersion operation

type PublishServerVersionOptions added in v0.3.0

type PublishServerVersionOptions struct {
	ServerData *upstreamv0.ServerJSON
	Claims     map[string]any
	JWTClaims  map[string]any
}

PublishServerVersionOptions is the options for the PublishServerVersion operation

type PublishSkillOptions added in v0.6.3

type PublishSkillOptions struct {
	Claims    map[string]any
	JWTClaims map[string]any
}

PublishSkillOptions is the options for the PublishSkill operation

type RecordFilter added in v1.0.0

type RecordFilter func(ctx context.Context, record any) (bool, error)

RecordFilter is a predicate applied to records after they are fetched from the database. Return true to keep the record, false to drop it. An error aborts the listing operation.

type RegistryCreateRequest added in v0.4.7

type RegistryCreateRequest struct {
	Sources []string       `json:"sources"`          // ordered list of source names
	Claims  map[string]any `json:"claims,omitempty"` // Authorization claims
}

RegistryCreateRequest represents the request body for creating or updating a registry

type RegistryEntriesResponse added in v1.0.0

type RegistryEntriesResponse struct {
	Entries []RegistryEntryInfo `json:"entries"`
}

RegistryEntriesResponse is the JSON envelope for listing registry entries.

type RegistryEntryInfo added in v1.0.0

type RegistryEntryInfo struct {
	EntryType  string `json:"entryType"`
	Name       string `json:"name"`
	Version    string `json:"version"`
	SourceName string `json:"sourceName"`
}

RegistryEntryInfo represents a lightweight entry in a registry listing.

type RegistryInfo added in v0.3.2

type RegistryInfo struct {
	Name         string         `json:"name"`
	Claims       map[string]any `json:"claims,omitempty"`
	CreationType CreationType   `json:"creationType,omitempty"`
	Sources      []string       `json:"sources"`
	CreatedAt    time.Time      `json:"createdAt"`
	UpdatedAt    time.Time      `json:"updatedAt"`
}

RegistryInfo represents detailed information about a registry

type RegistryService

type RegistryService interface {

	// CheckReadiness checks if the regSvc is ready to serve requests
	CheckReadiness(ctx context.Context) error

	// ListServers returns all servers in the registry with pagination info
	ListServers(ctx context.Context, opts ...Option) (*ListServersResult, error)

	// ListServerVersions returns all versions of a specific server
	ListServerVersions(ctx context.Context, opts ...Option) ([]*upstreamv0.ServerJSON, error)

	// GetServerVersion returns a specific server version by name
	GetServerVersion(ctx context.Context, opts ...Option) (*upstreamv0.ServerJSON, error)

	// PublishServerVersion publishes a server version to a managed registry
	PublishServerVersion(ctx context.Context, opts ...Option) (*upstreamv0.ServerJSON, error)

	// DeleteServerVersion removes a server version from a managed registry
	DeleteServerVersion(ctx context.Context, opts ...Option) error

	// ListSources returns all configured sources
	ListSources(ctx context.Context) ([]SourceInfo, error)

	// GetSourceByName returns a single source by name
	GetSourceByName(ctx context.Context, name string) (*SourceInfo, error)

	// CreateSource creates a new API-managed source
	CreateSource(ctx context.Context, name string, req *SourceCreateRequest) (*SourceInfo, error)

	// UpdateSource updates an existing API-managed source
	UpdateSource(ctx context.Context, name string, req *SourceCreateRequest) (*SourceInfo, error)

	// DeleteSource deletes an API-managed source
	DeleteSource(ctx context.Context, name string) error

	// ListSourceEntries returns all entries for a source (unshadowed, all types)
	ListSourceEntries(ctx context.Context, sourceName string) ([]SourceEntryInfo, error)

	// ListRegistries returns all configured registries
	ListRegistries(ctx context.Context) ([]RegistryInfo, error)

	// GetRegistryByName returns a single registry by name
	GetRegistryByName(ctx context.Context, name string) (*RegistryInfo, error)

	// CreateRegistry creates a new API-managed registry
	CreateRegistry(ctx context.Context, name string, req *RegistryCreateRequest) (*RegistryInfo, error)

	// UpdateRegistry updates an existing API-managed registry
	UpdateRegistry(ctx context.Context, name string, req *RegistryCreateRequest) (*RegistryInfo, error)

	// DeleteRegistry deletes an API-managed registry
	DeleteRegistry(ctx context.Context, name string) error

	// ListRegistryEntries returns all entries across a registry's linked sources (unshadowed, lightweight)
	ListRegistryEntries(ctx context.Context, registryName string) ([]RegistryEntryInfo, error)

	// ProcessInlineSourceData processes inline data for a managed/file registry
	ProcessInlineSourceData(ctx context.Context, name string, data string, format string) error

	// ListSkills lists skills in a registry with cursor-based pagination
	ListSkills(ctx context.Context, opts ...Option) (*ListSkillsResult, error)

	// GetSkillVersion gets a specific skill version. If the version is
	// "latest", the latest version will be returned.
	GetSkillVersion(ctx context.Context, opts ...Option) (*Skill, error)

	// PublishSkill publishes a skill
	PublishSkill(ctx context.Context, skill *Skill, opts ...Option) (*Skill, error)

	// DeleteSkillVersion deletes a skill version
	DeleteSkillVersion(ctx context.Context, opts ...Option) error
}

RegistryService defines the interface for registry operations

type Skill added in v0.6.3

type Skill struct {
	ID            string           `json:"id,omitempty"`
	Namespace     string           `json:"namespace"`
	Name          string           `json:"name"`
	Description   string           `json:"description"`
	Version       string           `json:"version"`
	Status        string           `json:"status,omitempty"`
	Title         string           `json:"title,omitempty"`
	License       string           `json:"license,omitempty"`
	Compatibility string           `json:"compatibility,omitempty"`
	AllowedTools  []string         `json:"allowedTools,omitempty"`
	Repository    *SkillRepository `json:"repository,omitempty"`
	Icons         []SkillIcon      `json:"icons,omitempty"`
	Packages      []SkillPackage   `json:"packages,omitempty"`
	Metadata      map[string]any   `json:"metadata,omitempty"`
	Meta          map[string]any   `json:"_meta,omitempty"`
	IsLatest      bool             `json:"isLatest,omitempty"`
	CreatedAt     time.Time        `json:"createdAt,omitempty"`
	UpdatedAt     time.Time        `json:"updatedAt,omitempty"`
}

Skill is a single skill returned by ListSkills, ListSkillVersions, GetSkillVersion, GetLatestSkillVersion, and PublishSkill.

func GetSkillVersionRowToSkill added in v0.6.3

func GetSkillVersionRowToSkill(row sqlc.GetSkillVersionRow) *Skill

GetSkillVersionRowToSkill maps a sqlc GetSkillVersionRow to a service Skill.

func ListSkillsRowToSkill added in v0.6.3

func ListSkillsRowToSkill(row sqlc.ListSkillsRow) *Skill

ListSkillsRowToSkill maps a sqlc ListSkillsRow to a service Skill.

type SkillIcon added in v0.6.3

type SkillIcon struct {
	Src   string `json:"src"`
	Size  string `json:"size,omitempty"`
	Type  string `json:"type,omitempty"`
	Label string `json:"label,omitempty"`
}

SkillIcon represents a display icon for a skill at the service layer.

type SkillPackage added in v0.6.3

type SkillPackage struct {
	RegistryType string `json:"registryType"`
	Identifier   string `json:"identifier,omitempty"`
	Digest       string `json:"digest,omitempty"`
	MediaType    string `json:"mediaType,omitempty"`
	URL          string `json:"url,omitempty"`
	Ref          string `json:"ref,omitempty"`
	Commit       string `json:"commit,omitempty"`
	Subfolder    string `json:"subfolder,omitempty"`
}

SkillPackage represents a package for a skill at the service layer.

type SkillRepository added in v0.6.3

type SkillRepository struct {
	URL  string `json:"url,omitempty"`
	Type string `json:"type,omitempty"`
}

SkillRepository represents source repository metadata at the service layer.

type SourceCreateRequest added in v1.0.0

type SourceCreateRequest struct {
	Format     string                   `json:"format,omitempty"`     // "toolhive" or "upstream"
	Git        *config.GitConfig        `json:"git,omitempty"`        // Git repository source
	API        *config.APIConfig        `json:"api,omitempty"`        // API endpoint source
	File       *config.FileConfig       `json:"file,omitempty"`       // Local file or URL source
	Managed    *config.ManagedConfig    `json:"managed,omitempty"`    // Managed registry (no sync)
	Kubernetes *config.KubernetesConfig `json:"kubernetes,omitempty"` // Kubernetes discovery source
	SyncPolicy *config.SyncPolicyConfig `json:"syncPolicy,omitempty"` // Sync schedule configuration
	Filter     *config.FilterConfig     `json:"filter,omitempty"`     // Name/tag filtering rules
	Claims     map[string]any           `json:"claims,omitempty"`     // Authorization claims
}

SourceCreateRequest represents the request body for creating or updating a source

func (*SourceCreateRequest) CountSourceTypes added in v1.0.0

func (r *SourceCreateRequest) CountSourceTypes() int

CountSourceTypes returns the number of source types configured

func (*SourceCreateRequest) GetSourceConfig added in v1.0.0

func (r *SourceCreateRequest) GetSourceConfig() any

GetSourceConfig returns the active source configuration

func (*SourceCreateRequest) GetSourceType added in v1.0.0

func (r *SourceCreateRequest) GetSourceType() config.SourceType

GetSourceType returns the source type based on which config is set

func (*SourceCreateRequest) IsInlineData added in v1.0.0

func (r *SourceCreateRequest) IsInlineData() bool

IsInlineData returns true if this is a file source with inline data

func (*SourceCreateRequest) IsNonSyncedType added in v1.0.0

func (r *SourceCreateRequest) IsNonSyncedType() bool

IsNonSyncedType returns true if the source type doesn't require syncing

type SourceEntriesResponse added in v1.0.0

type SourceEntriesResponse struct {
	Entries []SourceEntryInfo `json:"entries"`
}

SourceEntriesResponse is the JSON envelope for listing source entries.

type SourceEntryInfo added in v1.0.0

type SourceEntryInfo struct {
	EntryType string             `json:"entryType"`
	Name      string             `json:"name"`
	Claims    map[string]any     `json:"claims,omitempty"`
	Versions  []EntryVersionInfo `json:"versions"`
}

SourceEntryInfo represents a single entry within a source, including all versions.

type SourceInfo added in v1.0.0

type SourceInfo struct {
	Name         string               `json:"name"`
	Type         string               `json:"type"`                   // MANAGED, FILE, REMOTE, KUBERNETES
	CreationType CreationType         `json:"creationType,omitempty"` // API or CONFIG
	SourceType   config.SourceType    `json:"sourceType,omitempty"`   // git, api, file, managed, kubernetes
	Format       string               `json:"format,omitempty"`       // toolhive or upstream
	SourceConfig any                  `json:"sourceConfig,omitempty"` // Type-specific source configuration
	FilterConfig *config.FilterConfig `json:"filterConfig,omitempty"` // Filtering rules
	SyncSchedule string               `json:"syncSchedule,omitempty"` // Sync interval string
	Claims       map[string]any       `json:"claims,omitempty"`       // Authorization claims
	SyncStatus   *SourceSyncStatus    `json:"syncStatus,omitempty"`
	CreatedAt    time.Time            `json:"createdAt"`
	UpdatedAt    time.Time            `json:"updatedAt"`
}

SourceInfo represents detailed information about a source

type SourceListResponse added in v1.0.0

type SourceListResponse struct {
	Sources []SourceInfo `json:"sources"`
}

SourceListResponse represents the response for listing sources

type SourceSyncStatus added in v1.0.0

type SourceSyncStatus struct {
	Phase        string     `json:"phase"`                  // complete, syncing, failed
	LastSyncTime *time.Time `json:"lastSyncTime,omitempty"` // Last successful sync
	LastAttempt  *time.Time `json:"lastAttempt,omitempty"`  // Last sync attempt
	AttemptCount int        `json:"attemptCount"`           // Number of sync attempts
	ServerCount  int        `json:"serverCount"`            // Number of servers in registry
	SkillCount   int        `json:"skillCount"`             // Number of skills in registry
	Message      string     `json:"message,omitempty"`      // Status or error message
}

SourceSyncStatus represents the sync status of a registry

Directories

Path Synopsis
Package database provides a database-backed implementation of the RegistryService interface
Package database provides a database-backed implementation of the RegistryService interface
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL