Skip to main content
Glama
bytemonk-academy

Orders MCP server

MCP vs API: one orders service, two interfaces

Companion repo for the video "MCP vs API: why do we need MCP if REST already works?"

Clone it, run two commands, and do the same job twice. Once with a plain REST API. Once with an MCP server on top of it. Takes about 20 minutes.


What we are building

You run a small online store. Orders come in. Some get stuck and never ship. You want an AI agent to find the stuck ones and open a GitHub issue for each.

That is the whole example. One small, real job.

The first way, you give the agent your API docs and let it use curl. It has to figure out which endpoint to call, build a date filter for "more than 7 days", notice the response comes in pages, and convert cents to dollars.

The second way, you give it a tool called find_stale_orders that takes { older_than_days: 7 }.

Both call the same endpoint, GET /orders. The store does not change at all. What changes is who does the thinking: the agent, or your server.

                        ┌──────────────────────────────────┐
  Web frontend  ───────▶│                                  │
  Mobile app    ───────▶│   Orders service (Express)       │
  Microservice  ───────▶│   GET  /orders                   │
                        │   GET  /orders/:id               │
                        │   PATCH /orders/:id              │
                        └──────────────▲───────────────────┘
                                       │  plain HTTP, nothing AI specific
                        ┌──────────────┴───────────────────┐
  Claude Code   ───────▶│   Orders MCP server              │
  Cursor        ───────▶│   tool: find_stale_orders        │
  Codex         ───────▶│   input: { older_than_days: 7 }  │
                        └──────────────────────────────────┘

Your API is the door. MCP gives AI clients a standard handle to open it with.

The orders service never knows that Claude Code exists. The MCP server is just another HTTP client of your API. The only difference is that it describes itself in a way agents understand.


Related MCP server: OHMS

Try it in one minute

You need Node 20 or newer. Nothing else. No database, no API keys.

git clone https://github.com/bytemonk-academy/mcp-vs-api.git
cd mcp-vs-api
npm install
npm test

npm test runs 31 tests against both the REST API and the MCP server. If they pass, everything works and the rest is just you watching it happen.

Now start the service and leave it running:

npm run api

In a second terminal, look at the data:

npm run orders
  ID         CUSTOMER             STATUS      PLACED       DAYS  TOTAL
  ----------------------------------------------------------------------
  ORD-1001   Ada Lovelace         UNSHIPPED   2026-07-27   31    $129.00
  ORD-1002   Grace Hopper         UNSHIPPED   2026-08-03   24    $45.99
  ...

  Showing 20 of 24 matching orders.

  !! There are more. page.nextOffset = 20
     You have NOT seen all 24 orders.

Then ask it the question this whole demo is about:

npm run orders -- --stale=7

Eight orders. Same eight on any machine, at any time of day.


What is npm run orders?

It is a shortcut for curl.

It sends GET /orders to your API and prints the reply as a table instead of raw JSON. That is all it does. You can run the same request yourself:

curl "http://localhost:3000/orders"

You get the same data, just harder to read. The script is only there so you can check the data quickly. It is not part of the lesson. In Phase 1 the agent gets curl and the docs, nothing else.

It takes a few options:

npm run orders -- --stale=7             # unshipped for more than 7 days
npm run orders -- --status=UNSHIPPED    # filter by status
npm run orders -- --limit=5 --offset=5  # move through the pages by hand

Why the test data looks the way it does

There are 24 orders, kept in memory, with dates set relative to today. So there are always exactly 8 stale orders, whenever you clone this.

Three problems are put there on purpose, so you can see the difference yourself instead of taking the video's word for it:

  • The reply comes in pages. Ask for orders and you get 20 out of 24. Nothing in those 20 rows looks incomplete. An agent that stops at the first page gives a wrong answer and sounds sure about it.

  • Some old orders are cancelled. They look stale but they are not. If you filter on shippedAt instead of status, you count them by mistake.

  • Some orders sit just under the 7 day line. Count the days slightly wrong and you get a wrong total, not an error message.

The MCP server deals with all three in code, once, in src/mcp/server.ts. In the curl version, the agent has to get all three right every single time.


The exercise

Do these in order. Phase 1 before Phase 2 is the point, because the difference is the lesson.

Guide

What you do

Phase 1

docs/phase-1-rest-only.md

Give the agent your API docs, let it use curl, watch what it has to work out by itself

Phase 2

docs/phase-2-mcp.md

Turn on the Orders MCP server and GitHub's, run the same prompt again

After

docs/architecture.md

What changed, what did not, and when MCP is not worth it

Also here: the API reference you give the agent in Phase 1, prompts you can copy, and troubleshooting.

Phase 2 opens real GitHub issues, so use a test repo you do not mind filling up.


What is in here

src/
  data/orders.ts     The 24 test orders
  api/app.ts         The REST API. Knows nothing about MCP.
  api/server.ts      Starts it on a port.
  mcp/server.ts      The MCP server. Calls the REST API over HTTP.
scripts/orders.ts    The table viewer used above
clients/             Plain MCP clients, in Python and TypeScript
tests/               Tests for both halves
docs/                The walkthrough
.mcp.json            Claude Code reads this automatically
.cursor/mcp.json     Cursor reads this automatically

Three tools. Each one is a thin wrapper over an endpoint you already have:

Tool

Input

Calls

find_stale_orders

{ older_than_days: 7 }

GET /orders?status=UNSHIPPED&before=..., through every page

get_order

{ order_id: "ORD-1001" }

GET /orders/ORD-1001

mark_order_shipped

{ order_id: "ORD-1001" }

PATCH /orders/ORD-1001

src/mcp/server.ts is about 170 lines and most of it is comments. That is all an MCP server really is.


Seeing the protocol for yourself

Claude Code does nothing special here. It starts the server as a subprocess and sends JSON-RPC messages over stdin and stdout. clients/raw_mcp_client.py does the same thing by hand:

async with stdio_client(server) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        result = await session.call_tool("find_stale_orders", {"older_than_days": 7})

The same script then talks to GitHub's MCP server over HTTP to open the issues:

await session.call_tool("create_issue", {"owner": owner, "repo": name, "title": ...})

Same shape both times. One server is a Node process on your laptop. The other is run by GitHub. The client cannot tell them apart. That is the part worth remembering. There is a TypeScript version in clients/ if you would rather stay in one language.


Tests

npm test

31 tests. The MCP ones drive a real MCP client over stdio, the same way Claude Code does.

Worth reading if you plan to write your own server. They show what is actually worth checking: that every tool has a usable description and schema, that paging really works, that a 404 comes back as a tool error instead of a crash, and that cancelled orders stay out of the results.


Commands

npm run api        # REST API on :3000
npm run api:dev    # same, restarts when you edit a file
npm run orders     # print the orders as a table
npm run mcp        # run the MCP server directly (agents usually do this for you)
npm test           # the tests
npm run typecheck  # tsc --noEmit
npm run inspect    # MCP Inspector, to try the tools by hand

npm run inspect is the fastest way to see exactly what an agent sees: tool names, descriptions, and the input schema for each one.

The data is kept in memory, so restarting npm run api puts everything back to the start.


When is MCP worth it?

Phase 1 works. That is not a trick. A good agent will find the stale orders and open the issues using nothing but curl and your docs. MCP is not what makes the job possible.

What it changes is the shape of the integration. How to query your orders service now lives in one server, instead of in every agent's context window. The same capability works in Claude Code, Cursor, and Codex without writing a new integration for each one. And you choose which capabilities to expose, which is very different from handing over an API key.

What it does not change: authentication, authorization, validation, rate limiting, retries, and good service design are all still your job. An MCP server on top of a badly designed API is still a badly designed API.

Roughly, the value grows with the number of clients times the number of tools. One agent calling two functions you control? Skip it, just call the functions. Thirty tools across five teams and four clients? That is when a shared protocol starts to pay for itself. docs/architecture.md covers where the line sits.


MIT licensed. Use it in your own teaching, no credit needed.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables management of Shopify orders through the Admin REST API, allowing users to create new orders and retrieve order status details. It supports both local and remote access via SSE and STDIO transports for integration with MCP clients like Claude Desktop.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes Shopify order and inventory management tools via MCP, allowing agents to fetch, update, and print orders without exposing raw Shopify credentials.
  • F
    license
    A
    quality
    C
    maintenance
    Wraps a procurement REST API into MCP tools, enabling AI assistants to query purchase orders via natural language.
    2
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes order status lookup and knowledge base search tools from the Support Agent AI over MCP, enabling MCP clients to handle customer support queries with grounded, citation-backed answers.
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bytemonk-academy/mcp-vs-api'

If you have feedback or need assistance with the MCP directory API, please join our Discord server