MCP, and the two-part requirement
MCP brings in tools your process does not implement. The concept is small. There are two different ways to wire it up, they fail in opposite directions when half configured, and that difference is what gets tested.
Two paths, and only one of them has a pairing rule
Client-side. You connect to the server yourself, convert its tools, and hand them to create_deep_agent through the ordinary tools argument. There is no MCP-specific parameter on the agent constructor. Once the tools arrive, nothing downstream knows they came from anywhere unusual.
Provider-hosted. The model provider connects to the server for you and executes the calls. This is where mcp_servers and mcp_toolset live, and they belong to the chat model, not to the deep agent: you build the model with mcp_servers, and the matching toolset goes in the ordinary tools array alongside your other tools.
The exact field names are a reference lookup, and they differ in casing between Python and TypeScript. Do not spend memory on them. A semi open book exam will not build a ten-question section around something the reference table hands you in five seconds, and this lesson deliberately teaches the requirement rather than the schema.
Why the half-configured case is the interesting one
The instinct almost everybody brings to this is that a missing piece of configuration degrades quietly. That instinct is usually right. It is exactly what the empty base system prompt in the previous lesson does. Here it is wrong, and the exception is the point.
A provider-hosted server with no matching toolset does not start up and behave oddly. It fails validation, and the error names the rule. This is the rare case where the missing half announces itself, which saves you from debugging the model’s behaviour when the answer is sitting in the request body.
The client-side path is the one that behaves the way people expect. There, a server that is down, a server that exposes nothing, and a model that simply chose not to use an available tool all look identical from the outside: the agent runs, nothing errors, and when it needs the capability it works around the gap, apologises, or invents a plausible substitute.
So the two paths need opposite first moves, and the underlying instinct is the same one: first prove the capability is present. On the provider-hosted path that means reading the error you were given. On the client-side path it means asking what tools the agent actually has before asking why it did not use one.
MCP tools are ordinary tools once they land
On the client-side path, nothing about arriving over MCP makes a tool special downstream. In particular:
- Its description is in context on every request, exactly like a locally registered tool. Eight MCP tools is eight more permanent descriptions.
- It is subject to
LLMToolSelectorMiddlewareif the surface gets too wide. - It can be wrapped by
wrap_tool_callfor logging, substitution or rate-limit short-circuiting. - It counts against
ToolCallLimitMiddleware.
The context cost is the same on the provider-hosted path, because the model still has to be told what it can call. What differs is execution: the provider runs the tool and returns the result inline, so the call never passes through your own tool execution path, and interception points that wrap a local tool call are not sitting in front of it.
So MCP moves the implementation out of your process. It does not move the cost out of your context window, and conflating those two is the most common thing people get wrong about it once they are past the configuration stage.
Where MCP sits in the layer picture
MCP is a tool-sourcing mechanism, so it lives at the create_agent layer where tools live, not at the Deep Agents layer. The provider-hosted variant sits one layer lower still, on the model itself. Neither is a deep agent concern, which is why you will not find an MCP parameter on the agent constructor. That is one more instance of the pattern from lesson 1: when a question feels ambiguous, ask which layer owns the concern, and the ambiguity usually resolves itself.
Try it yourself
The two pieces
Small fact, disproportionate consequences. This is the sort of thing a certification tests because it is a configuration failure rather than a concept.
On the provider-hosted path, what two pieces of configuration must both be present for an MCP server's tools to reach the model, and what happens if only the first is there?
Reveal answer
An entry in mcp_servers, which declares the server and how to reach it, and a matching mcp_toolset in the tools array, whose mcp_server_name matches the server's name exactly. Both are required. If a server is declared and no toolset references it, the API rejects the request: every server defined in mcp_servers must be referenced by exactly one toolset, so a server definition you stopped using is a validation error rather than harmless leftover config.
Half configured
You declare a remote MCP server in mcp_servers and pass no mcp_toolset referencing it. What happens on the next call?
Show answer
Correct answer: D — The request is rejected, because every declared server must be referenced by exactly one toolset
The API enforces the pairing, so a server referenced by no toolset fails validation. The second option is the one most people pick, and the instinct behind it is normally sound: half-configured systems usually degrade quietly rather than fail. This one does not, and that is exactly why it is worth knowing. You get a rejected request naming the rule you broke rather than an agent that mysteriously ignores a capability.
Once they arrive
An MCP server contributes eight tools to your agent. Which of the previous lesson's facts still applies to them?
Show answer
Correct answer: D — Their descriptions sit in context on every request, exactly like local tools
An MCP tool is a tool. Its description is part of the surface the model reads on every request, so eight MCP tools is eight more descriptions of permanent context cost. The first option is the seductive one because MCP genuinely does move the implementation out of your process, and it is easy to let that feel like the description moved too. The model still has to be told what it can call.
Two minutes, docs open
A question turns on the exact field names inside an mcp_servers entry. The exam is semi open book. Where do you go?
Show answer
Correct answer: C — The chat model integration's reference page for the MCP parameters, in the question's language
Field names are a reference lookup in the library's own docs, in the right language, because the casing differs between Python and TypeScript. These parameters belong to the chat model integration rather than to the agent constructor, so the integration page is where they are documented. Only docs.langchain.com and smith.langchain.com are whitelisted, so the search engine is not merely slower, it is unavailable. The MCP specification is tempting and wrong: it defines the protocol, not this library's parameter schema.
Write the failure mode down
Two sentences in a scratch file, in your own words, one for each MCP path, about what a half-configured setup looks like from the outside.
Your first sentence says the provider-hosted path rejects the request when a declared server has no matching toolset, rather than degrading quietly. Your second says the client-side path has no such pairing rule, so there a dead or empty server really does surface as an agent that silently lacks the capability, indistinguishable from a model that just chose not to call a tool.