Documentation
¶
Overview ¶
Package catalog ships clawtool's built-in source catalog.
Per ADR-008, the catalog is the fast path for `clawtool source add <name>`. Each entry knows the canonical package, runtime, required env vars, and auth flow hint for one well-known MCP source server. The catalog is a single TOML file embedded in the binary — no network calls during a `source add`, no first-run download, fully offline-capable.
External catalog federation (Docker MCP Catalog, MCP Registry, Smithery) is a planned extension; this package currently exposes only the built-in.
Index ¶
Constants ¶
const DefaultRegistryURL = "https://registry.modelcontextprotocol.io"
DefaultRegistryURL is the official MCP Registry base URL (https://registry.modelcontextprotocol.io). This endpoint replaced the third-party server list previously curated in modelcontextprotocol/servers (PR #3950, 2026-04-14): the registry is now the canonical discovery surface for MCP servers across the ecosystem.
The clawtool catalog still ships an embedded `builtin.toml` for offline / hot-path source-add — the registry is a federated overlay, NOT a replacement. ProbeRegistry below is the foundation for future ticks that surface registry-only entries via `clawtool source registry` or fall back to the registry when a bare name misses the builtin catalog.
const DefaultSmitheryRegistryURL = "https://registry.smithery.ai"
DefaultSmitheryRegistryURL is the Smithery MCP catalog base URL (https://registry.smithery.ai). Smithery is a third-party catalog that complements the official MCP Registry — it ships hundreds of MCP servers (often ahead of the official registry's curation cadence) including remote-only entries hosted by Smithery itself. Probing both gives the operator a more complete view of the MCP ecosystem.
Wire shape differs from the official registry:
- endpoint: `/servers?page=1&pageSize=N` (cursor pagination, not limit-based)
- response: `{servers: [{qualifiedName, displayName, description, ...}]}` — flat, no `_meta` envelope
- no per-entry version field (server versions live one level deeper at the per-server detail endpoint, not in the list)
ProbeSmitheryRegistry projects Smithery's `qualifiedName` → RegistryServer.Name and `description` → RegistryServer.Description so callers can reuse the same RegistryResult shape across both registries.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Catalog ¶
type Catalog struct {
SchemaVersion int `toml:"schema_version"`
Entries map[string]Entry `toml:"entries"`
}
Catalog is the in-memory representation of one catalog file.
func Builtin ¶
Builtin parses the embedded catalog. Returns an error only when the embedded TOML itself is malformed — i.e., a build-time bug we want to surface loudly.
func (*Catalog) List ¶
func (c *Catalog) List() []NamedEntry
List returns all entries sorted by name. Drives `clawtool source list --available` (a future flag) and any introspection surface.
func (*Catalog) Lookup ¶
Lookup resolves a bare name (e.g. "github") to its entry. Returns ok=false when the name is not in the catalog so callers can fall back to the long-form path or report a curated suggestion.
func (*Catalog) SuggestSimilar ¶
SuggestSimilar returns up to `limit` candidate names that share a substring with `name` in either direction. Catches both partial input (`git` → `github`) and typos with extra characters (`github-typo` → `github`).
We don't reach for full Levenshtein here because catalog names are short and bidirectional substring matching covers the realistic typo patterns users hit at the CLI.
type Entry ¶
type Entry struct {
Description string `toml:"description"`
Runtime string `toml:"runtime"`
Package string `toml:"package"`
Args []string `toml:"args,omitempty"`
RequiredEnv []string `toml:"required_env,omitempty"`
AuthHint string `toml:"auth_hint,omitempty"`
Homepage string `toml:"homepage,omitempty"`
Maintained string `toml:"maintained,omitempty"`
}
Entry is one source-server description.
func (Entry) EnvTemplate ¶
EnvTemplate returns a map keyed by required_env names with `${VAR}`-style values that secrets resolution will fill in at spawn time. Empty when no auth required.
func (Entry) ToSourceCommand ¶
ToSourceCommand renders the runtime + package + args into the argv that would be exec'd to spawn this source. Used by CLI source-add to populate `[sources.<name>].command` in config.toml. Variable references like `${FILESYSTEM_ROOT}` are preserved verbatim — interpolation happens at spawn time against secrets + env, not now.
Mapping (per ADR-008):
npx → npx -y <package> [args...] node → node node_modules/<package>/index.js [args...] python → uvx <package> [args...] (uvx is the modern uv-managed runner) docker → docker run -i --rm <image> [args...] binary → <package> [args...] (PATH-resolved)
type NamedEntry ¶
NamedEntry pairs an entry with its catalog key (name) for sorted listing.
type RegistryResult ¶ added in v0.22.42
type RegistryResult struct {
BaseURL string `json:"base_url"`
Count int `json:"count"`
Servers []RegistryServer `json:"servers"`
}
RegistryResult is the parsed `ProbeRegistry` response: how many servers came back + their summary projections + the effective base URL used (echoes the resolved value back so callers writing diagnostics can show what was actually hit).
func ProbeRegistry ¶ added in v0.22.42
ProbeRegistry hits the MCP Registry's `/v0/servers` endpoint at `baseURL` and returns the first `limit` server entries.
`baseURL` defaults to DefaultRegistryURL when empty. Trailing slashes are tolerated. `limit` is clamped to the inclusive range [1, 50] — the upstream caps page size around 50, and callers asking for 0 or a negative number get the friendly default of 10.
The function is intentionally read-only and short-circuit- friendly: an unreachable endpoint, a non-200 response, or malformed JSON all surface as wrapped errors so the caller (a CLI verb or a future catalog-fallback path) can decide whether to fall back to the embedded builtin catalog or propagate the failure.
HTTP timeout is 8 seconds — long enough for sane network conditions, short enough that an offline operator gets a clear failure rather than a 30+ second hang.
func ProbeSmitheryRegistry ¶ added in v0.22.47
ProbeSmitheryRegistry hits Smithery's `/servers?page=1&pageSize=N` endpoint and projects the response into the same RegistryResult shape ProbeRegistry returns. Lets callers (CLI verb / MCP tool / catalog fallback path) treat the two registries as interchangeable read-only data sources.
Same defensive defaults as ProbeRegistry: empty baseURL falls to DefaultSmitheryRegistryURL, trailing slash tolerated, limit clamped to [1, 50] (Smithery's pageSize accepts up to 50).
Smithery's flat envelope means the inner unwrap step ProbeRegistry needs (`{servers: [{server: {...}}]}`) collapses to a direct slice decode here.
type RegistryServer ¶ added in v0.22.42
type RegistryServer struct {
// Name is the canonical server identifier in the registry,
// e.g. "ac.inference.sh/mcp" or "io.github.octocat/server".
// Always present.
Name string `json:"name"`
// Description is the one-line registry description. May be
// empty when the server author didn't supply one.
Description string `json:"description,omitempty"`
// Version is the upstream's declared semver. Different
// versions of the same server appear as separate entries
// in the registry (server vendors publish each release).
Version string `json:"version,omitempty"`
}
RegistryServer is the projection of one MCP Registry server entry that clawtool actually uses. The upstream payload is richer (remotes, packages, repository, _meta) — we capture only the fields useful for catalog probing + listing. Future migrations can extend this struct without breaking existing callers since JSON unmarshalling tolerates unknown fields by default.