MCP vs REST: when each wins for AI agent integration
Treating MCP and REST as alternatives is the wrong frame. They sit at different layers: REST is a transport plus conventions, MCP is a typed protocol designed for an LLM consumer. The real decision is which surface each consumer talks to, and how the two surfaces share a backend. This article gives the framework I use when scoping AI integrations for WordPress and WooCommerce builds.
This article anchors to the MCP server development service pillar.
TL;DR
- MCP and REST are complementary, not alternatives.
- REST wins for deterministic clients with hardcoded action sets and OpenAPI docs.
- MCP wins for LLM agents that need runtime tool discovery and typed mutating envelopes.
- The production default is REST as system of record, MCP as agent-facing surface in front.
- Same backend, two surfaces, one source of truth.
What each protocol actually is
REST. An architectural style from Roy Fielding’s 2000 dissertation (the dissertation source), typically expressed over HTTP with verbs and resource URLs. WordPress exposes a REST API under /wp-json/wp/v2/ (WordPress REST API handbook); WooCommerce extends it under /wp-json/wc/v3/. Documentation is usually OpenAPI (OpenAPI specification) and SDKs are generated from the schema at build time.
MCP. A JSON-RPC 2.0 based protocol Anthropic announced on 25 November 2024 (Anthropic announcement) for connecting LLM hosts (Claude Desktop, IDEs, custom agent runtimes) to data and tools. Three primitives: tools (callable functions), resources (read-only documents), prompts (server-supplied templates). Discovery is runtime via tools/list; the agent learns the available capabilities every session.
The shapes feel similar from a distance. They diverge fast under load.
The decision matrix
Six factors I score before picking a surface for a given action:
| Factor | REST favoured | MCP favoured |
|---|---|---|
| Consumer type | Deterministic web/partner client | LLM agent |
| Capability discovery | Compile-time via OpenAPI | Runtime via tools/list |
| Action shape | Fixed, well-known | Free-form intent |
| Mutation safety | Convention-based | Typed envelope + idempotency built-in |
| Authentication | Bearer tokens, OAuth | Same, plus per-tool scope tagging |
| Caching | HTTP cache headers | Out of band, application-level |
The matrix tells me which protocol is preferable for one action, not for the whole API. Most projects end up split.
Where REST clearly wins
A storefront fetching a category page. Hardcoded against /wp-json/wp/v2/categories?slug=widgets. The shape is known, the cache headers do work, the CDN can cache by URL.
A partner ERP integration syncing inventory daily. The partner team reads OpenAPI, generates a typed SDK, schedules a cron at 03:00 UTC. They want stable URLs, predictable response shapes, and HTTP status codes. MCP would add complexity without value.
Public, anonymous read traffic. A SEO crawler hitting product pages, a price comparison aggregator pulling product feeds. REST plus rate limiting handles this case with the most-mature infrastructure.
Webhook delivery. WooCommerce fires woocommerce_order_status_completed to a partner endpoint. The partner endpoint is a REST receiver. MCP is the wrong shape because the agent is not in the loop; the receiver is a deterministic system.
Where MCP clearly wins
An LLM agent acting on a user’s free-form intent. “Find me a waterproof jacket under 200 euros that ships to Berlin.” The agent does not know in advance which filter combination to apply; it needs to introspect the available tools, read the descriptions, decide. REST gives it 47 query parameters across 3 endpoints and no signal about which to use.
Mutating actions where idempotency matters. Creating an order from an LLM is the loudest example. The MCP order.intent tool with a typed input schema and an idempotency key is a tighter contract than a free-form POST /wp-json/wc/v3/orders call. Retries are safe by design, not by convention.
A tool surface that evolves frequently. Adding a new search filter or a new product type means publishing a new MCP tool with a describe block; the agent picks it up on the next tools/list without code changes on the agent side. With REST, every change is a coordinated SDK release.
Multi-step agent workflows. “Check if SKU AC-101 is in stock; if not, suggest three alternatives; if found, propose an order.” Each step is one tool call; the agent composes them. With REST, the agent has to hardcode the workflow shape into its prompt.
Where the boundary sits
For a typical WooCommerce build I draw the boundary like this:
| Action | Consumer | Surface |
|---|---|---|
| Public catalogue browse | Web client, crawlers | REST |
| Product detail page render | Web client | REST |
| Inventory sync (B2B) | Partner ERP | REST + OpenAPI |
| Webhook delivery | Partner endpoints | REST |
| Agent: search for a product | LLM | MCP |
| Agent: read order status | LLM | MCP |
| Agent: propose order | LLM | MCP |
| Agent: cancel order | LLM | MCP |
| Admin operations | WordPress admin | REST + cookie auth |
The MCP server’s tool handlers call the same /wp-json/wc/v3/ endpoints the REST consumers use. One source of truth for the data layer, two surfaces for two consumer types.
Authentication trade-offs
REST authentication is well-trodden: bearer tokens, OAuth 2.x, basic auth for development. The convention is “the token bearer can do anything the documentation says they can.” Scope refinement happens per-endpoint at the application level.
MCP defers to the same transport-layer choices, but the SDK encourages tagging scopes per tool. A single OAuth token can carry orders:read without orders:write, and the MCP server enforces that on every tool call. OpenAPI patterns support the same idea via securityDefinitions and per-operation security, but in practice most REST APIs document a single global scope and let the application sort out finer granularity.
For agent integrations specifically, the per-tool scope mapping in MCP is a real ergonomic win. The user grants orders:read to the agent; the agent literally cannot call order.cancel because the MCP server rejects it with a forbidden error before the handler runs. The auth surface is the same as REST under the hood, but the contract is more legible to both the user and the agent.
Caching
REST has decades of HTTP cache infrastructure: Cache-Control headers, ETag revalidation, Vary rules, CDN edge caching, browser caching, intermediate proxy caching. A GET /wp-json/wc/v3/products?stock_status=instock response with Cache-Control: public, max-age=60 caches at the edge with no extra effort.
MCP has none of that. Tool responses travel as JSON-RPC payloads inside POST requests. HTTP cache headers do not apply. Caching has to happen application-level, inside the tool handler, against an explicit key derived from the input. This is fine when the MCP server’s handlers themselves cache the upstream REST call (which is what I do in production), but it means the caching layer is your problem to design.
This is the strongest argument for keeping public read traffic on REST and routing only agent traffic through MCP. The HTTP cache infrastructure is too valuable to give up for the public surface.
The hybrid pattern
The default architecture I ship for WordPress and WooCommerce sites with AI agent ambitions:
┌──────────────────┐
│ WordPress core │
│ + WooCommerce │
│ (REST origin) │
└────────┬─────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌───────▼────────┐ ┌────▼─────┐ ┌──────▼──────┐
│ Public REST │ │ Webhook │ │ MCP server │
│ (cache at CDN) │ │ delivery │ │ (Workers) │
└───────┬────────┘ └────┬─────┘ └──────┬──────┘
│ │ │
┌───────▼────────┐ ┌────▼─────┐ ┌──────▼──────┐
│ Storefront, │ │ Partner │ │ LLM agent │
│ price feeds, │ │ endpoints│ │ (Claude, │
│ public APIs │ │ │ │ ChatGPT, │
│ │ │ │ │ custom) │
└────────────────┘ └──────────┘ └─────────────┘
Same WordPress origin. Three surfaces, three consumer profiles. The MCP server’s handlers call the same REST endpoints the public surface caches; the webhook delivery shares the WordPress event hooks the MCP server’s invalidation logic listens to.
The boundary between MCP and REST is a deployment decision, not a coding decision. The data layer (WooCommerce database, REST endpoints) is shared. The presentation layer (typed tools vs JSON resources) is split.
Common mistakes
Trying to make MCP do REST’s job. Caching public catalogue pages through MCP is wrong. Use REST plus a CDN.
Trying to make REST do MCP’s job. Documenting an LLM-friendly action surface in OpenAPI plus expecting the agent to “figure it out” produces brittle results. Agents do better with MCP’s tool discovery.
Two parallel data layers. If the MCP handlers re-implement business logic instead of calling the REST origin, every WordPress upgrade breaks both surfaces. Keep the data layer in WordPress; keep the protocol surfaces thin.
Forgetting the cost. An MCP server is one more deployment unit, one more auth strategy, one more thing to monitor. Do not ship one if your only consumer is a partner ERP integration; ship OpenAPI and call it done.
Where this fits in the cluster
This article covers the protocol-level decision. For the implementation walkthrough see building an MCP server for WooCommerce. For the auth strategy see MCP authentication patterns. For the typed tool design see writing typed catalogue tools with Zod for MCP. For the migration pathway from an existing API see migrating an existing WordPress API to MCP. The pillar is MCP server development.
Pricing is individual because the right shape depends on which consumers you serve and which actions need agent-grade contracts.
