ttlMs and cacheScope hints on list, server/discover and resources/read results
Each list result (such as `tools/list`), as well as each `server/discover` and `resources/read` result, carries `ttlMs` and `cacheScope` hints that clients should follow per the specification's caching utility. A cached list must be treated as stale as soon as a `list_changed` notification arrives, even before its TTL expires.
Claude Custom Connectors are the mechanism for connecting to remote MCP servers
In Claude, remote MCP servers are added as 'Custom Connectors'. The flow is: open Settings (Desktop: Ctrl+Comma, or menu icon > File > Settings; Browser: Cmd+Shift+Comma, or profile icon > Settings), click 'Connectors' in the sidebar, click 'Add' at the top-right, choose 'Add custom connector', paste the server URL, then click 'Add'.
Elicitation has two modes: form and URL
Elicitation supports two modes. Form mode: the server asks the client to collect structured data, and the request includes a schema the client uses to build an input form and validate the response. URL mode: the server provides a URL for the user to open, the interaction happens out of band and its data never passes through the client, making it suitable for sensitive flows such as credential entry or third-party OAuth authorization.
Elicitation uses the MRTR pattern with InputRequiredResult
Elicitation follows the Multi Round-Trip Requests (MRTR) pattern. When a server needs user input while processing a request such as tools/call, it responds with an InputRequiredResult whose inputRequests field carries one or more elicitation/create requests. The client gathers the input and retries the original request (with a new request id), attaching the collected inputResponses and echoing back any requestState the server included.
elicitation/create request shape example
An elicitation request delivered inside InputRequiredResult.inputRequests has method "elicitation/create" and params containing mode (e.g. "form"), message (e.g. "Please confirm your Barcelona vacation booking details:"), and requestedSchema. requestedSchema is a JSON Schema object with type "object", a properties map (fields typed boolean or string, string fields may use enum lists such as ["window", "aisle", "no preference"], each with a description and optional default), and a required array listing mandatory field names.
Elicitation client response options: provide, decline, cancel
Users responding to an elicitation can provide the requested information through UI controls (text fields, dropdowns, checkboxes), decline to provide information with an optional explanation, or cancel the entire operation. Clients validate responses against the provided schema before returning them to servers, and display which server is asking and why.
Roots are deprecated in 2026-07-28; use tool params or resource URIs
Roots are deprecated as of protocol version 2026-07-28 and scheduled for removal. New implementations should pass directories or files via tool parameters, resource URIs, or server configuration instead.
Root object structure and file:// scheme
A root is a JSON object with a "uri" and a "name", for example {"uri": "file:///Users/agent/travel-planning", "name": "Travel Planning Workspace"}. Roots are exclusively filesystem paths and always use the file:// URI scheme.
Roots list changes are picked up on the next roots/list request
The roots list can change as users work with different projects or folders; for example if a user opens an archive folder the client adds it to the roots list. Servers see the new boundary the next time they issue a roots/list request. Servers typically access files within roots using relative paths from the root directories or file search tools that respect root boundaries.
Sampling is deprecated in 2026-07-28; integrate LLM APIs directly
Sampling is deprecated as of protocol version 2026-07-28 and scheduled for removal. New implementations should integrate directly with LLM provider APIs instead of asking the client for completions.
Sampling flow uses InputRequiredResult with sampling/createMessage
Sampling follows the same Multi Round-Trip Requests flow as elicitation: the server responds to a request such as tools/call with an InputRequiredResult carrying a sampling/createMessage request; the client presents it to the user for approval, forwards the approved request to the LLM, optionally has the user review the generation, then retries the original tools/call with inputResponses containing the approved response.
Sampling request parameters: messages, modelPreferences, systemPrompt, maxTokens
A sampling request includes messages (array of {role, content:{type:"text", text}}), modelPreferences with hints (e.g. [{name: "claude-sonnet-4-20250514"}]) plus costPriority, speedPriority and intelligencePriority values between 0 and 1 (example values 0.3, 0.2, 0.9), a systemPrompt string, and maxTokens (example 1500).
Three client features available to servers: elicitation, roots, sampling
Beyond consuming server context, MCP clients may offer three features to servers: Elicitation (servers request specific information from users during interactions), Roots (clients specify which directories servers should focus on), and Sampling (servers request LLM completions through the client). As of protocol version 2026-07-28, both Roots and Sampling are deprecated; Elicitation is not.
server/discover RPC for up-front version selection
`server/discover` is a mandatory MCP RPC that returns the server's supported protocol versions, capabilities, and identity in a single request. Clients may call it to select a version up front, but calling it is optional — a client may send any request directly and handle an UnsupportedProtocolVersionError if one comes back.
Required _meta fields on every MCP request
Every MCP request must carry `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` in its `_meta`; clients should also include `io.modelcontextprotocol/clientInfo`. A request missing either required field is rejected with error code -32602 (Invalid params), the same code returned for many other malformed inputs.
MCP OAuth flow: 401 + WWW-Authenticate to token exchange
The end-to-end MCP authorization flow that a client must implement has six steps: (1) connect to the server URL and receive a 401 whose WWW-Authenticate header points at the protected-resource metadata URL via the `resource_metadata` parameter and optionally lists required scopes; (2) fetch the protected-resource and authorization-server metadata to discover endpoints and supported grants; (3) identify the client via dynamic client registration, a pre-registered static client id/secret, a Client ID Metadata Document URL, or an enterprise-managed IdP; (4) open the authorization URL in a browser for sign-in and consent; (5) receive the redirect to the client's callback URL carrying the authorization code; (6) exchange the code for tokens, persist them, and automatically retry the original request.
Mid-session 401 re-authorization and 403 insufficient_scope step-up
A server can refuse a single request mid-session with a `401` (token expired or revoked) or a `403 insufficient_scope` (token lacks required scopes) without the connection being dropped. On 401 the client parses the WWW-Authenticate challenge, re-runs the authorization flow, and retries the failed request. On insufficient_scope the client performs a step-up: it re-authorizes for the union of the currently held scopes and the newly required scopes, so the new token covers everything the old one did plus the new scopes.
Inspector OAuth client flags (CLI and TUI only)
Five OAuth flags are defined only by the Inspector CLI and TUI; the web client gets the same settings through its Client Settings dialog. They are `--client-config <path>` (install-level client config, env `MCP_CLIENT_CONFIG_PATH`, default `~/.mcp-inspector/storage/client.json`), `--client-id <id>` (static OAuth client ID, overrides client.json), `--client-secret <secret>` (for confidential clients, overrides client.json), `--client-metadata-url <url>` (CIMD metadata URL, overrides client.json), and `--callback-url <url>` (env `MCP_OAUTH_CALLBACK_URL`, default `http://127.0.0.1:6276/oauth/callback`).
server/discover result contents on a modern connection
On a modern (2026-07-28) connection, `server/discover` supplies `capabilities` (including `extensions`), `instructions`, and the list of `supportedVersions`. The server's name and version arrive in the result `_meta` under the key `io.modelcontextprotocol/serverInfo`.
Dynamic Client Registration request body for MCP clients
An MCP client that uses Dynamic Client Registration POSTs to the authorization server's `registration_endpoint` with JSON such as {"client_name": "My MCP Client", "redirect_uris": ["http://localhost:3000/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"]}, and receives client registration information back.
Client must offer manual client-info entry when DCR is unsupported
If an MCP client connects to a server whose authorization server does not support Dynamic Client Registration and the client is not pre-registered, it is the client developer's responsibility to provide an affordance for the end user to enter client registration information manually. Without this, the connection cannot complete.
Auth server metadata fields the client needs
The authorization server metadata JSON that an MCP client fetches contains at least `issuer`, `authorization_endpoint`, `token_endpoint` and `registration_endpoint`, for example {"issuer": "https://auth.your-server.com", "authorization_endpoint": "https://auth.your-server.com/authorize", "token_endpoint": "https://auth.your-server.com/token", "registration_endpoint": "https://auth.your-server.com/register"}. If the PRM lists multiple authorization servers, the client chooses one.
Consent requirements for one-click local MCP server configuration
An MCP client that supports one-click local server configuration MUST show a consent dialog before executing commands that displays the exact command including all arguments without truncation, clearly labels it as a potentially dangerous operation that runs code on the user's system, requires explicit approval, and allows cancellation. Clients SHOULD additionally highlight dangerous patterns (sudo, rm -rf, network operations, file access outside expected directories), warn about access to home directory/SSH keys/system directories, warn that servers run with the client's privileges, and run servers sandboxed (containers, chroot, application sandboxes) with least privilege and opt-in grants for extra file system or network access.
Validate OAuth authorization URL schemes received from servers
MCP clients MUST validate authorization URLs supplied by MCP servers: only http:// and https:// schemes are allowed, with http:// acceptable only for loopback addresses (localhost, 127.0.0.1, ::1) during local development while production authorization servers MUST use https://. Clients MUST reject javascript:, data:, file:, vbscript: and other dangerous schemes, and SHOULD use allowlist-based rather than blocklist-based validation. Passing a javascript: URL straight to window.open() gives the malicious server XSS inside the client.
Never open URLs via a shell in an MCP client
MCP clients MUST NOT use shell commands (cmd.exe, sh, PowerShell) to open authorization URLs, because the shell can interpret parts of an attacker-supplied URL as extra commands, yielding remote code execution. Clients SHOULD use platform-specific, non-shell URL opening mechanisms, reject URLs containing special characters that shells could interpret, use dedicated URL sanitization libraries, and log suspicious authorization URLs.
CSP settings for web-based MCP clients
Web-based MCP clients SHOULD send Content Security Policy headers to prevent JavaScript execution from untrusted sources: set script-src 'self' to block inline JavaScript, default-src 'self' to restrict resource loading, and consider script-src 'nonce-<random>' for dynamic content that genuinely needs inline scripts.
Client scope fallback when WWW-Authenticate carries no scope parameter
Clients should begin with only baseline scopes or those given in the initial WWW-Authenticate challenge, and cache recent failures to avoid repeated elevation loops for denied scopes. When the initial WWW-Authenticate challenge carries no scope parameter, the Scope Selection Strategy directs clients to fall back to requesting all scopes listed in scopes_supported, letting the authorization server and end user decide during consent. Scope accumulation is a client-side responsibility: clients SHOULD request the union of previously requested and newly challenged scopes when re-authorizing, so servers stay stateless about client scope sets; hierarchical redundancy need not be deduplicated because authorization servers normalize it, though servers must account for hierarchy when judging token sufficiency.
App class: connect, ontoolresult, callServerTool
In the UI, `import { App } from "@modelcontextprotocol/ext-apps"` and create `new App({ name, version })`. `app.connect()` establishes communication with the host and must be called once at app initialization. `app.ontoolresult = (result) => {...}` fires when the host pushes a tool result (e.g. the initial call that rendered the UI). `await app.callServerTool({ name, arguments })` lets the UI proactively call server tools; each call is a round-trip to the server so the UI should handle latency gracefully. The App class also provides methods for logging, opening URLs, and updating the model's context with structured data.
Adding MCP Apps support to a client: mcp-ui or App Bridge
A client that wants to support MCP Apps has two options: (1) use the `@mcp-ui/client` package, which provides React components for rendering and interacting with MCP Apps views; or (2) build on the SDK's App Bridge module, which handles rendering apps in sandboxed iframes, message passing, tool call proxying, and security policy enforcement — the `basic-host` example in the ext-apps repo shows the integration.
Client declares extension support in _meta clientCapabilities
An MCP client declares support for an extension per-request by including in the request `params._meta` a key `io.modelcontextprotocol/clientCapabilities` whose value is an object with an `extensions` map; e.g. `"_meta": {"io.modelcontextprotocol/clientCapabilities": {"extensions": {"io.modelcontextprotocol/enterprise-managed-authorization": {}}}}`. The request itself is normal JSON-RPC 2.0 with `jsonrpc`, `id`, `method`, `params`.
Client requirements for enterprise-managed authorization
A client supporting Enterprise-Managed Authorization must: (1) declare support in per-request capabilities via _meta; (2) support SSO login against the enterprise IdP and save the Identity Assertion (ID Token or SAML assertion); (3) handle ID-JAGs by exchanging them for MCP access tokens; (4) let administrators configure the enterprise IdP endpoints at organization level rather than per-user; (5) respect token scopes, since enterprise IdP tokens may carry scope restrictions differing from standard MCP authorization, and handle scope errors gracefully.
Client steps for client-credentials auth
To use OAuth client credentials, an MCP client must: (1) declare the extension in per-request capabilities under _meta, (2) obtain an access token from the authorization server using the client credentials grant before connecting to the MCP server, (3) send the token as `Authorization: Bearer <access_token>` on HTTP requests to the MCP server, and (4) implement token refresh, since client-credentials tokens typically have shorter lifetimes than user-delegated tokens.
Client declares oauth-client-credentials in per-request _meta capabilities
An MCP client declares support for the extension in its per-request capabilities, inside params._meta under the key "io.modelcontextprotocol/clientCapabilities" with {"extensions": {"io.modelcontextprotocol/oauth-client-credentials": {}}} on the JSON-RPC 2.0 request.
Extension negotiation: clients declare in _meta clientCapabilities, servers in server/discover
MCP extensions use a negotiation mechanism where clients declare support in the `extensions` field of the `io.modelcontextprotocol/clientCapabilities` object they send in each request's `_meta`, and servers advertise their supported extensions in the capabilities returned by `server/discover`.
Where a client declares extension support: clientCapabilities in request _meta
To add extension support to an MCP client, declare it in the `extensions` field of the `io.modelcontextprotocol/clientCapabilities` object that the client sends in each request's `_meta`, and read the server's `extensions` from the server's `server/discover` response.
Steps to implement an MCP extension in a client
The recommended process for adding extension support to an MCP client is: (1) review the extension specification in the relevant repository (ext-auth for auth extensions, ext-apps for MCP Apps), (2) declare support in the `extensions` field of `io.modelcontextprotocol/clientCapabilities` sent in each request's `_meta` and read the server's `extensions` from its `server/discover` response, (3) implement the extension's protocol requirements, and (4) submit a pull request to update the community-maintained support matrix.
Client capability JSON for Tasks extension
Example client request declaring Tasks support: {"jsonrpc":"2.0","id":1,"method":"...","params":{"_meta":{"io.modelcontextprotocol/clientCapabilities":{"extensions":{"io.modelcontextprotocol/tasks":{}}}}}}. The extension value is an empty object.
Handling input_required tasks mid-flight
If a task moves to `input_required`, the `tasks/get` response includes an `inputRequests` map containing elicitations or other server requests. The client presents them to the user or model and submits answers via `tasks/update` with `inputResponses`. This avoids needing a second connection or unsolicited server-to-client messages.
Clients must handle polymorphic tools/call results
A client that opts into Tasks must be prepared for a supported request such as `tools/call` to return either the standard result or a `CreateTaskResult` with `resultType: "task"`, and branch on `resultType`. Clients opt in once via the extension capability rather than per tool.
Polling loop rules for task clients
After receiving a taskId, call `tasks/get` respecting the server-supplied `pollIntervalMs`, and keep polling until a terminal status (`completed`, `failed`, or `cancelled`). Persist task IDs durably so polling can resume after a client crash or restart.
Required _meta keys on every MCP request
Each client request's params._meta carries three namespaced keys: `io.modelcontextprotocol/protocolVersion` (e.g. "2026-07-28"), `io.modelcontextprotocol/clientInfo` (an object with `name` and `version`, e.g. {"name": "example-client", "version": "1.0.0"}), and `io.modelcontextprotocol/clientCapabilities` (e.g. {"elicitation": {}}). protocolVersion and clientCapabilities are mandatory on every request; clientInfo should normally be included unless the client is configured not to.
server/discover is optional and its result is cacheable
Calling `server/discover` is optional: because every request carries the same `_meta` fields, a client may send any request directly and handle a version error if one comes back. The discovery response is typically cacheable (it carries ttlMs and cacheScope), so the discovery flow does not need to be repeated for every request.
Subscription acknowledgment message
The server acknowledges a subscription with the notification `notifications/subscriptions/acknowledged`, which is the first message carrying that subscription's ID in `_meta.io.modelcontextprotocol/subscriptionId`; no other notification for that subscription is sent before it. Its `notifications` field reflects the subset of the requested filter the server agreed to honor, with unsupported notification types omitted — so clients must check which filters were actually accepted.
Notifications carry subscriptionId and have no id
MCP notifications are JSON-RPC 2.0 notification messages with no `id` field, so no response is expected or sent. Every notification on a subscription stream carries `io.modelcontextprotocol/subscriptionId` in `params._meta`, whose value is the JSON-RPC ID of the `subscriptions/listen` request that opened the stream, letting clients correlate notifications with subscriptions. Example: {"jsonrpc":"2.0","method":"notifications/tools/list_changed","params":{"_meta":{"io.modelcontextprotocol/subscriptionId":4}}}.
Client refresh cycle after a list_changed notification
On receiving `notifications/tools/list_changed`, a client typically reacts by re-sending `tools/list` (with a new JSON-RPC id) and updating its tool registry, then notifying the LLM of the new capabilities if a conversation is active. Pseudo-code pattern: `async with client.listen(tools_list_changed=True) as sub: async for _event in sub: tools_response = await client.list_tools(); app.update_available_tools(client, tools_response.tools)`.
Client advertises extensions in _meta io.modelcontextprotocol/clientCapabilities
Clients advertise extension support inside `_meta["io.modelcontextprotocol/clientCapabilities"]` on each request, under an `extensions` object keyed by extension identifier. Example of a `tools/call` request params: `"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientCapabilities": {"extensions": {"io.modelcontextprotocol/ui": {"mimeTypes": ["text/html;profile=mcp-app"]}}}, "io.modelcontextprotocol/clientInfo": {"name": "ExampleClient", "version": "1.0.0"}}`.
Client-side completion implementation best practices
Clients SHOULD: debounce rapid completion requests, cache completion results where appropriate, and handle missing or partial results gracefully.
Clients MUST support at least JSON Schema 2020-12
Clients are required to validate schemas according to their declared or default dialect. All clients must support at least JSON Schema 2020-12.
Client response to out-of-band server requests
Clients receiving server-to-client requests with no associated outbound request SHOULD respond with a `-32602` (Invalid Params) error.
Client implementers should expose server instructions to users
MCP clients that support server instructions should expose instructions to users and provide transparency about what servers are injecting into context. Users should be able to see exactly what instructions are being sent to the model in chat logs or similar interfaces.
Client implementers should give users control over server instructions
MCP clients should allow users to review, enable, or disable server instructions to help users customize server usage and minimize conflicts or remove suboptimal instructions.
Client implementers should document their server instructions approach
MCP clients should be clear about how they handle and apply server instructions so users understand the behavior.
Recommended annotation practices for client authors
Client authors should treat annotations from untrusted servers as informational and use them for UX purposes, but keep actual safety guarantees in deterministic controls like network restrictions or sandboxing.
MCP client discovery behavior for authorization server location
MCP clients MUST support both discovery mechanisms. Clients MUST use the resource metadata URL from parsed WWW-Authenticate headers when present; otherwise, they MUST fall back to constructing and requesting well-known URIs in the order listed: first the path-specific well-known URI, then the root well-known URI.
MCP client authorization server metadata discovery interoperability
To handle different issuer URL formats and ensure interoperability with both OAuth 2.0 Authorization Server Metadata and OpenID Connect Discovery 1.0 specifications, MCP clients MUST attempt multiple well-known endpoints when discovering authorization server metadata.
MCP OAuth 2.0 metadata discovery with WWW-Authenticate header
When a client receives an HTTP 401 Unauthorized response from an MCP server, it MUST check for a WWW-Authenticate header. If the header includes a resource_metadata parameter, the client MUST use the URL from that parameter to locate the OAuth 2.0 protected resource metadata.