使用说明
mcp-cli
MCP tools from the command line. Zero context overhead.
Here for the auto-sprint? Check out the sprint skill — the autonomous pipeline that develops this repo.
Many MCP servers inject 15,000+ tokens of tool definitions into every Claude Code conversation — every message, every subagent. The gh CLI costs 0 tokens when unused.
mcp-cli gives you the same MCP tools via Bash: discoverable, pipeable, composable, and invisible until needed.
$ mcx my-server search '{"query":"sprint planning"}' | jq '.results[].title'
"Q1 Sprint Planning"
"Sprint Planning Template"
"Sprint Planning Best Practices"
$ mcx another-server get_datetime '{}'
2026-03-02T21:48:22.122294+00:00
$ mcx grep page
getPage my-server Get a page by ID
searchPages my-server Search pages
createPage my-server Create a new page
...
14 tool(s)
Supported platforms
| Platform | Supported versions | Notes |
|---|---|---|
| macOS | 13 Ventura, 14 Sonoma, 15 Sequoia | Current + 2 prior major versions (Apple's own support window) |
| Linux | Any glibc ≥ 2.17 | Matches Bun's minimum requirement |
| Windows | Not supported | — |
Bun ≥ 1.4.4 is required on all platforms.
macOS SQLite note: bun:sqlite on macOS uses the OS-bundled /usr/lib/libsqlite3.dylib rather than embedding SQLite (Linux statically embeds). The daemon requires SQLite ≥ 3.38 for unixepoch() support. macOS 13 Ventura ships SQLite 3.39.5, which satisfies this. macOS 12 Monterey ships 3.37.0 and is unsupported.
Install
One-line installer (macOS/Linux):
curl -fsSL https://github.com/theshadow27/mcp-cli/releases/latest/download/install.sh | sh
Installs mcx, mcpd, and mcpctl to ~/.mcp-cli/bin and adds it to your PATH.
From source (requires Bun):
git clone https://github.com/theshadow27/mcp-cli.git
cd mcp-cli
bun install
bun run build # binaries in dist/
Keeping up to date
mcx upgrade # install latest release
mcx upgrade --check # check without installing
Zero Config
mcp-cli reads your existing Claude Code configuration — ~/.claude.json and .mcp.json. If Claude Code can see a server, so can mcx.
No extra setup. No duplicate config. Just works.
You can also add servers in ~/.mcp-cli/servers.json for standalone use.
How It Works
mcx call server tool '{...}'
|
+-> mcpd (daemon) auto-starts on first call, stays alive 5min
| +-> server-pool persistent connections (stdio, SSE, HTTP)
| +-> auth OAuth/PKCE + macOS Keychain (reads Claude Code tokens)
| +-> SQLite tool cache, usage stats, auth tokens, work items, spans
| +-> event bus unified stream of session/work-item/CI/PR/cost events
| +-> phase engine `.mcx.yaml` → declarative work-item state machine
|
+-> stdout (JSON) pipe to jq, scripts, other tools
The mcx CLI is a thin client. The mcpd daemon manages connections, auth, and caching over a Unix socket. First call cold-starts the daemon (~2s); every call after that is instant.
Beyond raw MCP calls, the daemon also hosts Claude / Codex / Copilot / Gemini / OpenCode / ACP sessions, a unified event bus (mcx monitor), a per-work-item phase state machine (mcx phase, .mcx.yaml), and reactive automation modules — see Monitoring & Events and Phases & Automation.
Commands
Discovery
mcx ls # list servers and their status
mcx ls <server> # list tools on a server
mcx info <server> <tool> # show tool schema (TypeScript notation)
mcx grep <pattern> # search tools across all servers
mcx search <query> # search local tools, then registry
Calling Tools
mcx call <server> <tool> [json] # call a tool with inline JSON
mcx call <server> <tool> @file.json # load args from a file
echo '{"query":"test"}' | mcx call <server> <tool> # pipe from stdin
mcx <server> <tool> [json] # shorthand (skip "call")
mcx call <server> <tool> --jq '.field' # apply jq filter to output
mcx call <server> <tool> --full # bypass output size protection
Server Management
mcx add --transport stdio <name> -- <cmd> [args] # add stdio server
mcx add --transport http <name> <url> # add HTTP server
mcx add --transport http <name> <url> \
--client-id ID --client-secret SECRET # add with OAuth
mcx add-json <name> '{"type":"http","url":"..."}' # add from raw JSON
mcx remove <name> # remove a server
mcx get <name> # inspect server config and status
Options for add: --env KEY=VALUE (repeatable), --header "Name: Value" (HTTP/SSE), --scope {user|project|local}, --callback-port PORT.
Auth & Management
mcx auth <server> # trigger OAuth flow (opens browser)
mcx config show # show resolved config + sources
mcx config sources # list config file locations
mcx config get <key> # get CLI option or server config
mcx config set <key> <value> # set CLI option or server env var
mcx status # daemon PID, uptime, server states
mcx restart [server] # reconnect server(s)
mcx daemon restart # restart daemon (kills sessions)
mcx daemon shutdown # stop the daemon (alias: daemon stop)
mcx shutdown # stop the daemon (legacy shorthand)
mcx version # show CLI, daemon, and protocol versions
mcx upgrade # install latest release binaries
mcx upgrade --check # check for updates without installing
mcx update # update server entries from registry
mcx metrics # show daemon metrics (Prometheus-style)
mcx spans # list trace spans
mcx spans prune # delete exported spans
mcx logs <server> [-f] # view server stderr output
mcx logs --daemon [-f] # view daemon log file
mcx dump # snapshot daemon state for bug reports
mcx dump --stdout # write JSON to stdout instead of a file
mcx dump --include-transcripts # include the last 50 lines of each session log
mcx gc # prune merged branches + stale worktrees
mcx gc --dry-run # preview without changing anything
mcx telemetry # show telemetry status
mcx telemetry off # opt out of telemetry (see PRIVACY.md)
Registry
mcx install <slug> # install server from MCP registry
mcx install <slug> --as <name> # install with custom name
mcx install <slug> --env KEY=VALUE # install with env vars
mcx registry search <query> # search registry
mcx registry list # list all registry servers
Import / Export
mcx import # auto-find .mcp.json in parent dirs
mcx import /path/to/config.json # import from specific file
mcx import --claude # import from Claude Code config
mcx import --claude --all # import all Claude Code projects
mcx add-from-claude-desktop # import all servers from Claude Desktop config
mcx export # export to stdout
mcx export .mcp.json # export to file
mcx export --server <name> # export specific server(s)
Claude Sessions
Spawn and manage headless Claude Code sessions:
mcx claude spawn --task "describe the work" # start a session (non-blocking)
mcx claude spawn -w --task "work in isolation" # start in a git worktree
mcx claude ls # list active sessions (alias: list)
mcx claude send <session> <message> # send follow-up prompt
mcx claude wait [session] # block until session event
mcx claude wait --any # race: session idle or work item event
mcx claude log <session> [--last N] # view session transcript
mcx claude interrupt <session> # interrupt current turn
mcx claude bye <session> # end session, keep worktree (alias: quit)
mcx claude bye <session> --clean # end session + remove worktree + delete branch
mcx claude resume <worktree-or-branch> # reattach to orphaned worktree session
mcx claude resume --all # resume all orphaned worktree sessions
mcx claude worktrees # list mcx-created worktrees (alias: wt)
mcx claude worktrees --prune # remove orphaned worktrees + merged branches
Session IDs support prefix matching (like git SHAs). Use --wait on spawn or send to block until Claude produces a result. Use --json on ls or log for machine-readable output.
Agent Sessions
mcx agent is the unified command for managing non-Claude agent providers (Codex, ACP, OpenCode, Copilot, Gemini):
mcx agent <provider> spawn --task "..." # start an agent session
mcx agent <provider> ls # list sessions for this provider
mcx agent <provider> send <session> <msg> # send a message
mcx agent <provider> wait [session] # wait for session to idle
mcx agent <provider> log <session> # view session transcript
mcx agent <provider> bye <session> # end session
mcx agent <provider> worktrees # list worktrees for this provider
Supported providers: codex, acp, opencode, copilot, gemini. Each provider supports the same core subcommands as mcx claude.
Aliases
Save multi-step workflows as TypeScript scripts:
mcx alias save sprint-board - <<'TS'
const issues = await mcp.projectTracker.searchIssues({
jql: "sprint in openSprints() AND assignee = currentUser()",
fields: ["summary", "status", "priority"]
});
for (const issue of issues.issues) {
console.log(`${issue.key} [${issue.fields.status.name}] ${issue.fields.summary}`);
}
TS
mcx run sprint-board
# or just: mcx sprint-board
mcx alias ls # list saved aliases
mcx alias save <name> <@file | -> # save a script
mcx alias show <name> # print source
mcx alias edit <name> # open in $EDITOR
mcx alias rm <name> # delete
mcx run <alias> [--key value ...] # run with arguments
Alias scripts get a virtual mcp-cli module with:
mcp— proxy object:mcp.<server>.<tool>(args)calls tools through the daemonargs— parsed--key valuepairs from the CLIfile(path)— read a file as stringjson(path)— read and parse a JSON file
Inter-session messaging for coordinating between Claude sessions:
echo "body" | mcx mail -s "subject" <recipient> # send a message
mcx mail -H # list message headers
mcx mail -H -u <user> # list messages for a user
mcx mail --wait --for=<recipient> # block until message arrives
Terminal
mcx tty open "<command>" # run command in new terminal tab
mcx tty open --window "<command>" # run in new window
mcx tty open --headless "<command>" # run as background process
mcx config set terminal <name> # set preferred terminal
Supports: iTerm, Kitty, tmux, WezTerm, Ghostty, Terminal.app. Auto-detects from $TERM_PROGRAM.
Work Item Tracking
Track GitHub issues and PRs through their sprint lifecycle:
mcx track <number> # track an issue or PR by number
mcx track --branch <name> # track a branch (before PR exists)
mcx untrack <number> # stop tracking by number
mcx untrack --branch <name> # stop tracking by branch
mcx tracked # list all tracked work items
mcx tracked --json # machine-readable output
mcx tracked --phase <phase> # filter by phase (impl/review/repair/qa/done)
Monitoring & Events
The daemon hosts a unified event bus that fan-outs everything happening across servers, sessions, work items, PRs, CI, and cost/quota. Stream it with mcx monitor:
mcx monitor # human-readable one-liner per event (TTY)
mcx monitor --json # NDJSON to stdout (pipe to jq)
mcx monitor --subscribe session,work_item # filter by category
mcx monitor --session <id> # one session
mcx monitor --pr <n> # one PR
mcx monitor --work-item <id> # one work item (e.g. "#1441")
mcx monitor --type session.idle # one event type
mcx monitor --phase impl # only items in this phase
mcx monitor --all-repos # disable repo scoping
mcx monitor --until 'pr.merged' # exit when this event fires (glob)
mcx monitor --timeout 60 # exit after N seconds
mcx monitor --max-events 1 # exit after N events
mcx monitor --response-tail <id> # include session.response chunks (debug)
Event types include session.idle, session.result, session.permission_request, session.stuck, ci.started / ci.running / ci.finished (with per-check conclusions + allGreen), pr.merge_state_changed (with cascadeHead), pr.review_comment_posted, phase.changed, cost.session_over_budget / cost.sprint_over_budget, quota.utilization_threshold, daemon.restarted, worker.ratelimited.
Payloads come pre-enriched — cost, turns, lastTool, resultPreview, allGreen, etc. — so orchestrators react push-shaped without a 5-lookup hydration loop. This is the load-bearing primitive for the /sprint skill; see .claude/skills/sprint/README.md.
Event envelope contract
Every event is a flat JSON object — category-specific fields live at the top level, never under a nested payload. A nested payload is rejected by the type at typed call sites and stripped at runtime for events arriving over untyped ingress (the publishEvent IPC extra record, automation emit-event). Two fields are stamped by the producer side of the bus and are present on every event a daemon at this version emits — live, replayed, and heartbeat:
summary— one-line description, rendered from the same per-type formatters the human-readable output uses. Newlines collapsed, trimmed, capped at 120 chars, never empty. A producer may set it explicitly; it is normalized the same way either way.severity— actionability tier:info(heartbeats,session.tool_use, metrics) →notable(pr.opened,ci.started, reviews) →actionable(session.idle,session.result,ci.finished,pr.merged,phase.changed,alias.crashed) →urgent(session.permission_request,cost.*_over_budget,worker.ratelimited,daemon.restarted). A few types are value-dependent:pr.merge_state_changedisactionableonly with acascadeHead,quota.utilization_thresholdisurgentat ≥95%,pr.review_comment_postedisactionableonly whennewCount > 0. Unmapped event types default toinfo. A producer-supplied value outside the four tiers is discarded in favour of the table, so the field is always one of the four.
So the orchestrator's filter is a severity threshold rather than a hand-maintained event whitelist:
mcx monitor --subscribe session,work_item,ci --json \
| jq 'select(.severity == null or .severity == "actionable" or .severity == "urgent") | "\(.event) \(.summary)"'
The .severity == null clause makes the filter fail open: PROTOCOL_VERSION hashes ipc.ts only, so a long-lived pre-#1924 mcpd will happily serve a new mcx fieldless events without a mismatch error. Without the null clause that reads as a silent, healthy stream rather than a stale daemon. Drop the clause once the fields are required rather than optional.
Phases & Automation
mcx ships a declarative phase engine for work items. Declare a state machine in .mcx.yaml at the repo root, write each phase as a defineAlias script under .claude/phases/, and the daemon drives transitions per work item:
mcx phase list # all phases + install status
mcx phase show <name> [--full] # source, schema, declared transitions
mcx phase install # hash sources, write .mcx.lock
mcx phase check # verify lock matches sources (CI gate)
mcx phase why <from> <to> # is this transition legal?
mcx phase run <name> --work-item <id> # execute handler; returns action JSON
mcx phase run <name> --dry-run # preview without side effects
mcx phase advance --work-item <id> # run current phase, follow goto/spawn chain
Handler return shape: { action: "spawn" | "wait" | "goto" | "in-flight", ... }. The orchestrator pipes this to decide what to do next (spawn a session, wait for an external event, transition phases, etc.).
Automation modules are declared under automation: in .mcx.yaml and fire reactively off the event bus:
mcx automation list # all modules + status
mcx automation show <name> # module details
mcx automation log [name] # recent fires (use --limit N)
See docs/phases.md for the manifest schema and authoring guide.
PR Helpers
Worktree-aware GitHub PR helpers (don't trip over gh pr merge --delete-branch's local-branch cleanup):
mcx pr merge <pr> # squash-merge (default)
mcx pr merge <pr> --rebase # rebase-merge
mcx pr merge <pr> --merge # merge commit
mcx pr merge <pr> --auto # enable auto-merge
mcx pr merge <pr> --auto --wait # arm auto-merge + block until MERGED
mcx pr merge <pr> --auto --wait --timeout <ms>
mcx pr merge never deletes local branches — use mcx claude bye --clean or mcx gc for worktree/branch cleanup once a PR is merged. A plain mcx claude bye ends the session only and leaves the worktree and branch in place for inspection.
Virtual Filesystem
Clone remote content (e.g. Confluence spaces) as local git repos, edit locally, and push changes back:
mcx vfs clone confluence <space> [dir] # clone a Confluence space
mcx vfs clone confluence <space> [dir] --cloud-id <id> # specify cloud ID
mcx vfs pull [dir] # pull remote changes into local repo
mcx vfs push [dir] # push local changes back to remote
mcx vfs push [dir] --dry-run # preview push without applying
Notes
Attach annotations to MCP tools — useful for prompt engineering hints or usage reminders:
mcx note set <server>.<tool> "note text" # attach a note to a tool
mcx note get <server>.<tool> # read a note
mcx note ls # list all notes
mcx note rm <server>.<tool> # remove a note
Sites (browser-mediated APIs)
mcx site exposes named HTTP calls that proxy through a harvested browser session — useful for Teams, Outlook, and other web apps that don't have a public API. The catalog is defined in ~/.mcp-cli/sites/.
mcx sites # list configured sites
mcx site calls <site> # list named calls
mcx site describe <site> <call> # show URL, params, jq transforms
mcx site call <site> <call> --<key> <value> # invoke a call
mcx site browser [sites...] # open the harvest browser
mcx site disconnect # stop the browser
mcx site wiggle [site] # run the site's keep-alive script
Memory
mcx memory audit # Haiku-driven staleness + contradiction check
mcx memory audit --json # machine-readable (consumed by retro skills)
Domains
A domain is a name bound to a location — the table mcx routes and partitions by. See
docs/domains.md.
mcx domain add phoenix ~/github/phoenix # register a local domain
mcx domain add phoenix boxen0010:~/github/phoenix # same command, on another host
mcx domain ls [--json] # list domains
mcx domain show <name> [--json] # resolve to host + path
mcx domain which [path] # which domain owns this path? (default: cwd)
mcx domain rename <old> <new> # rename; path and domain_id are untouched
mcx domain rm <name> [--force] # refuses while dependent rows exist
mcx domain import --force # re-arm the one-shot legacy import
# (refuses unless mcx.db is empty; runs on next daemon start)
Utilities
mcx serve # run mcx as stdio MCP server
mcx serve kill <pid> # kill a specific serve instance
mcx serve kill --all # kill all serve instances
mcx serve kill --stale [hours] # kill instances older than N hours
mcx typegen # generate TypeScript types for aliases
mcx completions {bash|zsh|fish} # generate shell completions
mcx serve exposes tools as an MCP server for use in .mcp.json. Set MCP_TOOLS="server/tool,alias" to curate which tools are exposed.
TUI
mcpctl # interactive dashboard
# or: bun run packages/control/src/main.tsx
Tab bar with 5 views — navigate with Tab/Shift+Tab or press 1-5 to jump directly:
- Servers — server list, tool counts, connection states, restarts
- Logs — daemon and per-server log viewer
- Claude — Claude Code session list with transcript viewing
- Mail — message system (coming soon)
- Stats — usage statistics (coming soon)
Claude Code Integration
Add mcp-cli as a Claude Code skill to eliminate context bloat. Instead of injecting dozens of tool definitions (15K+ tokens) into every conversation, Claude calls tools via mcx on demand — 0 tokens at rest.
See skill/SKILL.md for the skill definition.
Architecture
packages/
core/ Shared types, IPC protocol, event types, phase manifest, env expansion
daemon/ mcpd — server pool, auth, SQLite, event bus, work items, phase engine,
agent session hosts (claude, codex, acp, opencode, copilot, gemini, mock)
command/ mcx — CLI entry point (main.ts), command dispatch, alias runner
control/ mcpctl — React/Ink TUI dashboard
- Runtime: Bun (build, test, compile, SQLite)
- Prod dependencies:
@modelcontextprotocol/sdk,zod(v4) - Transports: stdio, SSE, Streamable HTTP
- State:
~/.mcp-cli/— SQLite db (servers, aliases, work items, spans, events), PID file, Unix socket - Event bus: unified per-daemon stream with server-side filtering; consumed by
mcx monitor, phase scripts (ctx.waitForEvent), and automation modules
Development
bun install # install deps
bun test # run tests
bun typecheck # TypeScript validation
bun lint # biome lint + format
bun run build # compile binaries to dist/
bun dev:daemon # run daemon directly
bun dev:mcx -- ls # run CLI directly
License
Disclaimer
This project was developed entirely by Claude Code, without any sort of IDE.
The mcx claude commands exist because they were needed here first. Every sprint is planned, executed, reviewed, and retro'd by Claude sessions talking to each other through mcx. See the sprint skill for how it works.
