What is MCP Client?

MCP Client is the protocol component instantiated by an MCP Host to communicate directly with one MCP Server, carrying requests, metadata, responses, notifications, and transport or authorization state for that relationship.

Quick Facts

Full NameModel Context Protocol Client
SpecificationOfficial Specification

How It Works

An MCP Client is a protocol adapter inside or managed by an MCP Host. The Host owns the user experience, model interaction, approval policy, credential boundary, and coordination across Servers; the Client implements one direct protocol relationship; the Server exposes capabilities. A Host commonly creates one Client per Server, while a remote Server can serve many Clients. The Client is not the user-facing application, the language model, an MCP Server, or the policy authority that decides whether an operation is allowed.

Protocol revision is part of the contract. In MCP revision 2026-07-28, the core is stateless: there is no connection-level initialize / notifications/initialized handshake. Every Request carries io.modelcontextprotocol/protocolVersion and relevant io.modelcontextprotocol/clientCapabilities in _meta, and should carry clientInfo. A Client may call server/discover to obtain supported versions, Server Capabilities, identity, cache hints, and instructions, or it may send an operation directly and handle UnsupportedProtocolVersionError (-32022). Server identity and instructions are self-reported and must not drive security decisions.

MCP 2025-11-25 and earlier revisions are Legacy: a Client sends initialize, the Server returns the selected version and capabilities, and the Client sends notifications/initialized. A Dual-era Client must detect which era a Server implements and keep the semantics separate. Current stdio compatibility begins with a server/discover probe; current Streamable HTTP compatibility inspects a failed modern request before falling back. An unknown current version calls for a mutually supported retry or a clear error, not silent interpretation under another version.

Modern message flow is Client Request to Server Response, plus Notifications. If a Server needs user input, model sampling, or a deprecated Root list while processing an eligible operation, it returns resultType: "input_required" with inputRequests; the Client gathers only supported input, applies user and policy controls, and retries the original operation with a new JSON-RPC ID. It must echo opaque requestState exactly without parsing or reusing it for another request. This Multi Round-Trip Request pattern replaces Legacy Server-initiated JSON-RPC Requests. Roots and Sampling remain available during their deprecation window but should not be added to new integrations.

For normal operations, a Client can discover Tools, Resources, and Prompts, follow pagination cursors, honor ttlMs and cacheScope, and refresh cached lists when subscribed change notifications arrive. It must correlate Responses by unique non-null Request ID, distinguish resultType: "complete" from input_required, handle protocol and operation errors, and validate data against the negotiated revision. Tool descriptions and annotations are untrusted metadata. Validate input and output schemas, reject unsafe header mappings, do not dereference network $ref values by default, and namespace colliding Tool names across Servers before exposing them to a model.

The current standard Transport bindings are stdio and Streamable HTTP. With stdio, the Client launches a subprocess and exchanges newline-delimited UTF-8 JSON-RPC while logs stay on stderr. With Streamable HTTP, each message is posted to one MCP endpoint and the reply is JSON or a request-scoped SSE stream. The old standalone HTTP+SSE Transport is Deprecated, not a third current default. Modern HTTP has no Protocol-level Session ID or stream resumption: if a response stream breaks, retry as a new Request with a new ID and account for duplicate side effects. Cancellation closes the response stream on HTTP and uses notifications/cancelled on stdio; every request also needs a bounded timeout.

Authorization is optional in MCP, but an HTTP Client that uses the current profile acts as an OAuth Client. It discovers Protected Resource and Authorization Server metadata, obtains a Client ID, uses PKCE where required, validates the authorization issuer, includes the RFC 8707 resource value in authorization and token requests, requests least-privilege scopes, and sends the audience-bound Bearer token in every HTTP request. Credentials must be keyed by issuer and tokens by intended resource; never forward arbitrary upstream tokens or put tokens in URLs. Dynamic Client Registration is Deprecated in favor of Client ID Metadata Documents, while pre-registration remains valid. The HTTP profile does not apply to stdio, where credentials come from the execution environment.

Dynamic metadata discovery makes the Client an SSRF and credential-exposure boundary. Validate HTTPS URLs and redirects, block private, loopback, link-local, and cloud-metadata destinations unless an explicit local policy allows them, defend against DNS rebinding, isolate token storage, redact secrets from traces, and require user approval before opening authorization or Elicitation URLs. The Host must still enforce deterministic Authorization, Least Privilege, Tool confirmation, output validation, and data-use policy; protocol compliance does not make a Server or its content trusted.

Production traces should bind Server configuration or Origin, Transport, Protocol Era and Revision, Client and Server identity, Request ID, Method, Trace Context, advertised capabilities, authorization issuer and effective scopes, cache decision, retries, MRTR steps, cancellation, latency, Result Type, Error Code, and final effect status. Test current-current, Dual-era-to-Legacy, unsupported-version, pagination, cache invalidation, malformed Schema, timeout, cancellation race, broken stream, MRTR accept/decline, 401/403 step-up, SSRF, and duplicate-effect cases. Never log access tokens, secrets, unrestricted Tool payloads, or sensitive Elicitation values.

Key Characteristics

  • Host-managed relationship — one Client represents one direct Server relationship without becoming the user-facing Host or policy engine
  • Era-aware protocol state — current requests carry Version and Capabilities per call, while Legacy Servers require an initialization session
  • Typed message handling — correlates JSON-RPC IDs, validates Results and Schemas, paginates lists, caches safely, and handles Notifications
  • Transport-specific lifecycle — implements stdio or Streamable HTTP framing, cancellation, timeout, termination, and compatibility behavior
  • Controlled multi-round trips — handles InputRequiredResult, user consent, new Request IDs, and opaque requestState without granting implicit trust
  • Security boundary — isolates Server failures, OAuth credentials, metadata discovery, Tool exposure, traces, and user-approved side effects

Common Use Cases

  1. Host adapters — connect an IDE, assistant, or Agent Runtime to one local or remote MCP Server
  2. Dual-era interoperability — probe current Servers and apply an explicit Legacy fallback without mixing protocol semantics
  3. Protected remote access — perform OAuth discovery, user authorization, token refresh, scope step-up, and audience-bound requests
  4. Capability registry — discover, validate, namespace, cache, and refresh Tools, Resources, and Prompts before model exposure
  5. Reliability and audit — isolate timeouts, cancellations, malformed messages, retries, side effects, and traces per Server relationship

Example

loading...
Loading code...

Frequently Asked Questions

Does every MCP Server need its own MCP Client?

An MCP Host normally creates one Client for each direct Server relationship, which isolates protocol compatibility, transport failures, credentials, capabilities, and naming. A remote Server can still serve many Clients from different Hosts. Gateways and routers add another protocol and policy boundary rather than eliminating the relationship.

Does an MCP Client still send initialize?

Not when both sides use revision 2026-07-28. Current Requests carry Protocol Version and Client Capabilities in _meta, and server/discover is an optional discovery or compatibility probe. Revision 2025-11-25 and earlier use initialize followed by notifications/initialized. A Dual-era Client must detect the Server era and follow only that era's rules.

Which transports should a new MCP Client implement?

The current standard bindings are stdio for a Client-launched local subprocess and Streamable HTTP for an MCP endpoint. Streamable HTTP may return request-scoped SSE streams, but the earlier standalone HTTP+SSE Transport is Deprecated. Custom transports must preserve JSON-RPC, current message patterns, per-request metadata, cancellation, and interoperability requirements.

Does every MCP Client need OAuth?

No. MCP Authorization is optional and its OAuth profile applies to HTTP-based transports, not stdio. When used, the Client must discover and validate metadata, register or identify itself, bind authorization state and credentials to the issuer, use the target Resource Indicator, request minimal scopes, protect tokens, and handle 401 and 403 challenges without token passthrough.

What failures must an MCP Client test?

Test unsupported versions, Legacy fallback, malformed JSON-RPC and Schemas, duplicate IDs, pagination, stale caches, list changes, timeout and cancellation races, interrupted streams, MRTR accept or decline, invalid requestState reuse, authorization redirects, SSRF, expired or insufficient-scope tokens, and duplicate side effects after retries. Surface actionable errors without leaking credentials or sensitive payloads.

Related Tools

Related Terms

Related Articles