Skip to content

Commit 42fcffd

Browse files
committed
docs: quote the tools/list schemas exactly as the SDK sends them
Three JSON blocks introduced as the schema the SDK sends (two in tools.md, one in context.md) omitted the root "title" key the SDK emits, and one also dropped "type": "object". They now match the output byte for byte, the tutorial002 schema is pinned by a full snapshot like its siblings, and a survey of every schema block in the book found no other trimmed quote.
1 parent 12c4cd9 commit 42fcffd

3 files changed

Lines changed: 23 additions & 7 deletions

File tree

docs/tutorial/context.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ This is the part to internalise. Here is the input schema `tools/list` reports f
3232
"properties": {
3333
"query": {"title": "Query", "type": "string"}
3434
},
35-
"required": ["query"]
35+
"required": ["query"],
36+
"title": "search_booksArguments"
3637
}
3738
```
3839

docs/tutorial/tools.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ From those type hints the SDK generates a JSON Schema and sends it to the client
2727
"query": {"title": "Query", "type": "string"},
2828
"limit": {"title": "Limit", "type": "integer"}
2929
},
30-
"required": ["query", "limit"]
30+
"required": ["query", "limit"],
31+
"title": "search_booksArguments"
3132
}
3233
```
3334

34-
Both arguments are in `required` because neither has a default. You'll fix that in a moment.
35+
Both arguments are in `required` because neither has a default. You'll fix that in a moment. (The `title` keys are Pydantic artifacts; the properties, their types, and `required` are the contract.)
3536

3637
!!! tip
3738
Type hints aren't documentation here. They are **the contract**. If a client sends `"limit": "ten"`,
@@ -74,11 +75,13 @@ The schema follows:
7475

7576
```json
7677
{
78+
"type": "object",
7779
"properties": {
7880
"query": {"title": "Query", "type": "string"},
7981
"limit": {"default": 10, "title": "Limit", "type": "integer"}
8082
},
81-
"required": ["query"]
83+
"required": ["query"],
84+
"title": "search_booksArguments"
8285
}
8386
```
8487

tests/docs_src/test_tools.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,23 @@ async def test_call_returns_text_and_structured_content() -> None:
4040

4141

4242
async def test_default_value_makes_the_argument_optional() -> None:
43-
"""tutorial002: a plain Python default drops the argument from `required` and lands in the schema."""
43+
"""tutorial002: a plain Python default drops the argument from `required` and lands in the schema.
44+
45+
The whole schema is pinned because the page quotes it verbatim.
46+
"""
4447
async with Client(tutorial002.mcp) as client:
4548
(tool,) = (await client.list_tools()).tools
46-
assert tool.input_schema["required"] == ["query"]
47-
assert tool.input_schema["properties"]["limit"] == {"default": 10, "title": "Limit", "type": "integer"}
49+
assert tool.input_schema == snapshot(
50+
{
51+
"type": "object",
52+
"properties": {
53+
"query": {"title": "Query", "type": "string"},
54+
"limit": {"default": 10, "title": "Limit", "type": "integer"},
55+
},
56+
"required": ["query"],
57+
"title": "search_booksArguments",
58+
}
59+
)
4860
result = await client.call_tool("search_books", {"query": "dune"})
4961
assert result.structured_content == {"result": "Found 3 books matching 'dune' (showing up to 10)."}
5062

0 commit comments

Comments
 (0)