# Wrap Existing APIs as MCP Tools (Simple Guide)

> Learn how to wrap existing REST APIs as MCP tools so AI clients can safely and reliably call them. This guide shows you how to create a thin, safe layer between AI and your APIs using Node.js + MCP.

**Source:** https://mcpplaygroundonline.com/blog/wrap-existing-apis-as-mcp-tools-simple-guide  
**Author:** Nikhil Tiwari  
**Published:** 2025-12-20  
**Category:** Development  
**Reading time:** 6 min read

---

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 →](/mcp-test-server)

---

_Canonical page: https://mcpplaygroundonline.com/blog/wrap-existing-apis-as-mcp-tools-simple-guide — MCP Playground (mcpplaygroundonline.com), the free browser-based tool for testing MCP servers and building AI agents._
