Part 2 — Tools and MCP
A model on its own is a very good guesser. It has read an enormous amount of text and it can predict what should come next with startling fluency. What it cannot do is look anything up, change anything, or find out whether it was right.
Tools are the part of your system that fixes that. A tool is a function you write, described to the model in words, which the model can ask you to run on its behalf. The model never runs it — it emits a structured request, your code executes it, and you hand the result back. Everything the agent knows about the world beyond its training data, and everything it can change in the world, flows through that one narrow channel.
That is why this part exists, and why it is the longest one in the book.
Why tools are where agents succeed or fail
When an agent behaves badly in production, the instinct is to blame the model or the system prompt. In practice, the diagnosis is usually one of five things, and all five live in the tool layer.
The model picked the wrong tool, because two tool descriptions overlapped and neither said which was which.
The model called the right tool with garbage arguments, because the parameter description said id and left it at that.
The tool succeeded but returned forty kilobytes of JSON, which shoved everything useful out of the context window and derailed the next three turns.
The tool failed and returned Error: 500, which told the model nothing, so the model retried the identical call four times and gave up.
Or the tool was a thin wrapper over a corporate API with sixty optional parameters, and the model had no realistic chance of guessing the right combination.
None of those are model failures. They are interface design failures, and you can fix all of them without touching a prompt.
There is a reframing at the heart of this part that is worth stating up front, because everything else follows from it.
A tool description is not documentation. It is a prompt.
It is text you inject into the model’s context, on every single request, in the hope of changing the model’s behavior.
Once you see it that way, you stop writing Gets user data and start writing the sentence that will actually cause the right call at the right moment.
What this part covers
Chapter 1 — Designing tools an LLM can actually use. The principles, each with a bad version and a good version you can compare side by side. Documentation as the model’s only view of your code. Describing actions rather than implementations. Publishing tasks rather than raw API endpoints. Granularity. Concise output, and why verbose tool results poison the context for every turn that follows. Validation, and error messages that teach the model how to recover. This is the highest-leverage chapter in the book: it costs nothing to apply and it fixes more production bugs than any other single change.
Chapter 2 — Function calling: how the model actually invokes your code. The mechanics, end to end and unabridged. How you declare a tool as JSON Schema, how the model emits a call, how you parse and dispatch it, how you return the result, and how the multi-turn loop terminates. Parallel tool calls. Then the failure catalogue: hallucinated arguments, wrong types, non-idempotent double-fires, and the concrete defenses for each.
Chapter 3 — Mini-project 3: build your own @tool decorator framework.
You write the framework yourself, in about two hundred lines of Python.
A decorator that reads a function’s signature and docstring and generates the JSON Schema automatically.
A registry.
A dispatcher with schema validation, timeouts, and structured error returns.
A loop that wires it all to a model.
It runs offline against a mock model, so you can execute every line without an API key.
Chapter 4 — The Model Context Protocol, in depth. Why a protocol was needed at all, stated as arithmetic rather than hand-waving. Hosts, clients, servers. JSON-RPC, transports, primitives, tool definitions, results, structured content, errors. Then the current state of the specification as of the 2026-07-28 revision, which removed the stateful session model entirely — so you learn the protocol as it is today, not as the older tutorials describe it. The chapter closes with an honest accounting of what MCP costs you, because it is not free.
Chapter 5 — Mini-project 4: build an MCP client harness. You write a small MCP server, then a client that connects to it, discovers its tools, calls them, and handles every class of failure the protocol can produce. Runnable, verified, with real output.
What you will have built by the end
Two working artifacts and one durable instinct.
The first artifact is your own tool framework: a @tool decorator, a registry, and a validating dispatcher that returns structured errors and enforces timeouts.
It is small enough to read in one sitting and real enough to use.
Every agent framework you will ever pick up — LangChain, ADK, the Agents SDK, whatever comes next — is doing exactly this underneath, and having written it once you will never again be confused about what a framework is hiding from you.
The second artifact is an MCP client harness that speaks the real protocol to a real server, plus the server to test it against. When a vendor hands you an MCP endpoint, you will be able to point your harness at it and see precisely what it exposes before you let an agent anywhere near it.
The instinct is the one that matters most. By the end of this part you should not be able to look at a tool definition without asking: what does the model see, what will it do wrong, and what will this return when it fails.
Start with Chapter 1. It is the one you will come back to.