Model Context Protocol (MCP): Connect AI to Your Tools and DataPrimitives, client features and transports · Lesson 4 of 18

Client features, multi round-trip requests and extensions

Article · 15 min · 9 min lecture

Video lecture

Client features, multi round-trip requests and extensions

14 chapters · about 9 min · full transcript

Coming soon

Chapter 1 of 14

Client features and extensions

  • Elicitation: form and URL
  • Multi round-trip requests
  • Deprecated features
  • Extensions: Tasks, MCP Apps

The narrated lecture is in production

Every chapter is scripted and ready. Browse the chapters and read the full transcript now — the video will appear here when it’s published.

Chapters

Servers sometimes need something from the client

A tool may need a missing parameter, a user confirmation, a payment, or an OAuth sign-in to a third-party service mid-call. MCP defines client features for these cases. They evolved quickly, so this lesson separates what is current from what is deprecated.

Elicitation (current)

Elicitation lets a server ask the user for input through the host.

  • Form mode: the server sends a message and a restricted JSON Schema (flat object with primitive fields, which may include defaults); the host renders a form; the user can accept (with data), decline, or cancel.
  • URL mode (added in 2025-11-25): the server gives a URL for an out-of-band interaction that must not pass through the client, such as an OAuth consent screen, a payment page or entering an API key into the provider's own site. This keeps secrets out of the model's context and the host's logs.

Rules of thumb: never use form elicitation to collect passwords, API keys or payment card data; use URL mode for sensitive flows. Hosts must make clear which server is asking and let users refuse.

Multi Round-Trip Requests (new in 2026-07-28)

Older specs implemented elicitation (and sampling, and roots) as server-initiated requests sent back to the client over a held-open stream. That fought against stateless, load-balanced deployments.

2026-07-28 introduces Multi Round-Trip Requests (MRTR). Instead of calling the client, the server returns an interim result:

{"jsonrpc": "2.0", "id": 12, "result": {
  "resultType": "input_required",
  "inputRequests": {"confirm": {"method": "elicitation/create", "params": {
     "message": "Pause campaign 'Summer Sale' for all regions?",
     "requestedSchema": {"type": "object", "properties": {"ok": {"type": "boolean"}}, "required": ["ok"]}}}},
  "requestState": "opaque-server-token"}}

The client gathers the answers (for example by showing a form) and retries the original request with inputResponses attached (and the requestState echoed back). Every result now carries resultType: "complete" or "input_required". Because each round trip is an ordinary request, any server instance can handle it. The high-level SDKs hide most of this: in the Python v2 SDK you still write await ctx.elicit(...) inside a tool, and the SDK maps it to MRTR or legacy behavior depending on the protocol version.

Deprecated in 2026-07-28: sampling, roots and logging

  • Sampling let servers ask the client's model to generate text. Deprecated; the suggested migration is to integrate directly with an LLM provider API if your server needs generation.
  • Roots let clients tell servers which directories or files were in scope. Deprecated; pass directories or files via tool parameters, resource URIs or server configuration instead.
  • Logging via MCP notifications is deprecated; log to stderr (stdio) or use OpenTelemetry.

Under the new deprecation policy these features keep working for at least twelve months, but new implementations should not adopt them. You will still meet them in older servers and clients.

Utilities you will use

  • Progress notifications for long operations (sent on the response stream of the related request).
  • Cancellation of in-flight requests.
  • Completions for argument autocompletion in prompts and resource templates.
  • Pagination with cursors for long lists.

Extensions

2026-07-28 formalized an extensions framework: optional capabilities negotiated through an extensions field in client and server capabilities, identified like io.modelcontextprotocol/ui. Official extensions include:

  • Tasks (io.modelcontextprotocol/tasks): long-running work that returns a task handle; the client polls with tasks/get and can send input with tasks/update. Useful for report generation, bulk imports and anything taking minutes.
  • MCP Apps (io.modelcontextprotocol/ui): servers provide interactive HTML interfaces (charts, forms, dashboards) rendered inline in the conversation inside a sandbox. Community-maintained support lists include Claude (web and desktop), ChatGPT, VS Code GitHub Copilot, Microsoft 365 Copilot, Cursor and goose; verify with each client.
  • Authorization extensions: OAuth client credentials for machine-to-machine access, and Enterprise-Managed Authorization for centralized control through a company identity provider.

Extensions are always opt-in: both sides must declare support.

Worked example: a Riyadh events company booking assistant

A server exposes book_venue(date, guests).

  • Venue unavailable → form elicitation: "Try another date?" with a date field and a default.
  • Deposit required → URL elicitation to the payment provider's hosted page; the card number never touches the model or host.
  • Contract generation takes minutes → the tool returns a task handle; the host shows progress and fetches the PDF when done.
  • The server previously used sampling to summarize venue reviews; after upgrading, it calls an LLM API directly with its own key and cost controls.

Hands-on: elicitation in a Python tool

from pydantic import BaseModel, Field
from mcp.server import MCPServer
from mcp.server.mcpserver import Context

mcp = MCPServer("venues")

class AltDate(BaseModel):
    accept_alternative: bool = Field(description="Try another date?")
    date: str = Field(default="2026-12-18", description="Alternative date (YYYY-MM-DD)")

BOOKED = {"2026-12-17"}

@mcp.tool()
async def book_venue(date: str, guests: int, ctx: Context) -> str:
    """Book the main hall for a date and number of guests."""
    if date not in BOOKED:
        return f"Provisionally booked {date} for {guests} guests."
    result = await ctx.elicit(message=f"{date} is taken. Would you like another date?", schema=AltDate)
    if result.action == "accept" and result.data.accept_alternative:
        return await book_venue(result.data.date, guests, ctx)
    return "No booking made."

Test it in the Inspector; if your host does not support elicitation, design a fallback (return a clear message asking the user to choose a date).

Pitfalls

  • Collecting secrets through form elicitation.
  • Building new features on deprecated sampling or roots.
  • Assuming every host supports elicitation or MCP Apps; check and provide fallbacks.
  • Long-running tools that block without progress or tasks.

Measuring success

Elicitation completion and decline rates, time-to-complete for URL flows, task completion times, and the share of your servers still depending on deprecated features (target zero for new work).

Key takeaways

  • Elicitation asks users for input: form mode for simple data, URL mode for sensitive out-of-band flows.
  • 2026-07-28 replaces server-initiated requests with Multi Round-Trip Requests (input_required results and retries).
  • Sampling, roots and MCP logging are deprecated: use direct LLM APIs, tool parameters and stderr or OpenTelemetry.
  • Extensions such as Tasks, MCP Apps and enterprise authorization are opt-in and negotiated via capabilities.
  • Always design fallbacks for hosts that lack a feature.

Check your understanding

Quick questions to lock in the lesson. They don’t count towards your certificate.

  1. A server must collect a customer's card details to take a deposit. What is the right mechanism?
  2. Under 2026-07-28, how does a server ask the user a question mid-tool-call?
  3. A new server needs to summarize text with an LLM. What does the 2026-07-28 spec suggest?

Put it into practice

Identify one tool in your planned server that needs user input mid-call. Decide form versus URL mode, write the schema or URL flow, and describe the fallback for hosts without elicitation.

Enrol for free to save your progress

Reading is always free. Enrol to keep your place, take the final assessment and earn a verifiable certificate.