Prompt

How do I build an MCP server from an existing REST API?

Technology · Developer Tools / Developer tools2 observationsLast seen Jul 15, 2026

Latest observation

Jul 15, 2026 · OpenAI APIWeb search: off

To build an MCP server from an existing REST API, the basic idea is:

  1. Inspect your REST API
  2. Map API capabilities to MCP tools/resources/prompts
  3. Implement an MCP server that translates MCP calls into REST requests
  4. Add auth, validation, and error handling
  5. 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 GET endpoints.
  • Prompts: reusable prompt templates, optional and not usually needed for a straight API wrapper.

Good mapping examples

  • GET /users/{id} → resource or tool like get_user
  • GET /tickets?status=open → tool like list_tickets
  • POST /tickets → tool like create_ticket
  • PATCH /tickets/{id} → tool like update_ticket
  • DELETE /tickets/{id} → tool like delete_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.

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 from GET /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_api tool 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

  1. Document REST endpoints
  2. Choose which endpoints to expose
  3. Define MCP tools/resources
  4. Implement REST wrapper handlers
  5. Add schema validation
  6. Add auth and error handling
  7. Test with an MCP client
  8. 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.