MCP vs API: What the Difference Actually Is, From Someone Who Shipped Both

· Zakir Hossen

I have shipped MCP servers on four of my own products. Every one of them sits on top of a REST API I had already built. Not one of them replaced it.

That is the whole answer, and most explanations of this bury it. But it leaves the useful question open: if MCP does not replace your API, what does it actually change, and is it worth building?

The one-sentence version

An API is an interface for a developer who reads documentation. MCP is an interface for a model that cannot.

Same functions underneath. Different consumer, and the consumer is what changes the design.

What is actually different

Put the two side by side and the differences are narrow but they matter.

REST API MCP server
Who reads the interface A developer, once, at build time A model, every session, at runtime
How capabilities are found You read docs and write code The client asks the server what it can do
When the tool list is fixed Design time — you ship code Runtime — the server answers on connect
What a bad call costs A 400 you see in your logs A model that quietly does the wrong thing
Error messages written for A developer debugging A model deciding what to do next
Transport HTTP, your choice of shape JSON-RPC over stdio or HTTP

The row that matters most is the third one. On the HN thread about this, someone reduced the whole protocol to: tools can be added at runtime instead of at design time. That is closer to the truth than most long-form explanations, mine included.

The part that surprised me building one

I assumed an MCP server was a thin wrapper over my existing controllers. Take the endpoint, describe it in a schema, done.

That is technically true and produces a bad server.

Here is why. My scheduler’s REST API has an endpoint that takes social_account_ids. A developer integrating it reads the docs, calls the accounts endpoint once, hardcodes the IDs, and never thinks about it again.

A model does not do that. Given a tool that takes account IDs, a model will invent account IDs. They look plausible. The call succeeds against the schema and posts to the wrong channel, or fails with an error the model then tries to “fix” by inventing different IDs.

So the MCP server needed things the REST API never did:

  • A tool whose only job is “tell me what accounts exist”, so the model fetches real IDs instead of guessing. On REST this is a documentation problem. On MCP it is a tool.
  • Errors written as instructions, not as status. 422 Unprocessable Entity tells a developer to go read the docs. It tells a model nothing. The message has to say what to do instead.
  • A read-before-write tool. The model needs to see the existing queue before adding to it, or it duplicates work a human already did.
  • A safe default that is not “publish”. Publishing is irreversible. Scheduling is not. Every agent-created post gets a future timestamp so a human has a window to cancel.

None of that is protocol. It is interface design for a consumer that reasons instead of reading. That is the actual work, and it is why “just wrap your API” produces something that technically connects and practically misbehaves.

What MCP does not give you

Worth saying plainly, because the marketing around this is loose:

  • It is not faster. It is another layer over the same HTTP call.
  • It does not remove the need for an API. You still built one. MCP calls it.
  • It does not make a model reliable. It gives the model a well-described door. It will still walk through the wrong one sometimes.
  • It is not required for an AI feature. If your code decides what to call and the model only writes text, you want a normal API call, not MCP.

When to build one, and when not to

Build an MCP server when the model decides which action to take. That is the whole test.

Concretely, it is worth it when:

  • Your users already work inside an MCP-capable client — Claude Desktop, Claude Code, Cursor and similar — and want your product reachable from there without switching windows.
  • The set of useful actions is larger than one, and which one to take depends on context the model has and your code does not.
  • Your API is stable. An MCP server over an API you are still redesigning means maintaining two moving interfaces.

Skip it when:

  • Your code picks the endpoint and the model only generates content. Use the API. Adding MCP here is architecture for its own sake.
  • You have one action. A single-tool MCP server is a lot of protocol for one HTTP call.
  • You do not have an API yet. Build that first. The MCP server is a projection of it, and projecting something that does not exist yet means designing both at once, badly.

The honest summary

MCP is not an API replacement and treating it as one is how people end up disappointed. It is a second interface, aimed at a different consumer, over work you already did.

The value is not the protocol — it is that the runtime tool discovery lets a model use your product without anyone writing an integration first. Whether that is worth building depends entirely on whether models are actually the ones deciding what to call in your product.

For me, on a scheduler where the whole point is that an AI tool writes and queues the post, it clearly was. On a hiring platform where a human clicks the buttons, it clearly was not, and I have not built one there.


If you want the practical side, I wrote up how to build an MCP server — the structure, the mistakes, and the parts the tutorials skip.