Check the server's capabilities during initialize and degrade gracefully up front; never blindly call a feature the server never advertised.
Imagine plugging a new appliance into a wall socket. Before you switch it on, you check whether the socket actually supplies what the appliance needs. If the socket has no grounding pin, you do not just flip the switch and hope. You either pick a different socket or tell the user the appliance will run in a limited mode. MCP capability negotiation works the same way. During the opening handshake, the server hands the client a list of what it actually supports. The client reads that list first. If a feature is missing, the client disables the matching button or warns the user, instead of firing a call that is doomed to error.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Capability negotiation is the quiet backbone of every MCP session. Before a single tool runs or a single resource is read, the client and server settle on what each can actually do. This question targets the behavior that follows from that handshake: what happens when a feature you wanted is simply not on the server's menu. The answer reveals whether a candidate understands MCP as a negotiated protocol or merely as a bag of remote procedure calls.
The trap is treating the missing feature as a runtime surprise. Candidates who reach for try and catch are solving the wrong problem. The protocol already told you, during initialization, exactly what the server supports. The disciplined engineer reads that contract first and shapes the experience around it. Error handling still exists as a backstop, but it is not the discovery mechanism. Confusing the two is the single most common mistake here.
This deep dive walks through the initialize handshake, what each side advertises, why early detection beats runtime errors, what graceful degradation actually looks like, and how this whole dance buys MCP its forward and backward compatibility. By the end you should be able to defend the correct answer, explain precisely why each wrong option fails, and connect the small UX decision to the large architectural property it protects.
The initialize handshake
Every MCP connection opens with a three-step lifecycle. The client sends an initialize request carrying its protocol version and its own capabilities. The server replies with an initialize result containing its protocol version, server info, and crucially its capabilities object. The client then sends an initialized notification, and only after that may normal operations begin. Sending tool calls before the handshake completes is a protocol violation, and a well-behaved server will reject them.
The capabilities object is the heart of the exchange. It is not a marketing list of everything MCP can do. It is a precise declaration of what this particular server build, in this particular configuration, will honor. Two deployments of the same server image can advertise different capabilities if one was started with a flag the other was not. The client must therefore read the live object every session rather than caching assumptions across connections.
The ordering matters. Because capabilities arrive in the very first round trip, the client has complete knowledge of the server's surface area before it issues a single tools/call or resources/read. There is no excuse for discovering support by failing. The protocol designers placed this information at the front of the conversation precisely so that clients could plan rather than probe. Probing for capabilities by calling methods and watching which ones error is the behavior the handshake was designed to make unnecessary.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
| Behavior | When detected | User experience |
|---|---|---|
| Graceful degradation | At initialize, from capabilities object | Feature hidden or explained; no failed call |
| Call anyway, handle error | At runtime, via error response | Wasted round trip; cryptic error to debug |
| Silent skip | At runtime, no signal | Functionality vanishes with no explanation |
| Assume full support | Never; assumption only | Breaks against any partial server |
Real products, models, and research that use this idea.
- Claude Code and Claude Desktop read each MCP server's capabilities at session start and only register the tools and resources the server advertised.
- Cursor and Zed negotiate capabilities per MCP server, so a filesystem server without subscriptions simply omits live update behavior in their UIs.
What an interviewer would ask next. Try answering before peeking at the approach.
QWhat exactly does the client advertise back to the server during capability negotiation?
Client-side capabilities like roots and sampling. The server only requests sampling if the client declared support, so it is symmetric, not server-only.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Calling a capability the server never advertised and treating the runtime error as the discovery mechanism. The handshake exists precisely to avoid that.
60 second bullets to scan on the way to the call.
What the capabilities object is exchanged during
Which primitives and sub-flags a server can advertise
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.