CLI as MCP
Any command-line tool can become an MCP server. No code, no wrapper — just config.
{
"mcpServers": {
"kubectl": {
"command": "kubectl",
"cli": true
}
}
}That's it. mcp runs kubectl --help, discovers subcommands and flags, and exposes them as MCP tools automatically.
Why
MCP is becoming the standard protocol for AI tool integration. But most software ships as a CLI, not an MCP server. This bridge closes the gap: any CLI becomes accessible to GPT, Claude, Cursor, or any MCP-compatible client — without writing a single line of integration code.
You / AI agent --> mcp CLI --> CliTransport --> kubectl / docker / terraform / ...
|
servers.jsonHow discovery works
When you add a CLI server, mcp automatically:
Runs
<command> --helpto discover subcommandsRuns
<command> <subcommand> --helpfor each subcommand to discover flagsGenerates MCP tool definitions with proper
inputSchema
Each subcommand becomes a tool named <command>_<subcommand> (e.g. kubectl_get, kubectl_describe).
Flags are parsed into typed schema properties:
Calling tools
Tools accept a JSON object. Flags map to properties (dashes become underscores). Positional arguments go in args:
The args field supports shell quoting for arguments with spaces:
Each call spawns the CLI process, captures stdout, and returns it as MCP content. No long-running process — each invocation is independent.
If the command writes to stderr on success (e.g. warnings), it's appended to the output under a --- stderr --- delimiter so nothing is lost silently.
Configuration
Minimal
Full options
command
string
required
CLI executable to wrap
cli
bool
required
Must be true — marks this as a CLI server
cli_help
string
"--help"
Flag used to discover subcommands and options
cli_depth
number
2
How deep to recurse into subcommands for flag discovery
cli_only
string[]
[] (all)
Whitelist of subcommands to expose — everything else is hidden
args
string[]
[]
Base arguments prepended to every invocation
env
object
{}
Environment variables for the CLI process
cli_help
Most CLIs use --help. Some don't:
cli_only
Limit exposure to safe, read-only commands:
This is important for security — you probably don't want an AI agent running kubectl delete or kubectl exec.
cli_depth
Controls how deep the discovery goes:
1— only parse the top-level--help(subcommand names + descriptions, no flag details)2(default) — also run<subcommand> --helpto discover flags and buildinputSchema
Values greater than 2 are accepted but currently behave the same as 2 (no additional recursion depth).
Preset tools
If automatic discovery doesn't work for a specific CLI, you can define tools manually:
When tools is non-empty, automatic discovery is skipped. The args in each tool define the exact arguments passed to the CLI when that tool is called.
Examples
kubectl
docker
terraform
git (read-only)
How it works with proxy mode
CLI servers work with mcp serve just like any other server. Tools are namespaced the same way:
Idle timeout applies: since each CLI call is a separate process spawn, the CLI transport itself has no persistent connection to shut down. The idle timeout controls when the discovered tool cache is dropped.
Environment variables
MCP_TIMEOUT
60
Timeout in seconds for each CLI command execution
MCP_MAX_OUTPUT
1048576
Max output size in bytes (1 MB). Larger output is truncated
MCP_DISCOVERY_CONCURRENCY
10
Max parallel --help calls during subcommand discovery
Help format support
The discovery parser handles these common formats:
Cobra (Go)
kubectl, docker, gh
Yes
Clap (Rust)
ripgrep, fd
Yes
Click (Python)
flask, black
Yes
Argparse (Python)
most Python CLIs
Yes
Custom
varies
Best-effort, fallback to single tool
If a CLI's --help output doesn't follow standard patterns, discovery falls back to exposing the command as a single tool with a free-form args parameter.
Last updated
Was this helpful?