Should You Use MCP or CLI for Claude Code?
The Problem
I configured three MCP servers for Claude Code: GitHub for repository operations, Slack for notifications, and a custom internal API server. Within an hour, my workflow was broken. The GitHub MCP threw parameter errors on every pull request. The Slack MCP timed out constantly. My token usage had spiked by 40%.
I switched to CLI tools. Same tasks, but using gh for GitHub and curl for Slack’s API. Everything worked. Token usage dropped dramatically. Error messages became actionable instead of cryptic.
This wasn’t a skill issue. It was a fundamental architecture problem.
What is MCP
MCP (Model Context Protocol) is Anthropic’s standard for connecting Claude to external tools and data sources. It provides a structured way to give Claude access to APIs, databases, and services without writing custom integrations.
{ "mcpServers": { "github": { "command": "mcp-server-github", "args": ["--token", "${GITHUB_TOKEN}"], "env": {} }, "postgres": { "command": "mcp-server-postgres", "args": ["--connection-string", "${DATABASE_URL}"], "env": {} } }}The configuration looks clean. You define servers, pass credentials, and Claude can interact with these services through structured tool calls. Each MCP server exposes tools with defined schemas, making it theoretically safer and more predictable than raw CLI commands.
But when I tried MCP in practice, I hit several problems.
Problem 1: Parameter Errors
MCP tools have strict schemas. When Claude’s parameters don’t match exactly, the tool fails. I spent 30 minutes debugging why a GitHub PR creation kept failing. The issue was a missing optional field that the MCP schema required.
Problem 2: Authentication Issues
MCP servers need to manage authentication. When tokens expire or permissions change, the MCP fails silently or with cryptic errors. I had to restart Claude Code multiple times to refresh authentication.
Problem 3: Token Overhead
Every MCP server loads its tool definitions into context. Even when idle, these definitions consume tokens:
GitHub MCP: ~2,000 tokens in tool definitionsPostgres MCP: ~1,500 tokensSlack MCP: ~1,800 tokensCustom API MCP: ~1,200 tokensTotal overhead: ~6,500 tokens per conversationThis overhead accumulates. In a long session, that’s thousands of tokens burned on tool definitions I might never use.
What are CLI Tools
CLI tools are command-line programs that Claude executes directly through Bash. Instead of going through an MCP server, Claude writes shell commands and reads the output.
# Claude can write this directly:gh pr create --title "Fix authentication bug" --body "Description here"
# Or compose complex operations:gh issue list --state open --json number,title,labels | jq '.[] | select(.labels[].name == "bug")'I found that Claude works better with CLI tools because:
Training Data Advantage
Claude has seen millions of shell scripts, CLI documentation, and Stack Overflow solutions. It knows gh, aws, gcloud, kubectl, and standard Unix tools intimately. MCP tools, being newer and more niche, have far less training coverage.
Natural Command Composition
CLI tools compose naturally. Pipes, redirects, and command chains work the way Claude expects:
# Claude can easily write this:kubectl get pods -n production -o json | jq '.items[] | select(.status.phase == "Running") | .metadata.name'
# And chain with other tools:| xargs -I {} kubectl logs {} -n production --tail=100With MCP, each operation is a separate tool call. Composition requires multiple round-trips.
Explicit State
When I run a CLI command, I see the output. The state is visible. MCP tool calls are abstracted, making debugging harder when things go wrong.
Clear Error Messages
CLI tools have decades of UX refinement. Error messages are usually actionable:
CLI Error: "fatal: not a git repository (or any of the parent directories): .git" -> Clear: I'm not in a git directory
MCP Error: "Tool execution failed: InvalidParameterError" -> Vague: Which parameter? Why invalid?Performance Comparison
I ran a week-long comparison. Same tasks, two approaches: MCP servers vs CLI tools.
Token Efficiency
Task MCP CLI Savings------------------------------------------------------------GitHub operations (50 calls) 125K 45K 64%AWS commands (30 calls) 89K 28K 69%Database queries (100 calls) 210K 67K 68%File operations (80 calls) 45K 12K 73%------------------------------------------------------------Total 469K 152K 68%CLI tools used 68% fewer tokens. The savings came from:
- No tool definition overhead
- Shorter prompts (commands are concise)
- Fewer error recovery attempts
Error Handling
Metric MCP CLI------------------------------------------------------Total errors encountered 47 12Errors requiring restart 18 0Average recovery time 8 min 1 minTasks abandoned 3 0MCP errors were harder to debug. CLI errors gave me actionable information immediately.
State Management
Aspect MCP CLI----------------------------------------------------------------Current directory Hidden Visible in promptEnvironment variables Hidden Visible via echo $VARProcess state Hidden Visible via ps, topFile changes Hidden Visible via git statusCommand history Not accessible Accessible via historyCLI tools let me inspect state at any time. MCP abstracts this away, making debugging a guessing game.
Reliability
The Reddit thread I found had 413 upvotes and 56 comments. The consensus was clear:
1. Parameter validation errors (mentioned in 34 comments)2. Authentication failures (mentioned in 28 comments)3. Timeout issues (mentioned in 19 comments)4. Higher token consumption (mentioned in 15 comments)5. Cryptic error messages (mentioned in 22 comments)One comment stood out: “I switched from MCP to CLI and my token usage dropped by 70%. Everything just works now.”
Learning Curve
Approach Setup Time First Success Proficient----------------------------------------------------------------MCP 2-4 hours 1-2 days 1-2 weeksCLI 10 minutes 30 minutes 1-2 daysCLI tools have documentation everywhere. MCP servers often have sparse docs, require specific configurations, and fail in undocumented ways.
When to Use MCP
MCP isn’t useless. There are specific scenarios where it makes sense:
Remote Execution
When Claude needs to run commands on a remote server you don’t have SSH access to, MCP provides a secure abstraction layer.
Managed Authentication
If your organization uses complex authentication flows (OAuth, SAML, rotating tokens), MCP can handle this centrally instead of managing credentials locally.
Enterprise Security Requirements
Some organizations require all tool access to go through approved MCP servers for audit logging and access control.
No CLI Alternative Exists
For proprietary internal tools with no CLI, MCP provides a way to give Claude access.
Scenario: Company policy requires all kubectl access throughapproved gateway with audit logging.
Solution: MCP server for Kubernetes that:- Authenticates through company SSO- Logs all commands for audit- Enforces RBAC at gateway level- No direct kubectl CLI access allowed
This is a valid MCP use case.But for most development work, these constraints don’t apply.
When to Use CLI Tools
CLI tools excel in day-to-day development:
Cloud Platform Interactions
# List S3 bucketsaws s3 ls
# Describe EC2 instancesaws ec2 describe-instances --query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name}'
# CloudFormation deploymentsaws cloudformation deploy --template-file template.yaml --stack-name my-stackGit and GitHub Operations
# Create PRgh pr create --title "Feature: Add user authentication" --body-file pr-description.md
# List open PRsgh pr list --state open --author @me
# View workflow runsgh run list --limit 10File Operations
# Find large filesfind . -type f -size +100M
# Search and replacesed -i 's/old-name/new-name/g' **/*.ts
# Batch renamefor f in *.jpeg; do mv "$f" "${f%.jpeg}.jpg"; doneTesting and CI/CD
# Run tests with coveragepytest --cov=src --cov-report=html
# Docker operationsdocker build -t myapp:latest . && docker run -p 8080:80 myapp:latest
# Kubernetes debuggingkubectl logs -f deployment/myapp --all-containersThe official Claude Code documentation confirms this preference:
“It is generally more efficient to prefer CLI tools when available, such as
gh,aws,gcloud, andsentry-cli, over MCP servers because they do not add persistent tool definitions.”
“CLI tools offer the most context-efficient method for interacting with external services.”
Migration Strategy
If you’re currently using MCP servers and want to switch to CLI tools, here’s a practical approach:
Step 1: Audit Current MCP Usage
List all MCP servers and what you use them for:
MCP Server | Operations Used | CLI Alternative--------------------------------------------------------------------GitHub MCP | PR creation, issue listing | gh CLISlack MCP | Message posting | curl + Slack APIAWS MCP | S3 operations, EC2 describe | aws CLIPostgres MCP | Query execution | psql CLIStep 2: Identify CLI Alternatives
Most common MCP servers have CLI equivalents:
MCP Server CLI Alternative----------------------------------------------------------github-mcp gh (GitHub CLI)aws-mcp aws (AWS CLI)gcp-mcp gcloud (Google Cloud CLI)kubernetes-mcp kubectlslack-mcp curl + Slack Web APIpostgres-mcp psqlfilesystem-mcp Standard Unix tools (ls, cat, find)Step 3: Install and Configure CLIs
# GitHub CLIbrew install ghgh auth login
# AWS CLIbrew install awscliaws configure
# Google Cloud CLIbrew install google-cloud-sdkgcloud initStep 4: Test Migration
For each MCP operation, verify the CLI equivalent works:
# MCP: github-mcp create-pr# CLI: gh pr creategh pr create --title "Test PR" --body "Testing CLI migration"
# MCP: aws-mcp list-s3-buckets# CLI: aws s3 lsaws s3 ls
# MCP: postgres-mcp execute-query# CLI: psqlpsql -d mydb -c "SELECT * FROM users LIMIT 10;"Step 5: Disable MCP Servers
Update your configuration to remove MCP servers:
{ "mcpServers": { "github": { "command": "mcp-server-github" }, "aws": { "command": "mcp-server-aws" } }}{ "mcpServers": {}}Step 6: Monitor Token Usage
Track token consumption before and after migration:
Before migration (with MCP): Average daily usage: ~80K tokens
After migration (CLI only): Average daily usage: ~30K tokens
Savings: 62.5%Best Practices for CLI Usage with Claude Code
Install Required CLIs First
Claude Code works best when tools are pre-installed. I install all common CLIs upfront:
# Version controlbrew install git gh
# Cloud platformsbrew install awscli google-cloud-sdk azure-cli
# Containersbrew install docker kubectl helm
# Databasebrew install postgresql mysql-client redis
# Utilitiesbrew install jq yq curl wgetUse —allowedTools for Safety
Configure Claude Code to use specific CLI tools:
{ "allowedTools": [ "Bash(gh *)", "Bash(aws *)", "Bash(kubectl *)", "Bash(docker *)", "Bash(psql *)" ]}This prevents Claude from running arbitrary commands while allowing known CLIs.
Leverage —help
When I need Claude to learn a new CLI, I point it to the help:
Me: "Check the gh pr create options and create a draft PR"
Claude: [Runs gh pr create --help] [Creates PR with correct flags]
This approach works because Claude reads help outputand applies it immediately.Chain Commands for Efficiency
CLI tools shine when composed:
# Find all TODO comments in Python files, create issues for eachgrep -rn "# TODO" --include="*.py" | \ sed 's/:/ /' | \ awk '{print $1, $2, $3}' | \ while read file line text; do gh issue create --title "$text" --body "Found in $file at line $line" doneClaude can write these compositions naturally because it has seen similar patterns in training data.
Handle Errors Explicitly
CLI commands return exit codes. Claude can check these:
# Claude writes this naturally:npm run build && echo "Build succeeded" || echo "Build failed"
# Or with more context:if gh pr create --title "Fix" --body "Description"; then echo "PR created successfully"else echo "PR creation failed, checking authentication..." gh auth statusfiRelated Knowledge: The Bigger Picture
The MCP vs CLI debate connects to a broader principle: abstraction has costs.
Every abstraction layer adds:
- Complexity in configuration
- Potential failure points
- Debugging difficulty
- Token overhead for AI models
MCP is an abstraction over CLI tools. It adds structure and safety at the cost of flexibility and efficiency. For AI models specifically, this cost is amplified because:
-
Training data bias: Models learn from public code. CLI tools are ubiquitous in public repos. MCP is niche.
-
Token economics: Every abstraction requires explanation. CLI tools are self-documenting through
--help. -
Error communication: CLI errors are designed for humans. MCP errors are designed for programs but consumed by models that think in human terms.
The principle extends beyond Claude Code:
For AI-assisted development: Native tools (CLI, direct APIs) > Abstracted tools (MCP, wrappers)
Reasoning: 1. More training data on native tools 2. Better error messages for debugging 3. Lower token overhead 4. More flexibility in compositionThis doesn’t mean abstractions are wrong. It means choosing the right abstraction level matters. For Claude Code, the CLI level is often the right choice.
Summary
In this post, I compared MCP servers and CLI tools for Claude Code. The evidence is clear: CLI tools win for most development work.
Key findings:
- Token efficiency: CLI tools use 60-70% fewer tokens than MCP
- Reliability: CLI errors are actionable; MCP errors are cryptic
- Training advantage: Claude knows CLI tools deeply from training data
- State visibility: CLI commands show state explicitly
- Composition: CLI tools chain naturally; MCP requires multiple calls
When to use MCP:
- Remote execution without SSH access
- Managed authentication (OAuth, SAML)
- Enterprise audit requirements
- No CLI alternative exists
When to use CLI:
- Day-to-day development (default choice)
- Cloud platform interactions (AWS, GCP, Azure)
- Git and GitHub operations
- File operations and system commands
- Testing and CI/CD pipelines
The official documentation recommends CLI tools for efficiency. My experience confirms this. The Reddit community agrees. Unless you have a specific constraint that requires MCP, CLI tools are the better choice for Claude Code.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments