Skip to content
MCP Five

The HostProject #219 / 51

Build it

Twelve stages, their checkpoints, and the VERCEL_URL trap.

The full walkthrough is BUILD_FROM_SCRATCH.md. This is the shape, and the seven things that broke.

  1. Prerequisites, scaffold and install

    An ANTHROPIC_API_KEY this time β€” project #2 is the first one that costs money to run.

    Same scaffolding gotcha as project #1: create-next-app refuses a non-empty folder. Temp dir, then copy in.

  2. Read the types before you write any code

    The habit that changed the design in all five projects.

    Checkpoint

    You can state, from memory, the exact signature of registerTool and whether your model accepts temperature.

  3. The MCP client

    About two hundred lines of fetch β€” see Writing the client by hand.

    Checkpoint

    Run it against the live project #1 server, not a local one:

    bash
    npm run mcp:list
  4. Schema translation

    inputSchema β†’ input_schema, strip $schema, substitute an empty object for a missing one.

    Checkpoint

    bash
    npm run mcp:translate
  5. The agent loop (non-streaming)

    Get it right before making it pretty.

    Checkpoint

    The demo, in a terminal, before any React exists:

    bash
    npm run agent

    Two tool calls across two iterations, with the second one's count matching the first one's total.

  6. The route handler and the chat UI

    The key is read in exactly one place. The browser sends plain text and receives an NDJSON stream of loop events.

    Checkpoint

    bash
    curl -N -X POST http://localhost:3000/api/chat \
      -H "Content-Type: application/json" \
      -d '{"messages":[{"role":"user","content":"roll one d6"}]}'
  7. The second MCP server

    In this repo, at /api/toolbox β€” and with a deliberate secret_code collision, so namespacing has something to prove itself against.

  8. Auth on your own server

    withMcpAuth and a shared token.

    Checkpoint

    With MCP_SHARED_TOKEN set and the dev server restarted: no token gives 401, the right token gives 200.

  9. Typecheck, build, GitHub, deploy

    bash
    npx tsc --noEmit && npx eslint . && npm run build

    Checkpoint

    Verify against production, not localhost.

The gotcha worth the whole page

The reason this one is nasty: it works perfectly in development, works perfectly in preview if protection happens to be off, and fails only in the configuration you ship. And the symptom β€” "my MCP server is down" β€” points at the server, which is fine.

The other six

#What brokeWhere it's covered
1create-next-app refuses to share a folderBuild it, project #1
2The MCP package that isn't the one you installedBuild it, project #1
3The type files you can't findthe compendium
4.env* swallows .env.examplebelow
5The dev server that would not diebelow
6.env.local is read at startup, not per requestbelow
7The host called itself through a locked doorabove

.env* swallows .env.example. The Next.js .gitignore ships with .env*, which also matches the example file you actually want committed. Add !.env.example and keep that block last, because a later pattern wins.

The dev server that would not die. Killing the shell that started it does not kill it. Check the port, not the shell:

bash
Get-NetTCPConnection -LocalPort 3000 -State Listen

This one bit project #3 and project #4 as well. Three projects, same surprise β€” which is a good sign the mental model is wrong rather than the command.

.env.local is read at startup, not per request. Add a variable, and the running dev server does not know about it. Restart, then re-test β€” otherwise you will "fix" a working config three times.