mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Merge pull request #4650 from PrefectHQ/claude/mcp-conformance-tests-7ec13f
Pass the MCP conformance suite's draft and pending scenarios
This commit is contained in:
commit
fecced2b5c
25 changed files with 1727 additions and 84 deletions
|
|
@ -541,6 +541,59 @@ on handshake-era connections.
|
|||
|
||||
If you need to support both eras, branch on `ctx.protocol_version`: return an `InputRequiredResult` on modern connections and fall back to [`ctx.elicit()`](#requesting-input-on-handshake-connections) on handshake-era ones.
|
||||
|
||||
### Prompts and resources
|
||||
|
||||
`InputRequiredResult` is a **result type**, not a tools feature: any request can resolve to one. Prompts, resources, and resource templates ask for input exactly the way tools do — return an `InputRequiredResult`, read `ctx.input_responses` on the next round, and the client re-issues the same `prompts/get` or `resources/read` with the answer attached.
|
||||
|
||||
This prompt gathers the context it needs before rendering:
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP, Context
|
||||
from mcp_types import InputRequiredResult, ElicitRequest, ElicitRequestFormParams
|
||||
|
||||
mcp = FastMCP("Reporting Server")
|
||||
|
||||
ask_for_quarter = InputRequiredResult(
|
||||
result_type="input_required",
|
||||
input_requests={
|
||||
"quarter": ElicitRequest(
|
||||
method="elicitation/create",
|
||||
params=ElicitRequestFormParams(
|
||||
message="Which quarter should the summary cover?",
|
||||
requested_schema={
|
||||
"type": "object",
|
||||
"properties": {"quarter": {"type": "string"}},
|
||||
"required": ["quarter"],
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@mcp.prompt
|
||||
async def summarize(ctx: Context) -> str | InputRequiredResult:
|
||||
responses = ctx.input_responses
|
||||
if responses is None:
|
||||
return ask_for_quarter
|
||||
quarter = responses["quarter"].content["quarter"]
|
||||
return f"Summarize the {quarter} results."
|
||||
```
|
||||
|
||||
Resources and resource templates work the same way, with the URI standing in for the tool name:
|
||||
|
||||
```python
|
||||
@mcp.resource("report://summary")
|
||||
async def report(ctx: Context) -> str | InputRequiredResult:
|
||||
responses = ctx.input_responses
|
||||
if responses is None:
|
||||
return ask_for_quarter
|
||||
quarter = responses["quarter"].content["quarter"]
|
||||
return f"Revenue report for {quarter}"
|
||||
```
|
||||
|
||||
The same protocol requirement applies: returning an `InputRequiredResult` from a prompt or resource needs a 2026-07-28 connection, and FastMCP names the era mismatch if one arrives on an older one. Client-side, `read_resource` and `get_prompt` drive the loop the way `call_tool` does, so a configured elicitation handler answers all three without extra wiring.
|
||||
|
||||
### Sampling and roots
|
||||
|
||||
Elicitation is the most common request to carry this way, and **roots** requests work identically — the `input_requests` map holds them the same way, and each answer comes back in `ctx.input_responses` under its key (an `ElicitResult` or `ListRootsResult`). See [Client Roots](/clients/roots) for what a roots request contains. `fastmcp.Client` answers both from the handlers you already configured, so a guard tool that mixes them needs no extra client wiring.
|
||||
|
|
|
|||
|
|
@ -438,6 +438,10 @@ Notifications are only sent when these operations occur within an active MCP req
|
|||
|
||||
Clients can handle these notifications using a [message handler](/clients/notifications) to automatically refresh their prompt lists or update their interfaces.
|
||||
|
||||
## Requesting Input
|
||||
|
||||
A prompt can ask the client for information before it renders. On an MCP 2026-07-28 connection, return an `InputRequiredResult` describing what you need; the client answers and re-issues the `prompts/get`, and your function runs again with the answer on `ctx.input_responses`. See [Elicitation](/servers/elicitation#prompts-and-resources) for the full pattern.
|
||||
|
||||
## Server Behavior
|
||||
|
||||
### Duplicate Prompts
|
||||
|
|
|
|||
|
|
@ -783,6 +783,10 @@ def get_data_by_id(id: str) -> dict:
|
|||
|
||||
When `mask_error_details=True`, only error messages from `ResourceError` will include details, other exceptions will be converted to a generic message.
|
||||
|
||||
## Requesting Input
|
||||
|
||||
A resource or resource template can ask the client for information before it produces content. On an MCP 2026-07-28 connection, return an `InputRequiredResult` describing what you need; the client answers and re-issues the `resources/read`, and your function runs again with the answer on `ctx.input_responses`. See [Elicitation](/servers/elicitation#prompts-and-resources) for the full pattern.
|
||||
|
||||
## Server Behavior
|
||||
|
||||
### Duplicate Resources
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue