> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcp-use.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sampling

> Keep model generation in the MCP host, or request a completion with an input-required round.

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.

```typescript theme={null}
import { MCPServer } from "mcp-use";
import { z } from "zod";

const server = new MCPServer({
  name: "review-server",
  version: "1.0.0",
});

server.tool(
  {
    name: "save-review",
    description:
      "Save a review after the host has drafted it. Pass the completed review text.",
    inputSchema: z.object({
      documentId: z.string(),
      review: z.string().min(1),
    }),
  },
  async ({ documentId, review }) => {
    await reviews.save({ documentId, review });
    return {
      content: [{ type: "text", text: `Saved review for ${documentId}.` }],
    };
  },
);

export default server;
```

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`:

```typescript theme={null}
import { inputRequired, inputResponse } from "mcp-use";

// Continues the server above. `documents` stands in for your document store.
server.tool(
  {
    name: "summarize-document",
    description: "Summarize a stored document with the host's model.",
    inputSchema: z.object({ documentId: z.string() }),
  },
  async ({ documentId }, ctx) => {
    if (!ctx.client.can("sampling")) {
      return {
        isError: true,
        content: [
          { type: "text", text: "This client does not support sampling." },
        ],
      };
    }

    // The callback starts from the top on the initial call and on the retry.
    const response = inputResponse(ctx.inputResponses, "summary");

    if (response.kind === "missing") {
      const document = await documents.get(documentId);
      return inputRequired({
        inputRequests: {
          summary: inputRequired.createMessage({
            messages: [
              {
                role: "user",
                content: {
                  type: "text",
                  text: `Summarize this document:\n\n${document.text}`,
                },
              },
            ],
            maxTokens: 300,
          }),
        },
      });
    }

    if (response.kind !== "sampling") {
      return {
        isError: true,
        content: [{ type: "text", text: "Expected a sampling response." }],
      };
    }

    const blocks = Array.isArray(response.result.content)
      ? response.result.content
      : [response.result.content];
    const summary = blocks
      .map((block) =>
        block.type === "text" ? block.text : JSON.stringify(block),
      )
      .join("\n");

    return { content: [{ type: "text", text: summary }] };
  },
);
```

`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](/v2/typescript/server/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.

```typescript theme={null}
server.tool(
  {
    name: "index-documents",
    inputSchema: z.object({ collectionId: z.string() }),
  },
  async ({ collectionId }, ctx) => {
    await ctx.reportProgress(0, 100, "Starting");
    await indexCollection(collectionId, async (completed, total) => {
      await ctx.reportProgress(completed, total, "Indexing");
    });
    await ctx.reportProgress(100, 100, "Complete");

    return {
      content: [{ type: "text", text: "Index complete." }],
    };
  },
);
```

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:

```bash theme={null}
cd libraries/typescript/packages/server/examples/sampling
pnpm dev
```

The `sample-text` tool in
[`examples/views/basic`](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/views/basic)
requests a completion through an input-required round.

Use [Prompts](/v2/typescript/server/prompts) to package reusable model
instructions and [Elicitation](/v2/typescript/server/elicitation) when a tool
needs explicit user input.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.