mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-22 05:24:18 +02:00
Skip repeated type conversion and validation in proxy client elicitation handler (#1222)
Co-authored-by: Tapan Chugh <tapanc@cs.washington.edu>
This commit is contained in:
parent
bde9515ced
commit
1da1eb581a
2 changed files with 51 additions and 5 deletions
|
|
@ -566,11 +566,12 @@ class ProxyClient(Client[ClientTransportT]):
|
|||
A handler that forwards the elicitation request from the remote server to the proxy's connected clients and relays the response back to the remote server.
|
||||
"""
|
||||
ctx = get_context()
|
||||
result = await ctx.elicit(message, response_type)
|
||||
if result.action == "accept":
|
||||
return result.data
|
||||
else:
|
||||
return ElicitResult(action=result.action)
|
||||
result = await ctx.session.elicit(
|
||||
message=message,
|
||||
requestedSchema=params.requestedSchema,
|
||||
related_request_id=ctx.request_id,
|
||||
)
|
||||
return ElicitResult(action=result.action, content=result.content)
|
||||
|
||||
@classmethod
|
||||
async def default_log_handler(cls, message: LogMessage) -> None:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from typing import cast
|
|||
import pytest
|
||||
from anyio import create_task_group
|
||||
from mcp.types import LoggingLevel, ModelHint, ModelPreferences, TextContent
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from fastmcp import Client, Context, FastMCP
|
||||
from fastmcp.client.elicitation import ElicitRequestParams, ElicitResult
|
||||
|
|
@ -330,6 +331,50 @@ class TestProxyClient:
|
|||
assert results["elicitation_a"] == "Hello, Alice!"
|
||||
assert results["elicitation_b"] == "Hello, Bob!"
|
||||
|
||||
async def test_elicit_with_default_values(self, fastmcp_server: FastMCP):
|
||||
"""
|
||||
Test that the proxy client correctly handles elicitation with default values (fixes #1167).
|
||||
"""
|
||||
|
||||
@fastmcp_server.tool
|
||||
async def elicit_with_defaults(context: Context) -> str:
|
||||
class TestModel(BaseModel):
|
||||
content: str = Field(description="Your reply content")
|
||||
acknowledge: bool = Field(
|
||||
default=False, description="Send immediately or save as draft"
|
||||
)
|
||||
|
||||
result = await context.elicit(
|
||||
"Please provide input:", response_type=TestModel
|
||||
)
|
||||
|
||||
if result.action == "accept":
|
||||
return f"Content: {result.data.content}, Acknowledge: {result.data.acknowledge}"
|
||||
else:
|
||||
return f"Elicitation {result.action}"
|
||||
|
||||
proxy_server = FastMCP.as_proxy(ProxyClient(fastmcp_server))
|
||||
|
||||
# Test that elicitation works correctly through the proxy
|
||||
async def elicitation_handler(
|
||||
message: str,
|
||||
response_type: type,
|
||||
params: ElicitRequestParams,
|
||||
ctx: RequestContext,
|
||||
):
|
||||
# Verify the schema is correct - acknowledge should have default=False, not be nullable
|
||||
schema = params.requestedSchema
|
||||
assert schema["properties"]["acknowledge"]["type"] == "boolean"
|
||||
assert schema["properties"]["acknowledge"]["default"] is False
|
||||
|
||||
return {"content": "Test content", "acknowledge": True}
|
||||
|
||||
async with Client(
|
||||
proxy_server, elicitation_handler=elicitation_handler
|
||||
) as client:
|
||||
result = await client.call_tool("elicit_with_defaults", {})
|
||||
assert result.data == "Content: Test content, Acknowledge: True"
|
||||
|
||||
async def test_client_factory_creates_fresh_sessions(self, fastmcp_server: FastMCP):
|
||||
"""Test that the client factory pattern creates fresh sessions for each request."""
|
||||
from fastmcp.server.proxy import FastMCPProxy
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue