Skip to main content
Model generation belongs in the MCP host. The stateless TypeScript server does not expose a blocking ctx.sample(), so a tool callback cannot pause an HTTP request while the host runs a model completion. A tool that needs model output has two options:
  • Let the host generate first, then call a deterministic tool with the result.
  • Return an input_required result that embeds a sampling request. A capable client runs the completion and retries the original tool call; the callback runs again with the completion in its request context.

Keep generation in the host

Design the workflow so the host or model performs generation first, then calls a deterministic tool with the generated or selected value:
  1. A prompt or tool description tells the model what to generate.
  2. The host runs the model according to its own policy and credentials.
  3. The host calls a tool with the result.
  4. The tool validates the input and performs deterministic server work.
This keeps model choice, approval, credentials, and generation policy with the host. It also makes the server behavior reproducible and testable.

Request a completion in an input-required round

When the tool itself needs a completion, return inputRequired.createMessage() under a stable key. The client runs the completion with its own model and policy, then retries the tool call with the result in ctx.inputResponses:
inputResponse() returns kind: "sampling" with the client’s CreateMessageResult in result. Treat the completion as untrusted input and validate it before acting on it. When the request’s client capabilities do not declare sampling, the SDK fails the call with a missing-capability error instead of sending the request, so check ctx.client.can("sampling") first. The callback runs again for each round, so follow the same rules as Elicitation: use a stable key, and perform side effects only after the completion arrives. To read the client’s roots, return inputRequired.listRoots() the same way. The response has kind: "roots" and a roots array, and the client must declare the roots capability.

Report progress for the active request

Long-running tool work can still report request-scoped progress. ctx.reportProgress() returns false when the caller did not supply a progress token.
Progress notifications travel on the active response stream and must be sent before the callback returns. They are not a background push channel.

Run the example

The maintained example exposes a deterministic tool that explains the host-first design:
The sample-text tool in examples/views/basic requests a completion through an input-required round. Use Prompts to package reusable model instructions and Elicitation when a tool needs explicit user input.