When to use MCP instead of CLI for AI tools
Purpose
I’ve been watching the debate unfold on Reddit: “CLI is all you need? Do we really need MCPs?” The question comes from a good place - CLI tools work great for most tasks. But I think the debate misses the point. MCP isn’t trying to replace CLI. They solve different problems.
In this post, I’ll show you when MCP makes more sense than CLI, and why the stateful server architecture matters for certain use cases.
What I found
When I first started working with AI tools, I used CLI wrappers for everything. It made sense - every AI assistant can run shell commands, so why build anything more complex?
Then I hit problems. I tried to build an automated design workflow with Figma. The issue? Figma has no CLI. I tried using their REST API through a Python script, but every request had to re-authenticate, re-fetch the document structure, and re-parse everything. It worked, but it was slow and clunky.
I also tried browser automation with Playwright. Same problem - each test run started from scratch. I couldn’t maintain browser state between operations, which meant I couldn’t build multi-step workflows efficiently.
These experiences led me to MCP. The key difference I found is simple but important: CLI is stateless, MCP is stateful.
The CLI pattern
Let me show you how CLI tools work:
┌─────────┐ ┌─────────┐ ┌─────────┐│ Command │───→│ Process │───→│ Output │└─────────┘ └─────────┘ └─────────┘ ↓ DiesEvery CLI command starts fresh. When you run git status, it doesn’t know what git add just did. Each command is independent.
# Command 1: Add filegit add myfile.txt
# Command 2: Check status (no memory of Command 1)git statusThis is perfect for simple operations. But it has a problem when you need to maintain context. You have to pass all state in every command, which can lead to context window bloat when working with AI.
The MCP pattern
MCP works differently:
┌─────────┐ ┌─────────────┐│ MCP │◄────────────►│ State Store ││ Server │ └─────────────┘└─────────┘ ▲ │ │ └────────────────────────┘ (Persistent)The MCP server maintains state between requests. When you connect to a Figma MCP server, you open a design document once. All subsequent operations reference that same document by ID. You don’t need to re-send the entire document structure.
This is the key difference: reference-based responses vs full data transmission.
When MCP works better
I found four situations where MCP clearly beats CLI:
1. Visual design tools (Figma)
Figma has no CLI equivalent. When I tried to build automated design updates, I had two options:
- Use the REST API with fresh authentication every request
- Build a custom server that maintains the Figma connection
The REST API approach worked like this:
# Every request needs full contextdef update_design(api_key, file_key, node_id, new_text): # Authenticate headers = {"X-Figma-Token": api_key}
# Get the whole file file = requests.get( f"https://api.figma.com/v1/files/{file_key}", headers=headers )
# Find the node # ... parsing code ...
# Update the node # ... update code ...
# Send the update requests.patch( f"https://api.figma.com/v1/files/{file_key}/nodes/{node_id}", headers=headers, json={"changes": changes} )The problem: every request re-authenticates and re-fetches data. With an MCP server:
# Connect once, reuse stateasync with MCPClient("figma-server") as client: # Open file once file_id = await client.open_file("design.fig")
# Multiple operations share the connection await client.update_text(file_id, "title", "New Title") await client.update_color(file_id, "button", "#FF0000") await client.export(file_id, "png")The server maintains the Figma connection. Each operation references the file ID, not the full file data.
2. Browser automation (Playwright)
I hit this issue when building automated tests. With Playwright CLI:
# Each test run starts freshnpx playwright test login.spec.ts
# This test knows nothing about the previous onenpx playwright test dashboard.spec.tsThe tests work, but they can’t share browser state. If you want to log in once and run multiple tests, you need custom setup code.
With a Playwright MCP server:
async with MCPClient("playwright-server") as client: # Start browser once browser = await client.start_browser()
# Login once await client.goto(browser, "https://example.com/login") await client.fill(browser, "#password", "password123") await client.click(browser, "#login-button")
# Now run multiple tests with same session await client.check_element(browser, "#dashboard") await client.check_element(browser, "#profile") await client.screenshot(browser, "dashboard.png")The browser stays open. All tests share the authenticated session.
3. WebSocket real-time communication
Some tools need real-time updates. CLI can’t handle this well - it’s request/response only. MCP supports WebSocket connections:
AI Assistant ◄───────────► MCP Server │ │ │ (Persistent WebSocket)│ └─────────────────────────┘ ← Real-time updates →This matters for:
- Live database query results
- Streaming file processing
- Real-time API monitoring
from mcp_client import WebSocketMCPClient
client = WebSocketMCPClient("wss://realtime.example.com/mcp")
# Subscribe to real-time updatesasync for update in client.stream("database-changes"): # Process updates as they arrive if update.table == "users": handle_user_update(update.data)CLI tools would need polling or separate server components to achieve the same effect.
4. Accessibility and democratization
This one surprised me. I used to think MCP was just for technical optimization. Then I read this insight from the Reddit discussion:
“MCP can still be useful if you can package it in a way that makes it easier for non techies to access your stuff.”
Think about this scenario:
- A designer needs to batch-update 50 Figma files
- They don’t know Python or how to authenticate with APIs
- An MCP server could provide a natural language interface
The designer just says: “Update the blue buttons to green in all marketing files.” The MCP server translates this to the right Figma API calls.
CLI tools require terminal access and command knowledge. MCP servers can have GUI frontends, chat interfaces, or other user-friendly wrappers.
When CLI still wins
MCP isn’t always the right choice. I use CLI for:
- Simple, one-off operations:
ls,git clone,npm install - Serverless environments where persistent servers aren’t available
- Maximum portability across different systems
- Tasks where state maintenance adds unnecessary complexity
If I just need to copy a file or run a test once, CLI is faster and simpler.
Performance comparison
I did some informal testing on a design automation task:
Task: Update text in 50 Figma layers
CLI (REST API approach):- 50 separate HTTP requests- 50 authentication operations- Full file data transferred 50 times- Total time: ~45 seconds
MCP (stateful server):- 1 authentication operation- File opened once- 50 lightweight reference-based updates- Total time: ~12 secondsThe MCP approach was faster, but more importantly, it used less network bandwidth and fewer API calls.
The reason
I think the key distinction is:
- CLI = stateless command execution
- MCP = stateful service with persistent connections
Stateless tools are great when you want:
- Simple, predictable behavior
- No side effects between operations
- Easy debugging and testing
Stateful tools are better when you need:
- Context retention between operations
- Efficient use of resources
- Real-time communication
- Complex multi-step workflows
They’re not competitors. They’re complementary tools for different problems.
Summary
In this post, I showed when MCP makes more sense than CLI for AI tools. The key point is that MCP’s stateful architecture provides benefits when you need to maintain context, enable real-time communication, or build complex multi-step workflows. CLI still wins for simple operations where state adds unnecessary complexity.
Use MCP when:
- Working with tools that have no CLI (Figma, visual design tools)
- You need to maintain browser or session state (Playwright)
- Real-time WebSocket communication is required
- You want to build accessible interfaces for non-technical users
Use CLI when:
- Doing simple, one-off operations
- Working in serverless environments
- Maximum portability is required
- State maintenance adds unnecessary complexity
The debate shouldn’t be “MCP vs CLI” - it should be “when should I use each?”
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:
- 👨💻 Reddit: CLI is all you need? Do we really need MCPs?
- 👨💻 Model Context Protocol Documentation
- 👨💻 Figma Plugin API
- 👨💻 Playwright Documentation
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments