Skip to main content

Module registry

Module registry 

Source
Expand description

Resolving MCP servers from the official MCP registry.

The built-in catalog (catalog.rs) is twelve entries compiled into the binary. This module reaches the community registry at https://registry.modelcontextprotocol.io, which holds thousands, and turns one of its entries into the same CapabilityManifest the catalog produces, so installation, drift, update and mcp doctor all work on a registry server without knowing where it came from.

§Turning a registry entry into a launch command

A registry entry does not carry a command line. It describes a package (npm, PyPI, OCI, NuGet) plus the arguments and environment variables that package needs, and leaves assembling the invocation to the client. The rules used here, in order:

  1. Prefer a package whose transport is stdio; that is what Tuff can launch and what tuff mcp doctor can probe.
  2. The command is the entry’s runtimeHint when it sets one, otherwise it is derived from registryType: npm runs under npx, pypi under uvx, oci under docker, nuget under dnx.
  3. Arguments are runtimeArguments, then the package reference itself, then packageArguments. npx also gets -y so a first run does not stop on a prompt, and docker gets run -i --rm plus one -e per environment variable, because a container sees nothing otherwise.
  4. Environment variables contribute their names only, as { from_env = "NAME" } references. A registry entry can carry a default value for a variable; Tuff never copies one into a manifest, because a manifest is committed and a value there would be a leaked secret waiting to happen.

§What is refused, and why refusing is the right answer

An entry that cannot be expressed exactly is refused with the reason rather than installed approximately: a wrong launch command wastes more of someone’s time than a clear “no”.

  • Unresolved {placeholders}. The registry lets an argument or URL carry variables for the client to fill in. Tuff has nowhere to ask, and guessing a value would produce a command that looks right and fails.
  • Literal header values. A manifest has no field a literal can occupy, by design, so a header the registry documents as a constant (Accept: application/json) cannot be represented.
  • The superseded sse transport. A different handshake from Streamable HTTP; installing one as the other would write a config no harness could use.
  • Package kinds with no launcher, such as mcpb bundles.

§Remote servers and their headers

A remote entry’s required headers become [server.headers] references (RFC-106). Where the publisher documents the shape of the value, as Bearer {api_key}, that becomes the header’s format and the placeholder’s name becomes the variable. Where they document only the header, the variable holds the entire value, prefix included: Tuff does not guess a Bearer that nobody wrote down. Optional headers are left out and named at install time, since requiring a variable the server does not require would report a working server as broken.

Structs§

RegistryArgument
RegistryPackage
RegistryRemote
RegistryServer
One server as the registry describes it. Only the fields Tuff reads.
RegistryTransport
RegistryVariable

Constants§

DEFAULT_REGISTRY
The official registry. Overridable so a team can point at their own.

Functions§

default_capability_id
The capability id Tuff installs a registry server under.
fetch
Look one server up by its exact registry name, at its current version.
search
Search the registry for the current release of each matching server.
skipped_optional_headers
Headers a registry entry declares but Tuff leaves out of the manifest, because the server does not require them. Named at install time so the omission is visible and can be added by hand.
to_manifest
Build an installable manifest from a registry entry.