This lesson has one deliverable: a working MCP server, not a description of one. The brief is a document-library MCP server -- server name document-library-mcp-server, kebab-case, per the naming convention this course has used since lesson 13 -- exposing exactly three tools (search_documents, read_document, record_review_note), one resource, and one prompt. Everything from lesson 0's case for tools at all through lesson 33's catalogue of anti-patterns to avoid converges here into one artifact you actually ship, end to end: design the tool boundaries, implement the server, harden it against the inputs a real caller will eventually send, test it without a model, run a small selection eval, instrument it, and write the versioning and go-live discipline that keeps it alive after day one.
Acceptance criteria, stated upfront and concretely, the way a real spec should be written rather than discovered after the fact. First, search_documents takes a natural-language query and an optional tag, and returns at most 20 ranked matches -- id, title, snippet -- never the full corpus, regardless of how broad the query is. Second, read_document accepts only a document id previously returned by search, and rejects anything shaped like a path, an absolute path, or a traversal attempt with a structured error, not a stack trace or a leaked file. Third, record_review_note accepts a doc_id, a note, a rating, and a caller-supplied idempotency key, and calling it twice with the same key produces exactly one stored note, not two. Fourth, a resource exposes the library's catalogue for the host to read directly, with no tool call and no model turn spent on it. Fifth, a prompt template is offered for drafting a review. Sixth, a 14-prompt tool-selection eval scores at or above 90% before the catalogue ships. None of these is aspirational -- each one is checked by a test or a script later in this lesson.
The build runs in the order production tool catalogues actually get built in, not the order a tutorial would prefer: design the boundaries first, because a schema and a description are far cheaper to change before code depends on them than after; implement against that design; harden the implementation against the inputs an honest caller sends by accident and the inputs a dishonest one sends on purpose; prove both halves work without ever spending a model call on the proof; then, and only then, wire up observability and a shipping discipline for a catalogue that will keep changing after today.