philschmid/mcp-cli(新しいタブで開きます)
主要言語: TypeScript
Lighweight CLI to interact with MCP servers
- star 数
- 1,280
- watcher 数
- 3
- fork 数
- 161
- issue 数
- 235
- 最終更新
- 2026/02/06
主要言語: TypeScript
Lighweight CLI to interact with MCP servers
A lightweight, Bun-based CLI for interacting with MCP (Model Context Protocol) servers.
bun build --compilejq, chaining supportcurl -fsSL https://raw.githubusercontent.com/philschmid/mcp-cli/main/install.sh | bashor
# requires bun install
bun install -g https://github.com/philschmid/mcp-cliCreate mcp_servers.json in your current directory or ~/.config/mcp/:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"."
]
},
"deepwiki": {
"url": "https://mcp.deepwiki.com/mcp"
}
}
}# List all servers and tools mcp-cli # With descriptions mcp-cli -d
# View tool schema first mcp-cli info filesystem read_file # Call the tool mcp-cli call filesystem read_file '{"path": "./README.md"}'
mcp-cli [options] List all servers and tools
mcp-cli [options] info <server> Show server tools and parameters
mcp-cli [options] info <server> <tool> Show tool schema
mcp-cli [options] grep <pattern> Search tools by glob pattern
mcp-cli [options] call <server> <tool> Call tool (reads JSON from stdin if no args)
mcp-cli [options] call <server> <tool> <json> Call tool with JSON arguments
Both formats work: info <server> <tool> or info <server>/<tool>
Tip
Add -d to any command to include descriptions.
| Option | Description |
|---|---|
-h, --help |
Show help message |
-v, --version |
Show version number |
-d, --with-descriptions |
Include tool descriptions |
-c, --config <path> |
Path to config file |
| Stream | Content |
|---|---|
| stdout | Tool results and human-readable info |
| stderr | Errors and diagnostics |
# Basic listing $ mcp-cli github • search_repositories • get_file_contents • create_or_update_file filesystem • read_file • write_file • list_directory # With descriptions $ mcp-cli --with-descriptions github • search_repositories - Search for GitHub repositories • get_file_contents - Get contents of a file or directory filesystem • read_file - Read the contents of a file • write_file - Write content to a file
# Find file-related tools across all servers $ mcp-cli grep "*file*" github/get_file_contents github/create_or_update_file filesystem/read_file filesystem/write_file # Search with descriptions $ mcp-cli grep "*search*" -d github/search_repositories - Search for GitHub repositories
$ mcp-cli info github
Server: github
Transport: stdio
Command: npx -y @modelcontextprotocol/server-github
Tools (12):
search_repositories
Search for GitHub repositories
Parameters:
• query (string, required) - Search query
• page (number, optional) - Page number
...# Both formats work: $ mcp-cli info github search_repositories $ mcp-cli info github/search_repositories Tool: search_repositories Server: github Description: Search for GitHub repositories Input Schema: { "type": "object", "properties": { "query": { "type": "string", "description": "Search query" }, "page": { "type": "number" } }, "required": ["query"] }
# With inline JSON $ mcp-cli call github search_repositories '{"query": "mcp server", "per_page": 5}' # JSON output is default for call command $ mcp-cli call github search_repositories '{"query": "mcp"}' | jq '.content[0].text' # Read JSON from stdin (no '-' needed!) $ echo '{"path": "./README.md"}' | mcp-cli call filesystem read_file
For JSON arguments containing single quotes, special characters, or long text, use stdin to avoid shell escaping issues:
# Using a heredoc (no '-' needed with call subcommand) mcp-cli call server tool <<EOF {"content": "Text with 'single quotes' and \"double quotes\""} EOF # From a file cat args.json | mcp-cli call server tool # Using jq to build complex JSON jq -n '{query: "mcp", filters: ["active", "starred"]}' | mcp-cli call github search
Why stdin? Shell interpretation of {}, quotes, and special characters requires careful escaping. Stdin bypasses shell parsing entirely.
Chain multiple MCP calls together using pipes and shell tools:
# 1. Search and read: Find files matching pattern, then read the first one mcp-cli call filesystem search_files '{"path": "src/", "pattern": "*.ts"}' \ | jq -r '.content[0].text | split("\n")[0]' \ | xargs -I {} mcp-cli call filesystem read_file '{"path": "{}"}' # 2. Process multiple results: Read all matching files mcp-cli call filesystem search_files '{"path": ".", "pattern": "*.md"}' \ | jq -r '.content[0].text | split("\n")[]' \ | while read file; do echo "=== $file ===" mcp-cli call filesystem read_file "{\"path\": \"$file\"}" | jq -r '.content[0].text' done # 3. Extract and transform: Get repo info, extract URLs mcp-cli call github search_repositories '{"query": "mcp server", "per_page": 5}' \ | jq -r '.content[0].text | fromjson | .items[].html_url' # 4. Conditional execution: Check file exists before reading mcp-cli call filesystem list_directory '{"path": "."}' \ | jq -e '.content[0].text | contains("README.md")' \ && mcp-cli call filesystem read_file '{"path": "./README.md"}' # 5. Save output to file mcp-cli call github get_file_contents '{"owner": "user", "repo": "project", "path": "src/main.ts"}' \ | jq -r '.content[0].text' > main.ts # 6. Error handling in scripts if result=$(mcp-cli call filesystem read_file '{"path": "./config.json"}' 2>/dev/null); then echo "$result" | jq '.content[0].text | fromjson' else echo "File not found, using defaults" fi # 7. Aggregate results from multiple servers { mcp-cli call github search_repositories '{"query": "mcp", "per_page": 3}' mcp-cli call filesystem list_directory '{"path": "./src"}' } | jq -s '.'
Tips for chaining:
jq -r for raw output (no quotes)jq -e for conditional checks (exit code 1 if false)2>/dev/null to suppress errors when testing| jq -s '.' to combine multiple JSON outputsThe CLI uses mcp_servers.json, compatible with Claude Desktop, Gemini or VS Code:
{
"mcpServers": {
"local-server": {
"command": "node",
"args": ["./server.js"],
"env": {
"API_KEY": "${API_KEY}"
},
"cwd": "/path/to/directory"
},
"remote-server": {
"url": "https://mcp.example.com",
"headers": {
"Authorization": "Bearer ${TOKEN}"
}
}
}
}Environment Variable Substitution: Use ${VAR_NAME} syntax anywhere in the config. Values are substituted at load time. By default, missing environment variables cause an error with a clear message. Set MCP_STRICT_ENV=false to use empty values instead (with a warning).
Restrict which tools are available from a server using allowedTools and disabledTools:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"allowedTools": ["read_file", "list_directory"],
"disabledTools": ["delete_file"]
}
}
}Rules:
allowedTools: Only tools matching these patterns are available (supports glob: *, ?)disabledTools: Tools matching these patterns are excludeddisabledTools takes precedence over allowedToolsExamples:
// Only allow read operations "allowedTools": ["read_*", "list_*", "search_*"] // Allow all except destructive operations "disabledTools": ["delete_*", "write_*", "create_*"] // Combine: allow file operations but disable delete "allowedTools": ["*file*"], "disabledTools": ["delete_file"]
The CLI searches for configuration in this order:
MCP_CONFIG_PATH environment variable-c/--config command line argument./mcp_servers.json (current directory)~/.mcp_servers.json~/.config/mcp/mcp_servers.json| Variable | Description | Default |
|---|---|---|
MCP_CONFIG_PATH |
Path to config file | (none) |
MCP_DEBUG |
Enable debug output | false |
MCP_TIMEOUT |
Request timeout (seconds) | 1800 (30 min) |
MCP_CONCURRENCY |
Servers processed in parallel (not a limit on total) | 5 |
MCP_MAX_RETRIES |
Retry attempts for transient errors (0 = disable) | 3 |
MCP_RETRY_DELAY |
Base retry delay (milliseconds) | 1000 |
MCP_STRICT_ENV |
Error on missing ${VAR} in config |
true |
MCP_NO_DAEMON |
Disable connection caching (force fresh connections) | false |
MCP_DAEMON_TIMEOUT |
Idle timeout for cached connections (seconds) | 60 |
mcp-cli is designed to give AI coding agents access to MCP (Model Context Protocol) servers. MCP enables AI models to interact with external tools, APIs, and data sources through a standardized protocol.
Traditional MCP integration loads full tool schemas into the AI's context window, consuming thousands of tokens. The CLI approach:
jq, pipes, and scriptsAdd this to your AI agent's system prompt for direct CLI access:
## MCP Servers You have access to MCP servers via the `mcp-cli` CLI. Commands: ```bash mcp-cli info # List all servers mcp-cli info <server> # Show server tools mcp-cli info <server> <tool> # Get tool schema mcp-cli grep "<pattern>" # Search tools mcp-cli call <server> <tool> # Call tool (stdin auto-detected) mcp-cli call <server> <tool> '{}' # Call with JSON args ``` **Both formats work:** `info <server> <tool>` or `info <server>/<tool>` Workflow: 1. **Discover**: `mcp-cli info` to see available servers 2. **Inspect**: `mcp-cli info <server> <tool>` to get the schema 3. **Execute**: `mcp-cli call <server> <tool> '{}'` with arguments ### Examples ```bash # Call with inline JSON mcp-cli call github search_repositories '{"query": "mcp server"}' # Pipe from stdin (no '-' needed) echo '{"path": "./file"}' | mcp-cli call filesystem read_file # Heredoc for complex JSON mcp-cli call server tool <<EOF {"content": "Text with 'quotes'"} EOF ``` ### Common Errors | Wrong | Error | Fix | |-------|-------|-----| | `mcp-cli server tool` | AMBIGUOUS | Use `call server tool` | | `mcp-cli run server tool` | UNKNOWN_SUBCOMMAND | Use `call` | | `mcp-cli list` | UNKNOWN_SUBCOMMAND | Use `info` |
For Code Agents that support Agents Skills, like Gemini CLI, OpenCode or Claude Code. you can use the mcp-cli skill to interface with MCP servers. The Skill is available at SKILL.md
Create mcp-cli/SKILL.md in your skills directory.
By default, the CLI uses lazy-spawn connection pooling to avoid repeated MCP server startup latency:
┌────────────────────────────────────────────────────────────────────┐
│ First CLI Call │
│ $ mcp-cli info server │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ Check: /tmp/mcp-cli-{uid}/server.sock exists? │
└────────────────────────────────────────────────────────────────────┘
│ │
│ NO │ YES
▼ ▼
┌─────────────────────────┐ ┌───────────────────────────────────┐
│ Fork background daemon │ │ Connect to existing socket │
│ ├─ Connect to MCP server│ │ ├─ Send request via IPC │
│ ├─ Create Unix socket │ │ ├─ Receive response │
│ └─ Start 60s idle timer │ │ └─ Daemon resets idle timer │
└─────────────────────────┘ └───────────────────────────────────┘
│ │
└────────────────┬───────────────────┘
▼
┌────────────────────────────────────────────────────────────────────┐
│ On idle timeout (60s): Daemon self-terminates, cleans up files │
└────────────────────────────────────────────────────────────────────┘
Key features:
Control via environment:
MCP_NO_DAEMON=1 mcp-cli info # Force fresh connection MCP_DAEMON_TIMEOUT=120 mcp-cli # 2 minute idle timeout MCP_DEBUG=1 mcp-cli info # See daemon debug output
When daemon is disabled (MCP_NO_DAEMON=1), the CLI uses a lazy, on-demand connection strategy. Server connections are only established when needed and closed immediately after use.
┌─────────────────────────────────────────────────────────────────┐
│ USER REQUEST │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ mcp-cli info │ │ mcp-cli grep │ │ mcp-cli call │
│ (list all) │ │ "*pattern*" │ │ server tool {} │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Connect to ALL │ │ Connect to ALL │ │ Connect to ONE │
│ servers (N) │ │ servers (N) │ │ server only │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
List tools Search tools Execute tool
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ CLOSE CONNECTIONS │
└─────────────────────────────────────────────────────────────┘
When are servers connected?
| Command | Servers Connected |
|---|---|
mcp-cli info |
All N servers in parallel |
mcp-cli grep "*pattern*" |
All N servers in parallel |
mcp-cli info <server> |
Only the specified server |
mcp-cli info <server> <tool> |
Only the specified server |
mcp-cli call <server> <tool> '{}' |
Only the specified server |
The CLI includes automatic retry with exponential backoff for transient failures.
Transient errors (auto-retried):
ECONNREFUSED, ETIMEDOUT, ECONNRESET502, 503, 504, 429Non-transient errors (fail immediately):
401, 403bun install https://github.com/philschmid/mcp-cli
# Run in development bun run dev # Type checking bun run typecheck # Linting bun run lint bun run lint:fix # Run all tests (unit + integration) bun test # Run only unit tests (fast) bun test tests/config.test.ts tests/output.test.ts tests/client.test.ts # Run integration tests (requires MCP server, ~35s) bun test tests/integration/ # Build single executable bun run build # Build for all platforms bun run build:all
Test the CLI locally without compiling by using bun link:
# Link the package globally (run once) bun link # Now you can use 'mcp-cli' anywhere mcp-cli --help mcp-cli call filesystem read_file '{"path": "./README.md"}' # Or run directly during development bun run dev --help bun run dev info filesystem
To unlink when done:
bun unlink
Releases are automated via GitHub Actions. Use the release script:
./scripts/release.sh 0.2.0
All errors include actionable recovery suggestions, optimized for both humans and AI agents:
Error [AMBIGUOUS_COMMAND]: Ambiguous command: did you mean to call a tool or view info?
Details: Received: mcp-cli filesystem read_file
Suggestion: Use 'mcp-cli call filesystem read_file' to execute, or 'mcp-cli info filesystem read_file' to view schema
Error [UNKNOWN_SUBCOMMAND]: Unknown subcommand: "run"
Details: Valid subcommands: info, grep, call
Suggestion: Did you mean 'mcp-cli call'?
Error [SERVER_NOT_FOUND]: Server "github" not found in config
Details: Available servers: filesystem, sqlite
Suggestion: Use one of: mcp-cli info filesystem, mcp-cli info sqlite
Error [TOOL_NOT_FOUND]: Tool "search" not found in server "filesystem"
Details: Available tools: read_file, write_file, list_directory (+5 more)
Suggestion: Run 'mcp-cli info filesystem' to see all available tools
Error [INVALID_JSON_ARGUMENTS]: Invalid JSON in tool arguments
Details: Parse error: Unexpected identifier "test"
Suggestion: Arguments must be valid JSON. Use single quotes: '{"key": "value"}'
MIT License - see LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.