refactor: use snake case instead of camel case in types (#1894)

This commit is contained in:
Marcelo Trylesinski 2026-01-16 15:51:27 +01:00 • committed by GitHub
commit e94b386a13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
127 changed files with 1063 additions and 1057 deletions

View file

@ -442,7 +442,7 @@ def validated_tool() -> Annotated[CallToolResult, ValidationModel]:
"""Return CallToolResult with structured output validation."""
return CallToolResult(
content=[TextContent(type="text", text="Validated response")],
structuredContent={"status": "success", "data": {"result": 42}},
structured_content={"status": "success", "data": {"result": 42}},
_meta={"internal": "metadata"},
)
@ -757,8 +757,8 @@ async def run():
# List available resource templates
templates = await session.list_resource_templates()
print("Available resource templates:")
for template in templates.resourceTemplates:
print(f" - {template.uriTemplate}")
for template in templates.resource_templates:
print(f" - {template.uri_template}")
# List available prompts
prompts = await session.list_prompts()
@ -767,20 +767,20 @@ async def run():
print(f" - {prompt.name}")
# Complete resource template arguments
if templates.resourceTemplates:
template = templates.resourceTemplates[0]
print(f"\nCompleting arguments for resource template: {template.uriTemplate}")
if templates.resource_templates:
template = templates.resource_templates[0]
print(f"\nCompleting arguments for resource template: {template.uri_template}")
# Complete without context
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
ref=ResourceTemplateReference(type="ref/resource", uri=template.uri_template),
argument={"name": "owner", "value": "model"},
)
print(f"Completions for 'owner' starting with 'model': {result.completion.values}")
# Complete with context - repo suggestions based on owner
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
ref=ResourceTemplateReference(type="ref/resource", uri=template.uri_template),
argument={"name": "repo", "value": ""},
context_arguments={"owner": "modelcontextprotocol"},
)
@ -910,7 +910,7 @@ async def connect_service(service_name: str, ctx: Context[ServerSession, None])
mode="url",
message=f"Authorization required to connect to {service_name}",
url=f"https://{service_name}.example.com/oauth/authorize?elicit={elicitation_id}",
elicitationId=elicitation_id,
elicitation_id=elicitation_id,
)
]
)
@ -1706,7 +1706,7 @@ async def handle_list_tools() -> list[types.Tool]:
types.Tool(
name="query_db",
description="Query the database",
inputSchema={
input_schema={
"type": "object",
"properties": {"query": {"type": "string", "description": "SQL query to execute"}},
"required": ["query"],
@ -1867,12 +1867,12 @@ async def list_tools() -> list[types.Tool]:
types.Tool(
name="get_weather",
description="Get current weather for a city",
inputSchema={
input_schema={
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
},
outputSchema={
output_schema={
"type": "object",
"properties": {
"temperature": {"type": "number", "description": "Temperature in Celsius"},
@ -1970,7 +1970,7 @@ async def list_tools() -> list[types.Tool]:
types.Tool(
name="advanced_tool",
description="Tool with full control including _meta field",
inputSchema={
input_schema={
"type": "object",
"properties": {"message": {"type": "string"}},
"required": ["message"],
@ -1986,7 +1986,7 @@ async def handle_call_tool(name: str, arguments: dict[str, Any]) -> types.CallTo
message = str(arguments.get("message", ""))
return types.CallToolResult(
content=[types.TextContent(type="text", text=f"Processed: {message}")],
structuredContent={"result": "success", "message": message},
structured_content={"result": "success", "message": message},
_meta={"hidden": "data for client applications only"},
)
@ -2062,7 +2062,7 @@ async def list_resources_paginated(request: types.ListResourcesRequest) -> types
# Determine next cursor
next_cursor = str(end) if end < len(ITEMS) else None
return types.ListResourcesResult(resources=page_items, nextCursor=next_cursor)
return types.ListResourcesResult(resources=page_items, next_cursor=next_cursor)
```
_Full example: [examples/snippets/servers/pagination_example.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/pagination_example.py)_
@ -2103,8 +2103,8 @@ async def list_all_resources() -> None:
print(f"Fetched {len(result.resources)} resources")
# Check if there are more pages
if result.nextCursor:
cursor = result.nextCursor
if result.next_cursor:
cursor = result.next_cursor
else:
break
@ -2167,7 +2167,7 @@ async def handle_sampling_message(
text="Hello, world! from model",
),
model="gpt-3.5-turbo",
stopReason="endTurn",
stop_reason="endTurn",
)
@ -2205,7 +2205,7 @@ async def run():
result_unstructured = result.content[0]
if isinstance(result_unstructured, types.TextContent):
print(f"Tool result: {result_unstructured.text}")
result_structured = result.structuredContent
result_structured = result.structured_content
print(f"Structured tool result: {result_structured}")
@ -2306,7 +2306,7 @@ async def display_resources(session: ClientSession):
print(f"Resource: {display_name} ({resource.uri})")
templates_response = await session.list_resource_templates()
for template in templates_response.resourceTemplates:
for template in templates_response.resource_templates:
display_name = get_display_name(template)
print(f"Resource Template: {display_name}")

View file

@ -112,7 +112,7 @@ class Server:
for item in tools_response:
if item[0] == "tools":
tools.extend(Tool(tool.name, tool.description, tool.inputSchema, tool.title) for tool in item[1])
tools.extend(Tool(tool.name, tool.description, tool.input_schema, tool.title) for tool in item[1])
return tools

View file

@ -25,13 +25,13 @@ async def run(url: str) -> None:
arguments={},
ttl=60000,
)
task_id = result.task.taskId
task_id = result.task.task_id
print(f"Task created: {task_id}")
status = None
# Poll until done (respects server's pollInterval hint)
async for status in session.experimental.poll_task(task_id):
print(f" Status: {status.status} - {status.statusMessage or ''}")
print(f" Status: {status.status} - {status.status_message or ''}")
# Check final status
if status and status.status != "completed":

View file

@ -49,7 +49,7 @@ async def sampling_callback(context, params) -> CreateMessageResult:
```python
# Call a tool as a task (returns immediately with task reference)
result = await session.experimental.call_tool_as_task("tool_name", {"arg": "value"})
task_id = result.task.taskId
task_id = result.task.task_id
# Get result - this delivers elicitation/sampling requests and blocks until complete
final = await session.experimental.get_task_result(task_id, CallToolResult)

View file

@ -91,7 +91,7 @@ async def run(url: str) -> None:
print("Calling confirm_delete tool...")
elicit_task = await session.experimental.call_tool_as_task("confirm_delete", {"filename": "important.txt"})
elicit_task_id = elicit_task.task.taskId
elicit_task_id = elicit_task.task.task_id
print(f"Task created: {elicit_task_id}")
# Poll until terminal, calling tasks/result on input_required
@ -112,7 +112,7 @@ async def run(url: str) -> None:
print("Calling write_haiku tool...")
sampling_task = await session.experimental.call_tool_as_task("write_haiku", {"topic": "autumn leaves"})
sampling_task_id = sampling_task.task.taskId
sampling_task_id = sampling_task.task.task_id
print(f"Task created: {sampling_task_id}")
# Poll until terminal, calling tasks/result on input_required

View file

@ -20,5 +20,5 @@ class EchoResponse(BaseModel):
def echo(text: str) -> Annotated[CallToolResult, EchoResponse]:
"""Echo the input text with structure and metadata"""
return CallToolResult(
content=[TextContent(type="text", text=text)], structuredContent={"text": text}, _meta={"some": "metadata"}
content=[TextContent(type="text", text=text)], structured_content={"text": text}, _meta={"some": "metadata"}
)

View file

@ -14,7 +14,7 @@ icon_path = Path(__file__).parent / "mcp.png"
icon_data = base64.standard_b64encode(icon_path.read_bytes()).decode()
icon_data_uri = f"data:image/png;base64,{icon_data}"
icon_data = Icon(src=icon_data_uri, mimeType="image/png", sizes=["64x64"])
icon_data = Icon(src=icon_data_uri, mime_type="image/png", sizes=["64x64"])
# Create server with icons in implementation
mcp = FastMCP("Icons Demo Server", website_url="https://github.com/modelcontextprotocol/python-sdk", icons=[icon_data])
@ -40,9 +40,9 @@ def prompt_with_icon(text: str) -> str:
@mcp.tool(
icons=[
Icon(src=icon_data_uri, mimeType="image/png", sizes=["16x16"]),
Icon(src=icon_data_uri, mimeType="image/png", sizes=["32x32"]),
Icon(src=icon_data_uri, mimeType="image/png", sizes=["64x64"]),
Icon(src=icon_data_uri, mime_type="image/png", sizes=["16x16"]),
Icon(src=icon_data_uri, mime_type="image/png", sizes=["32x32"]),
Icon(src=icon_data_uri, mime_type="image/png", sizes=["64x64"]),
]
)
def multi_icon_tool(action: str) -> str:

View file

@ -161,32 +161,32 @@ if __name__ == "__main__":
# Test get_weather
result = await client.call_tool("get_weather", {"city": "London"})
print("\nWeather in London:")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Test get_weather_summary
result = await client.call_tool("get_weather_summary", {"city": "Paris"})
print("\nWeather summary for Paris:")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Test get_weather_metrics
result = await client.call_tool("get_weather_metrics", {"cities": ["Tokyo", "Sydney", "Mumbai"]})
print("\nWeather metrics:")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Test get_weather_alerts
result = await client.call_tool("get_weather_alerts", {"region": "California"})
print("\nWeather alerts for California:")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Test get_temperature
result = await client.call_tool("get_temperature", {"city": "Berlin", "unit": "fahrenheit"})
print("\nTemperature in Berlin:")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Test get_weather_stats
result = await client.call_tool("get_weather_stats", {"city": "Seattle", "days": 30})
print("\nWeather stats for Seattle (30 days):")
print(json.dumps(result.structuredContent, indent=2))
print(json.dumps(result.structured_content, indent=2))
# Also show the text content for comparison
print("\nText content for last result:")
@ -204,11 +204,11 @@ if __name__ == "__main__":
print(f"\nTool: {tool.name}")
print(f"Description: {tool.description}")
print("Input Schema:")
print(json.dumps(tool.inputSchema, indent=2))
print(json.dumps(tool.input_schema, indent=2))
if tool.outputSchema:
if tool.output_schema:
print("Output Schema:")
print(json.dumps(tool.outputSchema, indent=2))
print(json.dumps(tool.output_schema, indent=2))
else:
print("Output Schema: None (returns unstructured content)")

View file

@ -98,13 +98,13 @@ def test_simple_text() -> str:
@mcp.tool()
def test_image_content() -> list[ImageContent]:
"""Tests image content response"""
return [ImageContent(type="image", data=TEST_IMAGE_BASE64, mimeType="image/png")]
return [ImageContent(type="image", data=TEST_IMAGE_BASE64, mime_type="image/png")]
@mcp.tool()
def test_audio_content() -> list[AudioContent]:
"""Tests audio content response"""
return [AudioContent(type="audio", data=TEST_AUDIO_BASE64, mimeType="audio/wav")]
return [AudioContent(type="audio", data=TEST_AUDIO_BASE64, mime_type="audio/wav")]
@mcp.tool()
@ -115,7 +115,7 @@ def test_embedded_resource() -> list[EmbeddedResource]:
type="resource",
resource=TextResourceContents(
uri="test://embedded-resource",
mimeType="text/plain",
mime_type="text/plain",
text="This is an embedded resource content.",
),
)
@ -127,12 +127,12 @@ def test_multiple_content_types() -> list[TextContent | ImageContent | EmbeddedR
"""Tests response with multiple content types (text, image, resource)"""
return [
TextContent(type="text", text="Multiple content types test:"),
ImageContent(type="image", data=TEST_IMAGE_BASE64, mimeType="image/png"),
ImageContent(type="image", data=TEST_IMAGE_BASE64, mime_type="image/png"),
EmbeddedResource(
type="resource",
resource=TextResourceContents(
uri="test://mixed-content-resource",
mimeType="application/json",
mime_type="application/json",
text='{"test": "data", "value": 123}',
),
),
@ -164,7 +164,7 @@ async def test_tool_with_progress(ctx: Context[ServerSession, None]) -> str:
await ctx.report_progress(progress=100, total=100, message="Completed step 100 of 100")
# Return progress token as string
progress_token = ctx.request_context.meta.progressToken if ctx.request_context and ctx.request_context.meta else 0
progress_token = ctx.request_context.meta.progress_token if ctx.request_context and ctx.request_context.meta else 0
return str(progress_token)
@ -373,7 +373,7 @@ def test_prompt_with_embedded_resource(resourceUri: str) -> list[UserMessage]:
type="resource",
resource=TextResourceContents(
uri=resourceUri,
mimeType="text/plain",
mime_type="text/plain",
text="Embedded resource content for testing.",
),
),
@ -386,7 +386,7 @@ def test_prompt_with_embedded_resource(resourceUri: str) -> list[UserMessage]:
def test_prompt_with_image() -> list[UserMessage]:
"""A prompt that includes image content"""
return [
UserMessage(role="user", content=ImageContent(type="image", data=TEST_IMAGE_BASE64, mimeType="image/png")),
UserMessage(role="user", content=ImageContent(type="image", data=TEST_IMAGE_BASE64, mime_type="image/png")),
UserMessage(role="user", content=TextContent(type="text", text="Please analyze the image above.")),
]
@ -427,7 +427,7 @@ async def _handle_completion(
"""Handle completion requests"""
# Basic completion support - returns empty array for conformance
# Real implementations would provide contextual suggestions
return Completion(values=[], total=0, hasMore=False)
return Completion(values=[], total=0, has_more=False)
# CLI

View file

@ -19,7 +19,7 @@ SAMPLE_TOOLS = [
name=f"tool_{i}",
title=f"Tool {i}",
description=f"This is sample tool number {i}",
inputSchema={"type": "object", "properties": {"input": {"type": "string"}}},
input_schema={"type": "object", "properties": {"input": {"type": "string"}}},
)
for i in range(1, 26) # 25 tools total
]
@ -71,7 +71,7 @@ def main(port: int, transport: str) -> int:
start_idx = int(cursor)
except (ValueError, TypeError):
# Invalid cursor, return empty
return types.ListToolsResult(tools=[], nextCursor=None)
return types.ListToolsResult(tools=[], next_cursor=None)
# Get the page of tools
page_tools = SAMPLE_TOOLS[start_idx : start_idx + page_size]
@ -81,7 +81,7 @@ def main(port: int, transport: str) -> int:
if start_idx + page_size < len(SAMPLE_TOOLS):
next_cursor = str(start_idx + page_size)
return types.ListToolsResult(tools=page_tools, nextCursor=next_cursor)
return types.ListToolsResult(tools=page_tools, next_cursor=next_cursor)
# Paginated list_resources - returns 10 resources per page
@app.list_resources()
@ -100,7 +100,7 @@ def main(port: int, transport: str) -> int:
start_idx = int(cursor)
except (ValueError, TypeError):
# Invalid cursor, return empty
return types.ListResourcesResult(resources=[], nextCursor=None)
return types.ListResourcesResult(resources=[], next_cursor=None)
# Get the page of resources
page_resources = SAMPLE_RESOURCES[start_idx : start_idx + page_size]
@ -110,7 +110,7 @@ def main(port: int, transport: str) -> int:
if start_idx + page_size < len(SAMPLE_RESOURCES):
next_cursor = str(start_idx + page_size)
return types.ListResourcesResult(resources=page_resources, nextCursor=next_cursor)
return types.ListResourcesResult(resources=page_resources, next_cursor=next_cursor)
# Paginated list_prompts - returns 7 prompts per page
@app.list_prompts()
@ -129,7 +129,7 @@ def main(port: int, transport: str) -> int:
start_idx = int(cursor)
except (ValueError, TypeError):
# Invalid cursor, return empty
return types.ListPromptsResult(prompts=[], nextCursor=None)
return types.ListPromptsResult(prompts=[], next_cursor=None)
# Get the page of prompts
page_prompts = SAMPLE_PROMPTS[start_idx : start_idx + page_size]
@ -139,7 +139,7 @@ def main(port: int, transport: str) -> int:
if start_idx + page_size < len(SAMPLE_PROMPTS):
next_cursor = str(start_idx + page_size)
return types.ListPromptsResult(prompts=page_prompts, nextCursor=next_cursor)
return types.ListPromptsResult(prompts=page_prompts, next_cursor=next_cursor)
# Implement call_tool handler
@app.call_tool()

View file

@ -40,7 +40,7 @@ def main(port: int, transport: str) -> int:
name=name,
title=SAMPLE_RESOURCES[name]["title"],
description=f"A sample text resource named {name}",
mimeType="text/plain",
mime_type="text/plain",
)
for name in SAMPLE_RESOURCES.keys()
]

View file

@ -73,7 +73,7 @@ def main(
types.Tool(
name="start-notification-stream",
description=("Sends a stream of notifications with configurable count and interval"),
inputSchema={
input_schema={
"type": "object",
"required": ["interval", "count", "caller"],
"properties": {

View file

@ -87,7 +87,7 @@ def main(
types.Tool(
name="start-notification-stream",
description=("Sends a stream of notifications with configurable count and interval"),
inputSchema={
input_schema={
"type": "object",
"required": ["interval", "count", "caller"],
"properties": {

View file

@ -31,17 +31,17 @@ async def list_tools() -> list[types.Tool]:
types.Tool(
name="confirm_delete",
description="Asks for confirmation before deleting (demonstrates elicitation)",
inputSchema={
input_schema={
"type": "object",
"properties": {"filename": {"type": "string"}},
},
execution=types.ToolExecution(taskSupport=types.TASK_REQUIRED),
execution=types.ToolExecution(task_support=types.TASK_REQUIRED),
),
types.Tool(
name="write_haiku",
description="Asks LLM to write a haiku (demonstrates sampling)",
inputSchema={"type": "object", "properties": {"topic": {"type": "string"}}},
execution=types.ToolExecution(taskSupport=types.TASK_REQUIRED),
input_schema={"type": "object", "properties": {"topic": {"type": "string"}}},
execution=types.ToolExecution(task_support=types.TASK_REQUIRED),
),
]
@ -59,7 +59,7 @@ async def handle_confirm_delete(arguments: dict[str, Any]) -> types.CreateTaskRe
result = await task.elicit(
message=f"Are you sure you want to delete '{filename}'?",
requestedSchema={
requested_schema={
"type": "object",
"properties": {"confirm": {"type": "boolean"}},
"required": ["confirm"],
@ -121,7 +121,7 @@ async def handle_call_tool(name: str, arguments: dict[str, Any]) -> types.CallTo
else:
return types.CallToolResult(
content=[types.TextContent(type="text", text=f"Unknown tool: {name}")],
isError=True,
is_error=True,
)

View file

@ -26,8 +26,8 @@ async def list_tools() -> list[types.Tool]:
types.Tool(
name="long_running_task",
description="A task that takes a few seconds to complete with status updates",
inputSchema={"type": "object", "properties": {}},
execution=types.ToolExecution(taskSupport=types.TASK_REQUIRED),
input_schema={"type": "object", "properties": {}},
execution=types.ToolExecution(task_support=types.TASK_REQUIRED),
)
]
@ -60,7 +60,7 @@ async def handle_call_tool(name: str, arguments: dict[str, Any]) -> types.CallTo
else:
return types.CallToolResult(
content=[types.TextContent(type="text", text=f"Unknown tool: {name}")],
isError=True,
is_error=True,
)

View file

@ -44,7 +44,7 @@ def main(port: int, transport: str) -> int:
name="fetch",
title="Website Fetcher",
description="Fetches a website and returns its content",
inputSchema={
input_schema={
"type": "object",
"required": ["url"],
"properties": {

View file

@ -120,7 +120,7 @@ def main(port: int, log_level: str, retry_interval: int) -> int:
"Process a batch of items with periodic checkpoints. "
"Demonstrates SSE polling where server closes stream periodically."
),
inputSchema={
input_schema={
"type": "object",
"properties": {
"items": {

View file

@ -27,12 +27,12 @@ async def list_tools() -> list[types.Tool]:
types.Tool(
name="get_weather",
description="Get weather information (simulated)",
inputSchema={
input_schema={
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
},
outputSchema={
output_schema={
"type": "object",
"properties": {
"temperature": {"type": "number"},

View file

@ -28,8 +28,8 @@ async def run():
# List available resource templates
templates = await session.list_resource_templates()
print("Available resource templates:")
for template in templates.resourceTemplates:
print(f" - {template.uriTemplate}")
for template in templates.resource_templates:
print(f" - {template.uri_template}")
# List available prompts
prompts = await session.list_prompts()
@ -38,20 +38,20 @@ async def run():
print(f" - {prompt.name}")
# Complete resource template arguments
if templates.resourceTemplates:
template = templates.resourceTemplates[0]
print(f"\nCompleting arguments for resource template: {template.uriTemplate}")
if templates.resource_templates:
template = templates.resource_templates[0]
print(f"\nCompleting arguments for resource template: {template.uri_template}")
# Complete without context
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
ref=ResourceTemplateReference(type="ref/resource", uri=template.uri_template),
argument={"name": "owner", "value": "model"},
)
print(f"Completions for 'owner' starting with 'model': {result.completion.values}")
# Complete with context - repo suggestions based on owner
result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri=template.uriTemplate),
ref=ResourceTemplateReference(type="ref/resource", uri=template.uri_template),
argument={"name": "repo", "value": ""},
context_arguments={"owner": "modelcontextprotocol"},
)

View file

@ -39,7 +39,7 @@ async def display_resources(session: ClientSession):
print(f"Resource: {display_name} ({resource.uri})")
templates_response = await session.list_resource_templates()
for template in templates_response.resourceTemplates:
for template in templates_response.resource_templates:
display_name = get_display_name(template)
print(f"Resource Template: {display_name}")

Some files were not shown because too many files have changed in this diff Show more