Skip to content

mcp.json

Configure, authorize, inspect, edit, and repair local and remote MCP servers across CompozyOS scopes.

For people running agent work9 pages in this section

mcp.json is an optional JSON sidecar for MCP server declarations. CompozyOS accepts it at global, workspace, agent, and skill scopes.

Quick Reference

FieldTypeDefaultValid valuesDescription
mcpServersobject mapemptyServer-name keys with server objects.Camel-case top-level MCP server map.
mcp_serversobject mapemptyServer-name keys with server objects.Snake-case top-level MCP server map.
<server>.transportstringinferredstdio or http.MCP transport. url without transport is HTTP.
<server>.commandstringrequired for stdioNon-empty after trimming.Local MCP server command.
<server>.urlstring URLrequired for remoteAbsolute URL.Remote MCP endpoint for http.
<server>.authobjectemptyOAuth 2.1 PKCE config.Remote auth metadata and client settings.
<server>.argsstring arrayemptyStrings on stdio only.Command arguments for stdio servers.
<server>.envstring mapemptyString keys and values on stdio.Literal environment values for stdio servers.

Unknown JSON fields fail parsing. Trailing JSON values after the first document also fail parsing. Missing mcp.json files are treated as absent.

There is no implemented mcp.json tool-mapping schema today. The current parser accepts MCP server definitions only.

Supported Locations

LocationScopeApplies when
$COMPOZY_HOME/mcp.jsonGlobal top-level MCPGeneral runtime config loads. Defaults to ~/.compozy/mcp.json.
<workspace>/.compozy/mcp.jsonWorkspace top-level MCPA workspace root is resolved for the command or session.
<agent-dir>/mcp.jsonAgent-local MCPNext to AGENT.md.
<skill-dir>/mcp.jsonSkill-local MCPNext to SKILL.md.

Complete Example

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/work"],
      "env": {
        "LOG_LEVEL": "info"
      }
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "secret_env": {
        "GITHUB_TOKEN": "vault:mcp/global/github/env/GITHUB_TOKEN"
      }
    },
    "remote-docs": {
      "transport": "http",
      "url": "https://mcp.example.com/mcp",
      "auth": {
        "registration": "auto",
        "scopes": ["mcp.read", "mcp.write"]
      }
    }
  }
}

The snake-case form is also accepted:

{
  "mcp_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
    }
  }
}

Top-Level Keys

KeyTypeDefaultValid valuesDescription
mcpServersobject mapemptyKeys are server names; values are server objects.Primary JSON form.
mcp_serversobject mapemptyKeys are server names; values are server objects.Alternate JSON form. Loaded after mcpServers inside the same file.

If both top-level keys are present in the same file and both define the same server name, mcp_servers replaces the whole server object from mcpServers.

Server Object

FieldTypeDefaultValid valuesDescription
Map keystringrequiredNon-empty after trimming. Duplicate trimmed names fail.Server name.
transportstringinferredstdio or http.Local command servers default to stdio; URL servers default to http.
commandstringrequired for stdioNon-empty after trimming.Executable command. Only valid with stdio transport.
urlstring URLrequired for remoteAbsolute URL.Remote MCP endpoint. Required for http; invalid for stdio.
authobjectemptyOAuth config listed below.Remote MCP auth configuration. Only valid for remote transports.
argsstring arrayemptyStrings on stdio only.Process arguments for stdio servers.
envstring mapemptyString keys and values on stdio only.Literal environment values. CompozyOS does not expand $VAR, ~, or shell syntax. Management reads expose keys only.
secret_envstring mapemptyenv:NAME or vault:mcp/** refs on stdio only.Secret bindings resolved at launch. Management reads expose configured keys only.
catalog_entrystringemptyCompozyOS-managed catalog entry ID.Provenance stamped by catalog install. Generic settings replacement clears it.
catalog_versionstringemptyCompozyOS-managed catalog version.Provenance stamped with catalog_entry. Do not author these fields manually.

Both env and secret_env reject process-injection keys such as NODE_OPTIONS, PYTHONPATH, PYTHONHOME, LD_PRELOAD, and DYLD_*. Literal env also rejects secret-like names; place those bindings in secret_env with an env:NAME or vault:mcp/** ref.

Management read and write projection

GET /api/settings/mcp-servers does not return literal environment values or binding refs. Each stdio item exposes env_keys and secret_env_keys; OAuth config exposes client_secret_configured. To keep an unchanged value during an exact-target PUT, include its name in preserve_env. Use preserve_secrets.secret_env and preserve_secrets.oauth_client_secret for existing secret bindings. A rename or target change requires a new value or an explicit Vault binding because preservation never crosses keys, scopes, or source files.

Remote OAuth Auth Object

Remote MCP servers can use OAuth 2.1 authorization code with PKCE. The config contains only metadata and client settings; access tokens, refresh tokens, authorization codes, PKCE verifiers, and client-secret values are stored or handled by the auth subsystem and are never written to mcp.json.

CompozyOS-managed MCP secret refs live in the Vault under the mcp namespace. Catalog and settings writes create scope-qualified refs:

  • global: vault:mcp/global/<server>/env/<KEY> and vault:mcp/global/<server>/oauth/client-secret
  • workspace: vault:mcp/ws/<workspace-segment>/<server>/env/<KEY> and vault:mcp/ws/<workspace-segment>/<server>/oauth/client-secret

The workspace segment is the workspace ID when it already fits the Vault grammar; otherwise CompozyOS encodes it deterministically. A catalog install can also bind any existing, present vault:mcp/** ref without taking ownership of that ref.

When a later install replaces an owned canonical ref, CompozyOS deletes it only after the new binding is persisted and only when the replacement no longer references it. Shared and retained refs remain untouched. If cleanup fails and CompozyOS can restore every deleted secret, it restores the prior MCP definition and returns an error. If secret restoration is partial, or the prior definition cannot be restored, the replacement remains committed and the mutation returns a warning describing the residual cleanup state.

FieldTypeDefaultValid valuesDescription
registrationstringautoauto, pre_registered.auto resolves protected-resource metadata, CIMD, then one DCR fallback.
issuer_urlstring URLconditionalAbsolute http or https URL.Required with pre_registered; must match the discovered issuer.
client_idstringconditionalNon-empty.Required with pre_registered.
client_secret_refstringemptyvault:mcp/**.Optional client secret for pre_registered only.
scopesstring arrayemptyUnique non-empty strings.Requested OAuth scopes.

For registration = "auto", CompozyOS resolves protected-resource metadata, uses the provider's client metadata document support when available, and otherwise makes one Dynamic Client Registration attempt. A pre-registered entry must provide both issuer_url and client_id.

Client metadata identity

By default, CompozyOS identifies itself to compatible authorization servers with the public client metadata document at https://compozy.com/.well-known/mcp-client.json. It lists the default loopback callback http://127.0.0.1:2123/api/mcp/oauth/callback.

For a self-hosted daemon, a non-default port, or any custom callback, host your own client metadata document that lists the exact callback URI and set both global restart-required options in config.toml:

[mcp.oauth]
client_metadata_url = "https://compozy.example/.well-known/mcp-client.json"
redirect_uri = "https://compozy.example/api/mcp/oauth/callback"

CompozyOS skips CIMD when the active redirect URI is not listed in the document and can use the one available Dynamic Client Registration fallback instead. A provider that supports neither path fails authorization with a typed diagnostic; do not work around that by adding a secret to the catalog.

Authorize A Remote Server

OAuth sessions and PKCE verifiers live in the daemon, so CLI, HTTP, and UDS clients complete the same flow. Start authorization with a copyable URL:

compozy mcp auth login linear

For a remote operator or a daemon with a non-loopback HTTP bind, use manual completion and paste the full redirect URL:

compozy mcp auth login linear --manual

--timeout bounds the whole authorization attempt, including manual input and exchange. The active daemon PKCE session expiry can shorten that deadline; it never extends it.

Target a workspace sidecar explicitly with both selectors:

compozy mcp auth login linear --scope workspace --workspace <workspace-id>
compozy mcp auth status linear --scope workspace --workspace <workspace-id> -o json

The equivalent daemon routes are:

  • POST /api/settings/mcp-servers/{name}/auth/begin
  • POST /api/settings/mcp-servers/{name}/auth/exchange
  • POST /api/settings/mcp-servers/{name}/auth/logout
  • GET /api/settings/mcp-servers/{name}/auth/status

Each route requires scope; workspace targets also require workspace_id. The routes are available over HTTP and UDS. Begin requires a JSON body with mode: "automatic" or mode: "manual"; manual mode creates a fresh paste-based PKCE session instead of reusing an automatic callback session. The named status route reads only the target's redacted auth state; it does not start a runtime probe. GET /api/mcp/oauth/callback is HTTP-only. Automatic begin uses the configured mcp.oauth.redirect_uri exactly and requires its host to be loopback; it does not derive a callback from the daemon listener. Set redirect_uri explicitly when the daemon uses a non-default loopback port. An unavailable callback runtime returns a documented 503 HTML response. Exchange accepts a JSON body containing the full redirect_url only, and success requires redacted status with both authenticated and token_present.

Each pending session and issued token is bound to the exact scoped server definition. Editing or deleting the server invalidates pending completion. If the transport, remote URL, or OAuth settings change, CompozyOS keeps the previous token record but does not report it as authenticated, refresh it, revoke it against the replacement provider, or send its bearer to that provider. Authorize the new definition again. Tokens created before definition binding was introduced also require one new login.

Install From The Curated Catalog

Use the catalog install command when an MCP entry comes from Marketplace:

compozy mcp install github --scope workspace --workspace <workspace-id> \
  --vault-ref github_personal_access_token=vault:mcp/shared/github-token -o json

For workspace scope, pass both --scope workspace and --workspace <workspace-id>. The daemon loads the catalog entry, locks its command, URL, and auth fields, checks required values and bound Vault refs, writes the MCP sidecar through the serialized config-apply lifecycle, and stamps catalog provenance. Inspect the response's apply object for the record ID, lifecycle, active generation, and required repair action. The install does not probe the MCP server, so a successful config apply does not claim server readiness. OAuth entries return next_step: "authorize"; other entries return next_step: "none".

Direct API callers must always include the nullable values property: send null for an input-free entry. Omitting values violates the request contract and returns 400 before installation.

Use --set id=value for a non-secret catalog input, --secret id to enter one through stdin or a hidden prompt, or --vault-ref id=vault:mcp/... for an existing secret. Neither secret path puts secret material in shell arguments or history. Management reads return configured field names, never bound refs or secret values.

Structured JSON output returns the complete install response: the committed mcp_server, config apply outcome, next_step, and any top-level diagnostics. In particular, mcp_install_event_persist_failed means the server and config apply remain committed while the Marketplace install event was not persisted. Inspect warnings before deciding whether operator cleanup is required.

Inspect Runtime Status

The MCP Installed scope at /marketplace/mcps and GET /api/settings/mcp-servers keep configuration, authorization, runtime, and probe state separate. A configured server is not automatically ready.

SignalPayload fieldsInterpretation
ConfigOne scoped settings entryThe definition exists at the selected scope.
Authauth_status.status, token_present, diagnosticOAuth is unconfigured, needs login, authenticated, expired, or invalid.
Runtimeruntime_status.state, reason, diagnosticThe daemon reports ready or a concrete config, auth, permission, or availability state.
Proberuntime_status.probe, tool_countA probe was skipped, failed, or succeeded with a reported tool count.

Use the redacted CLI and native-tool surfaces for agent diagnostics:

compozy mcp auth status -o json
compozy mcp auth status linear --scope workspace --workspace <workspace-id> -o json

Inside a CompozyOS session, compozy__mcp_status and compozy__mcp_auth_status expose the corresponding redacted status. They do not return OAuth codes, tokens, PKCE verifiers, or secret values.

The web repair action appears only for OAuth-capable HTTP servers that need their first login, have expired or invalid auth, or report auth_refresh_failed. Authorization success still requires both authenticated and token_present=true; runtime and probe state remain independent.

Edit A Configured Server

Open /marketplace/mcps to inspect global definitions together with definitions from the active workspace, then open the matching Marketplace detail. MCP configuration supports:

  • stdio command, args, literal env, and bound secret_env refs;
  • remote http transport and absolute url;
  • OAuth automatic registration or a pre-registered issuer, client ID, optional client-secret ref, and scopes.

The structured mutation is PUT /api/settings/mcp-servers/{name} over HTTP and UDS. Supply scope and, for workspace definitions, workspace_id according to the generated Settings API reference. A generic settings edit clears catalog_entry and catalog_version because the resulting definition is operator-managed.

Deleting or replacing one scoped definition does not mutate a same-name definition in another workspace or at global scope. OAuth tokens and CompozyOS-owned Vault refs use scope-qualified identities for the same reason.

Repair Authorization

Use Authorize for needs_login and Reauthorize for expired, invalid, or refresh-failed OAuth state. The daemon preserves an existing token when begin, exchange, refresh, or operator completion fails.

# Automatic loopback completion.
compozy mcp auth login linear --scope global

# Paste the full redirect URL when operating away from the daemon host.
compozy mcp auth login linear --scope global --manual

# Remove the scoped credential when that is the intended repair.
compozy mcp auth logout linear --scope global -o json

Do not interpret a successful config write, browser open, or redirect as credential confirmation. Re-read status and require authenticated plus token_present=true.

Merge And Override Rules

mcp.json uses whole-object replacement. TOML uses field-level merging.

SituationBehavior
Same-name TOML [[mcp_servers]] overlayFields merge by name. Non-empty transport, command, URL, auth fields, args, and env keys overlay the existing server.
Same-name mcp.json sidecar overlayThe sidecar replaces the entire existing server object.
Same-name inline AGENT.md and agent-local mcp.jsonAgent-local sidecar replaces the whole inline server object.
Same-name SKILL.md metadata and skill-local mcp.jsonSkill-local sidecar replaces the whole frontmatter server object.
Duplicate names inside one JSON document after trimmingLoading fails.

Runtime Precedence

Top-level configuration loads in this order:

  1. Built-in defaults.
  2. $COMPOZY_HOME/config.toml.
  3. $COMPOZY_HOME/mcp.json.
  4. <workspace>/.compozy/config.toml.
  5. <workspace>/.compozy/mcp.json.

Daemon boot uses home config for boot-time daemon settings. MCP sidecars are applied by the general config loader used for session and runtime resolution.

Session startup then resolves MCP servers in this order:

  1. Top-level config MCP servers.
  2. Provider MCP servers.
  3. Agent MCP servers.
  4. Active skill MCP servers.

Provider and agent MCP servers use field-level merging when they come from TOML or YAML. Agent and skill sidecars replace same-name inline servers as whole objects.

Validation Errors

Error caseResult
Unknown top-level keyParse error.
Unknown server fieldParse error.
Trailing JSON valueParse error.
Empty server name after trimmingValidation error.
Duplicate trimmed server nameValidation error.
Missing stdio commandValidation error.
command on remote transportValidation error.
args on remote transportValidation error.
env on remote transportValidation error.
Forbidden key in env/secret_envValidation error.
Missing remote urlValidation error.
url on stdio transportValidation error.
auth on stdio transportValidation error.
Incomplete OAuth metadataValidation error.
Non-string values in args or envJSON decoding error.
Missing fileIgnored.

Examples By Scope

Global MCP Server

~/.compozy/
  config.toml
  mcp.json

Use this for tools every workspace may use.

Workspace MCP Server

my-project/
  .compozy/
    config.toml
    mcp.json

Use this for tools that only make sense inside one project.

Agent MCP Server

~/.compozy/agents/reviewer/
  AGENT.md
  mcp.json

Use this when the tool belongs to one agent.

Skill MCP Server

~/.compozy/skills/docs-search/
  SKILL.md
  mcp.json

Use this when the tool belongs to one skill. Marketplace skill MCP servers are blocked unless the skill is explicitly allowlisted in [skills].allowed_marketplace_mcp. Skill-local mcp.json symlinks must resolve inside the skill directory; CompozyOS rejects sidecars that escape the approved skill root.

  • config.toml documents top-level and provider MCP fields.
  • Vault documents env: versus vault: refs and redacted metadata management.
  • AGENT.md documents agent-local MCP declarations.
  • SKILL.md documents skill-local MCP declarations.
  • Marketplace covers discovery, guided install, updates, and trust.

On this page