Interfaces
I recently hacked together a tiny MCP server for personal use. The initial plan: just build a dead-simple MCP server, explore the landscape of libraries and open-source tooling around the ecosystem, and move on. Nothing fancy. But like most experiments, scope creeped just a bit.
After completing the minimal MCP server buildout, I wanted a bit of visualization for the project, so I built a small companion web UI. And to support that UI, I needed an API. Suddenly I had three different interfaces tied to the same functionality. I began to wonder: What are the pros/cons/tradeoffs between these? Which interface is superior? When would one be preferred over another and why?
This post is me thinking out loud about the core "interfaces" we use in software engineering: MCP, API, UI, and CLI: what they're good at, where they shine brightest, and where they may come up short.
Let's start in reverse chronological order with the newest "interface" and work our ways backwards from there.
MCP (Model Context Protocol) — The LLM-Native Interface
Perhaps technically – more of a specification or standard moreso than a "true interface", nevertheless. MCP isn't for humans or machines directly, it's for LLMs to talk to tools.
How it feels:
- You send loosely structured, natural-language-ish text into a black box
- The “client” (an AI model) infers meaning and calls the right tool or method
- Think: “LLM, fetch my tasks and sort them by priority” instead of crafting structured payloads
Why it's interesting:
- Lowest friction for humans (we speak in intent)
- Highest burden on machines (have to infer the intent)
- Slower than a direct "tool" calls
- It flips the traditional interface dynamic: the “client” does most of the interpretation
Early takeaways:
- Super flexible, with inference capabilities that would be difficult to build into a more traditional "contract"
- Zero-config for a human interacting through an LLM
- Non-deterministic slot-machine like predictability which can be fun but annoying depending on what your trying to accomplish
- Harder to guarantee correctness
API (Application Programming Interface) — The Contract-First Interface
Before MCP, the "headless" way to interact with machines was through an API
Traits:
- Strict, predictable, documented
Compared to MCP:
- More reliable and consistent
- Less flexible (no LLM inference in tool calls etc.)
- Deterministic
Taking a brief pause here. It was during the buildout of the API piece, after the MCP server was built, that I shared 80-90% of the code between tool calls and API endpoints, but they did feel fundamentally different. A lot has been written about the differences between these two interfaces. I don't have a strong take, but it was a bit of an odd programming bridge between the two despite sharing so much functionality.
UI (User Interface) — The Friendly Human Interface
Why it exists:
- Lowest barrier for humans
- Offers guidance, visual affordances, error recovery, context
Nice for:
- Explaining functionality through visuals
- Guardrails and constraints for regular users
Downsides:
- Slower to build
- More surface area for bugs
- Requires design + UX thinking
In the context of this small experiment, the UI presented the most amount of friction, contained the least amount of code reuse (or said differently, the greatest amount of unique code), and generally felt sluggish in implementing. This will likely depend on the complexity and scope of the project in total, I think this simply reflects how a "headless" or text-based interface was sufficient for my needs.
CLI — The Power User Interface
The most "developer-efficient" human interface.
Characteristics:
- Strict, explicit, fast
- Scriptable and composable
- Zero ambiguity
CLIs sit between API and UI: structured like an API, but operated by humans like a UI.
Best when:
- Power users want speed
- Tasks are repetitive or automatable
- You need precision
Who Wins?
Obviously: it depends. Each interface serves a different “consumer” with different constraints.
Generic summary of each:
- MCP: Best when the consumer is an AI
- API: Best when the consumer needs guarantees
- UI: Best when the consumer is a human
- CLI: Best when the human wants speed and control
So What Did I Learn?
I set out to build an MCP server to simply learn more about the protocol and its tradeoffs from both a developer and end user experience.
I found MCP to be pretty novel, due to its inference-based mechanics, which is a bit of a brain twister for someone like me (read: old). "You build this server with tools to then present them to an LLM which is then responsible for calling it at the appropriate time". That's...different.
Is this good? Many claim MCP servers have the tendency of polluting the context window leading to worse results from the LLM. That's a whole other topic worth exploring, but important nonetheless. Context window aside; it does feel less determinisitc and predictable, which to an old software engineer, feels a bit scary at times. It could also be a skill issue. I'm open to both possibilities.
So the question isn't: "Will MCP replace APIs?" which I've seen a lot. I think it's just another tool to explore and refine. I personally haven't found the ideal use case just yet but I'm not willing to make the call just yet.
Wrapping Up
This wasn’t a grand experiment—just a weekend curiosity. But building the same capability through MCP, API, UI, and (theoretical) CLI was a fun way to feel the ergonomics of each.
If you want to poke around the code, it’s here: 👉 https://github.com/pruett/dayta-mcp