MCP CLI client in Rust — Cross-platform MCP server interaction without runtime dependencies
A CLI for discovering, inspecting, and executing tools from Model Context Protocol (MCP) servers with lazy background daemon. Works on Linux, macOS, and Windows (via named pipes).
This is just an experiment for its own sake. I don't intend to rely on it heavily. Use the original https://github.com/philschmid/mcp-cli.
# Install from source
git clone https://github.com/gtrak/mcp-cli-rs.git
cd mcp-cli-rs
cargo build --release
# Create config at ~/.config/mcp/mcp_servers.toml
cat > ~/.config/mcp/mcp_servers.toml << 'EOF'
[[servers]]
name = "filesystem"
transport = { type = "stdio", command = "npx", args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"] }
EOF
# List available tools
./target/release/mcp listThis is a Rust rewrite of the original Bun-based MCP CLI. Key improvements:
- Windows Support — Full Windows compatibility using named pipes (original had Windows process spawning issues)
- No Runtime Dependencies — Single compiled binary, no Bun/Node.js required
- Cross-Platform — Native Unix sockets on Linux/macOS, named pipes on Windows
- Better Performance — Rust's async runtime with connection caching via daemon
- Rust toolchain (1.70+)
# Clone and build
git clone https://github.com/gtrak/mcp-cli-rs.git
cd mcp-cli-rs
cargo build --release
# Binary will be at ./target/release/mcp
# Optional: Copy to your PATH
cp ./target/release/mcp ~/.local/bin/- Linux/macOS: Uses Unix domain sockets for daemon IPC
- Windows: Uses named pipes for daemon IPC (requires daemon mode for server connections)
Two styles supported for tool calls:
# Space-separated (clearer for complex arguments)
mcp call filesystem read_file '{"path": "/etc/hosts"}'
# Slash-separated (compact)
mcp call filesystem/read_file '{"path": "/etc/hosts"}'# List all servers and their tools
mcp list
mcp list -d # With descriptions
mcp list --json # JSON output for scripting
# Show server information
mcp info filesystem # Server details
mcp info filesystem read_file # Tool schema
# Search for tools
mcp search "*file*" # Pattern matching across all servers
# Call a tool
mcp call filesystem read_file '{"path": "/etc/hosts"}'
mcp call filesystem/read_file < /tmp/args.json # From stdin
# Daemon control
mcp daemon # Start daemon
mcp shutdown # Stop daemon-c, --config <PATH> Custom config file path
--json Output as JSON
--no-daemon Run in direct mode (no connection caching)
--auto-daemon Auto-spawn daemon if not running (default)
--require-daemon Fail if daemon is not running
-h, --help Show help
-V, --version Show version
Config file location (in order of precedence):
- Path specified with
--config ~/.config/mcp/mcp_servers.toml~/.config/mcp/mcp.toml
[[servers]]
name = "filesystem"
transport = { type = "stdio", command = "npx", args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"] }
[[servers]]
name = "fetch"
transport = { type = "stdio", command = "npx", args = ["-y", "@modelcontextprotocol/server-fetch"] }
[[servers]]
name = "http-server"
transport = { type = "http", url = "http://localhost:3000/mcp" }
# Optional: Global settings
concurrency_limit = 5 # Max concurrent operations
retry_max = 3 # Max retry attempts
retry_delay_ms = 1000 # Initial retry delay
timeout_secs = 1800 # Operation timeout
daemon_ttl = 60 # Daemon idle timeout in seconds[[servers]]
name = "filesystem"
transport = { type = "stdio", command = "npx", args = ["-y", "@modelcontextprotocol/server-filesystem", "/"] }
# Allow only specific tools
allowed_tools = ["read_file", "list_directory"]
# Or block specific tools
disabled_tools = ["write_file", "delete_file"]| Variable | Description |
|---|---|
MCP_NO_DAEMON=1 |
Disable daemon (direct mode) |
MCP_DAEMON_TTL=N |
Set daemon idle timeout in seconds (default: 60) |
mcp list # List all servers with tool counts
mcp list -d # Include tool descriptions
mcp list -v # Verbose with full schemas
mcp list --json # Machine-readable JSON outputmcp info <server> # Server details (transport, tools count)
mcp info <server> <tool> # Tool schema (parameters, description)
# Examples
mcp info filesystem
mcp info filesystem read_file
mcp info fetch fetch_url# With JSON argument
mcp call <server> <tool> '<json>'
mcp call <server/tool> '<json>'
# Examples
mcp call filesystem read_file '{"path": "/etc/hosts"}'
mcp call filesystem/read_file '{"path": "/etc/hosts"}'
# With arguments from stdin
echo '{"url": "https://example.com"}' | mcp call fetch fetch_url
# Flag-style arguments (auto-converted to JSON)
mcp call fetch fetch_url --url https://example.com
mcp call filesystem read_file --path /etc/hosts --limit 100mcp search "*file*" # Find tools with "file" in the name
mcp search "read*" # Glob pattern matchingmcp daemon # Start daemon (runs in foreground)
mcp daemon --ttl 300 # Start with custom 5-minute TTL
mcp shutdown # Stop running daemonDaemon modes:
--no-daemon: Direct mode, no caching (slower but simpler)--auto-daemon: Spawn daemon if needed (default, recommended)--require-daemon: Fail if daemon not running
git clone https://github.com/gary/mcp-cli-rs.git
cd mcp-cli-rscargo build # Debug build
cargo build --release # Optimized release build# Run library tests
cargo test --lib
# Run integration tests
cargo test --test '*'
# Run all tests
cargo testsrc/
├── cli/ # CLI parsing and command dispatch
├── client/ # MCP client implementations (stdio, HTTP)
├── config/ # Configuration loading and types
├── daemon/ # Daemon lifecycle and management
├── error/ # Error types and handling
├── format/ # Output formatting (text, JSON)
├── ipc/ # Inter-process communication (sockets/pipes)
├── server/ # MCP server protocol handling
├── shutdown/ # Graceful shutdown handling
└── transport/ # Transport abstractions
Start the daemon:
mcp daemon
# Or use direct mode:
mcp --no-daemon listCreate the config file:
mkdir -p ~/.config/mcp
cat > ~/.config/mcp/mcp_servers.toml << 'EOF'
[[servers]]
name = "filesystem"
transport = { type = "stdio", command = "npx", args = ["-y", "@modelcontextprotocol/server-filesystem", "/"] }
EOF- Check server name:
mcp list - Check tool name:
mcp info <server> - Verify server is running:
mcp info <server>
- Verify the MCP server package is installed (e.g.,
npx @modelcontextprotocol/server-filesystem) - Check the command path in your config
- For HTTP servers, verify the URL is accessible:
curl http://localhost:3000/mcp
On Windows, named pipes require the daemon to be running:
# Start daemon first
mcp daemon
# Then use in another terminal
mcp list# Enable debug logging
RUST_LOG=debug mcp list
# Check daemon logs
cat ~/.cache/mcp-cli/daemon.logMIT License - See LICENSE for details.
- Model Context Protocol — MCP specification
- Original MCP CLI — Bun-based implementation that inspired this rewrite