# MCP and a plain API

Use the public API when your software knows what it wants: it has pagination, idempotency, versioning, webhooks and an OpenAPI description you can generate a client from. Use MCP when a *model* has to decide at runtime what to call, because MCP's contribution is discovery and descriptions written to be read by a model rather than by a developer.

- **Status:** Available
- **Audience:** developer
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/compare/mcp-vs-api/

## What MCP actually adds

- **Runtime discovery.** A client asks what tools exist and gets typed schemas back, so a model can be told what it may do without anybody hard-coding a list.
- **Descriptions aimed at a model.** A tool's description is part of the contract; on a plain API that text lives in documentation the caller may never read.
- **One envelope.** Every call has the same shape, so a client can support any server without bespoke code per endpoint.
- **Resources and prompts alongside tools**, so context and instructions travel through the same channel as actions.
- **A single endpoint.** Streamable HTTP: one URL, POST only in the 2026-07-28 revision.

None of that makes a request faster or more reliable. It makes the surface *legible to something that is deciding as it goes*, which is a real problem and not one REST was built for.

## What a plain API does better

| Need | The API gives you | MCP |
|---|---|---|
| A generated client | An OpenAPI 3.1.0 description | Schemas per tool, not a client-generation contract |
| Large result sets | Pagination, filters, stable ordering | Tools return what the tool returns |
| Safe retries | Idempotency keys and documented semantics | Retry behaviour is the client's problem |
| Being told when something happens | Outbound webhooks with signature verification | Nothing — a tool call is a call |
| Change management | Explicit versioning | A protocol revision, which is a different axis |
| Multi-step processes | Arazzo 1.1.0 workflow descriptions | You orchestrate the calls yourself |
| Event stream design | An AsyncAPI 3.1.0 description | Not applicable |

If you are writing a nightly synchronisation, a webhook consumer or a dashboard, the API is the correct answer and MCP would be a detour.

## They are not two views of the same surface

The MCP surface is a named set of tools — the public ones and the workspace ones — rather than a projection of every endpoint. A tool is chosen because it is a sensible unit of work for a model to invoke, which is not the same criterion as a resource being a sensible unit for a program to fetch.

> **Careful** So "it is in the API, therefore it is an MCP tool" is not a safe assumption, and neither is the reverse. Check [the tool lists](/developers/mcp-workspace-tools/) rather than inferring from the endpoints.

## Choosing

1. Write down who decides which call to make: your code, or a model, at the moment of the request.
   - Result: Code deciding means the API. A model deciding means MCP.
2. If it is a model, check whether it needs to be told when something changes.
   - Result: It probably also needs webhooks, which are an API concern — most real integrations use both surfaces.
3. Authenticate for the workspace, not for the person.
   - Result: Both surfaces are workspace-scoped and pass through the allowlist, the workspace kernel and row-level security. Neither is a side door.

> **Note** Connect's own application `/openapi.json`, `/docs` and `/redoc` are closed and stay closed. The public description is a separate, deliberately published artefact — do not point a client at the application's internal paths.

## Questions

### Is MCP a replacement for the API?

No, and treating it as one produces a client that reimplements pagination and retries badly. They are complementary surfaces over the same workspace-scoped services; most integrations that do anything substantial end up using the API for bulk and events and MCP for the model's own decisions.

### Which is more secure?

Neither, because both go through the same three isolation layers and the same authentication requirements. What differs is the failure mode: an MCP server must validate `Origin` and answer 403 when it is present and invalid, which surprises browser-based clients that work elsewhere.

### Can I expose Connect's tools to my own agent?

That is what the MCP server is for, with authentication that resolves to your workspace. Read [building an agent on Connect safely](/developers/agent-safety/) first — a tool that can act deserves the same thought as a person who can.

## Related

- [Model Context Protocol](https://connectbyjbrh.com/docs/protocols/mcp/)
- [The public API](https://connectbyjbrh.com/developers/public-api/)
- [Comparisons and concepts](https://connectbyjbrh.com/docs/compare/)
- [The Connect MCP server](https://connectbyjbrh.com/developers/mcp-server/)
- [The OpenAPI description](https://connectbyjbrh.com/developers/openapi-description/)
- [MCP and A2A](https://connectbyjbrh.com/docs/compare/mcp-vs-a2a/)

## What this page is based on

- `docs-source/facts.py` PROTOCOLS — MCP, OpenAPI 3.1.0, Arazzo, AsyncAPI
- `docs-source/sources/GENERAL.md` §10 — the application's own docs are closed
- `docs-source/sources/GENERAL.md` §2 — three isolation layers
- Connect capability registry (docs-source/facts.py)
