MCP vs API: why agents call MCP servers instead of REST endpoints
On this page
An MCP server can wrap an existing API, so the two aren't rivals. A REST API is built for programs whose developer read the documentation and wrote code against fixed endpoints. MCP is built for AI applications that find out at runtime what they can do: the server lists its tools with descriptions and JSON Schemas, the model picks one, and the client calls it the same way it calls any other server. If you're writing ordinary code, call the API. If you want an AI app to use a service without writing integration code for it, use (or build) an MCP server in front of that API.
Written in October 2026 against MCP specification revision 2026-07-28.
Creating an issue, twice
Creating a GitHub issue with the REST API takes an endpoint, headers and a body. GitHub's issues API documents POST /repos/{owner}/{repo}/issues with a bearer token, Accept: application/vnd.github+json and an X-GitHub-Api-Version header:
curl -L -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2026-03-10" \
https://api.github.com/repos/OWNER/REPO/issues \
-d '{"title":"Login button unresponsive on Safari","labels":["bug"]}'The same page says only title is required, that labels are silently dropped without push access, and that the list endpoint also returns pull requests, marked by a pull_request key. A developer reads that once. An agent calling the API directly has to be told, or find out.
Through MCP, the agent sees a tool definition first:
{
"name": "create_issue",
"description": "Create an issue in a repository. Requires title; labels need push access.",
"inputSchema": {
"type": "object",
"properties": {
"owner": { "type": "string" },
"repo": { "type": "string" },
"title": { "type": "string" },
"body": { "type": "string" },
"labels": { "type": "array", "items": { "type": "string" } }
},
"required": ["owner", "repo", "title"]
}
}and calls it with tools/call. The server turns that into the REST request with the right headers and API version. The shape above is illustrative; GitHub's own MCP server groups issue writes into an issue_write tool with a method argument.
REST API and MCP side by side
| REST API | MCP server | |
|---|---|---|
| Designed for | Developers writing integration code | AI applications choosing actions at runtime |
| Interface | Many endpoints, each a path plus an HTTP method | A few protocol methods (tools/list, tools/call, resources/read …) over JSON-RPC |
| Discovery | Documentation, sometimes an OpenAPI file | tools/list returns names, descriptions and input schemas from the server itself |
| Unit of action | One HTTP request | One tool, which may make several API requests |
| Results | Whatever JSON the endpoint returns | Content blocks for the model, plus optional structuredContent matching an outputSchema |
| Errors | Status codes and error bodies | Protocol errors, or a result with isError: true written for the model to correct |
| Auth | Per API: keys, OAuth apps, signed requests | Optional; remote servers that use it follow an OAuth 2.1 profile, and some accept a provider token instead |
| Work per new service | Client code for each API | Usually configuration rather than service-specific tool code, when transport, protocol and authentication support match |
Four costs of calling the API directly
An agent with a shell and curl, or a generic HTTP tool, can reach any API. Sometimes that's fine. The costs show up in four places.
Discovery. The agent needs endpoints, parameters and quirks like the ones above. For an internal API, that means putting documentation into context. An MCP server describes itself, and whoever runs the server maintains the description.
Credentials. A shell-based API call often uses credentials available in the agent's environment, where the model can read them and may echo them. A host-managed HTTP tool can instead attach credentials outside model-visible arguments. Remote MCP can provide the same isolation, depending on its implementation. The client still holds its MCP credential, and some servers (GitHub's among them) accept a provider token directly from the client. Where a server uses OAuth, the authorization specification requires tokens issued for that MCP resource, and servers "MUST NOT accept or transit any other tokens."
Granularity. API tokens already have scopes, and GitHub's fine-grained tokens can be limited to specific repositories and permissions. What differs is the surface the agent gets. An unrestricted generic HTTP tool is one tool: whatever the token allows, any endpoint, any method. Separately named MCP tools let a client or gateway allow list_issues, require approval for create_issue and leave delete_repository out, on top of the token's own limits. For shell-based API calls, command-pattern rules have documented limits. A host-managed HTTP tool or an API gateway can enforce method, route and request constraints directly; MCP gives compatible clients a standard named-tool interface to apply rules to.
Fit for the model. REST endpoints often return large objects built for UIs. A tool designed for an agent can return the fields that matter, combine several calls into one, and report errors the model can act on. The tools specification separates protocol errors from tool execution errors (isError: true) so the model can "self-correct and retry with adjusted parameters".
What MCP adds beyond tools
An API is mostly operations. MCP also defines resources, read-only context such as a file or a schema, and prompts, which are reusable templates. Servers can ask the user for input mid-call through elicitation and can notify clients when their tool list changes. None of that replaces the API underneath; it gives AI applications a consistent way to use it.
Revision 2026-07-28 is also stateless at the protocol level: every request carries the protocol version and client capabilities in _meta, and a server that needs state across calls returns an explicit handle. Anyone who has designed a REST API will recognize the model.
What APIs do better
- Deterministic code. A nightly sync job is simpler, faster and easier to test with a REST client or SDK.
- Coverage. An MCP server exposes what its author chose; the API usually covers more. GitHub's MCP server splits its functionality into toolsets and enables a default subset.
- Volume. Bulk operations, pagination over thousands of records and webhooks are API territory.
- One hop fewer. A direct call avoids another service in the path, with its own availability and limits.
Call the API, or put a server in front?
Call the API directly for application code and scheduled jobs with no model choosing actions, for endpoints or volume the MCP server doesn't offer, and for a sandboxed agent where one narrowly scoped token is acceptable.
Use an MCP server when:
- An AI app like Claude Code, Cursor, Codex or claude.ai should use the service without custom code.
- You want client or gateway rules for individual named tools, in addition to the API token's scopes and repository permissions.
- The upstream credential shouldn't live where the agent runs, and the server supports keeping it server-side.
- Several compatible apps and people should reach the service through one interface.
If you build one over your own API, keep tools task-shaped rather than mirroring every endpoint; a few well-described tools are easier for a model than eighty thin ones. Building an MCP server covers the official SDKs.
Scopes first, then per-tool rules
Wrapping an API in MCP doesn't make it safer by itself. The server acts with whatever account and scopes its credential has, and an agent allowed to call create_issue can still file the wrong issue. Set the outer limit with the upstream token's scopes, then decide per tool what each agent may do, in the client (see the MCP allowlist guide) or at a gateway (see Toolstile permissions). If the server signs in with OAuth, MCP authentication walks through the flow.