All field notes

How to Expose an Existing REST API to Claude or ChatGPT via MCP

You already have a REST API. You want Claude or ChatGPT to use it. Here is the cleanest path that does not require rewriting anything.

On this page6 sections
  1. 01Architecture
  2. 02Step 1: Pick the endpoints
  3. 03Step 2: Write the wrapper
  4. 04Step 3: Handle auth properly
  5. 05Step 4: Trim responses for the model
  6. 06Step 5: Test it before pointing a model at it

You already have a working REST API. You want Claude or ChatGPT to use it. Here's the cleanest path that doesn't require rewriting anything.

Architecture

You're going to build a thin MCP server that wraps your REST API. The MCP server takes tool calls from the model, translates each into an HTTP request to your existing API, and returns the response.

Claude → MCP server (you build this) → your REST API → your DB

This means:

  • Your API stays untouched
  • Auth, rate limits, and validation stay where they are
  • You decide which subset of endpoints the model gets

Step 1: Pick the endpoints

Don't expose everything. Pick the 3 to 8 operations that are useful in a chat context. A good starter set:

  • search_X: read-only, returns small results
  • get_X: fetch one record by id
  • create_X: write, but easy to undo
  • summarize_recent_X: aggregation

Skip anything destructive on the first cut.

Step 2: Write the wrapper

For each endpoint, create one MCP tool. The tool description should explain when to use it, not just what it does:

server.tool(
  "search_orders",
  "Find recent orders by customer email. Use when the user asks about a specific customer's purchase history. Returns up to 20 orders, newest first.",
  z.object({
    email: z.string().email(),
    limit: z.number().int().min(1).max(20).default(10),
  }),
  async ({ email, limit }) => {
    const r = await fetch(
      `${API}/orders?email=${encodeURIComponent(email)}&limit=${limit}`,
      { headers: { Authorization: `Bearer ${process.env.API_TOKEN}` } }
    );
    const data = await r.json();
    return { content: [{ type: "text", text: JSON.stringify(data) }] };
  }
);

Step 3: Handle auth properly

Two options:

  • Service token. The MCP server holds a token with limited scope and acts as a single user. Easy. Right for internal use.
  • Per-user token. The user passes their token via the MCP client config. Right for products where users have their own data.

Don't pass the model a token. It will leak it into responses.

Step 4: Trim responses for the model

Models pay per token. A 50KB JSON blob is wasteful and often unhelpful. Pick the fields a chat user actually cares about and drop the rest:

const trimmed = data.orders.map((o) => ({
  id: o.id,
  total: o.total,
  status: o.status,
  created: o.created_at,
}));

Step 5: Test it before pointing a model at it

Run every tool through PreMan with realistic inputs. Confirm the response is small, well-shaped, and useful as plain text. The cheapest debugging is the kind that doesn't require burning model tokens.

→ Wrap your REST API into an MCP in PreMan

Bring the loop to your API

Catch the regression. Open a verified fix.

Join the waitlist to see which users a release may affect, monitor endpoints in production, and prepare a reviewable fix PR when something breaks.