Skip to main content
Glama
bytemonk-academy

Orders MCP server

MCP vs API: 一つの注文サービス、二つのインターフェース

動画 「MCP vs API: RESTがすでに動いているのに、なぜMCPが必要なのか」 の付属リポジトリです。

クローンして、2つのコマンドを実行し、同じ作業を2回行います。1回目は素のREST APIで。もう1回は その上にMCPサーバーを載せて。所要時間は約20分です。


作るもの

あなたは小さなオンラインストアを運営しています。注文が入ってきます。中には滞留して出荷されないものもあります。AIエージェントに 滞留した注文を見つけ出し、それぞれについてGitHub issueを開いてもらいたいとします。

それがこの例のすべてです。小さくて現実的な、一つの仕事です。

1つ目の方法では、エージェントにAPIドキュメントを渡し、curlを使わせます。エージェントは どのエンドポイントを呼ぶべきか判断し、「7日以上」の日付フィルターを作り、レスポンスがページ分割されていることに気づき、 セントをドルに換算する必要があります。

2つ目の方法では、{ older_than_days: 7 } を受け取る find_stale_orders というツールを渡します。

どちらも同じエンドポイント GET /orders を呼びます。ストア側はまったく変わりません。変わるのは 誰が考えるか、つまりエージェントか、それともあなたのサーバーか、です。

                        ┌──────────────────────────────────┐
  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 }  │
                        └──────────────────────────────────┘

あなたのAPIはドアです。MCPはAIクライアントに、そのドアを開ける標準的な取っ手を与えます。

注文サービスは、Claude Codeが存在することに気づきません。MCPサーバーは、あなたのAPIの単なるもう一つのHTTP クライアントです。唯一の違いは、エージェントが理解できる方法で自分自身を説明することです。


Related MCP server: support-agent-mcp

1分で試す

Node 20以降が必要です。それ以外は不要です。データベースもAPIキーもありません。

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

npm test はREST APIとMCPサーバーの両方に対して31件のテストを実行します。すべて通れば、 すべてが機能しているということなので、あとは実際に動くのを見るだけです。

次にサービスを起動して、実行したままにします:

npm run api

2つ目のターミナルで、データを確認します:

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.

そして、このデモの核心となる質問を投げかけます:

npm run orders -- --stale=7

8件の注文。どのマシンでも、どの時間帯でも、同じ8件です。


npm run orders とは何か?

これはcurlのショートカットです。

APIに GET /orders を送信し、生のJSONではなくテーブルとしてレスポンスを表示します。 それだけです。同じリクエストを自分で実行することもできます:

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

同じデータが得られますが、読みにくいだけです。このスクリプトはデータを素早く確認するためのもので、 レッスンの一部ではありません。フェーズ1では、エージェントはcurlとドキュメントだけを渡され、それ以外は何もありません。

いくつかのオプションがあります:

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

テストデータがこのような形になっている理由

24件の注文がメモリ内に保持され、日付は今日を基準に設定されています。そのため、このリポジトリをクローンしたときは 常に正確に8件の滞留注文があります。

3つの問題が意図的に仕込まれています。動画の言葉を鵜呑みにするのではなく、自分で違いを確認できるようにです:

  • レスポンスがページ分割されています。 注文を要求すると、24件中20件が返ってきます。その20行には 不完全に見えるものは何もありません。最初のページで止まってしまうエージェントは、間違った答えを出し、 しかも自信満々です。

  • 古い注文の中にキャンセル済みのものがあります。 滞留しているように見えますが、実際は違います。status の代わりに shippedAt でフィルタリングすると、誤って数えてしまいます。

  • 7日ラインぎりぎりの注文があります。 日数を少し間違えて数えると、エラーメッセージではなく 間違った合計数になります。

MCPサーバーはこれら3つすべてをコード内で一度だけ処理します。src/mcp/server.ts にあります。curl バージョンでは、エージェントが毎回3つすべてを正しく処理する必要があります。


演習

順番に実行してください。フェーズ1をフェーズ2より先にやることが重要です。その違いこそがレッスンだからです。

ガイド

あなたがやること

フェーズ1

docs/phase-1-rest-only.md

エージェントにAPIドキュメントを渡し、curlを使わせ、自分で解決しなければならないことを観察する

フェーズ2

docs/phase-2-mcp.md

Orders MCPサーバーとGitHubのMCPサーバーを有効にして、同じプロンプトをもう一度実行する

その後

docs/architecture.md

何が変わり、何が変わらなかったか、そしてMCPが価値を持たない場合

こちらもあります: フェーズ1でエージェントに渡す APIリファレンス、 コピーして使えるプロンプト、トラブルシューティング。

フェーズ2は実際のGitHub issueを開くので、埋まっても気にならないテスト用リポジトリを使ってください。


中身の構成

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

3つのツール。それぞれが、すでにあるエンドポイントの薄いラッパーです:

ツール

入力

呼び出し

find_stale_orders

{ older_than_days: 7 }

GET /orders?status=UNSHIPPED&before=... を全ページにわたって実行

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 は約170行で、そのほとんどがコメントです。 MCPサーバーとは、つまりそういうものです。


プロトコルを自分の目で確認する

Claude Codeはここで特別なことをしているわけではありません。サーバーをサブプロセスとして起動し、 stdinとstdout経由でJSON-RPCメッセージを送信しているだけです。 clients/raw_mcp_client.py は同じことを手動で行います:

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})

同じスクリプトが、その後GitHubのMCPサーバーとHTTPで通信してissueを開きます:

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

どちらの場合も同じ形です。一方のサーバーはあなたのラップトップ上のNodeプロセスです。もう一方は GitHubが実行しています。クライアントは両者を区別できません。これが覚えておく価値のある部分です。 clients/ にTypeScript版もあります。1つの言語に統一したい場合はそちらをどうぞ。


テスト

npm test

31件のテスト。MCPのテストは、Claude Codeと同じ方法で、stdio経由で実際のMCPクライアントを駆動します。

独自のサーバーを書く予定があるなら読む価値があります。実際にチェックする価値があることを示しています: すべてのツールに使える説明とスキーマがあること、ページングが本当に機能すること、404がクラッシュではなく ツールエラーとして返ること、キャンセル済みの注文が結果に含まれないことです。


コマンド

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 は、エージェントが見るものを正確に確認する最速の方法です: ツール名、 説明、各ツールの入力スキーマです。

データはメモリ内に保持されるため、npm run api を再起動するとすべて初期状態に戻ります。


MCPが価値を持つのはいつか?

フェーズ1は機能します。これはトリックではありません。優れたエージェントは、curlとドキュメントだけを使って 滞留注文を見つけ、issueを開くことができます。MCPはその仕事を可能にするものではありません。

MCPが変えるのは、統合の形です。注文サービスへの問い合わせ方法が、各エージェントのコンテキストウィンドウの中ではなく、 1つのサーバーに存在するようになります。同じ機能が、新しい統合を毎回書くことなく、Claude Code、Cursor、Codexで 動作します。そして、公開する機能を自分で選べます。これはAPIキーを渡すのとはまったく異なります。

MCPが変えないもの: 認証、認可、検証、レート制限、リトライ、そして優れたサービス設計は、すべて依然として あなたの仕事です。設計の悪いAPIの上にMCPサーバーを載せても、それは依然として設計の悪いAPIです。

大まかに言えば、価値はクライアント数×ツール数の積に応じて大きくなります。1つのエージェントが あなたが管理する2つの関数を呼ぶだけ? スキップして、関数を直接呼べばいいだけです。5つのチームと4つのクライアントにまたがる30のツール? それこそが、共有プロトコルがコストに見合い始める時です。 docs/architecture.md で、その境界線がどこにあるかを説明しています。


MITライセンスです。自分の教材に自由に使ってください。クレジットは不要です。

Related MCP Connectors

Related MCP Servers

  • 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.
    -
  • 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