Skip to content
MCP Five

The ServerProject #112 / 51

Build it

Thirteen stages, a checkpoint for each, and two gotchas worth carrying.

The full walkthrough is BUILD_FROM_SCRATCH.md in the repo. This is the shape of it, and the two things that actually broke.

  1. Prerequisites

    Node, npm, a GitHub account, a Vercel account. No API keys β€” a server costs nothing to run and needs nothing to run it.

  2. Scaffold the Next.js app

    Checkpoint

    npm run dev serves the Next.js starter.

  3. Install the MCP packages

  4. The route handler skeleton

    The whole server is one file: app/api/mcp/route.ts.

    Checkpoint

    Knock on the door and get an answer:

    bash
    curl -X POST http://localhost:3000/api/mcp \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  5. Your first tool

    roll_dice, for the reason on The four tools: the model cannot fake it, so you can tell whether the tool actually ran.

  6. Read the response properly

    The reply may be plain JSON or Server-Sent Events, depending on how the handler feels. Both are legal. A client that assumes one gets a confusing parse error against a server that chose the other β€” which is exactly what project #2 has to deal with when it writes a client by hand.

  7. Three more tools, three more concepts

    say_hello for the minimum, cookie_jar for state and refusal, secret_code for a thing models are bad at.

  8. A resource and a prompt

    Checkpoint

    bash
    mcp '{"jsonrpc":"2.0","id":3,"method":"resources/list"}'
    mcp '{"jsonrpc":"2.0","id":4,"method":"resources/read","params":{"uri":"cookiejar://status"}}'
  9. Build a client in the browser

    A tiny MCP client in the page β€” the other half of the protocol, so you can watch the exact JSON going back and forth rather than trusting a description of it.

  10. The landing page, then typecheck and build

    bash
    npx tsc --noEmit && npx eslint . && npm run build
  11. Git, GitHub, and deploy via Vercel

    Vercel is wired to the repo, so shipping a new tool is a push.

    Checkpoint

    Verify against production, not localhost. Same curl, different hostname:

    bash
    curl -s -X POST https://YOUR-APP.vercel.app/api/mcp \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  12. Connect it to Claude

    bash
    claude mcp add --transport http cookie-jar https://learn-mcp-5-year-old.vercel.app/api/mcp

    Then say "roll me three twenty-sided dice" and watch it reach into the jar.

How a change reaches the internet

Push to GitHub, Vercel builds, and Claude sees the new tool on its next tools/list. There is no registration step and nothing to tell the model β€” it re-reads the list and your description does the rest.

The two gotchas worth carrying forward

Both of these bit again in later projects, which is the test of whether a gotcha is worth writing down.

#GotchaBit again in
1create-next-app refuses to scaffold into a non-empty folder#2, #3, #4, #5 β€” every single one
2mcp-handler peer-depends on @modelcontextprotocol/server, not …/sdk#5

The other two from project #1's appendix β€” the 406 from a missing Accept header, and the cookie jar forgetting β€” are covered on The vending machine and The sandcastle. All four, with causes and fixes, are in the compendium.