Mcp-Server Schema
Version: 0
Template
- Shape:
config_fragment - Filename: ``
Ecosystem Notes
- Codex MCP-server schema is a SUPERSET of Claude/Gemini. The full Codex spec adds (per developers.openai.com/codex/config-reference): cwd, enabled, required, env_vars (with source = local|remote), bearer_token_env_var, env_http_headers, http_headers, oauth_resource, scopes, startup_timeout_sec (+ _ms alias), tool_timeout_sec, default_tools_approval_mode, enabled_tools / disabled_tools (allow/ deny lists), experimental_environment (local|remote), and per-tool overrides via tools.
.approval_mode. None of these clear the universal-schema floor (all <= 1 file in corpus); they are adapter pass-through fields for the Codex adapter, NOT promoted to the cross-host schema. See ADR-0003 consequences re: per-instance lossy promotion when a Codex resource carrying these fields is installed via a non-Codex adapter. typefield NOT promoted to schema despite 13/25 corpus presence (8 'stdio' from ChrisWiles, 5 'http' from arc-kit). Reason: Codex spec discriminates transport by PRESENCE ofurlvscommand, not by atypefield. arc-kit'stype = 'http'is a Claude-style holdover by the author; Codex parser ignores it. Schema uses the spec-canonical discriminator (url-vs-command). Translator dropstypeon import to Codex; passes through for Claude/Gemini where it may still carry meaning.headersvshttp_headers(arc-kit): arc-kit usesheaders = {...}for API-key injection; Codex spec field ishttp_headers. Either arc-kit is wrong (Codex silently ignoresheaders) orheadersis an undocumented alias. Both seen in corpus (2/25). NEITHER promoted to schema until the spec/source confirms. Translator canonicalises on import: rewriteheaderstohttp_headerswhen targeting Codex, flag the original spelling in resource metadata for traceability.- Per-tool approval override (wp-calypso): chrome-devtools entry contains
tools.click.approval_mode = 'approve'andtools.evaluate_script.approval_mode = 'approve'. Counting choice: these are SUB-entries of one server entry, not separate server entries. At server-entry granularity, 1/25 has thetoolsfield — below floor. At nested-tool-entry granularity, 2/2 of wp-calypso's tools have approval_mode — but the denominator is meaningless across the corpus. Schema-wise: not promoted; adapter pass-through. Per ADR-0001, may also be a security-agent input (per-tool approval is a security control — translator should not silently drop it when porting to a host that lacks the concept). - Filename + key-name divergence: Claude
.mcp.json $.mcpServers(camelCase), Gemini.gemini/settings.json $.mcpServers(camelCase), Codex.codex/config.toml mcp_servers(snake_case). Adapter translates the key name on emit; the schema'stemplate.source_locationsdeclares each canonical location. - Hermes uses YAML instead of JSON/TOML and stores servers under
~/.hermes/config.yaml mcp_servers. The universal core fields (command,args,url,env) retain their meanings; Hermes then extends with HTTP auth/TLS keys (headers,ssl_verify,client_cert,client_key), lifecycle/timeout flags (enabled,timeout,connect_timeout,supports_parallel_tool_calls), tool exposure policy (tools), and server-initiated sampling policy (sampling). - Claude footgun:
mcpServersin.claude/settings.jsonis SILENTLY IGNORED by Claude Code (anthropics/claude-code#24477, #646). Adapters MUST write to.mcp.jsonor~/.claude.json. - Argument-style credential handling varies. abcdan/mcp.json embeds secrets directly in args (
--figma-api-key=XXXXXXXX). arc-kit usesheaders={X-API-Key=${...}}with ${VAR} substitution. Codex specbearer_token_env_varis the cleanest pattern (env-var indirection). Translator should detect literal secrets in args (high-entropy strings) and surface a warning per the security-agent stage (ADR-0001). No schema-level enforcement (legitimate args contain high-entropy values too — paths, UUIDs, etc.). - Remote-MCP wrapper detection. abcdan's Atlassian entry is structurally
command: npx args: [-y, mcp-remote, https://...sse]— a stdio wrapper around an SSE endpoint. arc-kit's HTTP entries express the same concept natively viaurl. Codex spec supports both. Translator detectingmcp-remote(or similar shims) and re-emitting native HTTP form when targeting a host that supports it is cleaner than literal-stdio round-tripping. Not v1; documented. - Server name (the JSON/TOML key) is the install identifier. Two installs with the same name into the same target file collide — manifest must record the server-name claim so a second install fails fast rather than silently overwriting.
Deliberately Excluded Concepts
Concept: transport_type_marker
The type field (corpus: 8 "stdio" from ChrisWiles Claude entries,
5 "http" from arc-kit Codex entries) is NOT a real transport
discriminator on any host. Codex spec discriminates by presence of
url vs command. arc-kit's type = "http" is a Claude-style
holdover the Codex parser ignores. Claude and Gemini accept the
field but do not parse it semantically (corpus uses it as
documentation only). Adapter behaviour:
- All adapters: pass-through if present; never emit if absent.
- Never lossy (lossy_when_dropped: false) — no host's runtime
depends on type. The validator rejects sources where type
contradicts the transport discriminator (type: "http" without
url, or type: "stdio" without command); see ADR-0010 and
ADR-0012 §7.
Field Names: type
Concept: http_transport_headers
HTTP transport custom headers. Codex spec field is http_headers;
arc-kit (2/25) uses headers — either an undocumented alias or
a typo Codex silently ignores. Both names listed in aliases under
host: codex because the translator preserves the source spelling
on import while canonicalising semantically (see
ecosystem_notes — translator rewrites headers → http_headers
when targeting Codex emit). Claude/Gemini have no HTTP-transport
custom-headers concept in spec (Gemini's headers extension is
undocumented and not corpus-attested). Adapter behaviour:
- codex adapter: emit as http_headers (canonical Codex name).
If source has headers, treat as http_headers and warn that
the spelling was normalised.
- hermes adapter: emit headers natively.
- other adapters: surface as lossy. HTTP authentication is
load-bearing; silently dropping headers means the install will
fail at runtime with confusing auth errors.
Aliases:
| Host | Field Name |
|---|---|
codex |
http_headers |
codex |
headers |
hermes |
headers |
Concept: stdio_working_directory
Working directory for the stdio MCP server process. Same name
(cwd) across both Codex and Gemini specs; same semantics. Claude
has no documented cwd field — stdio servers inherit Claude's
working directory. Adapter behaviour:
- codex / gemini-cli adapters: emit natively when present.
- claude-code adapter: surface as lossy. The MCP server's behaviour
depends on where it runs (e.g., a server reading config from a
relative path); silently dropping cwd means the server may not
find its config on Claude. Install proceeds only with
--allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
cwd |
gemini-cli |
cwd |
antigravity-cli |
cwd |
Concept: server_overall_timeout
Overall server timeout field shared by Gemini/Antigravity/Hermes (no corpus presence). Distinct from Codex's per-phase timeouts (startup_timeout_sec, tool_timeout_sec) — those are separate canonical_concepts. Adapter behaviour: - gemini-cli / antigravity-cli / hermes adapters: emit natively when present. - other adapters: surface as lossy. Adapter ergonomics note: if a future ADR-0017 unifies overall-vs-phase timeouts into one canonical_concept, this entry merges with codex_startup_timeout and codex_tool_call_timeout. Deferred per ADR-0012 (Scenario B).
Aliases:
| Host | Field Name |
|---|---|
gemini-cli |
timeout |
antigravity-cli |
timeout |
hermes |
timeout |
Concept: gemini_server_trust
Gemini-spec field for marking a server as "trusted" (no corpus
presence). Encodes a security control — trusted servers bypass
certain approval prompts. Adapter behaviour:
- gemini-cli adapter: emit natively when present.
- non-gemini adapters: surface as lossy. Security control —
silently dropping it means a server an author marked trusted
on Gemini gets default-untrusted treatment on Claude/Codex,
which may surprise the user. Install proceeds only with
--allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
gemini-cli |
trust |
antigravity-cli |
trust |
Concept: gemini_http_url_alias
Gemini's documented name for HTTP transport URL. The universal
core promotes url (the Codex spec name, 5/25 corpus presence
from arc-kit) as the canonical HTTP-URL field. httpUrl is the
SAME CONCEPT under a different name — this is a Scenario B case
(cross-host concept-equivalence under different names) called
out in ADR-0012 Consequences as deferred to ADR-0017. The
canonicalises_to: url annotation is the machine-readable anchor
ADR-0017 will consume.
For MVP:
- The translator on Gemini-source import should normalise httpUrl
to the universal url field. (Translator concern, not adapter.)
- If the translator fails to normalise and the canonical resource
carries httpUrl in Extensions, lossy detection per the table
above flags it as Gemini-only — over-strict for installs on
Codex (which supports the same concept under name url).
Acceptable until ADR-0017 introduces alias-aware translation.
Aliases:
| Host | Field Name |
|---|---|
gemini-cli |
httpUrl |
antigravity-cli |
httpUrl |
Concept: codex_server_lifecycle
Lifecycle flags controlling whether a configured server is active.
Codex exposes both enabled and required; Hermes exposes
enabled. enabled: false disables a server
without removing it from config; required: true causes Codex
to fail startup if the server doesn't initialise (vs default
warn-and-continue). Adapter behaviour:
- codex / hermes adapters: emit the fields they natively support.
- other adapters: surface as lossy. enabled: false is
particularly load-bearing — silently emitting the server as
active on Claude/Gemini contradicts the author's explicit
intent. Install proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
enabled |
codex |
required |
hermes |
enabled |
Concept: hermes_connect_timeout
Hermes-native initial connection timeout for MCP servers. Distinct from the overall request timeout above. Adapter behaviour: - hermes adapter: emit natively when present. - non-hermes adapters: surface as lossy. Dropping the connect timeout changes failure behaviour for slow or intermittently reachable remote MCP endpoints.
Aliases:
| Host | Field Name |
|---|---|
hermes |
connect_timeout |
Concept: hermes_parallel_tool_calls
Hermes-native concurrency flag allowing tools from one MCP server to run in parallel. Adapter behaviour: - hermes adapter: emit natively when present. - non-hermes adapters: surface as lossy. This is an explicit runtime-safety/performance choice by the author.
Aliases:
| Host | Field Name |
|---|---|
hermes |
supports_parallel_tool_calls |
Concept: hermes_http_auth_mode
Hermes-native HTTP auth mode selector (for example OAuth). Adapter behaviour: - hermes adapter: emit natively when present. - non-hermes adapters: surface as lossy. HTTP auth mode is load-bearing; silently dropping it breaks remote server access.
Aliases:
| Host | Field Name |
|---|---|
hermes |
auth |
Concept: hermes_sampling_policy
Hermes-native policy for MCP server initiated sampling requests. Adapter behaviour: - hermes adapter: emit natively when present. - non-hermes adapters: surface as lossy. Sampling controls are a real runtime capability and safety budget, not cosmetic metadata.
Aliases:
| Host | Field Name |
|---|---|
hermes |
sampling |
Concept: hermes_http_tls_controls
Hermes-native HTTP TLS controls for MCP servers, including custom CA bundles and mTLS client certificate/key material. Adapter behaviour: - hermes adapter: emit natively when present. - non-hermes adapters: surface as lossy. TLS verification and client-certificate auth are load-bearing security settings.
Aliases:
| Host | Field Name |
|---|---|
hermes |
ssl_verify |
hermes |
client_cert |
hermes |
client_key |
Concept: codex_env_vars_with_source
Codex-spec richer environment-variable declaration with
per-variable source = local|remote indirection (vs the
universal env field which is a flat {name: value} map).
Scenario B-adjacent: env_vars and the universal env overlap
in concept (env vars for the server process) but env_vars
encodes additional information (variable source). Adapter
behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. The source = remote
case encodes that a credential lives in Codex's secret store,
not in the local environment — dropping it means the variable
is unset at server startup on other hosts, which silently
breaks auth. Install proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
env_vars |
Concept: codex_bearer_token_env_var
Codex-spec field for HTTP-transport bearer auth: the name of an
env var whose value Codex injects as Authorization: Bearer
${value}. Cleanest credential pattern in the corpus (vs
args-embedded secrets at abcdan or template-interpolated headers
at arc-kit). Adapter behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. HTTP auth is load-bearing;
dropping the bearer-token directive means the HTTP server
rejects all requests with 401. Install proceeds only with
--allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
bearer_token_env_var |
Concept: codex_http_auth_metadata
Codex-spec HTTP-transport auth metadata: env_http_headers
(env-var-interpolated custom headers, vs the literal-values
http_headers above), oauth_resource (OAuth resource identifier),
scopes (OAuth scope list). Adapter behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. OAuth metadata is
load-bearing; dropping it means token-acquisition fails. Install
proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
env_http_headers |
codex |
oauth_resource |
codex |
scopes |
Concept: codex_startup_timeout
Codex-spec timeout for server startup phase (vs request handling).
Two unit-suffixed aliases for the same field — Codex spec
documents both, parser accepts either. Adapter behaviour:
- codex adapter: emit whichever the source carried; if both
present, prefer _sec per Codex spec precedence. The
validator warns on conflict.
- non-codex adapters: surface as lossy. Startup timeout encodes
an explicit author-chosen wait-budget; silently dropping it
means the host uses its default (which may be shorter for a
slow-starting server, causing intermittent install-time
failures). Install proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
startup_timeout_sec |
codex |
startup_timeout_ms |
Concept: codex_tool_call_timeout
Codex-spec timeout for individual tool calls (vs startup). Adapter
behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. Same rationale as
codex_startup_timeout. Install proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
tool_timeout_sec |
Concept: codex_default_tool_approval_mode
Codex-spec server-wide approval default — gates whether tools
from this server require user approval. Security-relevant.
Adapter behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. Author explicitly chose
an approval posture; silently dropping it means tools run
under the host's default (which may be more permissive),
bypassing the security control. Install proceeds only with
--allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
default_tools_approval_mode |
Concept: codex_tool_allowlist
Codex-spec per-server tool allowlist (enabled_tools) and
denylist (disabled_tools). Security control. Adapter behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. An author who restricted
the server's exposed tools via these lists chose explicit
attack-surface reduction; silently emitting the unrestricted
server elsewhere exposes more tools than the author intended.
Install proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
enabled_tools |
codex |
disabled_tools |
Concept: codex_experimental_environment
Codex-spec experimental_environment: local|remote for server
placement (whether Codex runs the server itself or expects a
remote executor). Adapter behaviour:
- codex adapter: emit natively when present.
- non-codex adapters: surface as lossy. remote placement
means the server runs outside the host's process — emitting
the entry on Claude/Gemini without the remote-executor
infrastructure would attempt local launch and fail. Install
proceeds only with --allow-lossy.
Aliases:
| Host | Field Name |
|---|---|
codex |
experimental_environment |
Concept: server_tool_policy
Host-specific server tool policy bucket. Codex uses tools for
per-tool approval overrides (tools.<id>.approval_mode);
Hermes uses tools for include/exclude/resource/prompt exposure
policy. The shared top-level key is enough for adapter preserve/
drop decisions, but the nested shapes are NOT equivalent and are
not canonicalised by dotpack today. Adapter behaviour:
- codex / hermes adapters: emit native tools values when the
nested shape matches the host they target; foreign-shape values
are adapter-side errors rather than silent rewrites.
- other adapters: surface as lossy. This remains a load-bearing
security/runtime control; silently dropping it is exactly the
failure mode dotpack exists to prevent.
Aliases:
| Host | Field Name |
|---|---|
codex |
tools |
hermes |
tools |