Back to Blog
Development

Wrap Existing APIs as MCP Tools (Simple Guide)

December 20, 20256 min readBy Nikhil Tiwari

One of the most common MCP use cases is wrapping existing APIs so AI clients can safely and reliably call them.

Instead of letting AI "guess" how to use an API, you expose clean MCP tools with strict inputs and predictable outputs.

This guide shows how to wrap a REST API using Node.js + MCP.

What Does "Wrap an API" Mean?

It means:

  • You already have an API (internal or external)
  • MCP acts as a thin, safe layer
  • AI calls MCP tools
  • MCP tools call your API
  • MCP returns structured results

AI never talks to your API directly.

Example Use Cases

  • Wrap a SaaS API
  • Wrap an internal microservice
  • Wrap a database-backed HTTP endpoint
  • Wrap third-party APIs (Stripe, GitHub, weather, etc.)

Basic Setup

Assuming you already have an MCP server running.

Install Axios (or use fetch):

npm install axios

Step 1: Decide What the Tool Should Do

Bad idea ❌

"Expose the whole API"

Good idea ✅

"Expose one clear action"

Example:

  • getUserById
  • createOrder
  • fetchWeather

One tool = one responsibility.

Step 2: Create a Simple API Wrapper Tool

Example: GET user from an API

import axios from "axios";
import { z } from "zod";

server.tool(
  "getUser",
  {
    userId: z.string(),
  },
  async ({ userId }) => {
    const response = await axios.get(
      `https://api.example.com/users/${userId}`
    );

    return {
      id: response.data.id,
      name: response.data.name,
      email: response.data.email,
    };
  }
);

Why this works well

  • Input is validated
  • Output is controlled
  • AI gets only what it needs

Step 3: Never Return Raw API Responses

Avoid this ❌

return response.data;

Instead, shape the output:

return {
  id: response.data.id,
  status: response.data.status,
};

This keeps your MCP contract stable even if the API changes.

Step 4: Handle API Errors Properly

Always assume the API can fail.

server.tool(
  "getUser",
  {
    userId: z.string(),
  },
  async ({ userId }) => {
    try {
      const response = await axios.get(
        `https://api.example.com/users/${userId}`
      );

      return {
        id: response.data.id,
        name: response.data.name,
      };
    } catch (error) {
      throw new Error("Failed to fetch user");
    }
  }
);

Keep error messages:

  • Short
  • Deterministic
  • Non-leaky (no secrets, no stack traces)

Step 5: Wrapping POST APIs

Example: Create a user

server.tool(
  "createUser",
  {
    name: z.string(),
    email: z.string().email(),
  },
  async ({ name, email }) => {
    const response = await axios.post(
      "https://api.example.com/users",
      { name, email }
    );

    return {
      userId: response.data.id,
      created: true,
    };
  }
);

AI doesn't care about HTTP status codes. It cares about clear success signals.

Step 6: Add Auth (API Keys, Tokens)

Never hardcode secrets.

const api = axios.create({
  baseURL: "https://api.example.com",
  headers: {
    Authorization: `Bearer ${process.env.API_TOKEN}`,
  },
});

Then reuse it in tools.

Step 7: Keep MCP Thin

MCP should:

  • Validate inputs
  • Call the API
  • Shape the output

Business logic should live outside MCP when possible.

Think:

MCP = adapter, not brain

Example Folder Structure

my-mcp-server/
├── index.js
├── api/
│   └── users.js
├── tools/
│   └── getUser.js
├── package.json

This keeps things clean as tools grow.

Best Practices (Short & Practical)

✅ Do

  • One API call per tool
  • Small response objects
  • Stable output fields
  • Clear error messages

❌ Avoid

  • Returning raw API payloads
  • Optional or inconsistent output fields
  • Chaining many API calls in one tool
  • Letting AI decide API parameters freely

When to Create Multiple Tools

Create separate tools if:

  • Inputs are very different
  • Permissions differ
  • Failure modes differ

Example:

  • getUser
  • updateUser
  • deleteUser

Clear beats clever.

Final Thought

Wrapping APIs with MCP is about control.

You're not making APIs "AI-friendly" by being flexible — you're making them AI-safe by being strict.

If a human can misuse an API, an AI definitely will. MCP is how you prevent that.

Ready to test your MCP server? Test it now on MCP Playground →

NT

Nikhil Tiwari

15+ years of experience in product development, AI enthusiast, and passionate about building innovative solutions that bridge the gap between technology and real-world applications. Specializes in creating developer tools and platforms that make complex technologies accessible to everyone.