PATTERN Cited by 4 sources
MCP as fallback for shell-less agents¶
Pattern¶
Expose system capabilities via MCP only when the consuming agent cannot run shell commands. For shell-capable agents, prefer:
- A well-designed CLI (concepts/agent-ergonomic-cli) with structured output (
--json), consistent flags, and actionable--help. - A short prose skill ("Use this skill whenever users want to create a new VM to run a task on").
- Progressive disclosure via CLI subcommands or API sub-paths as the agent explores.
Reserve MCP for the legitimate niche: agents without a shell (Claude Desktop, older clients, possibly future Chrome-only browser agents).
Thomas Ptacek, Fly.io, 2026-03-10:
"Skills and APIs are the best way to drive Sprites. But to make that work, you need an agent that can run shell commands for itself. So you'll want to reach for MCP sessions when you're stuck with an agent that can't run commands. Thankfully, most of us aren't using those kinds of agents anymore."
(Source: sources/2026-03-10-flyio-unfortunately-sprites-now-speak-mcp.)
Why this is positional, not prescriptive¶
This pattern does not say "MCP is bad." It says "MCP is the fallback shape, not the default shape, when the agent can run shell." The vendor shipping the recommendation (Fly.io) simultaneously ships an MCP server at sprites.dev/mcp — see systems/sprites-mcp — to cover the shell-less-agent case. The pattern's job is to reframe MCP's positional role, not to eliminate it.
MCP retains legitimate uses:
- Shell-less agent interop (the case this pattern names).
- Cross-vendor tool interop — an MCP server exposed by vendor A can be consumed by agents from vendors B, C, D without per-vendor integration work. Ptacek acknowledged this in sources/2025-11-06-flyio-you-should-write-an-agent: "MCP is just a plugin interface for Claude Code and Cursor, a way of getting your own tools into code you don't control."
- Enterprise governance (MCP Server Portal, proxy patterns, Unity AI Gateway) — treating MCP as the supervised agent tool-boundary in regulated environments.
- Browser / UI-only agents where the MCP HTTP/SSE transport is the only integration surface available.
Pattern elements¶
1. Identify shell capability¶
A shell-capable agent is one that can:
- Execute arbitrary binaries from a subprocess (run
my-cli --help, parse output). - Pipe, compose, and iterate (
ls | grep,while read line; do ...). - Persist state across invocations within a session (files, environment, cwd).
As of 2026, Claude Code, Codex CLI, Gemini CLI, Claude Code action, Aider, and similar are shell-capable. Claude Desktop, some MCP-only web UIs, and older MCP-only clients are not.
2. For shell-capable: ship a CLI + short skill¶
The minimal capability-disclosure artifact is a one-line skill + a CLI:
"Use this skill whenever users want to create a new VM to run a task on, or to manage the VMs already available."
Plus the sprite binary in the agent's PATH. The agent explores subcommands on demand via concepts/progressive-capability-disclosure.
3. For shell-less: ship a remote MCP server¶
Run an MCP server on your own infrastructure (vendor-hosted, like sprites.dev/mcp) or via a remote-MCP-server-via-platform-launcher shape. Apply patterns/tool-surface-minimization to keep the inventory small. Apply creation-quota guardrails (org scope / count cap / name prefix) to bound blast radius.
4. Don't ship just one¶
The Fly.io 2026-03-10 shape ships both: sprite CLI (for shell-capable agents) and sprites.dev/mcp (for shell-less). Each audience gets the surface that fits its capabilities. The mistake the pattern warns against is making MCP the default for all agents when the majority can do better with the CLI.
Why it's correct to ship both¶
| Agent class | Preferred surface | Why |
|---|---|---|
| Claude Code | sprite CLI |
Shell access; progressive disclosure minimises token cost |
| Codex CLI | sprite CLI |
Same |
| Gemini CLI | sprite CLI |
Same |
| Claude Desktop | sprites.dev/mcp |
No shell; MCP is the only integration channel |
| Browser-based agent UI | sprites.dev/mcp |
Same |
| Older MCP-only clients | sprites.dev/mcp |
Same |
| Cross-vendor agent | Either | MCP gives vendor-neutral interop; CLI gives capability-discovery efficiency |
| Governance-bound agent | MCP via proxy | Central MCP server enables audit, allowlist, and rate-limit policies |
The pattern's recommendation: ship both, let the agent-class dictate which one the user wires up. Don't assume MCP is the universal answer.
Contrast: the "MCP is the default" anti-pattern¶
The anti-pattern is the default assumption — common in 2024-2025 — that every integration should ship as MCP first. Consequences of that anti-pattern (collected from wiki sources):
- Context-window bloat. Tool descriptions for N operations consume O(N) tokens from session start. See concepts/context-window-as-token-budget.
- Attention misdirection. Pre-loaded tool descriptions for irrelevant capabilities signal importance weightings the user doesn't intend.
- Workstation-credential exposure. Local stdio MCP servers inherit the operator's full credential set; prompt injection in the cloud LLM becomes native-binary-execution on the operator's laptop.
- Config fragmentation. Each MCP client keeps its own config; adding/removing MCP servers becomes a per-client chore.
The CLI-first alternative for shell-capable agents avoids all four. The MCP-as-fallback pattern preserves MCP's legitimate role without making it the default.
Seen in¶
- sources/2026-03-10-flyio-unfortunately-sprites-now-speak-mcp — canonical wiki statement. Ptacek's "Skills and APIs are the best way to drive Sprites" paragraph. Fly.io ships the MCP-fallback server at
sprites.dev/mcpin the same post. - sources/2025-11-06-flyio-you-should-write-an-agent — structural ancestor. Ptacek, 2025-11-06: "MCP isn't a fundamental enabling technology… MCP is just a plugin interface for Claude Code and Cursor, a way of getting your own tools into code you don't control. Write your own agent. Be a programmer. Deal in APIs, not plugins." The 30-line Python minimal agent loop in that post is the shell-capable reference.
- sources/2025-04-10-flyio-30-minutes-with-mcp-and-flyctl — the original "local MCP is scary" post. Frames MCP as a convenience wrapper ("90 lines of Go, 30 minutes") rather than a fundamental integration abstraction. Pre-echoes the positional-pattern framing.
- sources/2025-05-07-flyio-provisioning-machines-using-mcps — the mutation-transition sequel. Ships a mutating MCP, then constrains it with CLI-refusal guardrails — again: MCP is tolerated, not preferred.
Related¶
- concepts/agent-ergonomic-cli — the CLI design stance that makes CLI-first viable.
- concepts/progressive-capability-disclosure — the discovery mechanism CLI-first relies on.
- concepts/context-as-importance-signal — one of the two costs this pattern avoids.
- concepts/context-window-as-token-budget — the other cost this pattern avoids.
- concepts/local-mcp-server-risk — the security cost avoided by not making local MCP the default.
- concepts/agent-with-root-shell — the precondition that makes CLI-first viable (the agent has root + shell in its sandbox).
- systems/model-context-protocol — the protocol whose positional role this pattern defines.
- systems/sprites-mcp — the canonical vendor-hosted MCP-as-fallback instance.
- systems/fly-flyctl — canonical CLI-first instance.
- systems/fly-mcp-launch — the user-deployed-remote-MCP shape; enables the same pattern when the vendor hasn't shipped one.
- systems/claude-code / systems/gemini-cli / systems/codex-cli — the three shell-capable agents Ptacek names.
- patterns/wrap-cli-as-mcp-server — the pattern that enables MCP-as-fallback to piggyback on an already-good CLI.
- patterns/remote-mcp-server-via-platform-launcher — the sibling deployment shape for fallback MCP.
- patterns/tool-surface-minimization — the complementary discipline within MCP for when MCP is the right answer.
- patterns/tool-call-loop-minimal-agent — the structural alternative: write a small agent loop yourself and skip MCP entirely.
- companies/flyio.