Last week you learned how MCP hosts and clients negotiate a connection and discover a server's capabilities. This week we zoom out one layer. Before you expose a capability to an agent through MCP, you should ask a more basic engineering question: what is the cleanest programmable surface for this API?
For many integrations, the answer is not "hand the model the API docs" and hope for the best. A raw REST API is optimized for application developers, not for an LLM reading a small tool description during a task. APIs often require multiple calls, pagination, auth headers, rate-limit handling, field selection, and awkward joins before they produce the answer a user actually wants.
A well-designed CLI can compress that mess into one reliable command.
The Printing Press project is a useful reference pattern here. It frames the CLI as an agent-native integration surface: a token-efficient command-line tool for an API, app, or site, often paired with an agent skill and an MCP server. The important design lesson is not that every class project needs to use that generator. The lesson is that a good CLI does more than wrap endpoints one-for-one.
An agent-native CLI should:
--json, --csv, or selected fields.doctor command that checks auth, config, API reachability, and common setup mistakes.This is why "agent-native" is a different design bar from "human can type it." A human may tolerate paging through docs, copy-pasting IDs, and manually joining results. An agent benefits from commands with crisp names, stable schemas, and enough built-in workflow knowledge to complete a task in one or two calls.
The clean pattern for this course is:
This separation matters. If your MCP tool and your CLI both contain their own copy of the API logic, one will eventually handle errors differently, format fields differently, or use stale authentication behavior. Put the API logic in one place, then wrap it twice.
A useful CLI command has a narrow contract:
alerts active, forecast point, or packages search.--limit, --dry-run, and read-only defaults when touching real systems.For agent use, structured output is not optional. A model can read a table, but a stable JSON shape lets downstream scripts, tests, and MCP tools reuse the same command safely. A command like:
weather-cli alerts CA --json --select event,severity,area,headline
is much easier for an agent to reason over than a raw API response with hundreds of fields.
MCP still uses the same three server primitives you studied:
| Primitive | Who controls it | Good fit this week |
|---|---|---|
| Tool | Model-controlled executable action | Call the same API operation your CLI command uses, such as get_alerts(state) |
| Resource | Host/application-driven context | Expose stable reference data, cached data, schemas, or command documentation |
| Prompt | User-invoked template | Create a reusable briefing request that instructs the model which tool to call and how to summarize results |
The difference is that this week you are not building the MCP server in isolation. You are building a toolchain: API client, CLI, and MCP server around one shared capability.
The first mistake is wrapping every API endpoint as its own command without asking what job the user or agent is trying to do. That creates breadth without usefulness. A better CLI may expose fewer commands but make each command answer a real operational question.
The second mistake is making the CLI and MCP server separate implementations. Keep one API client layer and two wrappers.
The third mistake is forgetting observability and setup checks. A doctor command is not polish. It is infrastructure. When an agent gets a 401 or an empty response, doctor --json should quickly reveal whether the token is missing, the base URL is wrong, or the API is reachable but returning no data.
Finally, keep the stdio rule from last week: if your MCP server uses stdio transport, do not write debugging output to stdout. Use logging to stderr or a file. Your CLI can print normal command output; your MCP stdio server cannot.