Implements icon support based on the Model Context Protocol specification, allowing servers to specify display icons with optional size, MIME type, and theme variants. ## Changes - Add `Icon` type to `pkg/model/types.go` with struct tags for automatic API validation - Add `icons` field to `ServerJSON` in `pkg/api/v0/types.go` - Add icon validation in `internal/validators/validators.go`: - Only HTTPS URLs allowed (no HTTP or data URIs) - Maximum URL length of 255 characters - Validates absolute URLs with proper scheme - Update JSON schema and OpenAPI documentation with Icon definitions - Add comprehensive test cases for icon validation - Add example icon to seed.json (Airtable server) - Change `websiteUrl` validation to HTTPS-only for consistency ## Implementation Details The implementation uses a two-layer validation architecture: 1. **Huma framework** validates struct tags (`required`, `maxLength`, `enum`, `pattern`) and returns 422 for violations 2. **Custom validators** handle business logic (HTTPS scheme requirement, absolute URL requirement) and return 400 for violations This approach leverages Huma's automatic validation while keeping business-specific rules in the validator layer. ## Icon Field Specification - `src` (required): HTTPS URL to icon resource, max 255 characters - `mimeType` (optional): One of `image/png`, `image/jpeg`, `image/jpg`, `image/svg+xml`, `image/webp` - `sizes` (optional): Array of size strings in "WxH" format or "any" for scalable formats - `theme` (optional): Either "light" or "dark" to indicate intended background Multiple icons can be provided (e.g., for different themes or sizes).
44 lines
1.6 KiB
Go
44 lines
1.6 KiB
Go
package validators
|
|
|
|
import "errors"
|
|
|
|
// Error messages for validation
|
|
var (
|
|
// Repository validation errors
|
|
ErrInvalidRepositoryURL = errors.New("invalid repository URL")
|
|
ErrInvalidSubfolderPath = errors.New("invalid subfolder path")
|
|
|
|
// Package validation errors
|
|
ErrPackageNameHasSpaces = errors.New("package name cannot contain spaces")
|
|
ErrReservedVersionString = errors.New("version string 'latest' is reserved and cannot be used")
|
|
ErrVersionLooksLikeRange = errors.New("version must be a specific version, not a range")
|
|
|
|
// Remote validation errors
|
|
ErrInvalidRemoteURL = errors.New("invalid remote URL")
|
|
|
|
// Registry validation errors
|
|
ErrUnsupportedRegistryBaseURL = errors.New("unsupported registry base URL")
|
|
ErrMismatchedRegistryTypeAndURL = errors.New("registry type and base URL do not match")
|
|
|
|
// Argument validation errors
|
|
ErrNamedArgumentNameRequired = errors.New("named argument name is required")
|
|
ErrInvalidNamedArgumentName = errors.New("invalid named argument name format")
|
|
ErrArgumentValueStartsWithName = errors.New("argument value cannot start with the argument name")
|
|
ErrArgumentDefaultStartsWithName = errors.New("argument default cannot start with the argument name")
|
|
|
|
// Server name validation errors
|
|
ErrMultipleSlashesInServerName = errors.New("server name cannot contain multiple slashes")
|
|
ErrInvalidServerNameFormat = errors.New("server name format is invalid")
|
|
)
|
|
|
|
// RepositorySource represents valid repository sources
|
|
type RepositorySource string
|
|
|
|
const (
|
|
SourceGitHub RepositorySource = "github"
|
|
SourceGitLab RepositorySource = "gitlab"
|
|
)
|
|
|
|
const (
|
|
SchemeHTTPS = "https"
|
|
)
|