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.tswith the safe practice datasrc/server.tswithsearch_notes,get_note,notes://catalog, andreview_projectsrc/index.tsfor stdiosrc/worker.tsfor remote HTTPREADME.md,TESTING.md, andSECURITY.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