AI-generated image
AI

I Replaced Five API Wrappers With MCP in a Weekend

3 min read

I spent the first half of 2025 writing custom API wrappers so that AI models could talk to our internal tools. A wrapper for the marketing API, one for the sales dashboard, one for the JetBrains Marketplace stats, two more for deployment scripts. Every wrapper was slightly different. Every one broke when the tool’s API changed. And every time I wanted to connect a new AI client, I had to write the integration again.

Then Anthropic published the Model Context Protocol and I rewrote all five in a weekend.

MCP is a standard for connecting AI models to tools. Think of it like LSP - Language Server Protocol - but instead of giving an editor access to a compiler, you give an AI model access to databases, APIs, file systems, anything you can wrap in a function. Write one server, and any MCP-compatible client can use it. Claude Code, a JetBrains plugin, your own automation script - same server, no changes.

What a minimal server looks like

from mcp.server import Server
from mcp.types import TextContent

server = Server("my-tools")

@server.tool()
async def get_weather(city: str) -> list[TextContent]:
    """Get current weather for a city."""
    data = await fetch_weather_api(city)
    return [TextContent(
        type="text",
        text=f"Weather in {city}: {data['temp']}C, {data['condition']}"
    )]

if __name__ == "__main__":
    server.run()

The decorator registers the function. The type hints become the input schema. The docstring becomes the description. The SDK handles transport and error handling. That is genuinely it.

To connect it to Claude Code, you add it to .mcp.json:

{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["path/to/server.py"]
    }
  }
}

Restart the client, and the tools show up automatically.

What I learned after building several of these

Group related tools in one server. Our marketing server has 22 tools - queue management, content validation, channel publishing. One process, one connection, one place to maintain. The temptation is to make one server per tool, but that is a lot of processes for no reason.

Return structured data, not prose. The model decides how to present it. Your server returns clean JSON or structured text. I made the mistake early on of having a tool return a formatted summary, and then the model would reformat it, and the result was worse than if I had just returned the raw data.

Rate-limit on the server side. Models are enthusiastic. They will call your tools in rapid succession if you let them. I added a simple sliding-window rate limiter to our marketing server after it tried to publish 40 posts in 90 seconds. Glad I had shadow mode on that day.

Handle errors as text, not exceptions. The model can work with “API returned 429, try again in 60 seconds” much better than a stack trace. Return error messages as content and let the model figure out what to do.

Where we ended up

Slaide has an MCP server and an Agent Skill, so any AI agent can author a presentation by writing a text file. Smart Inference uses MCP for routing visibility. Our marketing system runs 22 tools through one server.

The honest part: MCP is still young. The TypeScript SDK is more mature than the Python one. Documentation is sparse in places. And not every AI client supports it yet, though adoption is moving fast.

It took me a weekend to rewrite five integrations. Those five had cost me months. Sometimes standards arrive at exactly the right time.