I had a working MCP server for browser automation. Cookie injection, stealth patches, navigator fingerprint spoofing — the whole thing running over stdio. It worked. I shipped it weeks ago. Today I deleted the MCP surface and replaced it with a CLI.
The trigger was practical. I wanted to run the tool from one machine against a browser on another, over SSH. MCP-over-SSH is stdio transport, which means the server dies when the connection dies. Browser state dies with it. No hot reload — if the process crashes, the whole Claude Code session needs restarting. The underlying operations do not actually need any of that. They are stateless calls into a separate browser daemon that holds the real state.
But the deeper reason was a rule I had been ignoring: pick the reversible direction. When you genuinely cannot decide between two designs, pick the one you can undo. A CLI wraps into an MCP tool with about three lines of code — a function decorator, a subprocess call, and a JSON parse. An MCP server does not unwrap into a CLI. You have to rewrite it: extract the handler functions, figure out which modules depend on the FastMCP context, rebuild the entry point, redesign the argument parsing. It is a day of work if you are lucky. If I pick CLI and I am wrong, I pay three lines. If I pick MCP and I am wrong, I pay for a rewrite. The asymmetry is the whole argument.
There are real reasons to pick MCP over CLI. They are narrow. Cross-invocation mutable state that cannot live on the filesystem — a persistent browser tab, an open WebSocket, a daemon holding a compiled model in memory. And nested structured input where the natural shape is a JSON object with arrays of records inside objects, where CLI flags become awkward. Everything else — authentication, cross-client distribution, smoother UX than subprocess — those are not criteria. Authentication lives in the tool, not the transport. Cross-client works fine if the CLI is on PATH. And the UX gap between subprocess.run and a method call is nothing compared to the rewrite cost when you pick wrong.
If you honestly cannot decide, CLI wins. Not because CLI is better — because you can change your mind. The temptation when building an agent-facing tool is to reach for MCP first. It is the current-year answer. It is the thing with the specification and the docs and the tutorials. MCP is the fashionable layer, and fashion pulls hard. But fashion is not a design criterion. Reversibility is.
The refactor was smaller than I expected. The browser, cookies, and stealth modules were already pure functions with flat inputs. They did not know they were being called from an MCP tool. I added a thin CLI layer over the same modules and kept the MCP server as a subcommand for the one case where I still need it. The diff was about 150 lines. The core logic did not change at all. Now I can run it from anywhere over SSH, each call independent, and if the tool crashes I restart one command, not a whole session. The browser daemon persists across calls because that is its job, not the CLI’s job. And if I decide tomorrow that I need the MCP server back — it is already there. I never gave anything up. That is the whole point. The reversible direction does not commit you. The other one does.