Model Context Protocol
MCP is how an agent gets tools somebody else wrote. There are two entirely different ways to wire it up, they belong to different layers, and the questions come from confusing them.
Path one: the client-side adapter
You connect to the servers yourself, convert their tools into LangChain tools, and hand them to create_agent like any other tool.
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
client = MultiServerMCPClient({
"math": {
"transport": "stdio",
"command": "python",
"args": ["/path/to/math_server.py"],
},
"weather": {
"transport": "http",
"url": "http://localhost:8000/mcp",
"headers": {"Authorization": "Bearer YOUR_TOKEN"},
},
})
tools = await client.get_tools()
agent = create_agent("claude-sonnet-4-6", tools)stdio launches a local subprocess. http speaks to a URL. Once get_tools() returns, the agent has no idea these tools came from anywhere unusual.
Two behaviours worth knowing. Tool names can be prefixed with the server name to avoid collisions when two servers export the same name. And an MCP tool error is returned to the model as a ToolMessage with status="error" by default, so the agent gets a chance to self-correct rather than the run crashing.
Path two: the provider-hosted connector
The model provider connects to the MCP server directly. You never run a client.
from anthropic.types.beta import BetaMCPToolsetParam
from langchain_anthropic import ChatAnthropic
mcp_servers = [
{"type": "url", "url": "https://docs.langchain.com/mcp", "name": "LangChain Docs"}
]
model = ChatAnthropic(model="claude-sonnet-4-6", mcp_servers=mcp_servers)
mcp_tool = BetaMCPToolsetParam(type="mcp_toolset", mcp_server_name="LangChain Docs")
response = model.invoke("What are LangChain content blocks?", tools=[mcp_tool])The toolset is also where allowlisting and denylisting live, through default_config and per-tool configs. Setting default_config.enabled to false and enabling named tools is the allowlist pattern; leaving the default alone and disabling named tools is the denylist.
Which one, and the availability line
Client-side works with any model, handles local stdio servers, and puts the connection in your process where you can see it. The provider-hosted connector removes the client entirely but only supports remote servers reachable over https, and only supports tool calls, not the rest of the MCP feature set.
And the constraint that decides it for a lot of clients: the connector is not currently available on Amazon Bedrock or Google Cloud. If the deployment target is Bedrock, the client-side adapter is not a preference, it is the only path.
Try it yourself
Why the connector call is rejected
A remote MCP server is configured on the model and the call is rejected before the model ever runs.
mcp_servers = [
{"type": "url", "url": "https://docs.langchain.com/mcp", "name": "LangChain Docs"}
]
model = ChatAnthropic(model="claude-sonnet-4-6", mcp_servers=mcp_servers)
response = model.invoke("What are LangChain content blocks?")Show answer
Correct answer: C — Nothing references the server; every declared server must be named by exactly one mcp_toolset passed in tools
The connector has two halves: mcp_servers defines the connection, and an mcp_toolset entry in the tools array selects which of that server's tools are enabled. Declaring a server that no toolset references is a validation error rather than a quiet no-op, which is worth holding onto, because the surrounding intuition that a half-wired integration degrades silently is wrong here. The token option is the tempting one because auth is the usual cause of an empty result from a remote server, and here the server is public and the omission is structural.
The pairing rules
These are validation rules the API enforces, which means they are exactly the kind of thing that can be asked as a true-or-false pair.
State the three pairing rules between mcp_servers and mcp_toolset entries.
Reveal answer
First, the mcp_server_name on a toolset must match a server defined in mcp_servers. Second, every server defined in mcp_servers must be referenced by exactly one toolset, so an unused server definition is an error rather than a harmless leftover. Third, each server can be referenced by only one toolset, so you cannot split one server's tools across two toolset entries. The middle rule is the surprising one: declaring a server you do not use is not tolerated.
Where the connector does not run
A client wants the provider-hosted MCP connector, and their Claude models are served through AWS. What do you tell them?
Show answer
Correct answer: B — Available on the Claude API and some partner platforms, but not currently on Bedrock or Google Cloud
The connector is available on the Claude API and named partner platforms, and is explicitly not currently available on Amazon Bedrock or Google Cloud. The first option is the natural assumption, because a feature that looks like part of the model ought to travel with the model; this one is a platform feature of the API surface, so it does not.
Choosing a transport
You want an agent to use a tool server that runs as a local subprocess on the same machine. Which client-side transport?
Show answer
Correct answer: B — stdio, launched from a command and args
stdio launches and speaks to a local subprocess via command and args. The last option is the trap because it is true of the provider-hosted connector, which requires a publicly reachable https server and cannot connect to local stdio servers at all; it is not true of the client-side adapter, where stdio is the normal local path.
Two minutes in the docs
A navigation drill rather than a build. The exam is semi-open-book and this is precisely the shape of lookup it rewards.
- Starting from docs.langchain.com, find the page documenting MCP for Python agents.
- Write down the exact config keys for both transports, including which one takes command and args and which takes url.
- Find where it says what happens to an MCP tool error by default, and note the status value it sets on the returned message.
- Time the whole thing. Anything over three minutes means you are searching rather than navigating.