Skip to content
Closed
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
46 changes: 46 additions & 0 deletions pkg/registry/mocks/mock_provider.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion pkg/registry/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

package registry

import types "github.com/stacklok/toolhive-core/registry/types"
import (
types "github.com/stacklok/toolhive-core/registry/types"
"github.com/stacklok/toolhive/pkg/registry/api"
)

//go:generate mockgen -destination=mocks/mock_provider.go -package=mocks -source=provider.go Provider

Expand All @@ -30,4 +33,14 @@ type Provider interface {

// ListImageServers returns all available container servers
ListImageServers() ([]*types.ImageMetadata, error)

// Skills methods
// Providers that don't support skills (Local, Remote) return nil/empty results via BaseProvider.

// GetSkill returns a specific skill by namespace and name
GetSkill(namespace, name string) (*types.Skill, error)
// ListSkills returns all available skills
ListSkills(opts *api.SkillsListOptions) (*api.SkillsListResult, error)
// SearchSkills searches for skills matching the query
SearchSkills(query string) (*api.SkillsListResult, error)
}
29 changes: 29 additions & 0 deletions pkg/registry/provider_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type APIRegistryProvider struct {
apiURL string
allowPrivateIp bool
client api.Client
skillsClient api.SkillsClient
}

// NewAPIRegistryProvider creates a new API registry provider.
Expand All @@ -34,10 +35,17 @@ func NewAPIRegistryProvider(apiURL string, allowPrivateIp bool, tokenSource auth
return nil, fmt.Errorf("failed to create API client: %w", err)
}

// Create skills client
skillsClient, err := api.NewSkillsClient(apiURL, allowPrivateIp, tokenSource)
if err != nil {
return nil, fmt.Errorf("failed to create skills client: %w", err)
}

p := &APIRegistryProvider{
apiURL: apiURL,
allowPrivateIp: allowPrivateIp,
client: client,
skillsClient: skillsClient,
}

// Initialize the base provider with the GetRegistry function
Expand Down Expand Up @@ -188,6 +196,27 @@ func (p *APIRegistryProvider) GetImageServer(name string) (*types.ImageMetadata,
return nil, fmt.Errorf("server %s is not a container server", name)
}

// GetSkill returns a specific skill by namespace and name.
func (p *APIRegistryProvider) GetSkill(namespace, name string) (*types.Skill, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return p.skillsClient.GetSkill(ctx, namespace, name)
}

// ListSkills returns all available skills.
func (p *APIRegistryProvider) ListSkills(opts *api.SkillsListOptions) (*api.SkillsListResult, error) {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
return p.skillsClient.ListSkills(ctx, opts)
}

// SearchSkills searches for skills matching the query.
func (p *APIRegistryProvider) SearchSkills(query string) (*api.SkillsListResult, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return p.skillsClient.SearchSkills(ctx, query)
}

// ConvertServerJSON converts an MCP Registry API ServerJSON to ToolHive ServerMetadata
// Uses converters from converters.go (same package)
// Note: Only handles OCI packages and remote servers, skips npm/pypi by design
Expand Down
16 changes: 16 additions & 0 deletions pkg/registry/provider_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

types "github.com/stacklok/toolhive-core/registry/types"
"github.com/stacklok/toolhive/pkg/registry/api"
)

// BaseProvider provides common implementation for registry providers
Expand Down Expand Up @@ -131,6 +132,21 @@ func (p *BaseProvider) ListImageServers() ([]*types.ImageMetadata, error) {
return results, nil
}

// GetSkill returns nil for providers that don't support skills.
func (*BaseProvider) GetSkill(_, _ string) (*types.Skill, error) {
return nil, nil
}

// ListSkills returns empty results for providers that don't support skills.
func (*BaseProvider) ListSkills(_ *api.SkillsListOptions) (*api.SkillsListResult, error) {
return &api.SkillsListResult{}, nil
}

// SearchSkills returns empty results for providers that don't support skills.
func (*BaseProvider) SearchSkills(_ string) (*api.SkillsListResult, error) {
return &api.SkillsListResult{}, nil
}

// matchesQuery checks if a server matches the search query
func matchesQuery(name, description string, tags []string, query string) bool {
// Search in name
Expand Down
2 changes: 2 additions & 0 deletions pkg/registry/provider_cached.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const (
// CachedAPIRegistryProvider wraps APIRegistryProvider with caching support.
// Provides both in-memory and optional persistent file caching.
// Works for both CLI (with persistent cache) and API server (memory only).
// Skills methods (GetSkill, ListSkills, SearchSkills) are uncached pass-through
// to the underlying APIRegistryProvider; skills caching may be added later.
type CachedAPIRegistryProvider struct {
*APIRegistryProvider

Expand Down
Loading
Loading