From the team

MCP: Did Anthropic simply reinvent OpenAPI?

If you already have a good API, MCP should be a one-line change.

April 9, 2026

APIs keep getting renamed.

First it was XML and SOAP. Then RPC. Then REST. Now it is "MCP servers".

Some of the packaging changes. Some of the transport changes. Some of the surrounding tooling improves. But the core idea is the same: define capabilities clearly, describe the inputs precisely, and expose them in a way another machine can call reliably.

That is why the MCP hype feels a little funny. When Anthropic announced the Model Context Protocol, the first thing that stood out to me was not the protocol itself. It was the name.

Model Context Protocol is such an unnecessarily complicated phrase for something that is, in many cases, just a way to expose already well-defined backend capabilities to AI clients.

An MCP server is not some radically new class of software. In many cases it is a glorified name for something we already know how to build well: an API with good schemas, good descriptions, and predictable behavior.

The useful part is not the rebranding. The useful part is that MCP gives AI clients a shared convention for discovering tools and calling them remotely.

If your API is already well-designed, that should not require a rewrite.

We already solved most of this once

For years, the hard part of API design has not been "how do I return JSON over HTTP?"

The hard part has been everything around it:

  • Naming operations consistently
  • Defining inputs and outputs clearly
  • Validating payloads
  • Documenting behavior
  • Making the contract discoverable to other systems

OpenAPI already gave us a standard way to do that. A good OpenAPI document tells machines and humans almost everything they need to know: what operations exist, what they are called, what parameters they accept, and what shape the data takes.

So when people talk about "turning an app into an MCP server", the underlying reality is often much less dramatic than it sounds. If you already have well-structured endpoints and clean OpenAPI metadata, you are not building a whole new system. You are adding another interface on top of the same contract.

This should be much simpler

If you already have a clear API with good schemas and descriptions, converting it into something agents can consume should be almost trivial.

You should not need to rewrite routes, duplicate schemas, or maintain a second definition of the same capability just because the consumer is now an agent instead of a frontend or another backend service.

Elysia is just a good example of what this looks like in practice, because a lot of the useful metadata already lives where it should:

  • Route handlers define the behavior
  • Schemas define the inputs / outputs including metadata like description
  • OpenAPI metadata describes the operation and gives it a stable name

If you care about OpenAPI quality, you are probably already writing that metadata today, whether you are using Elysia or not.

So instead of manually re-registering everything as separate MCP tools, duplicating schemas, and rewriting handlers, you should be able to use what is already there.

Start with a normal API:

import { Elysia, t } from "elysia";
import { openapi } from "@elysiajs/openapi";

const app = new Elysia()
  .use(openapi())
  .get("/users/:id", ({ params }) => db.users.find(params.id), {
    params: t.Object({
      id: t.String({ description: "The user's unique ID" }),
    }),
    detail: {
      operationId: "get_user",
      summary: "Fetch a user by ID",
    },
  })
  .patch("/users/:id", ({ params, body }) => db.users.update(params.id, body), {
    params: t.Object({
      id: t.String({ description: "The user's unique ID" }),
    }),
    body: t.Object({
      name: t.Optional(t.String({ description: "The user's display name" })),
      email: t.Optional(t.String({ description: "The user's email address" })),
    }),
    detail: {
      operationId: "update_user",
      summary: "Update a user",
    },
  })
  .listen(3000);

The one-line change

Since you already have a clear API with good metadata, the conversion should be close to a one-line change. The existing route stays the source of truth.

Now just add one line to expose a POST /mcp endpoint:

import { mcp } from "@8monkey/elysia-mcp";

const app = new Elysia().use(openapi()).use(mcp());
// ...the rest of the route stays the same

The plugin is available at 8monkey-ai/elysia-mcp, all code was written by Claude itself.

From there, the same routes that already power your HTTP API can also be discovered and called as MCP tools. get_user and update_user are derived from the route metadata. Parameter descriptions come from the same schema fields you wrote for documentation. There is no second handler to maintain and no second schema to keep in sync.

And once that MCP layer exists, the same API can plug into tools like ChatGPT, Claude, Cursor, and other MCP-compatible clients without inventing a custom integration for each one.

MCP becomes boring, which is good

This is the part that the ecosystem keeps overcomplicating.

We keep inventing bigger words for smaller ideas. "Agents". "Tools". "MCP servers". "AI-native interfaces". Most of the time, what people actually mean is much simpler: an operation has a schema, a description, and another system should be able to call it reliably.

That should not require a second architecture or a new layer of ceremony. It should just be another interface over the same capability: same route, same schema, same business logic.

That is why I think the term "MCP server" gets overstated. In many teams, once you strip away the buzzwords, what people really need is:

  1. A well-designed API
  2. Good schema metadata
  3. A standard agent-facing transport

If you already have the first two, the third should not be expensive.

A call to framework authors

This should get easier everywhere.

Not just in Elysia. Not just in TypeScript. Not just in Bun.

Frameworks in every language should make this almost automatic. If a framework already has routing, schemas, validation, and OpenAPI metadata, exposing that same surface to MCP should feel like enabling another transport, not starting another project.

The industry does not need more hand-written glue code, more duplicated tool definitions, or more marketing terms for the same old interface problem. It needs better defaults.

Make the clean path the easy path. Let people define an operation once, describe it once, and expose it everywhere.

← All blog posts