Deploy and review

Deploy to a web-standard runtime

Package the HTTP handler for a Worker-style runtime and verify the exact endpoint produced by the platform configuration.

Our worker.ts takes a Request and returns a Response. Nothing in it is specific to Node. That’s the point of the v2 handler: it runs on Cloudflare Workers, Bun, Deno, and any other fetch-based runtime without an HTTP adapter in between.

I’ll use a Cloudflare Worker here. The steps are the same on other platforms, only the CLI changes.

Point Wrangler at the handler

Create wrangler.jsonc in the project root:

{
  "name": "project-notes-mcp",
  "main": "src/worker.ts",
  "compatibility_date": "2026-08-01"
}

Keep the compatibility date current when you set this up. And don’t add a single secret to this version. The practice-data server needs none, and a deployment with no secrets is a deployment that can’t leak them.

The runtime is part of the boundary

Routing to /mcp is the least of what the deployment has to provide. Before this endpoint is reachable by strangers, it needs:

  • one HTTPS /mcp endpoint
  • allowed host and origin validation
  • request and response size limits
  • timeouts and rate limits
  • authentication in front of handler.fetch() for private data
  • protected logs without request bodies or tokens

Some of those live in your wrapper, some in the platform’s settings. Write down which is which.

Run it locally first

Start the Worker on your machine:

npx wrangler dev

Wrangler prints Ready on http://localhost:8787. Our endpoint is http://localhost:8787/mcp.

Run npx @modelcontextprotocol/inspector --help to see the current flags for the remote transport, because they change between Inspector versions. Then connect the Inspector to the local /mcp URL and run the full set: discovery, both tools, the resource, the prompt. The results must match what stdio gave you.

Check the negative paths

Green checks are not enough. Try the things that should fail:

curl -i http://localhost:8787/notes

You should get HTTP/1.1 404 Not Found with the body Not found. A disallowed origin or host should be rejected by whatever boundary you put in front of the handler. And a malformed request must never return a stack trace. If any of these misbehave locally, they will misbehave in production, only louder.

Deploy

When the local matrix is clean:

npx wrangler deploy

Wrangler prints the public URL of the Worker. Append /mcp and that’s your endpoint.

Now record everything in TESTING.md: the public endpoint, the deployment version, the SDK version, the negotiated protocol revision, and today’s date. Then repeat the same matrix from a separate client session, ideally from a different machine. Testing from the terminal that just deployed proves less than you’d think.

One warning to close. If you ever swap the practice notes for private ones, deploy authentication and authorization first, then the data. An endpoint nobody announced is still public. Anyone who guesses or logs the URL can call it.

Lesson completed