feat: Add SDK support for SEP-1034 default values in elicitation schemas (#1337)
Co-authored-by: Tapan Chugh <tapanc@cs.washington.edu> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
parent
c0f165776d
commit
b85e7bd1a9
2 changed files with 57 additions and 0 deletions
|
|
@ -747,6 +747,8 @@ async def book_table(date: str, time: str, party_size: int, ctx: Context[ServerS
|
||||||
_Full example: [examples/snippets/servers/elicitation.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py)_
|
_Full example: [examples/snippets/servers/elicitation.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/elicitation.py)_
|
||||||
<!-- /snippet-source -->
|
<!-- /snippet-source -->
|
||||||
|
|
||||||
|
Elicitation schemas support default values for all field types. Default values are automatically included in the JSON schema sent to clients, allowing them to pre-populate forms.
|
||||||
|
|
||||||
The `elicit()` method returns an `ElicitationResult` with:
|
The `elicit()` method returns an `ElicitationResult` with:
|
||||||
|
|
||||||
- `action`: "accept", "decline", or "cancel"
|
- `action`: "accept", "decline", or "cancel"
|
||||||
|
|
|
||||||
|
|
@ -213,3 +213,58 @@ async def test_elicitation_with_optional_fields():
|
||||||
{},
|
{},
|
||||||
text_contains=["Validation failed:", "optional_list"],
|
text_contains=["Validation failed:", "optional_list"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
async def test_elicitation_with_default_values():
|
||||||
|
"""Test that default values work correctly in elicitation schemas and are included in JSON."""
|
||||||
|
mcp = FastMCP(name="DefaultValuesServer")
|
||||||
|
|
||||||
|
class DefaultsSchema(BaseModel):
|
||||||
|
name: str = Field(default="Guest", description="User name")
|
||||||
|
age: int = Field(default=18, description="User age")
|
||||||
|
subscribe: bool = Field(default=True, description="Subscribe to newsletter")
|
||||||
|
email: str = Field(description="Email address (required)")
|
||||||
|
|
||||||
|
@mcp.tool(description="Tool with default values")
|
||||||
|
async def defaults_tool(ctx: Context[ServerSession, None]) -> str:
|
||||||
|
result = await ctx.elicit(message="Please provide your information", schema=DefaultsSchema)
|
||||||
|
|
||||||
|
if result.action == "accept" and result.data:
|
||||||
|
return (
|
||||||
|
f"Name: {result.data.name}, Age: {result.data.age}, "
|
||||||
|
f"Subscribe: {result.data.subscribe}, Email: {result.data.email}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return f"User {result.action}"
|
||||||
|
|
||||||
|
# First verify that defaults are present in the JSON schema sent to clients
|
||||||
|
async def callback_schema_verify(context: RequestContext[ClientSession, None], params: ElicitRequestParams):
|
||||||
|
# Verify the schema includes defaults
|
||||||
|
schema = params.requestedSchema
|
||||||
|
props = schema["properties"]
|
||||||
|
|
||||||
|
assert props["name"]["default"] == "Guest"
|
||||||
|
assert props["age"]["default"] == 18
|
||||||
|
assert props["subscribe"]["default"] is True
|
||||||
|
assert "default" not in props["email"] # Required field has no default
|
||||||
|
|
||||||
|
return ElicitResult(action="accept", content={"email": "test@example.com"})
|
||||||
|
|
||||||
|
await call_tool_and_assert(
|
||||||
|
mcp,
|
||||||
|
callback_schema_verify,
|
||||||
|
"defaults_tool",
|
||||||
|
{},
|
||||||
|
"Name: Guest, Age: 18, Subscribe: True, Email: test@example.com",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test overriding defaults
|
||||||
|
async def callback_override(context: RequestContext[ClientSession, None], params: ElicitRequestParams):
|
||||||
|
return ElicitResult(
|
||||||
|
action="accept", content={"email": "john@example.com", "name": "John", "age": 25, "subscribe": False}
|
||||||
|
)
|
||||||
|
|
||||||
|
await call_tool_and_assert(
|
||||||
|
mcp, callback_override, "defaults_tool", {}, "Name: John, Age: 25, Subscribe: False, Email: john@example.com"
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue