In MCP, which component enforces user consent, and why not the protocol itself?
answer
- Three roles, only one has a user
- Bytes cannot certify a human decision
- The spec says so explicitly
- Servers see only what they were sent
- Compliance is not the same as safety
basics
~20 sThe host application enforces consent. MCP is a JSON-RPC wire protocol: it can require fields and reject malformed messages, but it cannot verify that a human approved anything, so the specification states its principles as guidance the host must carry out.
solid answer
~50 sThe **host** — the application the user is actually using — is the enforcement boundary. It owns the user interface, the user relationship and the model's context, and it decides what goes into each request before a client sends it. A **client** is just the per-server connector inside the host; a **server** only ever sees what the host chose to send it, and cannot read the whole conversation or see into other servers. The specification (revision 2026-07-28) says outright that MCP cannot enforce its security principles at the protocol level. That is a statement about what a wire format can do: it can require `_meta` fields, reject bad params with `-32602`, and define error codes, but no message shape proves a human said yes. The protocol supplies evidence; the host makes and enforces the decision.
go deeper
Say clearly that the host application enforces consent and that MCP only describes the expectation. Naming the three roles — host, client, server — is enough at this level.
Explain why no message field can prove a human approved something, and contrast that with what the protocol genuinely does enforce: required _meta fields, error codes, header agreement.
Turn it into an audit stance — when reviewing an integration, ask host questions about the consent surface and server-selection policy rather than accepting spec compliance as evidence of safety.
Own the organizational consequence: because enforcement is host-side, buying or building the host is the security decision, and any policy you set has to be expressible in that host's consent model.
## The short answer, and why it is not a cop-out MCP's security section names three principles — User Consent and Control, Data Privacy, Tool Safety — and then says plainly that MCP itself cannot enforce them at the protocol level. Candidates sometimes hear that as the specification dodging responsibility. It is not. It is an accurate statement about the limits of a message format, and it tells you exactly where to look when you audit a real deployment. ## What a wire protocol can and cannot do MCP is JSON-RPC 2.0 over stdio or Streamable HTTP. What it can enforce is everything mechanical: that `params._meta` carries `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` on every request; that a missing or malformed field draws `-32602`; that a required client capability the server needs draws `-32021` `MissingRequiredClientCapabilityError` with `data.requiredCapabilities`; that over Streamable HTTP the `MCP-Protocol-Version` header matches the `_meta` value or the server answers 400 with `-32020` `HeaderMismatchError`; that a request declaring an unsupported revision draws `-32022`. Every one of those is a property of bytes on a wire. Now consider what consent actually is: a human being understood what would be shared or done, and agreed to it. There is no field that can certify that. A client could always set `"userApproved": true` unconditionally; a server has no way to tell an honest host from a dishonest one, and no incentive structure in the protocol changes that. So the specification does the only intellectually honest thing: it states the principles as obligations on implementors, and points at the component that can actually discharge them. ## Why the host and not the client or the server The three roles are not interchangeable. The **host** is the application the user launched — an IDE, a chat client, an agent runtime. It renders the interface, holds the conversation, decides what context to assemble, and manages one client per server. The **client** is a thin per-server connector inside the host: it speaks the protocol, but it has no user to ask and no policy of its own. The **server** is on the other side of a process or network boundary; it sees only the request the host chose to send. It cannot read the conversation, cannot enumerate the host's other servers, and cannot see what a sibling server returned unless the host passed it along. Only one of those three has both the knowledge of what a request would expose and the ability to ask a human about it. That is the host, and that is why the spec calls it the enforcement boundary rather than distributing the duty. ## What the protocol contributes instead Saying enforcement is host-side does not mean the protocol is silent on security. It supplies the raw material a host needs to decide well: - **Per-request declaration.** Version and capabilities travel in `_meta` on every request, so nothing is inferred from earlier traffic. Servers MUST NOT infer capabilities from prior requests. - **Explicitly untrusted identity.** `io.modelcontextprotocol/clientInfo` and `io.modelcontextprotocol/serverInfo` are self-reported and the spec labels them untrusted. A host that pins policy to a name a server chose for itself has misread the document. - **Behavioural hints, marked as hints.** A tool's declared behaviour is a hint about intent that a client must treat as untrusted unless the server itself is trusted; it is not a security control. - **Real authorization for remote servers.** The OAuth 2.1 profile gives audience-bound tokens, mandatory PKCE, and a prohibition on token passthrough. That is enforceable, because it is cryptographic and server-side — but it answers "which principal is calling", not "did a human consent to this action". ## Consent has no connection to hang on Revision 2026-07-28 made MCP stateless: every request is self-contained, and an open connection — a stdio subprocess included — is explicitly not a conversation or a session. The `initialize` handshake and the `Mcp-Session-Id` header were removed. So a host cannot model consent as "this connection was approved"; the grant lives in host state, keyed to the user and the server's identity, and is checked as the host builds each request. ## What this means when you evaluate a deployment If someone tells you an MCP integration is secure because it is spec-compliant, that claim is close to empty. Compliance is about message shapes and error codes. The questions that matter are host questions: which servers may be configured and by whom, what the consent surface looks like, what data classes may cross into which server, and what the host does with a server's self-reported metadata. Note too that in 2026-07-28 the security best-practices document moved out of the specification into the documentation tutorials — good advice, but not normative spec text.
- If the protocol cannot enforce consent, what does it contribute to security at all?Structure and identity. Every request declares its protocol version and client capabilities in `_meta`, so nothing is inferred from earlier traffic; self-reported `clientInfo`/`serverInfo` are labelled untrusted; tool behaviour is expressed as hints marked as hints; and remote servers get an OAuth 2.1 profile with mandatory PKCE, audience-bound tokens and no token passthrough. Those give the host evidence and an identity to bind policy to. The decision stays with the host.
- Can a server refuse to act until it sees proof the user consented?It can demand authorization — a valid audience-bound token, a sufficient scope, a 403 with `insufficient_scope` to force step-up. It cannot demand consent, because there is no consent field and nothing would stop a client from asserting it. Authorization answers which principal is calling; consent is a human fact only the host can establish.
- Where does the client fit if it is not the enforcement point?It is the per-server connector inside the host, one per server, speaking the protocol and carrying requests and responses. It has no interface to ask a human anything and no policy of its own, so it implements what the host decides rather than deciding. Treating a client library as the security layer misplaces the boundary.
The protocol is the postal system: it can standardise envelopes and reject unaddressed mail, but it cannot know whether you meant to send the letter. The host is the person deciding what goes in the envelope.
saying these in an interview costs you the question
- Says the server validates that the user consented
- Assumes a spec-compliant implementation is therefore safe
- Points at the transport or TLS as the consent mechanism
- Confuses the client connector with the host application
- Believes a server can read the whole conversation by default