mcpg (gateway)
The MCPG gateway binary — run it, attach or embed a control plane (--enroll / --control-plane), MCPG_CONFIG, mcpg status, dev mode, --stdio.
mcpg — the gateway (and the hub CLI)
mcpg is the gateway server. Configuration comes from the MCPG_CONFIG env var
(a path or path-separator-joined list of files) and/or the repeatable --config
flag — the two layer together, later wins. See
Configuration below.
| Invocation | What it does |
|---|---|
mcpg | Run the gateway, loading config from MCPG_CONFIG. Re-attaches to a paired control plane automatically (see below). |
mcpg --config <source> | Load a config layer (repeatable, later wins). A source is a local path, a file:// path, an https:// URL (fetched at boot), or inline base64:/data: YAML. Applied after any MCPG_CONFIG files. |
mcpg --stdio | Run the gateway forcing the stdio JSON-RPC transport (e.g. when spawned by an MCP client). Overrides gateway.server.transport. |
mcpg --enroll <URL> | Run attached to a control plane, enrolling with the given URL on first contact (minted by mcpg cp enroll new or the console). Sticky — see below. |
mcpg --no-cp | One-off detached run despite a stored pairing (or a config attachment). |
mcpg --control-plane (alias --cp) | Run an embedded control plane in this process and auto-enroll over loopback — the all-in-one. --cp-<flag> passes through to the embedded server (--cp-bind-http → its --bind-http). |
mcpg --tunnel [wss-url] | Serve MCP by dialing an MCPG relay instead of binding a public port — a reverse tunnel. The optional value sets the relay endpoint (bare --tunnel uses the config's relay_url or the MCPG Cloud relay). Add --private (federation-only, no public URL), --tunnel-name <name>, --tunnel-mode <relay_terminated|e2ee>, --tunnel-relay <wss-url>. See reverse tunnels. |
mcpg status | This box: gateway (bind + health), agent pairing (endpoint, credentials, LKG hash), local control plane. |
mcpg dev --plugin <path> [--plugin …] [--stdio] | Local plugin-dev mode — load freshly-built plugin artifact(s) by path, layered onto your existing config. |
mcpg <word> […] | Front-door dispatch to the sibling mcpg-<word> binary: cp, cloud, admin, config, plugin. |
Composition flags — attaching to / embedding a control plane
The rule across the CLI family: flags shape the gateway; subcommands
run or operate everything else. The three flags conflict with each
other (and --enroll errors against an explicit gateway.control_plane
in config — config wins).
--enroll <URL>runs the agent in-process (thecp-attachedbuild feature, on in release binaries) and enrolls. The agent gRPC endpoint defaults to the enrollment URL's host on:7844;--cp-grpc <URL>overrides. The pairing persists inMCPG_STATE_DIR(gateway-pairing.json+gateway-agent/creds), so subsequent plainmcpgruns re-attach with the same instance identity — no re-enrollment.--control-plane/--cpboots the CP in-process withmcpg cp serve --devsemantics (sqlite in the state dir,auth_mode=none) and auto-enrolls this gateway over loopback: one command, and the console athttp://127.0.0.1:7843already shows the gateway online. Deliberately not sticky — the CP only exists inside--cpruns. It shares the state-dir database withmcpg cp serve --dev, so graduating to split processes keeps all data. (Requires theembedded-cpbuild feature, on in release binaries.)--no-cpdetaches for one run.
Configuration (MCPG_CONFIG + --config)
Config comes from two ordered inputs that layer together, later wins: the
MCPG_CONFIG env var (files only) and the repeatable --config flag.
MCPG_CONFIG is a single path or a path-separator-joined overlay list of
files:
MCPG_CONFIG=config.yaml mcpg # single file
MCPG_CONFIG=base.yaml:production.yaml mcpg # Unix overlay (':' separator)
MCPG_CONFIG="base.yaml;prod.yaml" mcpg # Windows overlay (';')
--config <source> adds layers after the MCPG_CONFIG files (repeat it;
later wins). Unlike MCPG_CONFIG, a --config source is not path-split, so it
can be more than a file path:
mcpg --config base.yaml --config prod.yaml # two files, prod wins
mcpg --config https://cfg.example.com/gateway.yaml # fetched at boot (https)
mcpg --config base64:Z2F0ZXdheToge30K # inline base64 YAML
mcpg --config 'data:application/yaml;base64,Z2F0…' # RFC 2397 data URI
| Source form | Resolved as |
|---|---|
path.yaml, /abs/path.yaml, file://… | a local file (re-read on hot-reload) |
https://host/cfg.yaml | fetched at boot over TLS (10s timeout, 5 MiB cap) |
http://host/cfg.yaml | refused unless MCPG_CONFIG_ALLOW_INSECURE_HTTP=1 (MITM risk) |
base64:<b64> / data:…;base64,<b64> | inline base64-decoded YAML |
Remote and inline (https/base64/data) layers are held in memory and
captured at boot — they are never written to disk, and a hot-reload reuses
the boot snapshot rather than re-fetching. Only file layers hot-reload. Put
secrets behind ${env.X} / cred:// references regardless of source.
Merge order: struct defaults → each YAML layer in order (MCPG_CONFIG files,
then --config sources) → MCPG_* env vars last. Env overrides use __
(double underscore) as the nested-key separator; MCPG_CONFIG itself is the
file entry point and is never treated as an override:
# Override gateway.server.bind_address without editing the file
MCPG_CONFIG=config.yaml MCPG_GATEWAY__SERVER__BIND_ADDRESS=0.0.0.0:8080 mcpg
Each __ segment maps to one level of nesting, so the env var name mirrors the
YAML path (gateway.server.bind_address → MCPG_GATEWAY__SERVER__BIND_ADDRESS).
Transport modes are http (default, Axum HTTP/SSE on gateway.server.bind_address,
default 127.0.0.1:8787) and stdio (JSON-RPC over stdin/stdout).
mcpg dev — local plugin loop
Each --plugin <path> adds one plugin to the running gateway by path (no OCI,
no packaging). The descriptor (plugin.yaml) is read from next to the artifact
(or the crate root for target/release/…).
mcpg plugin new --kind tool_gate --name my-gate # scaffold (delegates to mcpg-plugin)
cd mcpg-plugin-tool-gate-my-gate && cargo build --release
mcpg dev --plugin target/release/libmcpg_plugin_tool_gate_my_gate.so
# Iterate against an MCP client over stdio:
mcpg dev --plugin ./libfoo.so --plugin ./libbar.so --stdio
Examples
MCPG_CONFIG=config.yaml mcpg # run the gateway (HTTP :8787)
MCPG_CONFIG=config.yaml mcpg --stdio # stdio transport
mcpg plugin list ./target/release # delegate to mcpg-plugin
Where does the config come from in production? On Kubernetes the operator sets
MCPG_CONFIGfromMCPGGateway.spec.config; standalone, you author it with the config tooling.