ReleasePad
A blueprint-style diagram of an MCP server wiring a changelog feed into Claude, Cursor, and other AI tools.
Guide

How to Build an MCP Server for Your Changelog: A Step-by-Step Guide

Felix Macx · · 9 min read

Your changelog is structured data behind a webpage. An MCP server flips that — exposing the same data through a protocol that Claude, Cursor, and other AI tools natively understand. Here’s how to build one, step by step.

TL;DR

  • MCP (Model Context Protocol) is the open standard AI tools use to fetch external data; an MCP server for your changelog lets agents query it directly.
  • You need three things: a structured changelog feed (JSON), an MCP server wrapping that feed (Node or Python, ~150 lines), and a deployment target.
  • Expose at minimum two tools: list_releases (with filters) and get_release (by ID). That covers most agent use cases.
  • Total build time: half a day to a day for a working server; another day for polish, auth, and deployment.

An MCP server is a small service that speaks the Model Context Protocol, exposing tools and resources to AI clients through a stable, typed interface — instead of forcing the AI to scrape your HTML or guess from training data.


If you’ve already exposed your changelog as a structured feed, an MCP server is the natural next step. It takes the same underlying data and makes it queryable by AI tools the way a database is queryable by a backend — with a defined schema, typed parameters, and predictable responses.

This post walks through building one end to end. No prior MCP experience required. By the time you’re done, Claude, Cursor, and any other MCP-compatible tool will be able to answer questions about your product using fresh, accurate data straight from your changelog.

What an MCP Server Actually Does

Strip away the protocol details and an MCP server does three things:

  1. Advertises tools — it tells the AI client “here are the functions I expose, here are their parameters, here’s what they return.”
  2. Executes tool calls — the AI client invokes a tool with arguments, the server runs the logic, and returns structured data.
  3. Speaks the MCP wire format — JSON-RPC over stdio or HTTP/SSE.

For a changelog, the tools you expose are simple read operations. There’s no write path. Most of the complexity is in the protocol plumbing, and the SDK handles that for you.

The Architecture in One Diagram

┌──────────────┐     MCP      ┌──────────────┐    HTTPS    ┌─────────────────┐
│ Claude/Cursor│ ───────────▶ │  MCP Server  │ ──────────▶ │ Changelog Feed  │
│ (AI Client)  │ ◀─────────── │ (your code)  │ ◀────────── │ (JSON / DB / MD)│
└──────────────┘   JSON-RPC   └──────────────┘             └─────────────────┘

Three layers. The AI client speaks MCP to your server. Your server speaks HTTPS to your existing changelog feed (or directly to your database). The server is the translation layer.

If you don’t have a structured feed yet, start there. It’s the prerequisite. The MCP server is a thin wrapper; the feed is the source of truth.

Step 1: Define Your Tools

Before writing code, decide what tools your MCP server will expose. For a changelog, two are usually enough:

list_releases — return recent changelog entries.

  • Parameters: since (ISO date, optional), type (one of feature/fix/breaking/etc., optional), limit (int, default 20)
  • Returns: array of { id, published_at, title, summary, type, url }

get_release — return one entry in full.

  • Parameters: id (string, required)
  • Returns: full entry including body (markdown), tags, breaking_changes, etc.

Optional third tool worth adding:

search_releases — keyword search over the changelog.

  • Parameters: query (string, required), limit (int, default 10)
  • Returns: array of matches with relevance score.

Don’t expose more than 3–5 tools. AI clients pick from your tool list based on the user’s question; too many tools confuse the selection and waste context tokens.

Step 2: Set Up the Project

We’ll use the TypeScript SDK. The Python flow is nearly identical — the patterns transfer.

mkdir changelog-mcp && cd changelog-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript tsx @types/node
npx tsc --init

Create src/index.ts:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "changelog-mcp", version: "0.1.0" },
  { capabilities: { tools: {} } }
);

Boilerplate done. You have a server object; now we register tools.

Step 3: Register the Tools

Add the tool list handler:

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "list_releases",
      description:
        "List recent changelog entries for the product. Supports filtering by date and type.",
      inputSchema: {
        type: "object",
        properties: {
          since: { type: "string", description: "ISO date — only entries after this" },
          type: {
            type: "string",
            enum: ["feature", "fix", "improvement", "breaking", "deprecation"],
          },
          limit: { type: "number", default: 20 },
        },
      },
    },
    {
      name: "get_release",
      description: "Fetch a single changelog entry in full by its stable ID.",
      inputSchema: {
        type: "object",
        properties: { id: { type: "string" } },
        required: ["id"],
      },
    },
  ],
}));

The description field is the most important part. AI clients read it when deciding which tool to call. Write it like you’d write a function docstring for a teammate — clear, specific, unambiguous about what the tool does and when to use it.

Step 4: Implement the Tool Logic

Now the actual handlers. We’ll fetch from a JSON feed at https://yoursite.com/changelog.json — replace with your real feed URL or query your database directly.

const FEED_URL = "https://yoursite.com/changelog.json";

async function fetchFeed() {
  const res = await fetch(FEED_URL);
  return res.json() as Promise<Release[]>;
}

type Release = {
  id: string;
  published_at: string;
  title: string;
  summary: string;
  type: string;
  url: string;
  body?: string;
  tags?: string[];
};

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "list_releases") {
    const all = await fetchFeed();
    let filtered = all;

    if (args?.since) {
      filtered = filtered.filter((r) => r.published_at >= args.since);
    }
    if (args?.type) {
      filtered = filtered.filter((r) => r.type === args.type);
    }
    filtered = filtered.slice(0, args?.limit ?? 20);

    return {
      content: [{ type: "text", text: JSON.stringify(filtered, null, 2) }],
    };
  }

  if (name === "get_release") {
    const all = await fetchFeed();
    const entry = all.find((r) => r.id === args?.id);
    if (!entry) {
      return {
        content: [{ type: "text", text: `No release found with id ${args?.id}` }],
        isError: true,
      };
    }
    return { content: [{ type: "text", text: JSON.stringify(entry, null, 2) }] };
  }

  return {
    content: [{ type: "text", text: `Unknown tool: ${name}` }],
    isError: true,
  };
});

Add the transport and boot:

const transport = new StdioServerTransport();
await server.connect(transport);

Run it:

npx tsx src/index.ts

It’s now a working local MCP server. You can connect Claude Desktop to it by adding to your claude_desktop_config.json:

{
  "mcpServers": {
    "changelog": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/changelog-mcp/src/index.ts"]
    }
  }
}

Restart Claude Desktop and ask: “What’s new in the changelog this week?” — it’ll call list_releases and answer with real data.

Step 5: Switch to Remote Transport for Production

The stdio transport above only works locally. For a public changelog, you want a remote HTTP/SSE server users can connect to without running your code on their machine.

Swap the transport:

import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";

const app = express();
const transports = new Map<string, SSEServerTransport>();

app.get("/sse", async (req, res) => {
  const transport = new SSEServerTransport("/messages", res);
  transports.set(transport.sessionId, transport);
  res.on("close", () => transports.delete(transport.sessionId));
  await server.connect(transport);
});

app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  const transport = transports.get(sessionId);
  if (!transport) return res.status(404).send("No session");
  await transport.handlePostMessage(req, res);
});

app.listen(3000);

Deploy this anywhere that runs Node — Vercel, Fly.io, Cloudflare Workers (with Node compat), a Docker container behind your existing reverse proxy. Memory usage is negligible because the server is stateless; each request fetches the feed and returns a slice.

Step 6: Add Caching

The feed doesn’t change every second. Add a 60-second cache to avoid hammering your origin:

let cache: { data: Release[]; expires: number } | null = null;
const TTL_MS = 60_000;

async function fetchFeed() {
  if (cache && Date.now() < cache.expires) return cache.data;
  const res = await fetch(FEED_URL);
  const data = (await res.json()) as Release[];
  cache = { data, expires: Date.now() + TTL_MS };
  return data;
}

For high-traffic changelogs, bump TTL to 5 minutes. The freshness vs. load tradeoff is forgiving here because changelog data changes on the order of hours, not seconds.

Step 7: Publish a Connection Snippet

Make installation a one-liner. On your changelog page, add a section like:

Connect this changelog to your AI tool — add to your Claude Desktop config:

{ "mcpServers": { "yourproduct": { "url": "https://yoursite.com/mcp" } } }

Discoverability is half the value of running an MCP server. If users don’t know it exists, no one connects.

Common Pitfalls

Tool descriptions that are too vague. “Get changelog data” is useless. “List recent product changelog entries, optionally filtered by date or change type (feature, fix, breaking, etc.)” is specific enough for the AI to know when to call it.

Returning huge payloads. AI context windows are constrained. Default limit to 10–20 and let callers ask for more explicitly. Truncate entry bodies in list_releases; return full bodies only from get_release.

Forgetting the type field on entries. Without typed entries, you lose half the value of the API. Type your entries at the source.

Silently failing on bad input. Return clear isError: true responses with a human-readable explanation. The AI client will surface that to the user and recover gracefully.

Skipping rate limits. Even a public, unauthenticated server needs basic rate limiting (e.g., 60 req/min per IP). MCP clients can be chatty, especially when an agent is exploring.

What This Unlocks

Once your MCP server is live and discoverable, three things become possible that weren’t before:

  1. Accurate product Q&A in AI tools. When a developer asks Cursor “does this library support X?”, the assistant gets ground truth from your changelog instead of hallucinating.
  2. Agent-driven dependency monitoring. Autonomous agents can subscribe to your changelog via MCP, alerting their owners about breaking changes the moment you publish them.
  3. First-party presence in AI ecosystems. As MCP registries mature (Anthropic, vendor-specific, community), products with MCP servers will be the ones AI tools surface natively. Products without one will be invisible.

The build cost is one engineer-day. The strategic cost of not having one — over the next 12–18 months — is much higher.


ReleasePad ships with a structured changelog feed and an MCP endpoint out of the box. Connect your GitHub repo, and your changelog is available to Claude, Cursor, and any MCP-compatible tool from day one — no protocol code to write. Try it free →


Further Reading

Frequently Asked Questions

What is an MCP server for a changelog?

An MCP (Model Context Protocol) server is a small program that exposes your changelog to AI tools like Claude and Cursor through a standardized interface. Instead of the AI scraping your HTML page or guessing from stale training data, it asks the MCP server for your latest releases, gets structured JSON back, and uses that to answer user questions accurately. It's the cleanest way to make your changelog first-class data for AI agents.

Do I need an MCP server if I already have a JSON or RSS feed?

A structured feed is the prerequisite — MCP sits on top of it. The feed lets any client fetch your changelog; the MCP server adds discoverability, typed tool definitions, and authentication so AI tools can integrate with one click. If you only have time for one thing, build the feed first. If you want AI assistants to surface your product accurately in their native tool registries, add MCP next.

What language should I write my MCP server in?

TypeScript and Python are the two most-supported SDKs today, both maintained by Anthropic. TypeScript is the natural fit if your stack is JavaScript-based; Python is ideal for data/ML-heavy teams. Both produce functionally identical servers. Pick the one your team already runs in production so you can deploy it on existing infrastructure.

How do I host an MCP server?

MCP servers can run locally (stdio transport, for desktop AI tools) or as HTTP/SSE endpoints (for remote, cloud-hosted use). For a public changelog, you want the remote HTTP variant — deploy it like any small Node or Python service: Vercel, Cloudflare Workers, Fly.io, or a Docker container behind your existing load balancer. Memory and CPU requirements are minimal because the server is just a thin wrapper over your changelog feed.

Does an MCP server need authentication?

For a public-facing changelog, no — the same content is already visible on your website, so the MCP endpoint should be open. For internal changelogs or paid-tier release notes, yes — use bearer tokens or OAuth, both supported by the MCP spec. Most public changelog MCP servers are unauthenticated and rate-limited at the HTTP layer, which is the right default.

How do users connect their AI tool to my MCP server?

For Claude Desktop, users add your server URL to their MCP configuration file (claude_desktop_config.json) and restart. For Cursor and other tools, the flow is similar — a configuration entry pointing at your server. Make this easy by publishing a one-line install snippet on your changelog page so users can copy-paste it into their tool's config in seconds.

mcp model-context-protocol changelog ai-agents integration

Ready to put this into practice?

Your changelog shouldn't be an afterthought.

ReleasePad makes it easy to publish great release notes — from a public changelog page to an in-app widget, GitHub integration, and analytics. Free to get started.

Get started — it's free
Try me now!