Session 13. Build and secure an MCP server — Wed 30 Sep
Build and secure an MCP server
Wednesday, September 30, 2026 · 1h · Thread: interface engineering
Outcome
You build the part of a server that says no. A read-only MCP tool with one
narrow argument, and fetch_guard(url) — the gate it consults before it
fetches anything, which refuses private space, loopback, link-local, the cloud
metadata address, a scheme that is not http, and any host that is not on a
declared allowlist. Every refusal names the rule that fired. Then you read a
real comprehended surface — Orquestra's Solana catalogue through Gecko, from
dated recordings — and place each activity in the lowest lane that can do it.
Contract and threat boundary
| Input | A URL, as a string, arriving from whatever text reached the model. Plus three dated recordings of a hosted surface in fixtures/: a tool list documented on 3 September 2026, and two read-only responses captured on 19 August 2026. |
| Output | fetch_guard(url) -> {"allowed": bool, "reason": str}, a lane for each activity on the applied surface, and a self-attested safety checklist. |
| Budget | No model call, no socket, no DNS. Every verdict in this session is reached by parsing and arithmetic, which is the only part of a guard a laptop with the network unplugged can settle. The live surface and the fork rehearsal are opt-in, and neither is assessed. |
| Failures this session must handle | A URL that points inside. http://169.254.169.254/ hands out the instance's credentials to anything asking from inside the instance, and http://2130706433/ is the same trick with 127.0.0.1 written as one number. Both refused on the string, before the socket opens. A redirect. A public host answers 302 and names the next hop, and the next hop is the metadata service. Nothing about the first URL was wrong, so the guard runs on every hop. Excess scope. A fetch tool that takes any URL is not one capability, it is every capability the network offers. One tool, one argument, an allowlist a caller cannot widen. A caller who is only allowed to read. On the applied surface, sixteen tools exist and two of them can change on-chain state. A menu is not an authorization, and the recorded response says so itself. |
The threat is not a clever attacker. It is a fetcher that trusts its argument. Every URL in this session is one a working, well-tested tool will fetch happily, and the guard is the only thing standing between the argument and the socket.
Session flow
This week every class is one hour. What does not fit is self-study, listed in the follow-along.
- Before we start (3m). Pull, sync both extras, preflight green.
- You are on the other side now (7m). Section 1: the smallest honest server. One tool, one argument, an allowlist a caller cannot widen. Excess scope is the failure this shape prevents.
- The guard decides on the string (8m). Why a check after the request is not a guard. The three rules, scheme, address, allowlist, in that order, and why the order is graded.
- The lab (20m). Section 2: write
fetch_guard(ch13-e4). Finishing it against the check's thirty-one URLs is self-study. - Break it on purpose (7m). Section 3: a recorded redirect chain whose third hop is the cloud metadata service. The guard runs on every hop.
- The applied case (12m). Sections 4 to 7 and 10: the recorded surface, the
four lanes (
ch13-e2), and the safety checklist (ch13-e1). - Hand it in (3m).
bootcamp check ch13,submit, exit ticket. Homework: an external tools section in your project instructions: allowed hosts, data handling, who approves what.
Evidence
This session runs unattended. All three checks are deterministic, model-free and offline:
uv run bootcamp check ch13 # runs your notebook, prints its scorecard
uv run bootcamp submit ch13 --github <you> # hands in the notebook as it stands
ch13-e4 drives your guard with thirty-one URLs of its own and reads the reason
as well as the verdict: refused for the wrong reason fails, because the reason
is what the next person acts on. ch13-e2 asks for the lowest lane that can do
each activity, and one of the answers is never. ch13-e1 is the safety
checklist — self-attested, where claiming a lane you did not run is the failure.
Previous: MCP architecture and primitives · Next: Deploy and operate the capstone