mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-20 12:34:17 +02:00
Silence ty deprecation diagnostics and drop stale sampling doc mentions
This commit is contained in:
parent
1a43a3b8e9
commit
90f2e190d0
6 changed files with 15 additions and 22 deletions
|
|
@ -238,7 +238,7 @@ Custom spans are most useful around work that is expensive or hard to debug:
|
|||
- External calls such as databases, vector stores, HTTP APIs, or queue operations
|
||||
- Multi-step tool logic where one stage dominates latency
|
||||
- Prompt or resource generation that fans out to other systems
|
||||
- Sampling calls made from inside a tool via `ctx.sample(...)`
|
||||
- LLM calls a tool makes to a model provider
|
||||
|
||||
Avoid wrapping every small helper function or simple in-memory transformation. That usually adds noise without making traces easier to interpret.
|
||||
|
||||
|
|
@ -286,9 +286,9 @@ async def docs_resource(slug: str) -> str:
|
|||
return await load_doc(slug)
|
||||
```
|
||||
|
||||
### Sampling calls inside tools
|
||||
### LLM calls inside tools
|
||||
|
||||
If your tool uses `ctx.sample(...)`, keep the LLM work nested under the tool span so traces show both application logic and model latency together.
|
||||
A tool that [calls an LLM directly](/servers/sampling) should keep the model work nested under the tool span, so traces show application logic and model latency together.
|
||||
|
||||
For providers with their own OTEL integrations, prefer enabling that instrumentation rather than manually creating a span around every model call. For example, if you use Google GenAI, `logfire.instrument_google_genai()` will emit child spans with token and request metadata under the active FastMCP tool span.
|
||||
|
||||
|
|
|
|||
|
|
@ -1063,15 +1063,9 @@ async def process_data(data_uri: str, ctx: Context) -> dict:
|
|||
|
||||
# Report progress
|
||||
await ctx.report_progress(progress=50, total=100)
|
||||
|
||||
# Example request to the client's LLM for help
|
||||
summary = await ctx.sample(f"Summarize this in 10 words: {data[:200]}")
|
||||
|
||||
|
||||
await ctx.report_progress(progress=100, total=100)
|
||||
return {
|
||||
"length": len(data),
|
||||
"summary": summary.text
|
||||
}
|
||||
return {"length": len(data)}
|
||||
```
|
||||
|
||||
The Context object provides access to:
|
||||
|
|
@ -1079,7 +1073,6 @@ The Context object provides access to:
|
|||
- **Logging**: `ctx.debug()`, `ctx.info()`, `ctx.warning()`, `ctx.error()`
|
||||
- **Progress Reporting**: `ctx.report_progress(progress, total)`
|
||||
- **Resource Access**: `ctx.read_resource(uri)`
|
||||
- **LLM Sampling**: `ctx.sample(...)`
|
||||
- **Request Information**: `ctx.request_id`, `ctx.client_id`
|
||||
|
||||
For full documentation on the Context object and all its capabilities, see the [Context documentation](/servers/context).
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ def fastmcp_server():
|
|||
|
||||
@mcp.tool
|
||||
async def list_roots(context: Context) -> list[str]:
|
||||
result = await context.session.list_roots()
|
||||
result = await context.session.list_roots() # ty: ignore[deprecated]
|
||||
return [str(r.uri) for r in result.roots]
|
||||
|
||||
return mcp
|
||||
|
|
@ -58,11 +58,9 @@ class TestClientRoots:
|
|||
|
||||
async def roots_handler(ctx) -> list[Root]:
|
||||
calls.append(ctx)
|
||||
return [Root(uri="file://from/handler")] # ty: ignore[invalid-argument-type]
|
||||
return [Root(uri="file://from/handler")]
|
||||
|
||||
async with Client(
|
||||
fastmcp_server, mode="legacy", roots=roots_handler
|
||||
) as client:
|
||||
async with Client(fastmcp_server, mode="legacy", roots=roots_handler) as client:
|
||||
result = await client.call_tool("list_roots", {})
|
||||
|
||||
assert len(calls) == 1
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ async def _sample(
|
|||
answering a legacy server, so the stand-in server reaches the SDK session
|
||||
directly.
|
||||
"""
|
||||
result = await context.session.create_message(
|
||||
result = await context.session.create_message( # ty: ignore[deprecated]
|
||||
messages=messages,
|
||||
system_prompt=system_prompt,
|
||||
max_tokens=512,
|
||||
|
|
@ -72,7 +72,9 @@ def fastmcp_server():
|
|||
),
|
||||
SamplingMessage(
|
||||
role="assistant",
|
||||
content=TextContent(type="text", text="How can I assist you today?"),
|
||||
content=TextContent(
|
||||
type="text", text="How can I assist you today?"
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -66,13 +66,13 @@ async def _backend_list_roots(context: Context) -> list[Root]:
|
|||
FastMCP's server API. These helpers reach the SDK session directly to stand
|
||||
in for a legacy upstream, which is the only thing the proxy relay forwards.
|
||||
"""
|
||||
result = await context.session.list_roots()
|
||||
result = await context.session.list_roots() # ty: ignore[deprecated]
|
||||
return result.roots
|
||||
|
||||
|
||||
async def _backend_sample(context: Context) -> str:
|
||||
"""Issue a handshake-era `sampling/createMessage` from a backend server."""
|
||||
result = await context.session.create_message(
|
||||
result = await context.session.create_message( # ty: ignore[deprecated]
|
||||
messages=[
|
||||
SamplingMessage(
|
||||
role="user", content=TextContent(type="text", text="Hello, world!")
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ def test_removed_server_initiated_methods_are_absent(name):
|
|||
def test_server_sampling_handler_kwargs_are_rejected(kwarg):
|
||||
"""The server-side sampling handler existed only to answer `ctx.sample()`."""
|
||||
with pytest.raises(TypeError, match="SEP-2577"):
|
||||
FastMCP("gone", **{kwarg: None})
|
||||
FastMCP("gone", **{kwarg: None}) # ty: ignore[invalid-argument-type]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", MODERN_MODES)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue