Deploy and review

Complete the project-notes server

Finish a useful MCP server with two tools, one resource, one prompt, two transports, repeatable tests, and an honest security record.

We’re done building. This is the final walkthrough: what the repository should contain, the last checks, and how to know the project is finished rather than just working.

What you should have

  • src/notes.ts with the safe practice data
  • src/server.ts with search_notes, get_note, notes://catalog, and review_project
  • src/index.ts for stdio
  • src/worker.ts for remote HTTP
  • README.md, TESTING.md, and SECURITY.md

Four source files do the protocol work. Three documents make it usable and reviewable by someone else. The second group matters as much as the first.

One factory, two lifetimes

The whole shape fits in a few lines:

createServer()
  ├─ serveStdio()          one instance per connection
  └─ createMcpHandler()    one instance per HTTP request

Both transports expose the same two tools, one resource, and one prompt, because both call the same factory. Durable data and caller identity live outside the McpServer instance, so neither lifetime can break them.

The last commands

Run the checks once more:

npm run check
npm ls @modelcontextprotocol/server

The first prints nothing. The second prints the exact SDK version, which goes into TESTING.md next to today’s date.

Then run the Inspector matrix three times: stdio, local HTTP, deployed endpoint. Test the local host configuration from a clean terminal, not the one you’ve been developing in. Test the deployed endpoint from a separate client session.

Read the descriptions once more

Open the capability list in the Inspector and read every name and description as a stranger. Can you tell what each item does, and whether it changes anything? If you need to open server.ts to answer, rewrite the description until you don’t.

Check the evidence, not the happy path

Make sure each line here is backed by a recorded test, not a memory:

  • invalid inputs never reach handlers
  • absent notes are errors, not empty success
  • structured output matches its schema
  • stdout contains only protocol messages
  • the HTTP boundary rejects unexpected paths and callers
  • logs contain no note bodies or credentials
  • retrieved text remains untrusted data

Three sentences to end the README

Finish README.md with three plain sentences. What the server makes possible. What access it has. What must change before connecting private production data.

For this project the third sentence should name four things: authorization, least-privilege backend credentials, rate limits, and a repeated security review. Anyone who forks the project reads that sentence before the code, which is where it belongs.

What you built

A small MCP server with two read-only tools, one resource, one prompt, two transports, a repeatable test matrix, and an honest security record. More important, you can explain it to someone else: what it’s useful for, what protocol surface it exposes, and where its security boundary sits.

That’s the bar for every MCP server I’d connect to a real client.

Lesson completed