ADR: Remote header variables accept the registry's {name} spelling
- Status: Proposed
- Date: 2026-09-20
- Deciders: Pending maintainer review
- Related: ADR 0245, E2E-MCP-MARKET-SEMANTICS
Context
The official MCP registry spells a remote header variable {name} and declares the name in the header's variables map. Its schema describes variables as the values that replace "keys in the input value that are wrapped in {curly_braces}". Declared names may use lower case, such as api_key. The regression fixtures cover both cases; this ADR does not assert the frequency of either spelling in the live registry.
The builtin catalog and stdio templates spell a template variable ${NAME} in upper case. The registry adapter and the catalog template matcher knew only that spelling. In the reproduced mapping and resolution path, a registry record using the official spelling retained Authorization: Bearer {api_key} and had no requiredEnv entry. This establishes an unresolved template at the parser boundary. The tests do not establish rendered install-sheet behavior, actual HTTP transmission, or a user's observed response status.
Decision
- The registry adapter resolves
{name}only when that same header declares it invariables; undeclared braces remain literal. Legacy${NAME}tokens keep working without a variables map. Names need not be upper case when declared by the registry. Each header owns its variable definitions. - Add optional
headerBindingsto the shared catalog template. Each header maps exact tokens to an editablerequiredEnvinput or a fixed literal. Presence ofheaderBindings, including an empty map, selects explicit binding mode for all headers. A header absent from that map has no bound tokens: both{name}and${NAME}remain literal, regardless of globalrequiredEnvnames or defaults. Only catalogs with noheaderBindingsmetadata use the legacy global input scope. Same-named inputs in separate headers get distinct collision-safe names. Variabledefaultprefills the editable input; omittedisRequiredmeans optional. A fixedvalueis not editable and its content is never parsed again as a template. Bindings do not enter the hostMcpServerInputor persisted server config, so the runtime protocol remains unchanged. - Header templates accept both spellings and consume the
$, so a${NAME}header resolves without a stray dollar. URL templates keep the legacy${NAME}spelling with upper-case names. A header declaration never makes bare{name}text in a URL editable or substitutable, including when the header has a default.collectCatalogPlaceholdersandresolveCatalogEntryselect the same pattern for each field, so discovery and resolution agree. - stdio templates keep the
${NAME}spelling and the upper-case name rule. A brace pair inside a command or an argument is never rewritten, and the existing stdio contract is unchanged. requiredEnvnames are validated against the transport: variable names forhttp, environment-variable names forstdio.
Consequences
- Declared editable header variables yield prompts and resolve according to their own defaults and requiredness. Fixed variables and unbound brace text do not create prompts. Header-local bindings prevent cross-header leakage of defaults, optional flags, and literal values. Bare URL tokens remain literal through mapping, resolution and host persistence; explicit legacy
${NAME}URL templates retain their existing behavior. - Builtin catalog entries and stdio packages behave exactly as before.
- The catalog can express a header variable that is not an environment variable name, which is what the registry publishes.