QTG CLI & MCP — Reference
QTG ships 3 entry points for the control plane:
All 3 binaries share the existing environment-variable HMAC signing path. Role enforcement
happens server-side (HMAC middleware
ROLE_ALLOWED_ROUTES). The protected
connection-file mode below is a bounded preparation surface, not onboarding, issuance,
or activation.
Env vars (single set, all 3 binaries)
The shared HMAC client emits both
X-MG-* and X-QTG-* headers (v3 nonce +
timestamp), matching qtg.interfaces.api.middleware.auth.hmac.sign_request_headers.
Agent CLI (qtg-agent, 8 commands, read + propose only)
qtg-agent balances
GET /v3/balances. Returns the balance view this agent can see.
qtg-agent movements list / get / timeline
GET /v3/movements?limit=20, GET /v3/movements/{id},
GET /v3/movements/{id}/timeline.
qtg-agent authority describe
GET /v3/agent-authorities/{authority_key}. The authority_key is derived
from QTG_AGENT_NAMESPACE (strip agent/ prefix), or QTG_AUTHORITY_KEY if set,
or fetched from /v3/whoami as fallback.
qtg-agent template-proposals get
GET /v3/template-proposals/{id}. Poll this after template-propose until
status == "auto_promoted" (or admin promotes manually) to learn the
resulting template_key.
qtg-agent template-propose
POST /v3/agent-authorities/{authority_key}/template-proposals. Side-effect
free until promoted. Returns {proposal_id, status, ...}.
qtg-agent bridge-attempt
Same field set as template-propose plus optional --callback-url. D10 rule
applies — propose only, no auto-execute.
Nomovement-run. The agent CLI is read + propose only — it cannot execute a movement. A movement an agent originates (via the API) always parks atPENDING_APPROVALwithagent_auto_approve_skipped, regardless of the operator’sauto_approve_enabledsetting; a human promotes + approves.
Admin CLI (qtg)
qtg exposes all 8 agent commands plus the Free admin surface below. Venue
checks (qtg venue probe/smoke) are implemented and wired today. Key/role
provisioning (qtg admin keys / admin role) is still deferred to v0.2.0+ —
use legacy seed_auth_client.py / bootstrap_admin_cli_key.py for that.
qtg init
public plus the selected network bucket, and render a .env from .env.example.
It does not provision an inbound administrator credential, local signer, or agent
authority. Walkthrough: Local Setup.
Protected connection file (bounded preparation)
A protected POSIX connection file is supported only at the root of these commands:schema_version,
api_url, network, key_id, and secret_file; namespace and authority_key
are optional for CLI and namespace is required for MCP. secret_file is a raw-secret
filename, not secret JSON or a path; it must name a direct sibling in the same
protected directory. For example, these synthetic values are structurally complete:
network is exactly mainnet or testnet. When both namespace and
authority_key are supplied, agent/<key> normalization must make them the same
identity; contradictions fail before HTTP. The directory and both files must be owned
by the invoking user, with directory mode 0700 and file mode 0600; symlinks,
symlinked traversal, broad permissions, raw secrets in JSON, unknown fields, and ambient
QTG_* fallback are rejected. The selected network becomes X-QTG-Network; a different
process network fails closed.
No other --connection-file command is supported: local, venue, top-up, Pro, help,
and ordinary agent paths fail before file loading or command execution. auth check
only reads authenticated identity and, for a matching agent namespace, its existing
authority record. It does not evaluate policy, approval, provider, or live readiness.
An omitted or mismatching agent namespace is non-success. File-selected revoke requires
literal --yes; it still uses the server’s exact-current-credential revoke rules. The
legacy env-only revoke command remains compatible without --yes. File-selected CLI
failures with --json return only {"operation":"...","code":"..."} on stdout and
the code on stderr. MCP rejects invalid file/role/namespace/network startup contexts
with only a stable code and returns bounded operation/code errors from existing tools;
it neither adds tools nor grants permissions.
This does not bootstrap an administrator, issue a credential, authenticate pending keys,
activate policy, or make a process movement-ready. Existing stored-secret-at-rest risks
and legacy secret-output surfaces remain outside this preparation slice.
qtg whoami
GET /v3/whoami. Returns {client_id, key_id, role, namespace?}. Useful
sanity check for key/secret setup.
qtg audit query
GET /v3/audit/events. Supported filters mirror
src/qtg/interfaces/api/routes/audit.py (:59-98) exactly:
--time-range-start, --time-range-end, --actor-client-id,
--actor-key-id, --entity-type, --entity-key, --action,
--request-id, --outcome, --namespace, --cursor, --limit.
qtg template promote
POST /v3/template-proposals/{proposal_id}/promote. Admin-only. Promotion is governed: the route
returns 409 CONFIG_PROPOSAL_REQUIRED; promote through an agent_authority_proposal.promote
configuration proposal applied by a second admin.
qtg template patch
PATCH /v3/plan-templates/{template_key}. --namespace is the only field this command sends.
The auto-approve toggle and caps are governed — the raw HTTP route returns
409 CONFIG_PROPOSAL_REQUIRED for them — so change them through a route_template.auto_approve
configuration proposal (see Auto-Approve).
qtg allowlist list
GET /dashboard/allowed-addresses. Read-only view of the address allowlist
that guards fund movement. Filters: --chain-family (evm | cex),
--chain-id, --include-inactive (adds revoked rows).
A row with "chain_id": null is an any-chain wildcard — it authorises the
address on every chain of its family. Review those first when auditing.
The group is read-only by design. Registering and revoking stay on the audited
write surfaces — python -m qtg.interfaces.tools.seed_allowed_address /
... .revoke_allowed_address, or the dashboard writer-HMAC routes — because a
convenience CLI mutation on a fund-safety gate is an open security decision. See
Runbook — Address Allowlist Management.
qtg chain probe
qtg agent-wallet topup
The Agent Wallet top-up stage ladder — preflight, env-probe, init-packet,
seed-stage1, drill-stage2, live-stage3, validate-packet. init-packet requires an explicit
--output-dir; use an operator-private directory outside publishing or shared branches,
as an explicit path does not prove privacy. Only live-stage3 can sign or broadcast,
and it requires an explicit acknowledgement flag. See Agent Wallet.
qtg testnet-truncate
Truncates every network-scoped table in the testnet schema. Prompts unless
--yes is passed. There is no mainnet equivalent.
Human session CLI (qtg human)
JEP-877 protected human action / JEP-919 CLI onboarding surface — a closed,
local-only human session plane, separate from the HMAC auth commands and not a
credential issuance path:
qtg and qtg-agent; browser-wallet opt-in (KMS/SIWE) stays
disabled by default.
Venue CLI (qtg venue)
Adapter health check + live smoke test. See
guide/venue-smoke-test.md for the end-to-end
walkthrough.
qtg venue probe
binance, upbit, bybit). Exits non-zero if the probe
fails. Runs the probe harness locally; no movement is created.
qtg venue smoke
--max-source-debit is required
and must be ≥ --amount: it is threaded into approval as the operator-approved CEX
fee-on-top source-debit authority, so a withdrawal whose gross debit exceeds it is
rejected. Prompts for confirmation unless --no-confirm is passed. --timeout bounds
the observe phase (default 300s). Exits 0 only when the movement reaches COMPLETED;
exit 1 when one or more probes/transfer steps fail, exit 2 for unknown venue or missing credentials.
MCP server — Claude Desktop / Cursor
qtg-mcp is a stdio MCP server exposing 8 read+propose tools to MCP-aware clients (no movement-execution tool).
claude_desktop_config.json
Tool list
Boot-time role probe (fail-fast)
qtg-mcp does a synchronous GET /v3/whoami before opening the stdio
handshake. If:
- the env is incomplete → exit 2 with stderr
qtg-mcp: config error: ... - whoami HTTP fails → exit 1 with stderr
qtg-mcp: whoami probe failed: ... - role !=
agent→ exit 1 with stderrqtg-mcp: refusing to start — key role is 'admin', expected 'agent' - env namespace != server-reported namespace → exit 1 with stderr
qtg-mcp: namespace mismatch — ...
e2e smoke runbook
Out of scope (v0.1.0 GA)
- Template discovery (
qtg-agent templates list/search) — v0.2.0 - Streamable HTTP MCP transport — v0.2.0+ (stdio only for now)
qtg admin keys/admin role(key/role provisioning) — server routes pending; use legacyseed_auth_client.pyfor now.- Migration of 55+ legacy admin tools — v0.2.0+ gradual
- Colored / pretty CLI output (rich) — v0.2.0+
- Windows shell compatibility — macOS + Linux verified only