Build an MCP server that does something
No echo tool, no hello world: a server with a domain, nine tools, two transports and two auth models - connected to a real client and deliberately made to fail.
The component MCP servers explains why the protocol exists and what a server offers. This course builds one.
Not the one with the echo tool. There are enough of those. It answers not a single one of the questions that show up with your second server, and with the second server they all show up at once: Who clears the sessions away? What happens when two clients are there at the same time? How should a failed call look to the model? And how do you describe a tool so that a model can do something with it?
What runs at the end
The Simhaven helpdesk. Eight tickets, a product manual, nine tools. And an agent that classifies, answers, escalates and closes them without a single line of user interface anywhere. Members enter the same scenery from the other side in the parcours; here you build the service their agent works against.
The server runs over both transports, knows two kinds of authorisation, copes with several simultaneous clients and ends up as its own container next to the application. Around 560 lines of TypeScript in six files. No framework. No database. No abstraction layer on top of the SDK.
What you need
Node 22 and nothing else. The course writes TypeScript and lets Node strip the
types itself (--experimental-strip-types). No bundler, no build step, no tsc
in the way. That is not convenience: the MCP service of this project runs the
same way, and mcp/server.ts in the repo is started exactly like that.
Two packages come along, @modelcontextprotocol/sdk and zod. Both ran in the
examples at versions 1.30 and 3.25.
Where the examples come from
Everything printed as output in this course is real output. The error messages in chapter 6 were triggered and not staged, the character counts are measured, the container in chapter 7 was built and health-checked. Where a number stands, it stands because that is how it came out.
The second source is this repo itself. Under mcp/ runs a server with sixteen
editorial tools and two simulation worlds, with a session cap, a reaper and two
auth models side by side. Wherever this course makes a decision, you can read
next to it how it was decided there. And where it was once decided wrongly.
The roadmap
7 steps, one insight and one working state each. Every step stands on the one before it.
- 01The empty server25 min
The server is done in twenty lines. The decision is the transport, not the code.
Milestone One tool answers over stdio and over Streamable HTTP, both times against the same client.
- 02Tools you can actually describe25 min
The description is not a comment. It is the part of the tool that ends up in the prompt.
Milestone The schema rejects a wrong category with a message that says which ones would have been right.
- 03A domain, not a collection40 min
Nine tools that finish one task are worth more than thirty that half-cover everything.
Milestone The Simhaven helpdesk runs: eight tickets, read, classify, answer, escalate, close, count.
- 04State and sessions30 min
A shared transport rejects the second `initialize` - and a session has to remember what it was opened for.
Milestone Two clients work in separate inventories at the same time, and the reaper clears both away again.
- 05Who may do what30 min
A token per case is the more interesting design: it belongs to a run, not to a user.
Milestone The same container serves two endpoints with two auth models, and no session wanders between them.
- 06Connect it and let it fail30 min
The three typical failures triggered rather than claimed - and one of them looks like a success.
Milestone Unknown tool, missing required field and a result of 130,152 characters stand there as real output.
- 07Operations25 min
A service nobody sweeps and nobody asks falls over exactly when nobody is watching.
Milestone The server runs as its own container with a health check, a session cap and one log line per call.