diff --git a/docs/clients/sampling.mdx b/docs/clients/sampling.mdx index fbbf4ff6d..35cb8f2e7 100644 --- a/docs/clients/sampling.mdx +++ b/docs/clients/sampling.mdx @@ -1,7 +1,7 @@ --- title: LLM Sampling sidebarTitle: Sampling -description: Handle server-initiated LLM completion requests. +description: Answer a server's request for an LLM completion. icon: robot --- @@ -9,14 +9,14 @@ import { VersionBadge } from "/snippets/version-badge.mdx"; -Use this when you need to respond to server requests for LLM completions. +Use this when a server asks your client to run an LLM completion on its behalf. -A handshake-era MCP server can request an LLM completion from its client during tool execution, delegating the reasoning to whichever model the client controls. Answering those requests is what a sampling handler does, and it is how a FastMCP client stays interoperable with servers built before the protocol changed. +A sampling handler is the client's answer to that request: the server describes the messages it wants completed, your handler runs them against whatever model you control, and the result goes back. Servers reach your handler by two different routes, and a handler you register serves both. + +On a **handshake-era** connection the server pushes a `sampling/createMessage` request down the open session mid-tool-call. On a **modern** (`2026-07-28`) connection there is no such channel, so a server instead *returns* an input-required result naming what it needs, and your client answers it and re-calls the tool. Both paths dispatch to the same `sampling_handler`, so register one and it works either way — this page's examples pin `mode="legacy"` only because they demonstrate the push route with a legacy server. -**Sampling requires the older MCP protocol.** A server requests sampling by sending a request down to the client, and protocol version `2026-07-28` removed the server's ability to do that. Clients default to `mode="auto"`, which negotiates the newest version both sides support, so every example on this page passes `mode="legacy"`. See [protocol negotiation](/clients/client#protocol-negotiation). - -This page is about the client answering. Writing a FastMCP *server* is the other direction, and there is no `ctx.sample()` there — see [Sampling](/servers/sampling) under Servers for why, and for calling an LLM from your own server instead. +This page is the client side. Writing a FastMCP **server** is the other direction, and there is no `ctx.sample()` there — see [Sampling](/servers/sampling) under Servers for why, and for calling an LLM from your own server instead. ## Handler Template diff --git a/docs/more/settings.mdx b/docs/more/settings.mdx index 8395b8900..0fa4ca0e2 100644 --- a/docs/more/settings.mdx +++ b/docs/more/settings.mdx @@ -23,7 +23,7 @@ You can change which `.env` file is loaded by setting the `FASTMCP_ENV_FILE` env |---|---|---|---| | `FASTMCP_LOG_LEVEL` | `Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]` | `INFO` | Log level for FastMCP's own logging output. Case-insensitive. | | `FASTMCP_LOG_ENABLED` | `bool` | `true` | Enable or disable FastMCP logging entirely. | -| `FASTMCP_CLIENT_LOG_LEVEL` | `Literal["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]` | None | Default minimum log level for messages sent to MCP clients via `context.log()`. When set, messages below this level are suppressed. Individual clients can override this per-session using the MCP `logging/setLevel` request. | +| `FASTMCP_CLIENT_LOG_LEVEL` | `Literal["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]` | None | Default minimum log level for messages sent to MCP clients via `context.log()`. When set, messages below this level are suppressed. Handshake-era clients can override this per-session using the MCP `logging/setLevel` request; the modern protocol has no session to hold that level, so clients on it filter by level in their own log handler instead. | | `FASTMCP_ENABLE_RICH_LOGGING` | `bool` | `true` | Use rich formatting for log output. Set to `false` for plain Python logging. | | `FASTMCP_ENABLE_RICH_TRACEBACKS` | `bool` | `true` | Use rich tracebacks for errors. | | `FASTMCP_DEPRECATION_WARNINGS` | `bool` | `true` | Show deprecation warnings. | diff --git a/docs/servers/server.mdx b/docs/servers/server.mdx index 082830b12..ee778f887 100644 --- a/docs/servers/server.mdx +++ b/docs/servers/server.mdx @@ -195,7 +195,7 @@ These parameters tune how the server processes requests and communicates with cl - Default minimum log level for messages sent to MCP clients via `context.log()`. When set, messages below this level are suppressed. Individual clients can override this per-session using the MCP `logging/setLevel` request. One of `"debug"`, `"info"`, `"notice"`, `"warning"`, `"error"`, `"critical"`, `"alert"`, or `"emergency"` + Default minimum log level for messages sent to MCP clients via `context.log()`. When set, messages below this level are suppressed. Handshake-era clients can override this per-session using the MCP `logging/setLevel` request; the modern protocol has no session to hold that level, so clients on it filter by level in their own log handler instead. One of `"debug"`, `"info"`, `"notice"`, `"warning"`, `"error"`, `"critical"`, `"alert"`, or `"emergency"` diff --git a/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py index 0ee24ef8d..f72c4c344 100644 --- a/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py @@ -83,9 +83,9 @@ class AnthropicSamplingHandler: client=AsyncAnthropic(), ) - # Sampling is a server-initiated request, so it only exists on the - # handshake era; pass `mode="legacy"` to answer one. - client = Client(server_url, sampling_handler=handler, mode="legacy") + # Answers a handshake-era server's push request and a modern server's + # input-required round alike. + client = Client("https://example.com/mcp", sampling_handler=handler) ``` """ diff --git a/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py index c49c77635..23a6fa033 100644 --- a/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py @@ -71,9 +71,9 @@ class GoogleGenaiSamplingHandler: client=GoogleGenaiClient(), ) - # Sampling is a server-initiated request, so it only exists on the - # handshake era; pass `mode="legacy"` to answer one. - client = FastMCPClient(server_url, sampling_handler=handler, mode="legacy") + # Answers a handshake-era server's push request and a modern server's + # input-required round alike. + client = FastMCPClient("https://example.com/mcp", sampling_handler=handler) ``` """