Prompt
How do I build an MCP server from an existing REST API?
Latest observation
To build an MCP server from an existing REST API, the basic idea is:
- Inspect your REST API
- Map API capabilities to MCP tools/resources/prompts
- Implement an MCP server that translates MCP calls into REST requests
- Add auth, validation, and error handling
- Expose the server to MCP clients
Here’s a practical approach.
1) Decide what parts of the REST API become MCP features
MCP has a few main concepts:
- Tools: actions the model can call, usually map well to
POST,PUT,PATCH,DELETE, or any operation with side effects. - Resources: read-only data, often map to
GETendpoints. - Prompts: reusable prompt templates, optional and not usually needed for a straight API wrapper.
Good mapping examples
GET /users/{id}→ resource or tool likeget_userGET /tickets?status=open→ tool likelist_ticketsPOST /tickets→ tool likecreate_ticketPATCH /tickets/{id}→ tool likeupdate_ticketDELETE /tickets/{id}→ tool likedelete_ticket
If the API is large, don’t expose everything at once. Start with the most useful endpoints.
2) Pick a server implementation stack
Common choices:
- TypeScript/Node.js: very common for MCP servers
- Python: also good, especially if your API tooling is Python-based
If you want the simplest route, use the official MCP SDK for your language.
3) Write a thin adapter around the REST API
Your MCP server should:
- Accept MCP requests
- Validate inputs
- Call the REST API
- Return structured results back to the client
Core responsibilities
- Authentication
- API key, OAuth token, service account, etc.
- Request shaping
- Convert MCP input into REST query/body/path params
- Response normalization
- Return concise JSON with useful fields
- Error handling
- Convert REST errors into MCP-friendly errors
- Pagination
- Handle
page,limit, cursors, etc.
- Handle
4) Example: mapping a REST endpoint to an MCP tool
Suppose your REST API has:
POST /tickets
{
"title": "Bug report",
"priority": "high"
}
You might expose an MCP tool:
- Name:
create_ticket - Input schema:
title(string, required)priority(string, optional)
The tool handler then calls the REST API endpoint and returns the new ticket data.
5) Example MCP server in Node.js
This is a simplified example using the MCP SDK pattern.
import express from "express";
import fetch from "node-fetch";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "rest-api-wrapper",
version: "1.0.0",
});
const API_BASE_URL = process.env.API_BASE_URL;
const API_TOKEN = process.env.API_TOKEN;
server.tool(
"get_ticket",
{
ticket_id: z.string(),
},
async ({ ticket_id }) => {
const res = await fetch(`${API_BASE_URL}/tickets/${ticket_id}`, {
headers: {
Authorization: `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
},
});
if (!res.ok) {
throw new Error(`API error: ${res.status} ${await res.text()}`);
}
const data = await res.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
);
server.tool(
"create_ticket",
{
title: z.string(),
priority: z.enum(["low", "medium", "high"]).optional(),
},
async ({ title, priority }) => {
const res = await fetch(`${API_BASE_URL}/tickets`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ title, priority }),
});
if (!res.ok) {
throw new Error(`API error: ${res.status} ${await res.text()}`);
}
const data = await res.json();
return {
content: [
{
type: "text",
text: JSON.stringify(data, null, 2),
},
],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
6) Add resources for read-only endpoints
If the REST API is mostly data retrieval, use MCP resources where appropriate.
Example:
resource://ticket/{id}→ reads fromGET /tickets/{id}
This can be helpful when the client wants to inspect data without “calling a tool.”
7) Generate tools from OpenAPI if available
If your REST API has an OpenAPI spec, you can automate a lot:
- Parse paths and operations
- Create tool schemas from request bodies/parameters
- Generate a tool wrapper for each endpoint or a curated subset
This is often the fastest way to bootstrap an MCP server for a large API.
Recommended strategy
- Start with a manually curated list of high-value operations
- Later automate more endpoints from OpenAPI
- Keep the tool names clean and model-friendly
8) Be careful with tool design
Good MCP tools should be:
- Small and specific
- Named clearly
- Input-validated
- Return structured output
- Safe by default
Avoid:
- One giant
call_apitool that accepts arbitrary URLs - Exposing destructive actions without safeguards
- Returning huge raw payloads unless necessary
9) Handle auth and secrets properly
Common patterns:
- Store API credentials in environment variables
- Support per-user auth if the downstream REST API is user-specific
- Never expose secrets in tool outputs
- Redact sensitive fields from responses
If the API uses OAuth:
- Your MCP server may need to act as an OAuth client or proxy tokens from the host environment.
10) Test your server with an MCP client
Test with:
- Claude Desktop
- Another MCP-compatible client
- Local debugging logs
Check:
- Tool discovery works
- Input schemas are correct
- Responses are useful to the model
- Errors are understandable
- Pagination and rate limits behave well
11) Production tips
- Add timeouts and retries for REST calls
- Cache stable GET requests if appropriate
- Limit response size
- Log requests carefully, without leaking secrets
- Rate-limit if the downstream API has limits
- Version your MCP server as the REST API changes
12) A simple build checklist
- Document REST endpoints
- Choose which endpoints to expose
- Define MCP tools/resources
- Implement REST wrapper handlers
- Add schema validation
- Add auth and error handling
- Test with an MCP client
- Deploy and monitor
If you want a faster route
If you already have an OpenAPI spec, I can help you:
- turn it into an MCP server design,
- generate the tool definitions,
- or write a starter implementation in Python or TypeScript.
If you share a sample REST API spec or a few endpoints, I can sketch the exact MCP mapping.
Observation history
See 1 earlier observation
Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.
How did Obsurfable measure this prompt?
Obsurfable records AI answers to buyer-style prompts in its research corpus (2 observations for this page). Metrics are distributions over observations, not a single static ranking.
Which AI systems does Obsurfable collect answers from?
OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.