Session 12. MCP architecture and primitives — Tue 29 Sep

MCP architecture and primitives

Tuesday, September 29, 2026 · 1h

Outcome

Draw the host, client and server responsibilities of the Model Context Protocol, discover what a server offers, and tell a tool that reads from one that mutates before anything is called. You leave with two functions and one habit. The functions: describe_surface(listing), which turns a server's handshake and its listings into a map of what it offers and what it claimed and cannot serve, and review_tool(tool), which reads one tool definition and returns a verdict a caller can branch on. The habit is reading a surface as claims rather than as facts — a name is a claim, an annotation is a claim, and a description is somebody else's text sitting in your model's context.

Contract and threat boundary

Input Three recorded listings. Sixteen tool names read off a hosted MCP surface on 2026-09-03, and two servers written out on the page: one whose handshake and collections agree, one whose handshake announces more than it serves. Plus four tool definitions, one of them written to steer whoever reads it.
Output describe_surface(listing) -> dict — names and counts per primitive, plus advertised_but_empty. review_tool(tool) -> dict — {"name", "safe_to_expose", "reasons"}, with reason codes rather than prose. And the classification of the sixteen: which two can change state, which four only build unsigned bytes.
Budget No model call, no network, no server process. Every listing is on the page or inside the check. All three checks are deterministic, so the same notebook gives the same verdict on every machine. No new dependency: re and textwrap ship with Python.
Failures this session must handle A server that advertises a capability it cannot serve. resources: {} in the handshake, [] on the wire. Counted as zero it disappears; named as advertised-but-empty, somebody can go and ask why. An untrusted description. A tool annotated read-only whose description tells the model to call transfer_funds first. It gets flagged, not followed — and the benign tools beside it, which carry every word the flag looks for, do not.

The threat is not that a server is hostile. It is that a client believes a server about itself. Everything you learn on connect — the tool's name, the read_only flag, the sentence describing what it does — was written by whoever runs the server, and the protocol marks none of it as less trusted than your own system prompt. The boundary sits at the client. This session is what a client does at it.

Session flow

This week every class is one hour. The class does what needs a room, and the rest of the lab is self-study: the follow-along lists exactly what to finish, and where. Stuck on it? Ask the course MCP.

  1. Before we start (3m). Pull, sync, preflight cell green on every screen.
  2. Host, client and server, and the four primitives (10m). Which part owns the model, which part owns the capability, and which part owns the judgement. The four primitives, and the one that points back at you. Capabilities (what a server claims) against collections (what it lists).
  3. Live: a surface you did not write (7m). Section 1: sixteen tool names recorded off a hosted MCP surface. The room guesses which of them can move money, and holds the guess for the lab.
  4. Guided lab (20m). describe_surface over a listing with an announced empty drawer (ch12-e2), then the sixteen tools split into what can change state and what only builds bytes (ch12-e1). Whatever is not green by the end of the block moves to self-study.
  5. Failure injection (10m). Section 4: print four tool descriptions as the model receives them and read the third one out loud. Then write review_tool (section 5) and run it over those four. Getting ch12-e3 green against the check's own tools is self-study.
  6. The final assignment (7m). From your own repository to a certificate: make it, lock it, publish it, practise, and hand it in. It is separate from the capstone you present on Friday.
  7. Hand it in, and the exit ticket (3m). submit ch12 with what you have. One thing that works, one thing that is unclear, your next action. Homework: finish the lab, and list every MCP server your assistant can reach, its tool count, and who runs it.

Evidence

This session runs unattended. All three checks are deterministic and model-free:

uv run bootcamp check ch12                    # runs your notebook, prints its scorecard
uv run bootcamp submit ch12 --github <you>    # hands in the notebook as it stands

ch12-e2 drives your describe_surface with four listings of its own — a full surface, a server with an announced empty drawer, a quiet one that lists resources it never announced, and one whose printed totals disagree with what it listed. ch12-e1 reads which two of the sixteen tools can change state, and says why prepare_purchase is not one of them. ch12-e3 drives your review_tool with nine tool definitions: five safe, four of those written to fail a word search, and four that are not safe, one of them for two reasons.

Previous: State and memory · Next: Build and secure an MCP server