Wrap any REST API as an MCP server
Every REST API is one wrapper away from being usable by Claude, Cursor or ChatGPT. The wrapper is an MCP server — and the difference between a useful one and a frustrating one is decided before any code exists, in how you design the tool surface.
Updated July 2026
The core mistake: 1:1 endpoint mapping
The obvious approach — one MCP tool per REST endpoint — produces a bad server. An AI assistant choosing between 30 near-identical tools burns context on the choice, chains three calls where one would do, and picks wrong often enough to erode trust. The assistant is not a REST client; it does not want your resource model, it wants tasks.
Create an MCP server for our API.
Endpoints: GET /users, GET /users/:id, POST /users, PUT /users/:id,
DELETE /users/:id, GET /orders, GET /orders/:id, POST /orders,
GET /invoices, GET /invoices/:id, POST /invoices/:id/send ...Design the tool surface the way you would design CLI commands for a colleague: task-shaped, few, with the joins already done.
Create an MCP server for our billing API (https://api.example.com).
Tools:
- find_customer: search customers by name or email, return id, plan, status
- get_open_invoices: list unpaid invoices for a customer id, with amounts
- send_invoice_reminder: send the dunning email for one invoice id
Auth: BILLING_API_KEY sent as "Authorization: Bearer" header.
Read-heavy; send_invoice_reminder is the only write action.- 3–7 tools is the sweet spot for a single-purpose server. More than ten and selection quality drops.
- Fold lookups into the tool. If sending a reminder needs a customer id, let find_customer exist — but do not expose the four intermediate endpoints the API needs internally.
- Return shaped results, not raw payloads. “id, plan, status” beats the full 80-field customer object; the model reads every byte you return.
- Separate reads from writes and say so in the description — clients like ChatGPT restrict write tools on individual plans (details here), and a clean read/write split keeps the read tools usable everywhere.
Auth: the API key never goes in the prompt
The wrapper needs your API's credential, and there is exactly one right place for it: an encrypted secret, referenced by name. In the prompt above, BILLING_API_KEY is a name, not a value. You provide the value separately in the dashboard; it is encrypted with AES-256-GCM at rest and injected into the server's container as an environment variable at runtime — never logged, never echoed back, never part of the generated source.
The second auth layer is between the AI client and your MCP server: every deployed server sits behind OAuth 2.1 (PKCE, Dynamic Client Registration, Resource Indicators), so your wrapped API is not one guessable URL away from the public internet. How that handshake works: OAuth docs.
Rate limits: yours and theirs
| Layer | What limits it | What to do |
|---|---|---|
| Client → MCP server | OAuth gate before your container; plan quotas (free tier: 100k calls/mo) | Nothing — enforced for you. |
| MCP server → upstream API | The upstream's own rate limits | Tell the generator: “respect a limit of N req/s; on 429, back off and surface the error”. Shaped tools help here too — one task call instead of five endpoint calls. |
| Model behavior | Assistants retry failed calls | Return clear error messages (“rate limited, retry in 30s”) — models read them and actually wait. |
From prompt to installed tool, end to end
With the prompt written, the rest is mechanical: generation, static checks, container build and deploy take 45–90 seconds, and the dashboard gives you install snippets for Claude Desktop, Cursor and ChatGPT. The generated TypeScript is exportable — if your wrapper outgrows prompt-editing (complex retries, multi-step workflows), take the source and continue by hand with the boilerplate already written.
If your API resembles something common — Notion, GitHub, Stripe, PostgreSQL — check the templates first: forking a working server and swapping in your credential is faster than writing any prompt. Otherwise, the free tier covers one server — enough to wrap the API you use most and find out what your assistant does with it.
Skip the boilerplate — describe your tool, get a hosted MCP server.
BuildMyMCPServer generates the TypeScript server, wraps it in OAuth 2.1 and deploys it to a public Streamable HTTP URL for Claude, Cursor and ChatGPT. Free tier, source export, no lock-in.
Start building →