docs

MCP servers

External tools arrive via the Model Context Protocol: a stdio command or an HTTP/SSE URL, declared under mcp_servers: in config.yaml (DEX_MCP_SERVERS_JSON wins when set — same shape as JSON). Servers load once at daemon bootstrap, not per turn.

Declaring servers

mcp_servers:
  github: "npx -y github-mcp-server" # shorthand: command + args
  docs:
    url: "https://docs.example.com/mcp" # HTTP/SSE server
    headers: { authorization: "Bearer ${DOCS_TOKEN}" } # $VAR expands, fail-closed
    timeout_secs: 30
    allow: ["search"] # optional tool filter (deny wins)

Tool naming & caps

  • Each server's tools appear in the schema as mcp__<server>__<tool> (description prefixed with [<server>]), plus one mcp__<server>_read_resource reader when the server hosts resources.
  • The merged schema is capped at DEX_MCP_MAX_TOOLS (default 200, sorted by name, dropped count reported).
  • Servers connect in the background at startup; a 60 s liveness sweeper marks dead ones down before the next turn uses them.
  • /mcp in the TUI shows servers, tools, and connection errors.
  • GET /api/mcp shows per-server state/tool counts; POST /api/mcp/<server>/reconnect redials a fixed server without restarting the daemon.
  • DEX_MCP=0 or DEX_NO_MCP=1 disables all MCP servers.

OAuth

HTTP servers with OAuth (RFC 9728 protected-resource + RFC 8414 discovery + RFC 7591 registration + PKCE S256) log in via:

dex mcp login <server>    # browser + loopback callback
dex mcp logout <server>
dex mcp status
  • Tokens live in $XDG_DATA_HOME/dex/mcp/<server>.json (0600, never logged); refreshed once per 401 with a 60 s backoff on failure (invalid_grant drops the file).
  • Discovery/token URLs must be https (loopback http allowed); optional oauth_client_id/oauth_client_secret/ oauth_scope in config skip registration.
  • When an authorization server rejects resource with invalid_target, login retries once without it.
  • /mcp shows the same auth lines.