MCP is a protocol between an application that consumes capabilities and a server that exposes them. Its useful abstraction is a discoverable capability: an operation, a piece of contextual data, or a reusable interaction template. The server may implement that capability by calling an API, querying a database, running a constrained program, or computing a result itself.
The base specification defines the message and capability framework. The practical distinction is that an MCP client can learn a server’s interface through shared protocol operations instead of requiring a different integration mechanism for every service.
Start with the operation, not the acronym
Imagine one operation: read the checkout incident accessible to Alice.
| Interface | What the consuming program does | What still needs to be designed |
|---|---|---|
| Direct function/SDK | Calls incidents.get(id) using a library | Credentials, object policy, library distribution and upgrades |
| HTTP API | Sends a request to a known endpoint and parses its response | Endpoint knowledge, schema, retries, discovery and authentication integration |
| CLI | Runs an installed executable with arguments and reads output/exit status | Installation, process isolation, machine-readable output, credential handling |
| MCP | Discovers the tool contract and invokes it through a shared client | Tool semantics, identity, policy, bounded output, host behavior and version support |
All four can be well designed. All four can return JSON. All four can support fine-grained permissions. None becomes safe merely because of its interface category.
The strongest MCP argument is therefore not “APIs are unstructured” or “CLIs cannot be used by models.” It is that a recurring class of capability discovery and invocation can be standardized across many independently developed hosts and services.
Separate the layers
Human intent
|
AI host: conversation, model loop, context selection, approval policy
|
Model proposes a tool name and arguments
|
Host validates policy and routes through an MCP client
|
MCP server: discoverable contract and protocol adapter
|
Domain service: authorization, invariants, reads and effects
|
Database / API / queue / constrained executable
The model does not open the socket or become an OAuth client. Host code executes the call. You can also use an MCP client without a model, which the worked example does to make integration behavior deterministic.
“Function calling” usually describes the model-facing interface for requesting a function. MCP describes an application-facing integration protocol. A host can translate an MCP tool schema into its model provider’s tool format. It still owns that translation, the execution loop, and the decision about which tools to expose.
A skill supplies instructions or reusable procedures. It may teach an assistant how to use a CLI or an MCP tool. It does not, by itself, implement the remote capability, validate an access token, or enforce object ownership. A package called a “plugin” may bundle these layers; inspect what it actually installs and enables.
What MCP standardizes—and what it leaves open
| Shared contract | Advantage | Boundary that remains |
|---|---|---|
| Discovery of tools and schemas | A host can inspect capabilities at runtime | It must decide which capabilities are trustworthy and relevant |
| Common invocation and result envelopes | Reusable client and server machinery | Business meaning and side effects remain service-specific |
| Resources and prompts | Context and interaction templates have named interfaces | Hosts differ in how they use and display them |
| Transport and revision rules | Fewer bespoke connection implementations | Support varies across products and versions |
| HTTP authorization conventions | A standard path for delegated access | Your application still enforces tenant, object, and operation policy |
These are protocol affordances, not a guarantee that any arbitrary pair of products will complete a workflow. Capability support, authentication setup, schema dialects, result handling, and the host’s UX still matter. Read the actual transport contract rather than inferring behavior from a product’s “supports MCP” label.
The integration economics, without the marketing shortcut
Suppose H hosts need S services. Bespoke integrations can create up to H × S adapter relationships. A common protocol can move much of the reusable protocol work toward H host implementations plus S server implementations.
That is an architectural model, not a measured cost reduction. You still have a compatibility matrix, credentials to provision, service-specific semantics, and workflows to evaluate. The protocol reduces repeated plumbing; it does not make integration testing disappear.
The case gets stronger when independent customers choose their own hosts, your product exposes a coherent capability set, and the cost of maintaining host-specific integrations is significant. It gets weaker when you control both ends and already have a small, stable SDK integration.
For a provider, publishing an MCP server creates another product surface. Its consumers include humans configuring clients, models selecting tools, client implementations interpreting schemas, and security administrators controlling access. A tool description can be wire-compatible while changing model behavior enough to break an important workflow.
Why not just give the model an OpenAPI specification?
That can work. OpenAPI describes an HTTP API, and a host can generate tools from it. This is particularly attractive when one team controls the host and already has a mature API gateway.
MCP supplies a shared runtime interaction boundary beyond a static API description. It also gives providers an opportunity to expose task-shaped operations rather than every backend endpoint. But wrapping OpenAPI mechanically may simply move a large API catalog into the model’s context without improving selection or comprehension.
Consider an incident summary that requires six backend requests. A curated get_incident_context tool can return a bounded, consistent view. The tradeoff is that the provider now owns a higher-level contract. If customers need arbitrary composition, narrower tools or a constrained programmable interface may fit better. There is no universal “one API endpoint equals one MCP tool” rule.
Why not just use a CLI?
A mature CLI is often the best interface for local developer work. It offers discoverable help, pipelines, existing operational knowledge, and a natural fit with repositories and files. A model that writes shell commands can use it effectively.
The costs emerge around execution authority and portability: which executable runs, which version is installed, what environment it inherits, how credentials are stored, and whether command output is stable. Shell expansion adds another interpretation layer if the host builds command strings unsafely. These concerns can be controlled; they are not intrinsic defects of every CLI.
An MCP server can itself wrap a CLI. That is useful only if the adapter adds a contract you need: constrained arguments, structured output, consistent discovery, or controlled remote access. A wrapper that forwards arbitrary shell strings adds a protocol hop while preserving broad execution authority.
The limitations that should influence a decision
Syntax does not settle meaning. A schema can require service: string; it cannot establish whether “checkout” denotes the right service in the right account. Include stable identifiers, units, time ranges, and ambiguity handling in the domain contract.
A shared protocol does not standardize business transactions. Two servers cannot atomically update their unrelated databases merely because both accept MCP. Partial completion needs application-level recovery.
Discoverability can become overload. Hundreds of descriptions compete with the task and evidence for model context. Tool selection, selective loading, and response shaping remain design work. Anthropic’s code-execution account describes both catalog and intermediate-result overhead; its reported savings are examples, not a universal benchmark.
Interoperability is not behavioral equivalence. Two hosts can invoke the same tool successfully while making different choices about approval, resources, elicitation, or context inclusion.
Read access can still move sensitive data. A harmless-looking read can feed private content into model context, logs, or a second server. Authentication to both systems does not authorize every transfer between them.
Distributed failure remains ambiguous. A timeout can occur before a write starts or after it commits. The absence of a response is not evidence of the absence of an effect.
A decision you can defend
| Situation | Starting choice | Reason to reconsider |
|---|---|---|
| One scheduled job moving known records | Direct API/SDK | Multiple independent hosts need the same interactive capability |
| Local build, grep, git, and file workflows | Existing CLI | You need a narrower remote capability boundary or cross-host integration |
| SaaS product consumed by customers’ chosen assistants | MCP adapter over the domain API | Required client features are poorly supported or workflows remain deterministic |
| High-volume, fixed service-to-service computation | Direct typed API/RPC | An AI-facing discovery surface is a separate requirement |
| Large API with open-ended agent composition | Evaluate curated tools, search/discovery, and constrained code execution | Measured task success or security cost favors a simpler surface |
Our recommendation is to keep the domain implementation independent of MCP. Add MCP when interoperability and capability discovery earn their maintenance cost. Preserve the API or CLI when it remains the best interface for deterministic consumers.
Before continuing, explain why “MCP replaces APIs,” “MCP is only a JSON wrapper,” and “MCP makes tool use safe” are all incomplete statements. Each captures a visible part of the system while missing a different boundary.