« Track Overview · Warmup · Hitchhiker's · Deep Dive · Principal Deep Dive · Core Contributor · Staff Notes
Phase 03 — Model Context Protocol (MCP): Build a Server & Client From Scratch
Answers these JD lines: Docker's "MCP tooling" and "agent tool interfaces"; Citi's "Build MCP servers with clean integration boundaries between agents, APIs, and enterprise data sources"; Anthropic's Claude-Code / agent-runtime roles. MCP is one of the most concrete, named, differentiating skills across jd.md.
Why this phase exists
Phase 02 gave you one agent talking to its own tools. But real enterprises have dozens of data sources and dozens of AI apps, and wiring every app to every source is the M×N integration problem — bespoke glue everywhere. The Model Context Protocol (MCP), opened by Anthropic in late 2024 and now an industry standard, turns M×N into M+N: a tool/data author writes one MCP server, and any MCP host (Claude Desktop, Claude Code, VS Code, Cursor, your own agent) can use it. It is "USB-C for AI tools."
You will build a faithful miniature — a real JSON-RPC 2.0 server and client speaking the
actual method names (initialize, tools/list, tools/call, resources/read, prompts/get,
notifications/tools/list_changed) with real capability negotiation and permission gating. The
transport is in-memory (deterministic, offline) but the protocol is real. When you're done, MCP
stops being a buzzword and becomes something you can implement, debug, and reason about the
security of.
Concept map
- Participants: a Host (the AI app) runs one Client per Server connection; the server exposes context. (Contrast: Phase 02's tools live inside one app; MCP tools live behind a protocol boundary in a separate server.)
- Two layers: the data layer (JSON-RPC 2.0 messages + lifecycle + primitives) and the transport layer (stdio for local, Streamable HTTP + OAuth for remote).
- Primitives: server-side tools (actions), resources (data), prompts
(templates); client-side sampling, elicitation, logging; all discovered via
*/list. - Lifecycle:
initialize→ capability negotiation →notifications/initialized. - Security: an MCP server is someone else's code your host connects to — supply-chain risk, tool-poisoning, and the need for permission gating + human approval (forward-ref Phases 09/10/13).
The lab
| Lab | You build | Proves you understand |
|---|---|---|
| 01 — MCP Server & Client Over stdio | a JSON-RPC 2.0 server + client with the initialize handshake, tools/resources/prompts, permission gating, and list_changed notifications | the real wire protocol, the lifecycle, and where the trust/permission boundary sits |
Integrated scenario
Citi wants an agent to query an enterprise data source without hard-coding that source into
every agent. You write one MCP server that exposes the source as a query tool plus a
schema resource plus a few prompts with few-shot examples, enforce an allow-list of which
tools each connecting agent may call, and audit every call. Now any team's agent connects to
the same server with a clean, versioned, permission-gated boundary — exactly the "clean
integration boundaries between agents, APIs, and enterprise data sources" the JD asks for. That
server is a durable platform asset, not a one-off integration.
Deliverables checklist
-
Lab 01 green under
LAB_MODULE=solution pytestand your ownlab.py. -
You can walk the
initializehandshake and capability negotiation by hand. - You can name the three server primitives and two client primitives and their methods.
- You can explain why an MCP server is a security boundary and how to gate it.
Key takeaways
- MCP solves M×N integration with one protocol; it's the interop layer of the agent ecosystem.
- The wire protocol is just JSON-RPC 2.0 with a defined lifecycle and primitives — you can implement it.
- A server is untrusted code you connect to: permission-gate tools, and put human approval on dangerous ones. The protocol standardizes discovery and transport; it does not make the server safe — that's your job (Phases 09/10/13).