How I Turned a REST API into an MCP Server

RDRajesh Dhiman
5 min read

πŸ› οΈ How I Turned a REST API into an MCP Server (And Why You Should Too)

πŸ” Introduction: Turning a Fast Food Joint into Fine Dining

Let’s say you walk into a fast food restaurant. You shout, β€œOne burger!” and they toss it to you in under 30 seconds. Quick, dirty, and done. That’s your typical REST API: fast, unstructured, and a little unpredictable.

But what if you wanted to open a high-end place β€” where every dish has a printed menu, the ingredients are verified, and the chef follows a consistent recipe? That’s what Modular Contract Protocols (MCPs) are like. They don’t just serve data; they serve it with structure, clarity, and a smile.

In this post, I’ll show you exactly how I wrapped the public Hacker News API in an MCP β€” turning a chaotic data stream into a clean, LLM-friendly microservice.


🧠 Wait... What’s an MCP Again?

Let me break it down:

MCP stands for Modular Contract Protocol. It’s a way of writing API logic where every endpoint:

  • Has a clear input and output contract
  • Is modular and self-contained
  • Can be called by humans, machines, or LLMs
  • Plays nicely in a function-calling world (like OpenAI or Claude)

In simple terms: it's like giving every API endpoint its own resume. It knows who it is, what it accepts, and what it gives back.


πŸ”₯ Why Wrap an Existing API?

I wanted to showcase how powerful MCPs are by not building everything from scratch. Instead, I took the Hacker News API β€” a basic REST interface with zero documentation, no validation, and no structure β€” and made it:

  • 🌱 Type-safe with Zod
  • πŸ€– Callable by LLM agents
  • πŸ“œ OpenAPI-exportable via zod-openapi
  • 🌍 Deployable & reusable

You get all the benefits of modern, clean backend architecture β€” without rebuilding the wheel.


🚧 Step 1: Picking the API

I went with Hacker News API. Why?

  • It’s public and requires no authentication
  • It returns JSON (yay!)
  • It’s a little raw β€” making it perfect for a glow-up

Hacker News gives you endpoints like:

  • /topstories.json β†’ returns an array of story IDs
  • /item/{id}.json β†’ returns the details for a story or comment

But there’s no validation. No input schema. No docs. Just vibes.


🧱 Step 2: MCP Project Structure

I set up the project with this simple folder structure:

src/
β”œβ”€β”€ contracts/                // Zod + OpenAPI metadata
β”œβ”€β”€ resolvers/                // Business logic
β”œβ”€β”€ handlers/                 // Express routes
β”œβ”€β”€ utils/                    // Hacker News client
β”œβ”€β”€ docs/openapi.ts           // OpenAPI spec generator (zod-openapi)
β”œβ”€β”€ setup/zod-openapi-init.ts // Shared zod setup with OpenAPI support
└── server.ts                 // Main entry point 

Think of it like building with LEGO blocks β€” every piece does one thing, and snaps into place without duct tape.


πŸ§ͺ Step 3: Creating the First Contract

Let’s start with the endpoint to list top stories.

βœ… Zod Contract

export const listTopStoriesOutput = z.array(z.number()).openapi({
  description: "Array of Hacker News story IDs",
});
 

It’s like saying: β€œHey, this endpoint gives back an array of numbers. No more, no less.”


βš™οΈ Step 4: Writing the Resolver

The resolver is the actual brain. It connects to Hacker News, fetches the data, and validates it.

import { fetchTopStoryIds } from "../utils/hnClient";
import { listTopStoriesOutput } from "../contracts/listTopStories.contract";

export const listTopStoriesHandler = async (req, res) => {
  try {
    const storyIds = await fetchTopStoryIds();
    res.json(listTopStoriesOutput.parse(storyIds));
  } catch (e) {
    res.status(500).json({ error: "Something went wrong!" });
  }
};
 

πŸ“– Step 5: Adding the getStory Endpoint

This one lets you fetch details about any story by ID.

βœ… Input Contract

export const getStoryInput = z
  .object({
    id: z
      .string()
      .regex(/^[0-9]+$/)
      .openapi({ description: "Story ID" }),
  })
  .openapi({ title: "GetStoryInput" });
 

βœ… Output Contract

export const getStoryOutput = z
  .object({
    id: z.number().openapi({ description: "ID of the story" }),
    title: z.string().openapi({ description: "Title of the story" }),
    by: z.string().openapi({ description: "Author" }),
    score: z.number().openapi({ description: "Score or points of the story" }),
    url: z.string().optional().openapi({ description: "URL (if any)" }),
    time: z.number().openapi({ description: "Unix timestamp" }),
    type: z.string().openapi({ description: "Item type (story/comment)" }),
  })
  .openapi({ title: "GetStoryOutput" });
 

πŸš€ Step 6: Hosting + OpenAPI + LLM Ready

After writing the resolvers, I hosted the whole thing here:

πŸ”— https://mcp-news-server.onrender.com

Test it:

  • /api/listTopStories
  • /api/getStory/8863
  • /openapi.json

And yes, it works with LangChain, Claude, OpenAI, or any custom LLM runner!


🎁 What You Can Do Next

  • Wrap any REST API you love in an MCP
  • Add contracts, deploy, and share with LLMs
  • Use zod-openapi to create swagger-compatible specs
  • Register it in an agent-aware toolchain or build your own GPT plugin

πŸ’¬ TL;DR

Modular Contract Protocols give your API structure and meaning. By wrapping a basic REST API like Hacker News with Zod contracts and generating OpenAPI with zod-openapi, you can:

  • Build more robust backend tools
  • Make them compatible with LLMs
  • Reduce guesswork and increase composability

Let’s stop building brittle REST services β€” and start building smart, structured, machine-readable APIs.

πŸ’‘ Try it yourself β€” and let me know what you wrap next!

Share this article

Related Articles

A2A vs MCP: Agent Chatter vs Contract Clarity

Explore the key differences between Agent-to-Agent (A2A) communication and Modular Contract Protocols (MCP) β€” and why you need both to build powerful AI systems.

tRPC and the T3 Stack Explained: Why Type Safe Web Development Is the Future (2025 Guide)

Unlock the power of tRPC and the T3 Stack for modern web development in 2025. Discover how type safe APIs, modular architecture, and the latest trends like AI integration and Jamstack are transforming how developers build fast, scalable, and maintainable applications.

Is Your AI Website Invisible? A Complete SEO Guide for AI-Generated Sites

Your AI-built website might be invisible to Google. Learn the common SEO pitfalls of AI sites and how to fix them with this friendly, step-by-step guide.