mcp2cli

Config Reference

Complete reference for the mcp2cli YAML configuration schema.


Config File Location

~/.local/share/mcp2cli/configs/<name>.yaml

Override with: MCP2CLI_CONFIG_DIR=/custom/path


Full Schema

schema_version: 1 # Required. Always 1.
app:
profile: bridge # Application profile (only "bridge" currently)
server:
display_name: "My MCP Server" # Human-readable name for --help banners
transport: streamable_http # streamable_http | stdio
endpoint: "http://localhost:3001/mcp" # Required for streamable_http transport
protocol_version: auto # auto | 2026-07-28 | 2025-11-25
stdio:
command: "npx" # Subprocess command (required for stdio)
args: # Subprocess arguments
- "@modelcontextprotocol/server-everything"
cwd: "/path/to/working/dir" # Optional working directory
env: # Optional environment variables
API_KEY: "sk-abc123"
NODE_ENV: "production"
roots: # Optional: exposed via roots/list
- uri: "file:///home/user/project"
name: "Project Root"
defaults:
output: human # human | json | ndjson
timeout_seconds: 120 # Operation timeout (0 = no timeout)
logging:
level: warn # trace | debug | info | warn | error
format: pretty # pretty | json
outputs:
- kind: stderr # stderr | stdout | file
# - kind: file
# path: /var/log/mcp2cli.log
auth:
browser_open_command: "xdg-open" # For OAuth browser flows (null = disabled)
token_store_file: null # Custom token path (auto-derived if null)
events:
enable_stdio_events: true # Human-readable events on stderr
http_endpoint: null # HTTP webhook URL (POST JSON per event)
local_socket_path: null # Unix socket path (NDJSON)
sse_endpoint: null # SSE server bind address (host:port)
command: null # Shell command per event
profile: # Optional: customize CLI surface
display_name: "My Custom CLI"
aliases: {} # Rename commands
hide: [] # Hide commands from help/ls
groups: {} # Custom command grouping
flags: {} # Rename flags per command
resource_verb: get # Verb for resource reads
discovery: # Optional: where the command list comes from
auto: true # Discover on demand when nothing is cached
snapshot: null # Inventory snapshot, relative to this file
ttl_seconds: null # Re-discover when the list is older than this
branding: # Optional: publish as a CLI under its own name
name: "email" # Product name (data dir, OAuth client, clientInfo)
about: "Send mail from your terminal" # Help header
version: "1.4.0" # What --version prints
after_help: null # Text after the top-level help
builtin_commands: [auth] # Built-ins to expose (omit = all, [] = none)
attribution: false # Append "— powered by mcp2cli" to the header

Field Reference

schema_version

TypeDefaultRequired
integer1Yes

Must be 1. Used for future config migrations.


app

app.profile

TypeDefaultRequired
string"bridge"Yes

The application profile to use. Currently only bridge is supported.


server

server.display_name

TypeDefaultRequired
string"MCP Bridge Server"No

Human-readable name shown in --help banners and JSON output.

server.transport

TypeDefaultRequired
stringstreamable_httpYes

Transport protocol. Values:

ValueDescription
streamable_httpHTTP JSON-RPC with SSE streaming
stdioStdin/stdout with subprocess

server.protocol_version

TypeDefaultValues
stringautoauto, 2026-07-28, 2025-11-25

Which MCP protocol revision to speak:

  • auto (default) — probe with server/discover and use the stateless 2026-07-28 revision when the server supports it; fall back to the 2025-11-25 initialize handshake otherwise (the spec’s backward-compatibility algorithm).
  • 2026-07-28 — modern only. Requests carry per-request _meta metadata; never falls back to the handshake (fails fast against legacy servers).
  • 2025-11-25 — legacy only. Skips the probe and goes straight to the initialize handshake (saves one round trip on servers you know are legacy).

server.endpoint

TypeDefaultRequired
string | nullnullFor HTTP

Full URL for the MCP server endpoint. Required when transport: streamable_http.

Special value: https://demo.invalid/mcp activates the built-in demo backend.

server.stdio.command

TypeDefaultRequired
string | nullnullFor stdio

Executable to spawn as the MCP server subprocess.

server.stdio.args

TypeDefault
string[][]

Arguments passed to the subprocess.

server.stdio.cwd

TypeDefault
string | nullnull

Working directory for the subprocess. If null, inherits the current directory.

server.stdio.env

TypeDefault
map<string, string>{}

Environment variables merged into the subprocess environment.

server.roots

TypeDefault
array[]

Roots exposed to the server via roots/list. Each entry has:

FieldTypeDescription
uristringRoot URI (typically file:// paths)
namestringHuman-readable label

defaults

defaults.output

TypeDefaultValues
stringhumanhuman, json, ndjson

Default output format. Overridden by --json or --output flags.

defaults.timeout_seconds

TypeDefaultRange
integer1200–∞

Default timeout for all MCP operations, in seconds. 0 disables timeouts.

Overridden by --timeout flag per-command.


logging

logging.level

TypeDefaultValues
stringwarntrace, debug, info, warn, error

Minimum log level for tracing output.

logging.format

TypeDefaultValues
stringprettypretty, json

Log output format. json is useful for log aggregation.

logging.outputs

TypeDefault
array[{kind: stderr}]

Log output destinations. Each entry:

FieldValuesDescription
kindstderr, stdout, fileOutput target
path(file only)File path for kind: file

auth

auth.browser_open_command

TypeDefault
string | nullnull

Command to open URLs in the browser (for OAuth flows). Examples: xdg-open, open, wsl-open.

auth.token_store_file

TypeDefault
string | nullnull (auto-derived)

Custom path for token storage. If null, defaults to instances/<name>/tokens.json.


events

events.enable_stdio_events

TypeDefault
booleantrue

Write human-readable event lines to stderr.

events.http_endpoint

TypeDefault
string | nullnull

HTTP URL for webhook event delivery. Each event is POSTed as JSON.

events.local_socket_path

TypeDefault
string | nullnull

Path to a Unix domain socket for NDJSON event delivery.

events.sse_endpoint

TypeDefault
string | nullnull

Bind address for an SSE (Server-Sent Events) HTTP server. Format: host:port.

events.command

TypeDefault
string | nullnull

Shell command executed per event. Environment variables available:

VariableContent
MCP_EVENT_TYPEEvent type name
MCP_EVENT_JSONFull JSON event
MCP_EVENT_APP_IDConfig name
MCP_EVENT_MESSAGEOne-line message

profile

Optional profile overlay for CLI customization.

profile.display_name

TypeDefault
string | nullnull

Custom name for --help banner. If null, uses server.display_name.

profile.aliases

TypeDefault
map<string, string>{}

Command renames. Keys are original names (dot-notation for grouped), values are new names.

aliases:
long-running-operation: lro # Top-level rename
create.payload: object # Grouped subcommand rename

profile.hide

TypeDefault
string[][]

Commands to hide from --help and ls.

profile.groups

TypeDefault
map<string, string[]>{}

Custom grouping. Keys are group names, values are lists of command names.

groups:
mail:
- send
- reply
- draft-create

profile.flags

TypeDefault
map<string, map<string, string>>{}

Per-command flag renames. Outer key is command name, inner map is original→new.

flags:
echo:
message: msg

profile.resource_verb

TypeDefault
string"get"

Verb for the resource read command.


discovery

Where the dynamic CLI gets its command list. See Branded CLI → discovery for how the three sources are reconciled.

discovery.auto

TypeDefault
booleantrue

Discover the server’s capabilities on demand when no tools are cached, so the first command ever run against a config already works. Built-in commands (auth, jobs, …) never trigger it. The discovery is time-boxed — 10 seconds on the way to --help, 30 on the way to a command, or --timeout if given — rather than subject to defaults.timeout_seconds per request. Set to false to restore the explicit workflow, where ls or tool list populates the cache.

discovery.snapshot

TypeDefault
string (path)null

Path to an inventory snapshot written by mcp2cli package snapshot, relative to the config file. It seeds the cache whenever it is newer than what is cached, which gives a published CLI instant, offline --help — also before login.

discovery.ttl_seconds

TypeDefault
integernull (never)

Before running a command, re-discover if the cached command list is older than this many seconds. If the refresh fails, the stale list is kept and nothing is reported. --help never triggers a refresh.


branding

Identity of a CLI published on top of mcp2cli. The presence of this section switches the runtime into embedded mode: own help header and version, only the listed built-in commands, own OAuth client name and MCP clientInfo, own data directory, and mcp2cli’s usage telemetry off unless telemetry.enabled: true is set explicitly. Full description: Branded CLI.

FieldTypeDefaultDescription
namestringinvoked nameProduct name. Names the data directory; shown on the OAuth consent screen and sent as MCP clientInfo.name
aboutstringserver.display_nameOne-line description at the top of --help
versionstringmcp2cli’s versionPrinted by --version; sent as clientInfo.version
after_helpstringnullFree text after the top-level help
builtin_commandslistallAllowlist from auth, jobs, doctor, inspect, ls, ping, log, complete, subscribe, unsubscribe, tool, resource, prompt. [] exposes none
attributionbooleanfalseAppend — powered by mcp2cli to the help header

Environment Variable Overrides

Any config field can be overridden via environment variable:

MCP2CLI_<PATH__TO__FIELD>=<value>
Config PathEnvironment Variable
logging.levelMCP2CLI_LOGGING__LEVEL
server.endpointMCP2CLI_SERVER__ENDPOINT
defaults.outputMCP2CLI_DEFAULTS__OUTPUT
defaults.timeout_secondsMCP2CLI_DEFAULTS__TIMEOUT_SECONDS

Additionally:

VariableDescription
MCP2CLI_CONFIG_DIROverride config directory path
MCP2CLI_DATA_DIROverride data directory path
MCP2CLI_CONFIGPath of the config file to load, instead of looking one up by name
MCP2CLI_INVOKED_ASCommand name to run as, instead of the one in argv[0]. With MCP2CLI_CONFIG, this is how a launcher starts a published CLI without a symlink

Data Directories

PathContent
configs/Named config YAML files
instances/<name>/discovery.jsonCached discovery inventory
instances/<name>/tokens.jsonStored auth credentials
instances/<name>/session.jsonNegotiated capabilities cache
instances/<name>/daemon.jsonDaemon PID file
instances/<name>/daemon.sockDaemon Unix socket
instances/<name>/jobs/Background job records
active.jsonCurrently active config pointer

Default base: ~/.local/share/mcp2cli/

A config with a branding section uses ~/.local/share/<branding.name>/ instead (~/Library/Application Support/<name>/ on macOS), so a published CLI never shares state — in particular, tokens — with the user’s own mcp2cli setup. With MCP2CLI_DATA_DIR set it uses $MCP2CLI_DATA_DIR/apps/<branding.name>/.


Minimal Configs

HTTP server

schema_version: 1
server:
transport: streamable_http
endpoint: http://localhost:3001/mcp

Stdio server

schema_version: 1
server:
transport: stdio
stdio:
command: npx
args: ['@modelcontextprotocol/server-everything']

Demo mode

schema_version: 1
server:
transport: streamable_http
endpoint: https://demo.invalid/mcp

telemetry

Anonymous usage telemetry configuration. See Telemetry Collection Guide for full details.

FieldTypeDefaultDescription
enabledbooltrueMaster switch. Set to false to disable telemetry
endpointstring?nullOptional HTTP endpoint for shipping NDJSON event batches
batch_sizeint25Number of events to batch before shipping to HTTP endpoint
telemetry:
enabled: true
# endpoint: "https://your-collector.example.com/v1/events"
# batch_size: 25

Disabling telemetry

Any one of these disables telemetry completely:

# In config
telemetry:
enabled: false
Terminal window
# Via environment
export MCP2CLI_TELEMETRY=off
# Via CLI flag
mcp2cli --no-telemetry ls
# Via DO_NOT_TRACK standard
export DO_NOT_TRACK=1

See Also