mcpgawkdocs ← Site

CLI reference

18 commands, grouped by what you are trying to do. Flags and usage are printed from the version you have installed.

Start here

scanstatus

Approve and protect

baselineapprovedecideguardwrong

Look closer

verifypanelrunsdemo

When something goes wrong

checkupreport

Set up and account

install-nodeloginlogoutskillspush

Exit codes

The same vocabulary across every command, so a script can branch on it.

CodeMeansRead it as
0cleannothing to act on
1findingssomething was found and is reported
2usagethe command was called wrongly
3cannot runnot installed, or the capability is not on this tier
4incompleteit ran but could not finish, so it is NOT clean

4 is not 0. A run that timed out or could not reach a server exits 4. "Could not check" and "checked and clean" must never be the same signal to a script.

Start here

Find out what your agents can already reach.

mcpgawk scan

Measure MCP servers on this machine: every tool they expose, what each one costs your context window, and what it can reach. With no argument it reads every agent config it can find. Give it a config path to scan only that client. Local servers are launched only after you say yes, because scanning one means running its code.

usage: mcpgawk scan [-h] [--stdio STDIO] [--http HTTP] [--sse SSE] [--header HEADER]
                    [--login] [--oauth-client-id OAUTH_CLIENT_ID]
                    [--oauth-client-secret-env VAR]
                    [--oauth-redirect-uri OAUTH_REDIRECT_URI] [--only ONLY] [--yes]
                    [--no-signals] [--no-track] [--json] [--fleet-json] [--with-spec]
                    [--verbose] [--full] [--detail] [--supply-chain] [--oauth-scopes]
                    [config]

positional arguments:
  config                path to an mcp.json config

options:
  -h, --help            show this help message and exit
  --stdio STDIO         one stdio server, e.g. "npx -y @modelcontextprotocol/server-
                        filesystem /tmp"
  --http HTTP           one streamable-HTTP server URL
  --sse SSE             one SSE server URL
  --header HEADER       HTTP header, e.g. "Authorization: Bearer XYZ" (repeatable)
  --login               for a remote --http/--sse server that needs OAuth: open the browser,
                        sign in once, and scan (token stored locally in ~/.gawk/oauth)
  --oauth-client-id OAUTH_CLIENT_ID
                        with --login, for a server that REFUSES automatic client
                        registration (figma, Slack — enterprise posture): use this pre-
                        registered OAuth client id. Register the pinned redirect URI mcpgawk
                        prints with the provider first
  --oauth-client-secret-env VAR
                        environment variable holding the pre-registered client's secret
                        (never passed on the command line; omit for a public client + PKCE)
  --oauth-redirect-uri OAUTH_REDIRECT_URI
                        override the pinned redirect URI (must match the provider's
                        registration EXACTLY)
  --only ONLY           comma-separated server names to scan from the config
  --yes, -y             launch discovered/configured local (stdio) servers WITHOUT the
                        consent prompt (scanning a stdio server runs its code) — for CI /
                        non-interactive use
  --no-signals          skip BOUNDED heuristic signals (facts only)
  --no-track            do NOT record this scan locally (drift/rug-pull detection is on by
                        default; history stays on this machine, at ~/.mcpgawk/history.json)
  --json                emit JSON labels instead of a table
  --fleet-json          emit the FLEET STATUS as JSON (one row per server, grouped by the
                        tool it lives in) — what the IDE extension renders, so state is
                        computed once here
  --with-spec           with --fleet-json, include each server's launch spec
                        (command/args/env or url) so a local front-end can verify it by
                        click — MAY carry secrets from your config; kept off by default and
                        never printed without this flag
  --verbose             show the full per-tool table, not just flagged tools
  --full                print the full per-server surface even when a baseline makes what-
                        changed the default view
  --detail              print the full narrative report for EVERY server instead of the
                        fleet status list (the list is the default when more than one server
                        is scanned)
  --supply-chain        opt-in: query the public npm/PyPI registry for the launched
                        package's deprecation/yank status (network egress — package
                        name+version only)
  --oauth-scopes        opt-in: locally decode a supplied Bearer JWT's scope claim (no
                        network; reads a credential you already provided)

mcpgawk status

One answer to 'am I protected'. Read-only — opens nothing, starts nothing. Coverage is reported PER AGENT, never in aggregate: the hook installs into Claude Code only, so a single cheerful tick would tell a Cursor user they are covered when they are not.

usage: mcpgawk status [-h]

options:
  -h, --help  show this help message and exit

Approve and protect

Decide what a server is allowed to be, then hold it to that.

mcpgawk baseline

The shared baseline every pillar compares against. `verify` and `monitor` read this so that approving a server once is approving it everywhere, instead of each keeping its own memory and contradicting the others.

usage: mcpgawk baseline [-h] [--json] [--server NAME]

options:
  -h, --help     show this help message and exit
  --json         machine-readable (the cross-runtime shape)
  --server NAME  one server (name or alias) instead of all

mcpgawk approve

Accept a server's current tools as the baseline you trust. Until you do, a tool that appeared after the last baseline is treated as drift and its calls are blocked. Run it with no server name to see what is waiting.

usage: mcpgawk approve [-h] [--all] [--list] [server]

positional arguments:
  server      the server name as it appears in your config, or its asserted identity

options:
  -h, --help  show this help message and exit
  --all       approve every server with pending drift
  --list      show which servers have changes you have not approved, and change nothing

mcpgawk decide

The one screen a human is required for. Opens a LOCAL page showing each server that changed since you trusted it, what changed, and lets you approve or keep blocking. Read-only over your state until you click; approval needs the token printed here, so an agent cannot drive it.

usage: mcpgawk decide [-h] [--port PORT] [--no-open]

options:
  -h, --help   show this help message and exit
  --port PORT  local port (default: 7717)
  --no-open    print the URL, do not open a browser

mcpgawk guard

Puts the approved baseline in your agent's loop. A single PreToolUse hook, installed once, checks every MCP tool call — no per-server rewiring and no proxy. The decision is made locally in ~10ms; nothing is uploaded and there is nothing to sign in to.

usage: mcpgawk guard [-h] [--settings PATH] [{status,install,uninstall}]

positional arguments:
  {status,install,uninstall}
                        default: status

options:
  -h, --help            show this help message and exit
  --settings PATH       settings file to edit (default: ~/.claude/settings.json)

mcpgawk wrong

The false-positive affordance. `mcpgawk wrong <server> <tool>/<kind>` records that YOU judged that finding wrong. It keeps appearing, labelled 'muted by you', because a mistake you silenced must stay reviewable — absence of a finding is never safety, including absence you asked for.

usage: mcpgawk wrong [-h] [--undo] server finding-id

positional arguments:
  server      the server name as it appears in your config
  finding-id  the finding as the report prints it: <tool>/<kind>, e.g.
              read_note/injection:reader-directed

options:
  -h, --help  show this help message and exit
  --undo      withdraw the mute

Look closer

Run a server and watch it, or read what happened.

mcpgawk verify

config.json: { "mcpServers": { "local": { "command": "node", "args": ["server.js"], "allowedHosts": ["api.myservice.com"] }, "remote": { "url": "https://mcp.example.com/mcp", "transport": "http", "headers": { "Authorization": "Bearer ${MCP_TOKEN}" } } } } Local (stdio) servers run in a no-egress sandbox — all checks apply. Remote (http/sse) servers can't be sandboxed — only output-based checks (tool-poisoning) apply. ${VAR_NAME} in "headers"/"env" values is substituted from the environment at load time — so a config.json committed to a repo never needs to contain a literal secret (export MCP_TOKEN=... and mcpgawk verify resolves it; a config that references an unset variable fails loudly at startup). --isolate: run local servers in an OS-level container sandbox whose ONLY route out is the verifying egress proxy (ADR-0014). Blocks raw-socket/DNS/UDP exfil outright AND still observes every HTTP(S) destination — allowlisted hosts stay reachable, so SSRF-canary / undeclared-egress checks keep their signal. Covers node/python scripts and install-on-launch commands (npx/uvx); the package install runs contained too, observed against an explicit registry allowlist. Requires Docker; degrades to the default proxy sandbox with a warning otherwise. Slower per probe (a container network per call) — the default remains the everyday path. --baseline <file>: first run records a fingerprint of each server's tools; later runs flag DRIFT (added / removed / changed tools) — i.e. a rug-pull. --behaviour-profile <file>: write a gawk.behaviour/1 profile (per-tool observed source/sink) — feed it to `mcpgawk enforce --behaviour-profile` so toxic-flow blocks by BEHAVIOUR, not name. --sarif <file>: write a SARIF 2.1.0 report — GitHub code scanning / most CI security dashboards ingest this natively. A suppressed finding is encoded as a SARIF suppression (shows as "dismissed" on GitHub), not silently dropped from the file. --junit <file>: write a JUnit XML report — renders as a pass/fail test tree in most CI UIs. A suppressed finding becomes a <skipped/> testcase, not a <failure> or nothing. --suppress <file>: exclude REVIEWED findings (by deterministic findingId) from status/exit-code — a legitimate, accepted finding no longer fails CI forever. Never auto-created; use `mcpgawk verify suppress` to add an entry after actually reviewing a finding. Suppressed findings still APPEAR in every output format, marked, never hidden. --webhook <url>: POST the JSON report to <url> when there are findings or drift (alert sink). --audit-log <file>: append ONE JSONL line per reproduction attempt (every attempt, not just ones that produce a finding) — server/tool/check/attempt, whether it completed, the raw response text (truncated to 2000 chars) and egress observed, or the infra failure detail. A "clean" report on its own is a verdict to trust; this is the evidence to check that verdict against. Off by default (raw tool output may contain the target's own data — opt in deliberately). --out <file>: write the JSON report incrementally as each server finishes, not only once at the very end (atomic tmp-file-then-rename, same pattern as never leaving a half-written file). A killed/timed-out run (a slow OAuth-fronted remote, a hung server) leaves the last-known-good snapshot on disk instead of losing every server that already finished cleanly. --json still controls whether the full report also prints to stdout at the end; --out is independent of it. --audit-source: ALSO statically audit each server's SOURCE CODE (AST + semgrep, handled by the Python side before this CLI runs — you won't see these flags again in errors from here). Local script paths are audited in place; npm/pypi launch specs (npx/uvx) are fetched from the public registry — a network call, fetch-only, nothing executed. Remote (url) servers have no local source: reported not-applicable. --source-dir <path>: with --audit-source, skip resolution and audit exactly this directory (single-server configs only). serve: open a local web UI (default http://127.0.0.1:7878) to paste a config and verify in the browser. suppress: record that a specific findingId (from a prior run's output) has been reviewed and accepted — appends to --file, creating it if it doesn't exist yet.

usage: mcpgawk verify <config.json> [--unsafe] [--isolate] [--json] [--html <file>] [--csv <file>]
                          [--sarif <file>] [--junit <file>] [--behaviour-profile <file>] [--suppress <file>]
                          [--baseline <file>] [--webhook <url>] [--audit-log <file>] [--out <file>]
                          [--audit-source] [--source-dir <path>]
       mcpgawk verify serve [--port <n>] [--host <addr>]   # local web UI
       mcpgawk verify suppress <findingId> --file <file> --reason "<why>" [--approved-by "<who>"]

mcpgawk panel

One window over the whole machine: which agents are covered, every MCP server and its state, what the runtime guard has actually seen, and anything waiting on you. A control surface, not a viewer: re-scan, verify, sign-in, approve and protect all live here — but only on the tokened URL this command prints. A bare 127.0.0.1:7718 (bookmark, restored tab) renders read-only with no buttons, by design. Drift decisions also live in `mcpgawk decide`.

usage: mcpgawk panel [-h] [--port PORT] [--no-open]

options:
  -h, --help   show this help message and exit
  --port PORT  local port (default: 7718)
  --no-open    print the URL, do not open a browser

mcpgawk runs

Your local run history — scans, and (with mcpgawk Platform) verify, enforce and monitor runs, newest first. Read from ~/.mcpgawk/runs.db; nothing is uploaded anywhere. A run that never closed shows as RUNNING, and as INCOMPLETE once its process is gone — it is never reported as success.

usage: mcpgawk runs [-h] [--kind {scan,verify,enforce,monitor,guard}] [--limit LIMIT]
                    [--json] [--prune]

options:
  -h, --help            show this help message and exit
  --kind {scan,verify,enforce,monitor,guard}
                        only this kind of run
  --limit LIMIT         how many to show (default 20)
  --json                machine-readable output
  --prune               drop finished runs older than 90 days, then report what is left

mcpgawk demo

A self-contained walkthrough: mcpgawk plants a deliberately-bad MCP server in a temporary sandbox, measures it, you approve it, the server turns hostile, and the guard blocks the tool that appeared afterwards. Nothing touches your real fleet, agents, or state. Offline; a few seconds.

usage: mcpgawk demo [-h] [--sandbox DIR] [--clean]

options:
  -h, --help     show this help message and exit
  --sandbox DIR  use this directory for the sandbox instead of a fresh temp one
  --clean        delete the sandbox on exit (default: keep it so you can inspect it)

When something goes wrong

Capture what happened, redacted, in one file you can send.

mcpgawk checkup

Exercises every surface in turn — version, status, scan, verify, the run history and every panel tab — then writes one file with what each step did. A step that fails is kept, not hidden: that is the point. Steps that would launch your local servers ask once and can be declined without stopping the rest. Nothing is uploaded. Stop it at any time with Ctrl-C and the bundle is still written.

usage: mcpgawk checkup [-h] [--output PATH] [--note TEXT] [--yes] [--strict]

options:
  -h, --help     show this help message and exit
  --output PATH  write here instead of ./mcpgawk-checkup-<timestamp>.zip
  --note TEXT    what you were trying to do — travels in the bundle
  --yes, -y      do not ask before launching local servers (for a non-interactive run)
  --strict       remove hostnames, package names and command arguments as well

mcpgawk report

Collects everything about this machine into a single redacted zip: version and how mcpgawk was installed, per-agent hook state, the entire run history, the entire call log, every verify run, open drift alerts, and an inventory of both state directories. Nothing is uploaded — the command prints a path and stops. Server responses are removed by field name, home directories become ~, and every URL keeps its parameter names and loses their values. A store that could not be read is listed as 'unavailable', which means nobody looked — never 'nothing there'.

usage: mcpgawk report [-h] [--output PATH] [--strict] [--note TEXT]

options:
  -h, --help     show this help message and exit
  --output PATH  write here instead of ./mcpgawk-report-<timestamp>.zip
  --strict       also remove hostnames, package names and command arguments — for a machine
                 whose owner will not let internal infrastructure leave it (credentials,
                 server responses and env values are always removed)
  --note TEXT    what you were doing when it went wrong — travels in the bundle

Set up and account

Installation, licensing and the bits you touch once.

mcpgawk install-node

Download the Node runtime that `verify` uses to run a server in a sandbox. About 26 MB, into mcpgawk's own directory: no admin rights, and nothing on the system is changed.

usage: mcpgawk install-node [-h] [--yes]

options:
  -h, --help  show this help message and exit
  --yes, -y   skip the confirmation — required in a non-interactive session, because this
              downloads and then RUNS third-party code

mcpgawk login

Validates your key against Lemon Squeezy and saves it to ~/.gawk/config.json (mode 0600) so you don't need to export GAWK_LICENSE_KEY yourself. Re-run any time to switch keys.

usage: mcpgawk login <license-key>

mcpgawk logout

mcpgawk logout: no saved key to remove.

mcpgawk skills

Discovers agent skills across every supported host (Claude Code, Codex, Cursor, Copilot, Windsurf, Antigravity, Kiro, Gemini, opencode, Amp) and scans their content locally — nothing is uploaded anywhere. Give paths to scan a specific skill dir, a skills root, or a project instead of the whole machine.

usage: mcpgawk skills [-h] [--json] [--fail-on-findings] [paths ...]

positional arguments:
  paths               skill dir / skills root / project root (default: discover all hosts)

options:
  -h, --help          show this help message and exit
  --json              machine-readable output
  --fail-on-findings  exit 1 if any finding fires (CI gate) — default reports and exits 0,
                      because a signal is a signal, not a verdict

mcpgawk push

Push a scan receipt (Report v0) to your Finix dashboard fleet. The server appears in the dashboard even though you never scanned it from the portal -- that is the point. mcpgawk push --http https://your-server/mcp scan a live server and push the receipt mcpgawk push --stdio "npx -y @scope/server /tmp" scan a local stdio server and push mcpgawk push --file report.json push a Report v0 your CI already produced Needs a license key: `mcpgawk login <key>` once, or export GAWK_LICENSE_KEY (CI). Endpoint overridable via GAWK_INGEST_URL.

usage: mcpgawk push (--stdio "<cmd>" | --http <url> | --sse <url> | --file <report.json>) [--source cli|ci]