AI coding

CLI, MCP Server or Code Sandbox: Picking a Wrapper

Antonio Evans11 min read

A split scene with three vertical panels.
Key points

Key points

  1. 1Choose the wrapper based on the contract you can keep and the audit evidence you must produce, not on which surface is trendiest.
  2. 2A CLI wrapper ships fastest and debugs easiest, but its contract is fragile and credentials often leak into the agent's shell environment.
  3. 3An MCP server gives a typed, discoverable contract and one place to enforce auth and log every call, at the cost of a new service you must operate.
  4. 4A code sandbox trades contract stability for execution flexibility, and it is the right tool only when the agent must compute, not just call.

Start from the contract and the audit

Two questions settle most wrapper decisions before you write any code. First: how stable is the contract you can promise the agent? Second: what evidence must you produce after the fact? Everything else, setup speed included, is negotiable.

A wrapper is a boundary. On one side sits an internal system with its own schemas, quirks and release cadence. On the other side sits a model that reads a tool description, decides what to call, and interprets the result. The wrapper's job is to make that boundary predictable in both directions.

The predictability requirement is sharper than it looks, because agents are literal readers of instructions. A requirements practice built for AI work puts it plainly: vague acceptance criteria get interpreted however the worker likes, and specific testable criteria give both the worker and the validator a clear target in this account of AI-native requirements work. The same holds for tool descriptions and output schemas.

That single insight drives the whole comparison. Whichever surface you pick, the deliverable is not "a way to call the system." It is a stated contract plus a record of every call made under it.

There is also a scale effect worth planning for. Production agent success rates start degrading after roughly 35 minutes of human-equivalent work, and doubling task duration roughly quadruples the failure rate rather than doubling it, per a survey of long-horizon agent research. Wrappers that fail loudly and idempotently are what let an agent recover inside that window instead of compounding one bad call into a lost task.

The three surfaces at a glance

DimensionCLI wrapperMCP serverCode sandbox
Time to first working callHoursDaysDays, plus infrastructure
Contract shapeText on stdout plus process exit codeTyped tool schema, discoverableWhatever code the agent writes
Contract stabilityFragile: parsing breaks on format changesStable if you version the schemaNot applicable: input is arbitrary code
Where credentials liveOften the agent's own environmentServer side, off the agent hostInside the sandbox or injected per run
Enforcement pointNone by defaultOne choke point for auth, policy, loggingKernel or microVM boundary
Audit trailShell history, if anythingEvery call, at the serverExecution logs plus sandbox records
Main failure modeSilent parse failures and exit code misuseTool sprawl, context bloat, service downtimeOver-broad permissions, runaway jobs
Best fitLocal developer workflows, single-user agentsMulti-user access to internal systemsCompute-heavy or exploratory work

Read the table as a set of independent dials rather than a ranking. You can raise contract stability on a CLI by adding a JSON mode. You can lower the operational burden of an MCP server by keeping its tool count small. You cannot, however, get audit evidence out of a surface that does not have an enforcement point.

CLI wrapper: fastest to build, hardest to keep stable

The case for a CLI is real and the evidence is concrete. One engineer who built several MCP servers, deleted them, and rebuilt the same tools as CLIs measured roughly 40 percent lower token usage for a file conversion task after the switch, because a CLI call only consumes tokens when it runs while MCP tool definitions sit in the prompt persistently in this write-up of the redesign. The same account notes MCP servers crash, lose connections and add startup latency, while a CLI binary is stateless and always available.

That is the honest case for CLIs: low ambient cost and no service to operate. But the contract is where teams get hurt. If your wrapper parses human-formatted output, a column reordering or a status string going from "Running" to "running" causes silent failures rather than errors, the same account warns.

You can make a CLI contract much more durable with four habits.

  1. Emit JSON to stdout and send everything else (progress, warnings, spinners) to stderr. Stdout becomes your API.
  2. Use exit codes as control flow, documented and distinct per condition, so the agent can branch without parsing prose.
  3. Make commands idempotent, because agents retry and networks fail.
  4. Keep the schema flat and the types consistent across subcommands.

The practices behind both accounts converge on the same mechanics. A production CLI rebuilt for humans and agents alike routes every output decision through a terminal check, so spinners appear only on a TTY, and emits a --json path that returns the full data structure the human table trims for brevity per this CLI design retrospective.

Exit codes deserve their own paragraph because they are the most commonly broken part of the contract. A process that succeeds exits 0. Beyond that, a wrapper owes the agent a documented mapping, for example 1 for a general failure, 2 for a usage error, 3 for not found, 4 for permission denied and 5 for a conflict. Note also that shells report a signal termination as 128 plus the signal number, so a process killed with signal 9 surfaces as 137, as the classic exit code appendix explains in the Advanced Bash-Scripting Guide. If your wrapper passes that number through without explanation, the agent has no idea whether to retry, escalate or stop.

The security boundary is the CLI's weakest dimension. Some agent frameworks mediate CLI access through sandboxed execution with approval gates rather than raw shell access, but a developer's terminal accumulates tools, scripts, credentials and ambient permissions over time, and the agent will test multiple strategies when more than one can complete a task as this analysis of CLI versus MCP governance puts it. When an MCP server fails, agents with shell access fall back to raw API calls using credentials from the user's environment, which the same analysis observes in Claude Code and Cursor.

Observability follows the same pattern. You get whatever the shell or the agent framework happens to record, which is operational telemetry at best. There is no enforcement point where you can log an authorization decision, only a process that either ran or did not.

MCP server: a typed contract and one place to enforce policy

An MCP server moves the boundary from "a program the agent runs" to "a service that exposes named tools." Each tool has a name, a description and an input schema. The provider owns the definition, the schema and the behavior, and the LLM cannot call outside those boundaries per the same governance analysis.

That ownership is the whole value proposition. The Model Context Protocol is an open standard donated to the Linux Foundation's Agentic AI Foundation in December 2025, which standardizes how models connect to external tools and data sources as described in this guide to agent code execution. A standard contract plus a single hosted endpoint means every call can cross one enforcement point.

Three properties matter most for a practitioner choosing MCP.

Discoverability. The agent can list tools and read their schemas at runtime. Your internal system's capabilities become self-describing, which reduces the prompt engineering needed to route work correctly.

Enforceability. Authorization, rate limits and logging live in the server, not in the model's instructions. That placement is the difference between a control and a hope. On the audit side, the recommended placement is explicit: logging for authorization belongs at the policy decision point or an MCP gateway that enforces before a tool executes, because that is the moment intent becomes a possible side effect, and logging only after the tool runs misses the control point in this audit trail guide. An auditor eventually samples sensitive actions and asks for the initiator, any approval, the policy that allowed it, and evidence that denials were logged too.

Operability cost. You now run a service. It can be down, slow or misconfigured. Every tool you expose also loads its description and schema into the agent's context on every turn, so a bloated server with dozens of tools burns context before doing any work as this side-by-side test describes. The mitigation is progressive disclosure: expose a small set of tools, or one discovery tool, instead of the full catalog per the CLI redesign account.

A useful sanity check on whether MCP is warranted: MCP earns its overhead when you expose many tools behind one server, need stateful sessions across calls, require dynamic discovery at scale, or build multi-agent systems where protocol-level composition matters. For everything else, a well-designed CLI often wins again from the redesign account.

Code sandbox: when the agent must compute, not call

The sandbox is a different category. A CLI and an MCP server both expose a fixed set of operations. A sandbox exposes execution itself: the agent writes code and something isolated runs it.

The architectural invariant that keeps this safe is a separation of concerns. Production agent systems split reasoning (what code to write), execution (where and how it runs) and integration (what systems the code can reach), and the reasoning layer never executes anything directly. It emits structured calls, and a separate layer runs them, keeping API keys, database credentials and production infrastructure out of the model's reach per this execution architecture guide.

Isolation strength is the dial. Options range from sandboxed interpreters and serverless functions to microVMs with hardware-enforced boundaries, where each workload runs a separate kernel so an exploit inside one sandbox cannot reach the host or its neighbors. Historically stronger isolation meant slower startup; snapshot restore has narrowed that gap, with platforms resuming microVMs from standby in under 25 milliseconds per the same guide.

The contract question changes shape here. There is no output format to break, because the agent writes the parser each time. But that flexibility is also the risk: the "contract" is the sandbox's permission set, network reach and time limits, and those are what you have to version carefully. A sandbox with unrestricted filesystem access and no timeout enforcement is a liability, not a feature.

Sandboxes shine for exploratory work over data the agent should sample rather than load. Practitioners report pointing agents at duckdb and jq so they introspect large CSV, Parquet and JSON files with probing queries instead of pulling hundreds of megabytes into context in this discussion of when MCP makes sense versus a CLI. That pattern needs execution, not a fixed tool list.

Observability and audit: what each surface can actually prove

Here is the decision rule most teams miss. Tool traces and LLM traces are operational telemetry, not control evidence. A trace tells you the model said something and a function was called. An authorization record tells you whether the action was permitted under the policy in force at that moment, for that agent, acting for that user, against that resource per Permit.io's audit guide.

Build your audit envelope before you pick the wrapper, then check which surface can fill it. The fields that matter:

- Agent identity (unique, not a shared service account)
- Human principal or delegation chain
- Tool name and parameters
- Resource and action
- Policy ID and version
- Decision (allow or deny) plus reason
- Approval record if human-in-the-loop was required
- Timestamp, request ID, trace ID, tenant and environment
- Outcome of the side effect

Shared service accounts are a common failure. When multiple agents and humans share one credential, you cannot determine which actor performed which action, and incident response time climbs as a result. Agent identity answers which autonomous process acted; user identity answers which human allowed it; both are required for non-repudiation per this audit trail best practices piece. The same source recommends recording the agent's configuration and model information, a cryptographic hash of each log entry to detect tampering, and human approval details including who reviewed, when, and the outcome.

Against that bar: a bare CLI wrapper usually fails it, an MCP server with a policy point passes it, and a sandbox passes execution evidence but not authorization evidence unless you add a decision log in front of it. Alerting is a separate design problem; the same piece suggests alerting on sequences rather than single calls, since privilege escalation chains, clustered policy denials and intent drift show up in patterns.

A decision procedure you can run this week

Work through these five steps in order. Stop at the first one that decides the question.

  1. Write the audit envelope you must produce. If a regulator, customer or internal control requires authorization evidence, a bare CLI is out unless you add a mediating layer. This step alone settles most enterprise cases.
  2. Count the operations. If you are exposing a small handful of well-understood operations to a single-user or developer workflow, a CLI with a strict JSON and exit code contract is the cheapest durable option.
  3. Check who the callers are. Multi-user, remote or browser-based agents need a hosted endpoint with credentials off the client. That is MCP territory, since CLI tools work locally and hosting them yourself means rebuilding the security you were trying to avoid per the governance analysis.
  4. Ask whether the agent must compute. If the work is exploratory, data-heavy or requires writing code against a schema you cannot enumerate, you need a sandbox with a scoped permission set and timeouts, not a longer tool list.
  5. Plan the failure path. For every surface, decide what the agent sees when the underlying system changes. A typed schema fails validation loudly; a parsed table fails silently. Prefer loud.

A worked example with numbers makes the tradeoff concrete. Suppose an internal inventory system exposes 12 operations, used by 40 employees through a shared agent and by 6 developers running agents locally.

For the 40 employees, the audit requirement is likely real. Twelve tools fit comfortably in a context window, so tool bloat is not a problem. One MCP server with a policy point in front, logging the envelope above, is the right call. For the 6 developers, the same operations behind a CLI with --json and documented exit codes will feel faster and cost fewer tokens, and their work stays on their machines where the shell is already the audit trail they have.

Both wrappers can share one internal client library. That is the practical insight: build the client once, then expose two thin surfaces over it, and keep the JSON schema in one place so the CLI's --json output and the MCP tool's output schema cannot drift apart.

If your team would rather have a working surface than build one, the skill library behind every Quanta expert can be installed into a coding agent, and an expert can take the job end to end: Quanta Skills. For teams that need every kind of model behind one key while they build the wrapper, Quanta Inference exposes text, image, video, audio and embedding models through a single OpenAI-compatible endpoint.

One caution to carry into implementation: an agent's report that it finished is generated text, not a record of what ran. Teams that get reliable results put independent checks behind the agent, run them on the final state, and hand the recorded output to a reviewer per this definition of done guide. The same discipline applies to wrappers: prove the call happened with a record the agent did not write.

FAQ

FAQ

Can I start with a CLI and migrate to MCP later?

Yes, and it is a reasonable sequence, provided you separate concerns from day one. Put the actual work in a library, keep a single JSON schema for results, and let the CLI be a thin shell over it. When you need a hosted endpoint with credentials off the client and one enforcement point for logging, wrap the same library in an MCP server. Teams that inline business logic in shell scripts pay for the migration.

What makes an MCP server's contract more stable than a CLI's?

The contract is declared rather than inferred. An MCP tool publishes a name, description and input schema, and the provider owns them, so a change to the schema surfaces as a validation error instead of a silently different parse. A CLI contract is whatever text lands on stdout, and a cosmetic change to a table can break parsing without any error at all per this CLI guidance.

Do I need a sandbox if I already have an MCP server?

Only if the agent has to write and run code rather than select from fixed tools. Sandboxes matter for exploratory data work, computation against schemas you cannot enumerate, and any case where the value comes from probing rather than calling. If your operations are a known list, a typed tool surface is safer, because a sandbox widens the permission set you must review.

How do I keep credentials away from the agent?

For MCP, hold credentials in the server and never pass them to the client, so the agent host has nothing to leak. For a CLI, avoid exporting secrets into the agent's shell environment, since agents with shell access fall back to raw API calls using credentials from the user's environment when a tool fails per this analysis. For sandboxes, inject short-lived credentials per run rather than baking them into the image.

What is the minimum audit record for a sensitive agent action?

At minimum, capture the agent identity, the human principal or delegation chain, the tool and parameters, the resource and action, the policy version, the allow or deny decision with its reason, any human approval, timestamps and correlation IDs, and the outcome of the side effect per this audit guide. Log denies as carefully as allows, because explainable denials are how you show the control was active rather than merely configured.

Sources

Sources

  1. How I Validate Quality When AI Agents Write My Code
  2. Long-Horizon Planning and Goal Decomposition in AI Agents
  3. Writing CLI Tools That AI Agents Actually Want to Use
  4. Building a CLI That Works for Humans and Machines
  5. Appendix E. Exit Codes With Special Meanings
  6. CLI vs MCP: You're Asking the Wrong Question - Lunar.dev
  7. How Do AI Agents Execute Code?
  8. AI Agent Audit Trail: Proving What an Agent Did and Why - Permit.io
  9. MCP vs CLI: I Tested Both and Here's What Won - YouTube
  10. When does MCP make sense vs CLI? - Hacker News
  11. AI agent audit trails: audit log best practices - Runlayer
  12. Definition of done for AI coding agents
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles