Whetstone.
MCPThe MCP connector, and its two-part requirement
Module 4, Lesson 125 min

The MCP connector, and its two-part requirement

MCP is the Model Context Protocol: a standard way for a server to publish capability so any client can use it, instead of every integration being bespoke. The connector is how a Messages API request reaches one of those servers.

Tools and MCPs is 10.6% of the paper. Most of that is tool implementation, which you already have. This lesson is the connector, and it turns on one configuration fact that the API checks for you.

Both objects, or nothing

A working MCP call needs two things in the request, and they work together:

An mcp_servers entry. This declares the connection: where the server lives and how to authenticate.

A matching mcp_toolset. This exposes tools to the model.

The shape. Note that mcp_server_name is required, and it is the link between the two objects.
{
  "mcp_servers": [
    {
      "type": "url",
      "url": "https://example.com/mcp",
      "name": "my-server"
    }
  ],
  "tools": [
    { "type": "mcp_toolset", "mcp_server_name": "my-server" }
  ]
}

Be honest about what you know here. The per-tool selector fields inside default_config and configs are something to check on the day. What is not up for debate is that both objects have to be present and that mcp_server_name has to match a declared server. Memorise the requirement, look up the rest.

The header, and the dead header

Current: mcp-client-2025-11-20.

Deprecated: mcp-client-2025-04-04.

The old one shows up in blog posts, in Stack Overflow answers, and in your own repo from earlier in the year. Seeing 2025-04-04 in a snippet is a dating signal, the same way thinking.type was in Module 2. Treat the whole snippet as old, not just that line.

Why the split exists

It looks like ceremony until you name the two concerns.

You have already built this distinction, more than once, without calling it that. A database connection string is not a query. Installing a package is not importing a symbol from it. In both cases the expensive, credentialled, infrastructure-shaped step is separate from the cheap per-use decision about what you actually want right now, and nobody would want them fused.

mcp_servers is connection: address and auth, the expensive-to-set-up part. mcp_toolset is exposure: what this particular request puts in front of the model.

Separating them means you can connect to a server with forty tools and expose four of them on a request where only four are relevant. Every tool definition you expose costs context on every single turn, so exposing everything a server has, on every call, is a real bill and a real distraction for the model. Connection is a fact about your infrastructure. Exposure is a decision per request.

The gap you already met

Recap, because it is the seam between two exam domains: strict is not available on mcp_toolset.

So moving a tool out of your own definitions and into an MCP server is not a pure refactor. You lose strict tool use in the process, and nothing in the diff will tell you.

One note on where to confirm this on the day, because it is not where you would look first. The strict tool use page places strict on a tool definition alongside name, description and input_schema and never mentions MCP at all, so reading that page leaves you inferring from silence. The quotable sentence is on the Tool reference page, in the table of optional tool definition properties: the strict row’s “Available on” column reads “All tools except mcp_toolset”. One row, explicit, and it also tells you allowed_callers is excluded on mcp_toolset for the same reason.

Worth knowing that the Tool reference is where this class of fact lives generally. It is the page that carries the type strings, the GA-versus-beta status, the client-versus-server execution column, and which optional properties each tool accepts. If a question is about a property rather than a behaviour, go there first.

Practice

Try it yourself

Quiz

The half-configured connector

Your request has an mcp_servers entry pointing at a working, reachable server. There is no mcp_toolset. What happens?

  1. AThe server's tools are available, because declaring the server is what exposes them
  2. BThe request is rejected, because the API requires every declared server to be referenced by a toolset
  3. CThe server's tools are available but read-only until a toolset narrows them down
  4. DThe request succeeds and the model simply cannot see the server's tools, so it answers without them
Show answer

Correct answer: B — The request is rejected, because the API requires every declared server to be referenced by a toolset

Both halves are required, and the requirement is enforced rather than merely conventional: the connector docs list under Validation rules that every MCP server defined in mcp_servers must be referenced by exactly one MCPToolset. So a declared-but-unused server is a rejected request, not a quiet one. The silent answer is the designed trap and it is genuinely tempting, because half-configured integrations usually do fail quietly and because the split itself invites that guess: the connection worked, so surely only exposure is missing. Read the Validation rules section rather than reasoning from the shape. The read-only answer is invented plausibility, there is no such tier.

Quiz

Predict what happens

The server is reachable and the credentials are valid. Predict what comes back.

A request with one half of the connector wired
{
  "model": "claude-sonnet-5",
  "mcp_servers": [
    { "type": "url", "url": "https://example.com/mcp", "name": "invoices" }
  ],
  "tools": [
    { "name": "get_weather", "description": "Current conditions for a city", "input_schema": { "type": "object" } }
  ],
  "messages": [{ "role": "user", "content": "List my unpaid invoices." }]
}
  1. AIt calls an invoices tool from the connected server
  2. BThe request is rejected, because the invoices server is declared but never referenced by a toolset
  3. CIt calls get_weather, because that is the only tool defined
  4. DIt answers without any tools at all, because it can see no invoice tool present
Show answer

Correct answer: B — The request is rejected, because the invoices server is declared but never referenced by a toolset

The tools array carries a plain tool definition but no mcp_toolset, so the invoices server is declared and unused, and the connector's Validation rules make that a rejected request rather than a degraded one. The answers-without-tools option is the genuinely tempting one and it describes what the model would do if the request ever reached it: the connection is fine, the credentials are fine, and only exposure is missing, which sounds like a degradation rather than an error. It never gets that far. The get_weather answer is wrong for a separate reason worth keeping: being the only available tool does not make a tool applicable.

Recall

The current header and the dead one

Two values, one live, one deprecated. Both worth knowing, because reading an old blog post is how you end up with the wrong one.

What is the MCP connector's beta header, and which earlier one is deprecated?

Reveal answer

The current header is mcp-client-2025-11-20. The earlier mcp-client-2025-04-04 is deprecated. If you find the 04-04 value in a snippet, you are looking at code from an earlier generation of the connector and should not copy it forward.

Recall

Why it takes two objects at all

Not a trivia card. If you can explain the split, you will never forget that both are needed.

What does each of the two objects actually do, and why is that a sensible split?

Reveal answer

mcp_servers declares the connection: where the server is and how to authenticate to it. mcp_toolset controls exposure: which of that server's tools this request puts in front of the model. Connection and exposure are genuinely different concerns, and separating them means you can connect once and expose different subsets per request instead of dumping every tool a server has into every call.

Quiz

Strict, revisited

Deliberate repeat from Module 2, because this is the one place two domains of the exam overlap.

  1. Astrict: true works on mcp_toolset the same way it works on your own tool definitions
  2. Bstrict: true is not available on mcp_toolset
  3. Cstrict: true is required on mcp_toolset, since the model cannot see the schema otherwise
  4. Dstrict: true moves to the mcp_servers entry for MCP tools
Show answer

Correct answer: B — strict: true is not available on mcp_toolset

Strict tool use is unavailable on mcp_toolset. The moves-to-mcp_servers answer is the sharpest trap, because it rewards someone who half-remembers that placement is the theme of this topic and then guesses the other object. The capability is simply absent, so the right answer is a gap, not a different location.

Do

Write both halves, then break one

Ninety seconds in a scratch file. The point is the pairing, not the field names, which are a lookup on the day.

  • Write an mcp_servers entry with a type, a url and a name.
  • Write the tools array containing the mcp_toolset entry that pairs with it, with mcp_server_name matching the name above.
  • Now delete the mcp_toolset and write one sentence saying which validation rule that breaks.
  • Then restore it and instead change mcp_server_name to a name no server has, and write which rule that breaks.
  • Underneath, write the current connector beta header and the deprecated one, each labelled.
Done whenYou have both objects and the names match, your two sentences name the server-must-be-used rule and the server-must-exist rule rather than describing a quiet degradation, and you labelled 2025-11-20 current and 2025-04-04 deprecated.
Sign in to track your progress →