MCP vs REST API: What Changes When an AI Is the Client

An MCP server rarely replaces an API. It usually sits on top of one, rewritten for a client that reads the interface at run time and decides for itself what to call. Here is what that changes, and when you need which.

7 min read

MCP does not replace your API. An API is a contract for a developer, who reads the documentation once and writes code that calls fixed endpoints. An MCP server is a contract for an AI model, which reads the list of tools every time it connects and decides, mid-conversation, which one to call. Most MCP servers call an existing API or service layer underneath. What changes is who the client is, and that one change moves discovery, the shape of each operation, error messages and sign-in. If you need the basics first, start with what MCP is; this post is about the difference.

The short version

  • Who reads the contract: an API is read by a person writing code; an MCP server is read by a model at run time.
  • Discovery: an API is discovered through documentation or an OpenAPI file; an MCP client asks the server for its tools with tools/list.
  • Shape: an API exposes resources and verbs (POST /items); good MCP tools are shaped around jobs (“add a task, unless one like it already exists”).
  • Errors: an API answers with a status code a program branches on; an MCP tool answers with text a model can read and act on.
  • Transport: an API is usually HTTP and JSON of its own design; MCP is JSON-RPC 2.0 over stdio or HTTP, the same for every server.
  • Who holds the credential: a script holds an API key; an assistant holds a token issued when a person signed it in.

The client changes, so the contract changes

A developer integrating your API does the hard thinking once. They read the reference, pick the three endpoints they need, handle the edge cases and ship. After that, the calls are fixed; nothing is decided at run time.

A model integrating your MCP server does that thinking every session. It sees each tool’s name, description and input schema, and chooses from them on the spot. So the descriptions stop being documentation and become part of the interface. A vague description is not a docs bug any more; it is a wrong call waiting to happen.

Discovery is built in

With an API, discovery happens outside the protocol: a docs site, an SDK, an OpenAPI file someone remembers to update. With MCP it is a request. The client sends tools/list and the server answers with every tool’s name, description and JSON Schema for its input. The MCP tools specification (opens in a new tab) also allows the list to vary with the authorization on the request, so a server can show a caller only the tools their scopes permit.

That is why the same MCP server works in Claude, ChatGPT, Cursor and other clients without anyone writing glue code for each: they all ask the same question and get the same answer.

Tools are jobs, not endpoints

The tempting first MCP server is one tool per endpoint. It works, but it hands the model a toolbox of parts and asks it to assemble each job itself, spending calls and context as it goes. Anthropic’s engineering guide to writing tools for agents (opens in a new tab) names this directly: tools that merely wrap existing API endpoints are a common mistake, and fewer, more deliberate tools usually do better.

A concrete case from a task board. The REST shape is list items, create item, update item. The MCP shape on fenbs is fenbs_create_item, which checks the open tasks and those finished in the last 14 days before it files anything. If one looks like the same thing, nothing is made and the assistant gets the likely matches back with created: false, plus what to do next: comment on the open one, or reopen the finished one. A developer would build that check once into their own code. An assistant, left to itself, forgets.

The same job, two contracts
# REST: the caller decides the steps
GET  /v1/boards/{board}/items?q=login
POST /v1/boards/{board}/items

# MCP: the tool carries the steps
tools/call fenbs_create_item { board, title, kind, note }
-> created: false, likely matches, and what to do instead

Errors are written to be read

An API error is for a program: 403, perhaps a code, and the calling code branches. A model cannot branch on a status it was never told about. MCP separates protocol errors, such as an unknown tool, from tool execution errors, which come back as an ordinary result marked isError so the model can read the message, correct itself and try again.

The practical rule: write every refusal as a sentence the assistant can repeat to the person it works for. On fenbs, a refusal names the permission that was missing and the role the caller holds, so an assistant can say “I can’t move that task: my role on this board does not include moving tasks between lanes” instead of reporting a failed call.

One wire format for every server

Every REST API invents its own URLs, pagination and error bodies. MCP fixes all of that: messages are JSON-RPC 2.0, carried either over stdio, for a server the client starts on the same machine, or over Streamable HTTP, for a remote one. The MCP architecture overview (opens in a new tab) describes this as a data layer and a transport layer, so the same messages work either way.

The current revision, 2026-07-28, made the protocol stateless: the handshake and protocol-level sessions are gone, and every request carries its protocol version and client capabilities with it, as the 2026-07-28 changelog (opens in a new tab) sets out. That brings an MCP server closer to an ordinary HTTP service in how it scales, though the request format is still MCP’s own.

Who holds the key

A script calling an API usually holds a long-lived key that someone created and pasted into a secret store. An assistant calling a remote MCP server usually holds a token issued when a person signed it in through a browser, scoped to what that person approved. The specification builds this on OAuth. How to implement it is covered in how to add authentication to an MCP server, and what the person approving it sees is in OAuth for MCP servers.

When you need which

  • A cron job, a CI step, a webhook handler or a data sync: an API. The steps are known in advance and a program runs them.
  • An assistant in a chat window, an editor or a terminal, deciding what to do from what someone asked: an MCP server.
  • Both: build the MCP server on the same service layer as the API, so the two cannot disagree about what is allowed.

That last point matters more than it looks. If the permission check lives in the API handler and the MCP server calls the database directly, an assistant can do things a person cannot. On fenbs, the web interface and the MCP server both call the same service, so a person and an assistant are allowed exactly the same things and refused for exactly the same reasons. The API page documents the REST endpoints; API keys are not available yet, and MCP covers the same ground in the meantime.

What an MCP server does not change

Your data model, your permissions and your rate limits stay where they are. The MCP server is a translation layer with opinions: it chooses which jobs to expose, how to describe them and how to explain a refusal. If you are about to write one, how to build an MCP server walks through it; if you are choosing one for your team, see what to look for in an MCP server for project management.

Related

The protocol in plain words: MCP in the glossary. How tools relate to the model’s own function calling: MCP vs function calling. Connecting an assistant to a board: Claude, Claude Code, ChatGPT, Cursor.

Questions people ask.

Does MCP replace REST APIs?

No. MCP is a way for AI assistants to discover and call a product’s tools. Most MCP servers call the product’s existing API or service layer underneath, and scripts, CI jobs and integrations between programs still use the API.

Can I turn my OpenAPI spec straight into an MCP server?

You can generate one, and it will work, but one tool per endpoint tends to make the model do the assembly itself. Start from the generated list, then merge endpoints into tools shaped around the jobs people actually ask for, and rewrite the descriptions for a model.

Is MCP slower than calling the API directly?

Speed is rarely the issue that matters. The bigger cost is context: every tool definition the client loads is text the model reads, which is another reason to keep the tool list short.

Should an assistant use my API key instead of MCP?

Better not. A pasted key usually carries more access than the assistant needs and cannot be told apart from your own scripts. A token issued by signing the assistant in can be scoped, listed and revoked on its own.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.