diff --git a/fastmcp_slim/fastmcp/cli/apps_dev.py b/fastmcp_slim/fastmcp/cli/apps_dev.py index b4074b14b..8a7e0ba46 100644 --- a/fastmcp_slim/fastmcp/cli/apps_dev.py +++ b/fastmcp_slim/fastmcp/cli/apps_dev.py @@ -792,7 +792,7 @@ _LOG_PANEL_HTML = """\ function renderEntry(entry) { var div = document.createElement("div"); var isError = entry.direction === "response" && entry.body - && (entry.body.error || (entry.body.result && entry.body.result.isError)); + && (entry.body.error || (entry.body.result && entry.body.result.is_error)); div.className = "log-entry" + (isError ? " error" : ""); var dirClass = isError ? "error" : entry.direction; var arrows = {request: "\u2192", response: "\u2190", bridge: "\u2191", notification: "\u2193"}; diff --git a/fastmcp_slim/fastmcp/cli/client.py b/fastmcp_slim/fastmcp/cli/client.py index 9b7b876bf..73fe46815 100644 --- a/fastmcp_slim/fastmcp/cli/client.py +++ b/fastmcp_slim/fastmcp/cli/client.py @@ -191,7 +191,7 @@ async def _terminal_elicitation_handler( return ElicitResult(action="cancel") return ElicitResult(action="accept", content={}) - schema = params.requestedSchema + schema = params.requested_schema properties = schema.get("properties", {}) required = set(schema.get("required", [])) @@ -371,7 +371,7 @@ def format_tool_signature(tool: mcp_types.Tool) -> str: """Build ``name(param: type, ...) -> return_type`` from a tool's JSON schemas.""" params: list[str] = [] - schema = tool.inputSchema + schema = tool.input_schema properties = schema.get("properties", {}) required = set(schema.get("required", [])) @@ -386,8 +386,8 @@ def format_tool_signature(tool: mcp_types.Tool) -> str: sig = f"{tool.name}({', '.join(params)})" - if tool.outputSchema: - ret = _json_schema_type_to_str(tool.outputSchema) + if tool.output_schema: + ret = _json_schema_type_to_str(tool.output_schema) sig += f" -> {ret}" return sig @@ -441,10 +441,10 @@ def _format_call_result_text(result: CallToolResult) -> None: console.print(_sanitize_untrusted_text(block.text)) elif isinstance(block, mcp_types.ImageContent): size = len(block.data) * 3 // 4 # rough decoded size - console.print(f"[dim][Image: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Image: {block.mime_type}, ~{size} bytes][/dim]") elif isinstance(block, mcp_types.AudioContent): size = len(block.data) * 3 // 4 - console.print(f"[dim][Audio: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Audio: {block.mime_type}, ~{size} bytes][/dim]") else: console.print(_sanitize_untrusted_text(str(block))) @@ -454,9 +454,9 @@ def _content_block_to_dict(block: mcp_types.ContentBlock) -> dict[str, Any]: if isinstance(block, mcp_types.TextContent): return {"type": "text", "text": block.text} if isinstance(block, mcp_types.ImageContent): - return {"type": "image", "mimeType": block.mimeType, "data": block.data} + return {"type": "image", "mimeType": block.mime_type, "data": block.data} if isinstance(block, mcp_types.AudioContent): - return {"type": "audio", "mimeType": block.mimeType, "data": block.data} + return {"type": "audio", "mimeType": block.mime_type, "data": block.data} return {"type": "unknown", "value": str(block)} @@ -477,8 +477,8 @@ def _tools_to_json(tools: list[mcp_types.Tool]) -> list[dict[str, Any]]: { "name": t.name, "description": t.description, - "inputSchema": t.inputSchema, - **({"outputSchema": t.outputSchema} if t.outputSchema else {}), + "inputSchema": t.input_schema, + **({"outputSchema": t.output_schema} if t.output_schema else {}), } for t in tools ] @@ -512,9 +512,9 @@ async def _handle_tool_call( sys.exit(1) tool = tool_map[tool_name] - parsed_args = parse_tool_arguments(arguments, input_json, tool.inputSchema) + parsed_args = parse_tool_arguments(arguments, input_json, tool.input_schema) - required = set(tool.inputSchema.get("required", [])) + required = set(tool.input_schema.get("required", [])) provided = set(parsed_args.keys()) missing = required - provided if missing: @@ -553,7 +553,7 @@ async def _handle_resource( data.append( { "uri": str(block.uri), - "mimeType": block.mimeType, + "mimeType": block.mime_type, "text": block.text, } ) @@ -561,7 +561,7 @@ async def _handle_resource( data.append( { "uri": str(block.uri), - "mimeType": block.mimeType, + "mimeType": block.mime_type, "blob": block.blob, } ) @@ -573,7 +573,7 @@ async def _handle_resource( console.print(_sanitize_untrusted_text(block.text)) elif isinstance(block, mcp_types.BlobResourceContents): size = len(block.blob) * 3 // 4 - console.print(f"[dim][Blob: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Blob: {block.mime_type}, ~{size} bytes][/dim]") async def _handle_prompt( @@ -626,7 +626,7 @@ async def _handle_prompt( elif isinstance(msg.content, mcp_types.ImageContent): size = len(msg.content.data) * 3 // 4 console.print( - f" [dim][Image: {msg.content.mimeType}, ~{size} bytes][/dim]" + f" [dim][Image: {msg.content.mime_type}, ~{size} bytes][/dim]" ) else: console.print(f" {_sanitize_untrusted_text(str(msg.content))}") @@ -718,7 +718,7 @@ async def list_command( "uri": str(r.uri), "name": r.name, "description": r.description, - "mimeType": r.mimeType, + "mimeType": r.mime_type, } for r in res ] @@ -749,9 +749,9 @@ async def list_command( f" {_sanitize_untrusted_text(tool.description)}" ) if input_schema: - _print_schema("Input", tool.inputSchema) - if output_schema and tool.outputSchema: - _print_schema("Output", tool.outputSchema) + _print_schema("Input", tool.input_schema) + if output_schema and tool.output_schema: + _print_schema("Output", tool.output_schema) console.print() if resources: diff --git a/fastmcp_slim/fastmcp/cli/generate.py b/fastmcp_slim/fastmcp/cli/generate.py index 0530e13a8..14577655e 100644 --- a/fastmcp_slim/fastmcp/cli/generate.py +++ b/fastmcp_slim/fastmcp/cli/generate.py @@ -165,7 +165,7 @@ def _to_python_identifier(name: str) -> str: def _tool_function_source(tool: mcp_types.Tool) -> str: """Generate the source for a single ``@call_tool_app.command`` function.""" - schema = tool.inputSchema + schema = tool.input_schema properties: dict[str, Any] = schema.get("properties", {}) required = set(schema.get("required", [])) @@ -361,10 +361,10 @@ def generate_cli_script( console.print(block.text) elif isinstance(block, mcp_types.ImageContent): size = len(block.data) * 3 // 4 - console.print(f"[dim][Image: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Image: {block.mime_type}, ~{size} bytes][/dim]") elif isinstance(block, mcp_types.AudioContent): size = len(block.data) * 3 // 4 - console.print(f"[dim][Audio: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Audio: {block.mime_type}, ~{size} bytes][/dim]") async def _call_tool(tool_name: str, arguments: dict) -> None: @@ -401,8 +401,8 @@ def generate_cli_script( return for tool in tools: sig_parts = [] - props = tool.inputSchema.get("properties", {}) - required = set(tool.inputSchema.get("required", [])) + props = tool.input_schema.get("properties", {}) + required = set(tool.input_schema.get("required", [])) for pname, pschema in props.items(): ptype = pschema.get("type", "string") if pname in required: @@ -443,7 +443,7 @@ def generate_cli_script( console.print(block.text) elif isinstance(block, mcp_types.BlobResourceContents): size = len(block.blob) * 3 // 4 - console.print(f"[dim][Blob: {block.mimeType}, ~{size} bytes][/dim]") + console.print(f"[dim][Blob: {block.mime_type}, ~{size} bytes][/dim]") @app.command @@ -487,7 +487,7 @@ def generate_cli_script( console.print(f" {msg.content.text}") elif isinstance(msg.content, mcp_types.ImageContent): size = len(msg.content.data) * 3 // 4 - console.print(f" [dim][Image: {msg.content.mimeType}, ~{size} bytes][/dim]") + console.print(f" [dim][Image: {msg.content.mime_type}, ~{size} bytes][/dim]") else: console.print(f" {msg.content}") console.print()""") @@ -566,7 +566,7 @@ def _schema_type_label(prop_schema: dict[str, Any]) -> str: def _tool_skill_section(tool: mcp_types.Tool, cli_filename: str) -> str: """Generate a SKILL.md section for a single tool.""" - schema = tool.inputSchema + schema = tool.input_schema properties: dict[str, Any] = schema.get("properties", {}) required = set(schema.get("required", [])) diff --git a/fastmcp_slim/fastmcp/client/client.py b/fastmcp_slim/fastmcp/client/client.py index 98847dd62..0cb91c40e 100644 --- a/fastmcp_slim/fastmcp/client/client.py +++ b/fastmcp_slim/fastmcp/client/client.py @@ -511,7 +511,7 @@ class Client( client = Client(server, auto_initialize=False) async with client: result = await client.initialize() - print(f"Server: {result.serverInfo.name}") + print(f"Server: {result.server_info.name}") print(f"Instructions: {result.instructions}") ``` """ @@ -782,7 +782,7 @@ class Client( Updates Task object's cache and triggers events/callbacks. """ # Extract task ID from notification params - task_id = notification.params.taskId + task_id = notification.params.task_id if not task_id: return diff --git a/fastmcp_slim/fastmcp/client/elicitation.py b/fastmcp_slim/fastmcp/client/elicitation.py index 50778dc6e..10291fffd 100644 --- a/fastmcp_slim/fastmcp/client/elicitation.py +++ b/fastmcp_slim/fastmcp/client/elicitation.py @@ -45,10 +45,10 @@ def create_elicitation_callback( try: # requestedSchema only exists on ElicitRequestFormParams, not ElicitRequestURLParams if isinstance(params, ElicitRequestFormParams): - if params.requestedSchema == {"type": "object", "properties": {}}: + if params.requested_schema == {"type": "object", "properties": {}}: response_type = None else: - response_type = json_schema_to_type(params.requestedSchema) + response_type = json_schema_to_type(params.requested_schema) else: # URL-based elicitation doesn't have a schema response_type = None @@ -65,7 +65,7 @@ def create_elicitation_callback( # (single "value" property). This lets handlers return T directly # for ctx.elicit("msg", str/int/float/bool). if isinstance(params, ElicitRequestFormParams) and set( - params.requestedSchema.get("properties", {}).keys() + params.requested_schema.get("properties", {}).keys() ) == {"value"}: content = {"value": content} else: diff --git a/fastmcp_slim/fastmcp/client/mixins/prompts.py b/fastmcp_slim/fastmcp/client/mixins/prompts.py index c790e033c..b45cb7f07 100644 --- a/fastmcp_slim/fastmcp/client/mixins/prompts.py +++ b/fastmcp_slim/fastmcp/client/mixins/prompts.py @@ -89,16 +89,16 @@ class ClientPromptsMixin: for _ in range(max_pages): result = await self.list_prompts_mcp(cursor=cursor) all_prompts.extend(result.prompts) - if not result.nextCursor: + if not result.next_cursor: break - if result.nextCursor in seen_cursors: + if result.next_cursor in seen_cursors: logger.warning( f"[{self.name}] Server returned duplicate pagination cursor" - f" {result.nextCursor!r} for list_prompts; stopping pagination" + f" {result.next_cursor!r} for list_prompts; stopping pagination" ) break - seen_cursors.add(result.nextCursor) - cursor = result.nextCursor + seen_cursors.add(result.next_cursor) + cursor = result.next_cursor else: raise RuntimeError( f"[{self.name}] Reached auto-pagination limit" @@ -311,7 +311,7 @@ class ClientPromptsMixin: if isinstance(raw_result, mcp_types.CreateTaskResult): # Task was accepted - extract task info from CreateTaskResult - server_task_id = raw_result.task.taskId + server_task_id = raw_result.task.task_id self._submitted_task_ids.add(server_task_id) task_obj = PromptTask( diff --git a/fastmcp_slim/fastmcp/client/mixins/resources.py b/fastmcp_slim/fastmcp/client/mixins/resources.py index 58445206d..073ed29e8 100644 --- a/fastmcp_slim/fastmcp/client/mixins/resources.py +++ b/fastmcp_slim/fastmcp/client/mixins/resources.py @@ -88,16 +88,16 @@ class ClientResourcesMixin: for _ in range(max_pages): result = await self.list_resources_mcp(cursor=cursor) all_resources.extend(result.resources) - if not result.nextCursor: + if not result.next_cursor: break - if result.nextCursor in seen_cursors: + if result.next_cursor in seen_cursors: logger.warning( f"[{self.name}] Server returned duplicate pagination cursor" - f" {result.nextCursor!r} for list_resources; stopping pagination" + f" {result.next_cursor!r} for list_resources; stopping pagination" ) break - seen_cursors.add(result.nextCursor) - cursor = result.nextCursor + seen_cursors.add(result.next_cursor) + cursor = result.next_cursor else: raise RuntimeError( f"[{self.name}] Reached auto-pagination limit" @@ -164,18 +164,18 @@ class ClientResourcesMixin: for _ in range(max_pages): result = await self.list_resource_templates_mcp(cursor=cursor) - all_templates.extend(result.resourceTemplates) - if not result.nextCursor: + all_templates.extend(result.resource_templates) + if not result.next_cursor: break - if result.nextCursor in seen_cursors: + if result.next_cursor in seen_cursors: logger.warning( f"[{self.name}] Server returned duplicate pagination cursor" - f" {result.nextCursor!r} for list_resource_templates;" + f" {result.next_cursor!r} for list_resource_templates;" " stopping pagination" ) break - seen_cursors.add(result.nextCursor) - cursor = result.nextCursor + seen_cursors.add(result.next_cursor) + cursor = result.next_cursor else: raise RuntimeError( f"[{self.name}] Reached auto-pagination limit" @@ -365,7 +365,7 @@ class ClientResourcesMixin: if isinstance(raw_result, mcp_types.CreateTaskResult): # Task was accepted - extract task info from CreateTaskResult - server_task_id = raw_result.task.taskId + server_task_id = raw_result.task.task_id self._submitted_task_ids.add(server_task_id) task_obj = ResourceTask( diff --git a/fastmcp_slim/fastmcp/client/mixins/tools.py b/fastmcp_slim/fastmcp/client/mixins/tools.py index 975f18f11..29607b075 100644 --- a/fastmcp_slim/fastmcp/client/mixins/tools.py +++ b/fastmcp_slim/fastmcp/client/mixins/tools.py @@ -93,16 +93,16 @@ class ClientToolsMixin: for _ in range(max_pages): result = await self.list_tools_mcp(cursor=cursor) all_tools.extend(result.tools) - if not result.nextCursor: + if not result.next_cursor: break - if result.nextCursor in seen_cursors: + if result.next_cursor in seen_cursors: logger.warning( f"[{self.name}] Server returned duplicate pagination cursor" - f" {result.nextCursor!r} for list_tools; stopping pagination" + f" {result.next_cursor!r} for list_tools; stopping pagination" ) break - seen_cursors.add(result.nextCursor) - cursor = result.nextCursor + seen_cursors.add(result.next_cursor) + cursor = result.next_cursor else: raise RuntimeError( f"[{self.name}] Reached auto-pagination limit" @@ -170,7 +170,7 @@ class ClientToolsMixin: # Reflect tool-level errors on the span so callers see ERROR # status even though the MCP protocol call itself succeeded. - if result.isError and span.is_recording(): + if result.is_error and span.is_recording(): span.set_attribute("error.type", "tool_error") description = "" if result.content and isinstance( @@ -366,7 +366,7 @@ class ClientToolsMixin: if isinstance(raw_result, mcp_types.CreateTaskResult): # Task was accepted - extract task info from CreateTaskResult - server_task_id = raw_result.task.taskId + server_task_id = raw_result.task.task_id self._submitted_task_ids.add(server_task_id) task_obj = ToolTask( @@ -418,13 +418,13 @@ async def _parse_call_tool_result( from fastmcp.client.client import CallToolResult data = None - if result.isError and raise_on_error: + if result.is_error and raise_on_error: if result.content and isinstance(result.content[0], mcp_types.TextContent): msg = result.content[0].text else: msg = f"Tool '{name}' returned an error" raise ToolError(msg) - elif result.structuredContent and not result.isError: + elif result.structured_content and not result.is_error: try: raw_fastmcp_meta = (result.meta or {}).get("fastmcp") fastmcp_meta = ( @@ -441,15 +441,15 @@ async def _parse_call_tool_result( if wrap_from_meta: # Meta tells us the result is wrapped — unwrap and validate. - structured_content = result.structuredContent.get("result") + structured_content = result.structured_content.get("result") elif name in tool_output_schemas: output_schema = tool_output_schemas.get(name) if output_schema and output_schema.get("x-fastmcp-wrap-result"): - structured_content = result.structuredContent.get("result") + structured_content = result.structured_content.get("result") else: - structured_content = result.structuredContent + structured_content = result.structured_content else: - structured_content = result.structuredContent + structured_content = result.structured_content # Type-validate through the schema if available. output_schema = tool_output_schemas.get(name) @@ -470,8 +470,8 @@ async def _parse_call_tool_result( return CallToolResult( content=result.content, - structured_content=result.structuredContent, + structured_content=result.structured_content, meta=result.meta, data=data, - is_error=result.isError, + is_error=result.is_error, ) diff --git a/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py index 0ab04f7b7..537e162b4 100644 --- a/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py @@ -54,16 +54,16 @@ _ANTHROPIC_IMAGE_MEDIA_TYPES = frozenset( def _image_content_to_anthropic_block(content: ImageContent) -> ImageBlockParam: """Convert MCP ImageContent to Anthropic ImageBlockParam.""" - if content.mimeType not in _ANTHROPIC_IMAGE_MEDIA_TYPES: + if content.mime_type not in _ANTHROPIC_IMAGE_MEDIA_TYPES: raise ValueError( - f"Unsupported image MIME type for Anthropic: {content.mimeType!r}. " + f"Unsupported image MIME type for Anthropic: {content.mime_type!r}. " f"Supported types: {', '.join(sorted(_ANTHROPIC_IMAGE_MEDIA_TYPES))}" ) return ImageBlockParam( type="image", source=Base64ImageSourceParam( type="base64", - media_type=content.mimeType, # type: ignore[arg-type] # ty:ignore[invalid-argument-type] + media_type=content.mime_type, # type: ignore[arg-type] # ty:ignore[invalid-argument-type] data=content.data, ), ) @@ -103,7 +103,9 @@ class AnthropicSamplingHandler: messages=messages, ) - model: ModelParam = self._select_model_from_preferences(params.modelPreferences) + model: ModelParam = self._select_model_from_preferences( + params.model_preferences + ) # Convert MCP tools to Anthropic format anthropic_tools: list[ToolParam] | None = None @@ -113,8 +115,8 @@ class AnthropicSamplingHandler: # Convert tool_choice to Anthropic format # Returns None if mode is "none", signaling tools should be omitted anthropic_tool_choice: ToolChoiceParam | None = None - if params.toolChoice: - converted = self._convert_tool_choice_to_anthropic(params.toolChoice) + if params.tool_choice: + converted = self._convert_tool_choice_to_anthropic(params.tool_choice) if converted is None: # tool_choice="none" means don't use tools anthropic_tools = None @@ -126,14 +128,14 @@ class AnthropicSamplingHandler: kwargs: dict[str, Any] = { "model": model, "messages": anthropic_messages, - "max_tokens": params.maxTokens, + "max_tokens": params.max_tokens, } - if params.systemPrompt is not None: - kwargs["system"] = params.systemPrompt + if params.system_prompt is not None: + kwargs["system"] = params.system_prompt if params.temperature is not None: kwargs["temperature"] = params.temperature - if params.stopSequences is not None: - kwargs["stop_sequences"] = params.stopSequences + if params.stop_sequences is not None: + kwargs["stop_sequences"] = params.stop_sequences if anthropic_tools is not None: kwargs["tools"] = anthropic_tools if anthropic_tool_choice is not None: @@ -229,9 +231,9 @@ class AnthropicSamplingHandler: content_blocks.append( ToolResultBlockParam( type="tool_result", - tool_use_id=item.toolUseId, + tool_use_id=item.tool_use_id, content=result_content, - is_error=item.isError if item.isError else False, + is_error=item.is_error if item.is_error else False, ) ) else: @@ -285,9 +287,11 @@ class AnthropicSamplingHandler: content=[ ToolResultBlockParam( type="tool_result", - tool_use_id=content.toolUseId, + tool_use_id=content.tool_use_id, content=result_content_str, - is_error=content.isError if content.isError else False, + is_error=content.is_error + if content.is_error + else False, ) ], ) @@ -364,7 +368,7 @@ class AnthropicSamplingHandler: anthropic_tools: list[ToolParam] = [] for tool in tools: # Build input_schema dict, ensuring required fields - input_schema: dict[str, Any] = dict(tool.inputSchema) + input_schema: dict[str, Any] = dict(tool.input_schema) if "type" not in input_schema: input_schema["type"] = "object" diff --git a/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py index 4b65c613d..50f41db8e 100644 --- a/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py @@ -100,10 +100,10 @@ class GoogleGenaiSamplingHandler: google_tools = [ _convert_tool_to_google_genai(tool) for tool in params.tools ] - tool_config = _convert_tool_choice_to_google_genai(params.toolChoice) + tool_config = _convert_tool_choice_to_google_genai(params.tool_choice) # Select the model based on preferences - selected_model = self._get_model(model_preferences=params.modelPreferences) + selected_model = self._get_model(model_preferences=params.model_preferences) # Configure thinking if a budget is specified thinking_config = ( @@ -117,10 +117,10 @@ class GoogleGenaiSamplingHandler: model=selected_model, contents=contents, config=GenerateContentConfig( - system_instruction=params.systemPrompt, + system_instruction=params.system_prompt, temperature=params.temperature, - max_output_tokens=params.maxTokens, - stop_sequences=params.stopSequences, + max_output_tokens=params.max_tokens, + stop_sequences=params.stop_sequences, thinking_config=thinking_config, tools=google_tools, # ty: ignore[invalid-argument-type] tool_config=tool_config, @@ -150,7 +150,7 @@ def _convert_tool_to_google_genai(tool: MCPTool) -> GoogleTool: """ from fastmcp.utilities.json_schema import compress_schema - schema = compress_schema(tool.inputSchema, prune_titles=True) + schema = compress_schema(tool.input_schema, prune_titles=True) return GoogleTool( function_declarations=[ FunctionDeclaration( @@ -207,7 +207,7 @@ def _sampling_content_to_google_genai_part( return Part( inline_data=Blob( data=base64.b64decode(content.data), - mime_type=content.mimeType, + mime_type=content.mime_type, ) ) @@ -215,7 +215,7 @@ def _sampling_content_to_google_genai_part( return Part( inline_data=Blob( data=base64.b64decode(content.data), - mime_type=content.mimeType, + mime_type=content.mime_type, ) ) @@ -249,7 +249,7 @@ def _sampling_content_to_google_genai_part( # Our IDs are formatted as "{function_name}_{uuid8}", so extract the name. # Note: This is a limitation of MCP's ToolResultContent which only carries # toolUseId, while Google's FunctionResponse requires the function name. - tool_use_id = content.toolUseId + tool_use_id = content.tool_use_id if "_" in tool_use_id: # Split and rejoin all but the last part (the UUID suffix) parts = tool_use_id.rsplit("_", 1) diff --git a/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py b/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py index 581471048..afffbc16f 100644 --- a/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py @@ -64,12 +64,12 @@ def _image_content_to_openai_part( content: ImageContent, ) -> ChatCompletionContentPartImageParam: """Convert MCP ImageContent to OpenAI image_url content part.""" - if content.mimeType not in _OPENAI_IMAGE_MEDIA_TYPES: + if content.mime_type not in _OPENAI_IMAGE_MEDIA_TYPES: raise ValueError( - f"Unsupported image MIME type for OpenAI: {content.mimeType!r}. " + f"Unsupported image MIME type for OpenAI: {content.mime_type!r}. " f"Supported types: {', '.join(sorted(_OPENAI_IMAGE_MEDIA_TYPES))}" ) - data_url = f"data:{content.mimeType};base64,{content.data}" + data_url = f"data:{content.mime_type};base64,{content.data}" return ChatCompletionContentPartImageParam( type="image_url", image_url={"url": data_url}, @@ -80,10 +80,10 @@ def _audio_content_to_openai_part( content: AudioContent, ) -> ChatCompletionContentPartInputAudioParam: """Convert MCP AudioContent to OpenAI input_audio content part.""" - audio_format = _OPENAI_AUDIO_FORMATS.get(content.mimeType) + audio_format = _OPENAI_AUDIO_FORMATS.get(content.mime_type) if audio_format is None: raise ValueError( - f"Unsupported audio MIME type for OpenAI: {content.mimeType!r}. " + f"Unsupported audio MIME type for OpenAI: {content.mime_type!r}. " f"Supported types: {', '.join(sorted(_OPENAI_AUDIO_FORMATS))}" ) return ChatCompletionContentPartInputAudioParam( @@ -112,12 +112,12 @@ class OpenAISamplingHandler: ) -> CreateMessageResult | CreateMessageResultWithTools: openai_messages: list[ChatCompletionMessageParam] = ( self._convert_to_openai_messages( - system_prompt=params.systemPrompt, + system_prompt=params.system_prompt, messages=messages, ) ) - model: ChatModel = self._select_model_from_preferences(params.modelPreferences) + model: ChatModel = self._select_model_from_preferences(params.model_preferences) # Convert MCP tools to OpenAI format openai_tools: list[ChatCompletionToolParam] | None = None @@ -126,8 +126,8 @@ class OpenAISamplingHandler: # Convert tool_choice to OpenAI format openai_tool_choice: ChatCompletionToolChoiceOptionParam | None = None - if params.toolChoice: - openai_tool_choice = self._convert_tool_choice_to_openai(params.toolChoice) + if params.tool_choice: + openai_tool_choice = self._convert_tool_choice_to_openai(params.tool_choice) # Build kwargs to avoid sentinel type compatibility issues across # openai SDK versions (NotGiven vs Omit) @@ -135,12 +135,12 @@ class OpenAISamplingHandler: "model": model, "messages": openai_messages, } - if params.maxTokens is not None: - kwargs["max_completion_tokens"] = params.maxTokens + if params.max_tokens is not None: + kwargs["max_completion_tokens"] = params.max_tokens if params.temperature is not None: kwargs["temperature"] = params.temperature - if params.stopSequences: - kwargs["stop"] = params.stopSequences + if params.stop_sequences: + kwargs["stop"] = params.stop_sequences if openai_tools is not None: kwargs["tools"] = openai_tools if openai_tool_choice is not None: @@ -240,7 +240,7 @@ class OpenAISamplingHandler: tool_messages.append( ChatCompletionToolMessageParam( role="tool", - tool_call_id=item.toolUseId, + tool_call_id=item.tool_use_id, content=content_text, ) ) @@ -327,7 +327,7 @@ class OpenAISamplingHandler: openai_messages.append( ChatCompletionToolMessageParam( role="tool", - tool_call_id=content.toolUseId, + tool_call_id=content.tool_use_id, content="\n".join(result_texts), ) ) @@ -417,7 +417,7 @@ class OpenAISamplingHandler: openai_tools: list[ChatCompletionToolParam] = [] for tool in tools: # Build parameters dict, ensuring required fields - parameters: dict[str, Any] = dict(tool.inputSchema) + parameters: dict[str, Any] = dict(tool.input_schema) if "type" not in parameters: parameters["type"] = "object" diff --git a/fastmcp_slim/fastmcp/client/tasks.py b/fastmcp_slim/fastmcp/client/tasks.py index 8c8e84067..d1fcd07a1 100644 --- a/fastmcp_slim/fastmcp/client/tasks.py +++ b/fastmcp_slim/fastmcp/client/tasks.py @@ -162,7 +162,7 @@ class Task(abc.ABC, Generic[TaskResultT]): >>> task = await client.call_tool("slow_operation", {}, task=True) >>> >>> def on_update(status: GetTaskResult): - ... print(f"Task {status.taskId} is now {status.status}") + ... print(f"Task {status.task_id} is now {status.status}") >>> >>> task.on_status_change(on_update) >>> result = await task # Callback fires when status changes diff --git a/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py index 715665727..677f3c8ef 100644 --- a/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +++ b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py @@ -43,7 +43,7 @@ class CallToolRequestResult(CallToolResult): return cls( tool=tool, arguments=arguments, - isError=result.isError, + isError=result.is_error, content=result.content, ) @@ -84,7 +84,7 @@ class BulkToolCaller(MCPMixin): results.append(result) - if result.isError and not continue_on_error: + if result.is_error and not continue_on_error: return results return results @@ -112,7 +112,7 @@ class BulkToolCaller(MCPMixin): results.append(result) - if result.isError and not continue_on_error: + if result.is_error and not continue_on_error: return results return results @@ -146,6 +146,6 @@ class BulkToolCaller(MCPMixin): return CallToolRequestResult( tool=tool, arguments=arguments, - isError=result.isError, + isError=result.is_error, content=result.content, ) diff --git a/fastmcp_slim/fastmcp/resources/template.py b/fastmcp_slim/fastmcp/resources/template.py index 2e583c7bd..91d0df52c 100644 --- a/fastmcp_slim/fastmcp/resources/template.py +++ b/fastmcp_slim/fastmcp/resources/template.py @@ -340,10 +340,10 @@ class ResourceTemplate(FastMCPComponent): # Note: This creates a simple ResourceTemplate instance. For function-based templates, # the original function is lost, which is expected for remote templates. return cls( - uri_template=mcp_template.uriTemplate, + uri_template=mcp_template.uri_template, name=mcp_template.name, description=mcp_template.description, - mime_type=mcp_template.mimeType or "text/plain", + mime_type=mcp_template.mime_type or "text/plain", parameters={}, # Remote templates don't have local parameters ) diff --git a/fastmcp_slim/fastmcp/server/context.py b/fastmcp_slim/fastmcp/server/context.py index 3385cbd21..ae04e3dd7 100644 --- a/fastmcp_slim/fastmcp/server/context.py +++ b/fastmcp_slim/fastmcp/server/context.py @@ -401,7 +401,7 @@ class Context: """ progress_token = ( - self.request_context.meta.progressToken + self.request_context.meta.progress_token if self.request_context and self.request_context.meta else None ) @@ -471,12 +471,12 @@ class Context: request = request_factory(cursor) result = await call_method(request) all_items.extend(extract_items(result)) - if not result.nextCursor: + if not result.next_cursor: break - if result.nextCursor in seen_cursors: + if result.next_cursor in seen_cursors: break - seen_cursors.add(result.nextCursor) - cursor = result.nextCursor + seen_cursors.add(result.next_cursor) + cursor = result.next_cursor return all_items async def list_resources(self) -> list[SDKResource]: diff --git a/fastmcp_slim/fastmcp/server/providers/proxy.py b/fastmcp_slim/fastmcp/server/providers/proxy.py index 71c7abc73..3583eb997 100644 --- a/fastmcp_slim/fastmcp/server/providers/proxy.py +++ b/fastmcp_slim/fastmcp/server/providers/proxy.py @@ -152,9 +152,9 @@ class ProxyTool(Tool): name=mcp_tool.name, title=mcp_tool.title, description=mcp_tool.description, - parameters=mcp_tool.inputSchema, + parameters=mcp_tool.input_schema, annotations=mcp_tool.annotations, - output_schema=mcp_tool.outputSchema, + output_schema=mcp_tool.output_schema, icons=mcp_tool.icons, meta=mcp_tool.meta, tags=get_fastmcp_metadata(mcp_tool.meta).get("tags", []), @@ -217,9 +217,9 @@ class ProxyTool(Tool): # Preserve backend's meta (includes task metadata for background tasks) return ToolResult( content=result.content, - structured_content=result.structuredContent, + structured_content=result.structured_content, meta=result.meta, - is_error=result.isError, + is_error=result.is_error, ) def get_span_attributes(self) -> dict[str, Any]: @@ -277,7 +277,7 @@ class ProxyResource(Resource): name=mcp_resource.name, title=mcp_resource.title, description=mcp_resource.description, - mime_type=mcp_resource.mimeType or "text/plain", + mime_type=mcp_resource.mime_type or "text/plain", icons=mcp_resource.icons, meta=mcp_resource.meta, tags=get_fastmcp_metadata(mcp_resource.meta).get("tags", []), @@ -312,7 +312,7 @@ class ProxyResource(Resource): contents.append( ResourceContent( content=item.text, - mime_type=item.mimeType, + mime_type=item.mime_type, meta=item.meta, ) ) @@ -320,7 +320,7 @@ class ProxyResource(Resource): contents.append( ResourceContent( content=base64.b64decode(item.blob), - mime_type=item.mimeType, + mime_type=item.mime_type, meta=item.meta, ) ) @@ -370,11 +370,11 @@ class ProxyTemplate(ResourceTemplate): return cls( client_factory=client_factory, - uri_template=mcp_template.uriTemplate, + uri_template=mcp_template.uri_template, name=mcp_template.name, title=mcp_template.title, description=mcp_template.description, - mime_type=mcp_template.mimeType or "text/plain", + mime_type=mcp_template.mime_type or "text/plain", icons=mcp_template.icons, parameters={}, # Remote templates don't have local parameters meta=mcp_template.meta, @@ -410,7 +410,7 @@ class ProxyTemplate(ResourceTemplate): contents.append( ResourceContent( content=item.text, - mime_type=item.mimeType, + mime_type=item.mime_type, meta=item.meta, ) ) @@ -418,7 +418,7 @@ class ProxyTemplate(ResourceTemplate): contents.append( ResourceContent( content=base64.b64decode(item.blob), - mime_type=item.mimeType, + mime_type=item.mime_type, meta=item.meta, ) ) @@ -435,7 +435,7 @@ class ProxyTemplate(ResourceTemplate): description=self.description, mime_type=result[ 0 - ].mimeType, # Use first item's mimeType for backward compatibility + ].mime_type, # Use first item's mimeType for backward compatibility icons=self.icons, meta=self.meta, tags=get_fastmcp_metadata(self.meta).get("tags", []), @@ -949,10 +949,10 @@ async def default_proxy_sampling_handler( ctx = get_context() result = await ctx.sample( list(messages), - system_prompt=params.systemPrompt, + system_prompt=params.system_prompt, temperature=params.temperature, - max_tokens=params.maxTokens, - model_preferences=params.modelPreferences, + max_tokens=params.max_tokens, + model_preferences=params.model_preferences, ) content = mcp_types.TextContent(type="text", text=result.text or "") return mcp_types.CreateMessageResult( @@ -973,7 +973,7 @@ async def default_proxy_elicitation_handler( ctx = get_context() # requestedSchema only exists on ElicitRequestFormParams, not ElicitRequestURLParams requested_schema = ( - params.requestedSchema + params.requested_schema if isinstance(params, ElicitRequestFormParams) else {"type": "object", "properties": {}} ) diff --git a/fastmcp_slim/fastmcp/server/sampling/run.py b/fastmcp_slim/fastmcp/server/sampling/run.py index e464508d2..7dbcadcfd 100644 --- a/fastmcp_slim/fastmcp/server/sampling/run.py +++ b/fastmcp_slim/fastmcp/server/sampling/run.py @@ -88,7 +88,7 @@ class SampleStep: def is_tool_use(self) -> bool: """True if the LLM is requesting tool execution.""" if isinstance(self.response, CreateMessageResultWithTools): - return self.response.stopReason == "toolUse" + return self.response.stop_reason == "toolUse" return False @property @@ -575,7 +575,7 @@ async def sample_step_impl( # Check if this is a tool use response is_tool_use_response = ( isinstance(response, CreateMessageResultWithTools) - and response.stopReason == "toolUse" + and response.stop_reason == "toolUse" ) # Always include the assistant response in history diff --git a/fastmcp_slim/fastmcp/tools/base.py b/fastmcp_slim/fastmcp/tools/base.py index 1e14e76bd..a3cc0e11a 100644 --- a/fastmcp_slim/fastmcp/tools/base.py +++ b/fastmcp_slim/fastmcp/tools/base.py @@ -105,7 +105,7 @@ class ToolResult(BaseModel): is_error: bool = Field( default=False, description="Whether this result represents a tool execution error. " - "When True, it maps to CallToolResult.isError so the error is returned " + "When True, it maps to CallToolResult.is_error so the error is returned " "to the client rather than raised.", ) diff --git a/fastmcp_slim/fastmcp/utilities/inspect.py b/fastmcp_slim/fastmcp/utilities/inspect.py index 2e3348e22..c27f00cd8 100644 --- a/fastmcp_slim/fastmcp/utilities/inspect.py +++ b/fastmcp_slim/fastmcp/utilities/inspect.py @@ -121,7 +121,7 @@ async def inspect_fastmcp_v2(mcp: FastMCP[Any]) -> FastMCPInfo: key=tool.key, name=tool.name or tool.key, description=tool.description, - input_schema=mcp_tool.inputSchema if mcp_tool.inputSchema else {}, + input_schema=mcp_tool.input_schema if mcp_tool.input_schema else {}, output_schema=tool.output_schema, annotations=tool.annotations.model_dump() if tool.annotations else None, tags=list(tool.tags) if tool.tags else None, @@ -263,7 +263,7 @@ async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo: key=mcp_tool.name, name=mcp_tool.name, description=mcp_tool.description, - input_schema=mcp_tool.inputSchema if mcp_tool.inputSchema else {}, + input_schema=mcp_tool.input_schema if mcp_tool.input_schema else {}, output_schema=None, # v1 doesn't have output_schema annotations=None, # v1 doesn't have annotations tags=None, # v1 doesn't have tags @@ -307,7 +307,7 @@ async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo: uri=str(mcp_resource.uri), name=mcp_resource.name, description=mcp_resource.description, - mime_type=mcp_resource.mimeType, + mime_type=mcp_resource.mime_type, annotations=None, # v1 doesn't have annotations tags=None, # v1 doesn't have tags title=None, # v1 doesn't have title @@ -323,11 +323,11 @@ async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo: for mcp_template in mcp_templates: template_infos.append( # noqa: PERF401 TemplateInfo( - key=str(mcp_template.uriTemplate), - uri_template=str(mcp_template.uriTemplate), + key=str(mcp_template.uri_template), + uri_template=str(mcp_template.uri_template), name=mcp_template.name, description=mcp_template.description, - mime_type=mcp_template.mimeType, + mime_type=mcp_template.mime_type, parameters=None, # v1 doesn't expose template parameters annotations=None, # v1 doesn't have annotations tags=None, # v1 doesn't have tags @@ -348,14 +348,14 @@ async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo: } # Extract server-level icons and website_url from serverInfo - server_info = client.initialize_result.serverInfo + server_info = client.initialize_result.server_info server_icons = ( [icon.model_dump() for icon in server_info.icons] if hasattr(server_info, "icons") and server_info.icons else None ) server_website_url = ( - server_info.websiteUrl if hasattr(server_info, "websiteUrl") else None + server_info.website_url if hasattr(server_info, "websiteUrl") else None ) return FastMCPInfo( @@ -443,7 +443,7 @@ async def format_mcp_info(mcp: FastMCP[Any] | FastMCP1x) -> bytes: templates_result = await client.list_resource_templates_mcp() # Get server info from the initialize result - server_info = client.initialize_result.serverInfo + server_info = client.initialize_result.server_info # Combine into MCP protocol structure with environment metadata result = { @@ -456,7 +456,7 @@ async def format_mcp_info(mcp: FastMCP[Any] | FastMCP1x) -> bytes: "tools": tools_result.tools, "prompts": prompts_result.prompts, "resources": resources_result.resources, - "resourceTemplates": templates_result.resourceTemplates, + "resourceTemplates": templates_result.resource_templates, } return pydantic_core.to_json(result, indent=2) diff --git a/tests/client/client/test_client.py b/tests/client/client/test_client.py index 3cccc8ba2..b10fd5d8a 100644 --- a/tests/client/client/test_client.py +++ b/tests/client/client/test_client.py @@ -70,7 +70,7 @@ async def test_call_tool_mcp(fastmcp_server): # Check that we got the raw MCP CallToolResult object assert hasattr(result, "content") assert hasattr(result, "isError") - assert result.isError is False + assert result.is_error is False # The content is a list, so we'll check the first element # by properly accessing it content = result.content @@ -356,7 +356,7 @@ async def test_initialize_called_once(fastmcp_server): async with client: # Verify that initialization succeeded by checking initialize_result assert client.initialize_result is not None - assert client.initialize_result.serverInfo is not None + assert client.initialize_result.server_info is not None async def test_initialize_result_connected(fastmcp_server): @@ -372,8 +372,8 @@ async def test_initialize_result_connected(fastmcp_server): # Verify the initialize result has expected properties assert hasattr(result, "serverInfo") - assert result.serverInfo.name == "TestServer" - assert result.serverInfo.version is not None + assert result.server_info.name == "TestServer" + assert result.server_info.version is not None async def test_initialize_result_disconnected(fastmcp_server): @@ -401,8 +401,8 @@ async def test_server_info_custom_version(): async with client: result = client.initialize_result assert result is not None - assert result.serverInfo.name == "CustomVersionServer" - assert result.serverInfo.version == "1.2.3" + assert result.server_info.name == "CustomVersionServer" + assert result.server_info.version == "1.2.3" # Test without version (backward compatibility) server_without_version = FastMCP("DefaultVersionServer") @@ -411,9 +411,9 @@ async def test_server_info_custom_version(): async with client: result = client.initialize_result assert result is not None - assert result.serverInfo.name == "DefaultVersionServer" + assert result.server_info.name == "DefaultVersionServer" # Should fall back to FastMCP version - assert result.serverInfo.version == fastmcp.__version__ + assert result.server_info.version == fastmcp.__version__ class _DelayedConnectTransport(ClientTransport): @@ -717,7 +717,7 @@ async def test_resource_template(fastmcp_server): # Check that our template is available assert len(result) == 1 - assert "data://user/{user_id}" in result[0].uriTemplate + assert "data://user/{user_id}" in result[0].uri_template # Now use the template with a specific user_id uri = cast(AnyUrl, "data://user/123") @@ -739,8 +739,8 @@ async def test_list_resource_templates_mcp(fastmcp_server): # Check that we got the raw MCP ListResourceTemplatesResult object assert hasattr(result, "resourceTemplates") - assert len(result.resourceTemplates) == 1 - assert "data://user/{user_id}" in result.resourceTemplates[0].uriTemplate + assert len(result.resource_templates) == 1 + assert "data://user/{user_id}" in result.resource_templates[0].uri_template async def test_mcp_resource_generation(fastmcp_server): @@ -772,7 +772,7 @@ async def test_mcp_template_generation(fastmcp_server): assert hasattr(template, "uriTemplate") assert hasattr(template, "name") assert hasattr(template, "description") - assert "data://user/{user_id}" in template.uriTemplate + assert "data://user/{user_id}" in template.uri_template async def test_template_access_via_client(fastmcp_server): @@ -811,7 +811,7 @@ async def test_tagged_template_metadata(tagged_resources_server): template = templates[0] # Verify template metadata is preserved - assert "template://{id}" in template.uriTemplate + assert "template://{id}" in template.uri_template assert template.description == "A tagged template" diff --git a/tests/client/client/test_error_handling.py b/tests/client/client/test_error_handling.py index 5496b0326..ee8161690 100644 --- a/tests/client/client/test_error_handling.py +++ b/tests/client/client/test_error_handling.py @@ -27,7 +27,7 @@ class TestErrorHandling: async with client: result = await client.call_tool_mcp("error_tool", {}) - assert result.isError + assert result.is_error assert isinstance(result.content[0], TextContent) assert "test error" in result.content[0].text assert "abc" in result.content[0].text @@ -43,7 +43,7 @@ class TestErrorHandling: async with client: result = await client.call_tool_mcp("error_tool", {}) - assert result.isError + assert result.is_error assert isinstance(result.content[0], TextContent) assert "test error" not in result.content[0].text assert "abc" not in result.content[0].text @@ -57,7 +57,7 @@ class TestErrorHandling: async with Client(transport=FastMCPTransport(mcp)) as client: result = await client.call_tool_mcp("validated_tool", {"x": "abc"}) - assert result.isError + assert result.is_error # Pydantic validation error message should NOT be masked assert isinstance(result.content[0], TextContent) assert "Input should be a valid integer" in result.content[0].text @@ -73,7 +73,7 @@ class TestErrorHandling: async with client: result = await client.call_tool_mcp("custom_error_tool", {}) - assert result.isError + assert result.is_error assert isinstance(result.content[0], TextContent) assert "test error" in result.content[0].text assert "abc" in result.content[0].text @@ -283,7 +283,7 @@ class TestLogLevel: with caplog.at_level(logging.WARNING): result = await client.call_tool_mcp("custom_level_tool", {}) - assert result.isError + assert result.is_error assert isinstance(result.content[0], TextContent) assert "Missing required parameter" in result.content[0].text assert any( @@ -307,7 +307,7 @@ class TestLogLevel: with caplog.at_level(logging.ERROR): result = await client.call_tool_mcp("regular_error_tool", {}) - assert result.isError + assert result.is_error assert isinstance(result.content[0], TextContent) assert "Something went wrong" in result.content[0].text assert any( @@ -428,7 +428,7 @@ class TestLogLevel: ) assert len(results) == 1 - assert results[0].isError + assert results[0].is_error assert "Expected sampling error" in results[0].content[0].text # type: ignore assert any( "Error calling sampling tool" in record.message diff --git a/tests/client/client/test_initialize.py b/tests/client/client/test_initialize.py index 2c0ccfdf4..7bbe3aeb8 100644 --- a/tests/client/client/test_initialize.py +++ b/tests/client/client/test_initialize.py @@ -14,7 +14,7 @@ class TestInitialize: async with client: # Should be automatically initialized assert client.initialize_result is not None - assert client.initialize_result.serverInfo.name == "TestServer" + assert client.initialize_result.server_info.name == "TestServer" assert client.initialize_result.instructions is None async def test_auto_initialize_explicit_true(self, fastmcp_server): @@ -23,7 +23,7 @@ class TestInitialize: async with client: assert client.initialize_result is not None - assert client.initialize_result.serverInfo.name == "TestServer" + assert client.initialize_result.server_info.name == "TestServer" async def test_auto_initialize_false(self, fastmcp_server): """Test that auto_initialize=False prevents automatic initialization.""" @@ -42,7 +42,7 @@ class TestInitialize: result = await client.initialize() assert result is not None - assert result.serverInfo.name == "TestServer" + assert result.server_info.name == "TestServer" assert client.initialize_result is result async def test_initialize_idempotent(self, fastmcp_server): @@ -90,7 +90,7 @@ class TestInitialize: # Access via property result = client.initialize_result assert result is not None - assert result.serverInfo.name == "TestServer" + assert result.server_info.name == "TestServer" # Call method - should return cached result2 = await client.initialize() diff --git a/tests/client/sampling/handlers/test_anthropic_handler.py b/tests/client/sampling/handlers/test_anthropic_handler.py index 2338156d1..a0497ffff 100644 --- a/tests/client/sampling/handlers/test_anthropic_handler.py +++ b/tests/client/sampling/handlers/test_anthropic_handler.py @@ -252,7 +252,7 @@ def test_message_to_result_with_tools(): assert result.role == "assistant" assert result.model == "claude-3-5-sonnet-20241022" - assert result.stopReason == "toolUse" + assert result.stop_reason == "toolUse" content = result.content_as_list assert len(content) == 2 assert content[0] == TextContent(type="text", text="I'll help you with that.") diff --git a/tests/client/sampling/handlers/test_google_genai_handler.py b/tests/client/sampling/handlers/test_google_genai_handler.py index 938757659..9a401f2f9 100644 --- a/tests/client/sampling/handlers/test_google_genai_handler.py +++ b/tests/client/sampling/handlers/test_google_genai_handler.py @@ -372,7 +372,7 @@ def test_response_to_result_with_tools_text_only(): assert result.role == "assistant" assert result.model == "gemini-2.0-flash" - assert result.stopReason == "endTurn" + assert result.stop_reason == "endTurn" assert isinstance(result.content, list) assert len(result.content) == 1 assert result.content[0].type == "text" @@ -394,7 +394,7 @@ def test_response_to_result_with_tools_function_call(): result = _response_to_result_with_tools(mock_response, model="gemini-2.0-flash") - assert result.stopReason == "toolUse" + assert result.stop_reason == "toolUse" assert isinstance(result.content, list) assert len(result.content) == 1 tool_use = result.content[0] @@ -421,7 +421,7 @@ def test_response_to_result_with_tools_mixed_content(): result = _response_to_result_with_tools(mock_response, model="gemini-2.0-flash") - assert result.stopReason == "toolUse" + assert result.stop_reason == "toolUse" assert isinstance(result.content, list) assert len(result.content) == 2 text_content = result.content[0] @@ -576,7 +576,7 @@ def test_normal_response_text_and_function_call(): assert isinstance(result.content[1], ToolUseContent) # ty: ignore[not-subscriptable] assert result.content[1].name == "lookup" # ty: ignore[not-subscriptable] assert result.content[1].input == {"q": "test"} # ty: ignore[not-subscriptable] - assert result.stopReason == "toolUse" + assert result.stop_reason == "toolUse" def test_thought_with_function_call_keeps_function_call(): @@ -598,4 +598,4 @@ def test_thought_with_function_call_keeps_function_call(): assert len(result.content) == 1 # ty: ignore[invalid-argument-type] assert isinstance(result.content[0], ToolUseContent) # ty: ignore[not-subscriptable] assert result.content[0].name == "get_weather" # ty: ignore[not-subscriptable] - assert result.stopReason == "toolUse" + assert result.stop_reason == "toolUse" diff --git a/tests/client/tasks/test_client_task_notifications.py b/tests/client/tasks/test_client_task_notifications.py index 1ae825080..728306264 100644 --- a/tests/client/tasks/test_client_task_notifications.py +++ b/tests/client/tasks/test_client_task_notifications.py @@ -206,7 +206,7 @@ async def test_notification_with_failed_task(task_notification_server): status = await task.status() assert status.status == "failed" assert ( - status.statusMessage is not None + status.status_message is not None ) # Error details in statusMessage per spec diff --git a/tests/client/tasks/test_client_tool_tasks.py b/tests/client/tasks/test_client_tool_tasks.py index 8b98f69cd..0bec286cb 100644 --- a/tests/client/tasks/test_client_tool_tasks.py +++ b/tests/client/tasks/test_client_tool_tasks.py @@ -79,7 +79,7 @@ async def test_tool_task_status_and_wait(tool_task_server): task = await client.call_tool("echo", {"message": "test"}, task=True) status = await task.status() - assert status.taskId == task.task_id + assert status.task_id == task.task_id assert status.status in ["working", "completed"] # Wait for completion diff --git a/tests/client/test_elicitation.py b/tests/client/test_elicitation.py index bd3647dd5..daa529bee 100644 --- a/tests/client/test_elicitation.py +++ b/tests/client/test_elicitation.py @@ -108,7 +108,7 @@ async def test_elicitation_handler_parameters(): assert captured_params["message"] == "Test message" assert "ScalarElicitationType" in str(captured_params["response_type"]) - assert captured_params["params"].requestedSchema == { + assert captured_params["params"].requested_schema == { "properties": {"value": {"title": "Value", "type": "integer"}}, "required": ["value"], "title": "ScalarElicitationType", @@ -135,7 +135,7 @@ async def test_elicitation_response_title_and_description_on_scalar(): return "no answer" async def elicitation_handler(message, response_type, params, ctx): - captured_schema.update(params.requestedSchema) + captured_schema.update(params.requested_schema) return ElicitResult(action="accept", content={"value": True}) async with Client(mcp, elicitation_handler=elicitation_handler) as client: @@ -164,7 +164,7 @@ async def test_elicitation_response_title_on_dict_shorthand(): return "ok" if isinstance(result, AcceptedElicitation) else "none" async def elicitation_handler(message, response_type, params, ctx): - captured_schema.update(params.requestedSchema) + captured_schema.update(params.requested_schema) return ElicitResult(action="accept", content={"value": "low"}) async with Client(mcp, elicitation_handler=elicitation_handler) as client: @@ -188,7 +188,7 @@ async def test_elicitation_response_title_on_list_shorthand(): return "ok" if isinstance(result, AcceptedElicitation) else "none" async def elicitation_handler(message, response_type, params, ctx): - captured_schema.update(params.requestedSchema) + captured_schema.update(params.requested_schema) return ElicitResult(action="accept", content={"value": "red"}) async with Client(mcp, elicitation_handler=elicitation_handler) as client: @@ -302,7 +302,7 @@ class TestScalarResponseTypes: message, response_type, params: ElicitRequestParams, ctx ): assert isinstance(params, ElicitRequestFormParams) - assert params.requestedSchema == {"type": "object", "properties": {}} + assert params.requested_schema == {"type": "object", "properties": {}} assert response_type is None return ElicitResult(action="accept") @@ -612,7 +612,7 @@ async def test_structured_response_type( ) # Verify the schema has the dataclass fields (available in params) - schema = params.requestedSchema + schema = params.requested_schema assert schema["type"] == "object" assert "name" in schema["properties"] assert "age" in schema["properties"] diff --git a/tests/client/test_elicitation_enums.py b/tests/client/test_elicitation_enums.py index 6e8b1e7fd..2ab890be6 100644 --- a/tests/client/test_elicitation_enums.py +++ b/tests/client/test_elicitation_enums.py @@ -170,7 +170,7 @@ async def test_dict_based_titled_single_select(): async def elicitation_handler(message, response_type, params, ctx): # Verify schema follows SEP-1330 pattern with type: "string" - schema = params.requestedSchema + schema = params.requested_schema assert schema["type"] == "object" assert "value" in schema["properties"] value_schema = schema["properties"]["value"] @@ -205,7 +205,7 @@ async def test_list_list_multi_select_untitled(): async def elicitation_handler(message, response_type, params, ctx): # Verify schema has array with enum pattern - schema = params.requestedSchema + schema = params.requested_schema assert schema["type"] == "object" assert "value" in schema["properties"] value_schema = schema["properties"]["value"] @@ -243,7 +243,7 @@ async def test_list_dict_multi_select_titled(): async def elicitation_handler(message, response_type, params, ctx): # Verify schema has array with SEP-1330 compliant items (anyOf pattern) - schema = params.requestedSchema + schema = params.requested_schema assert schema["type"] == "object" assert "value" in schema["properties"] value_schema = schema["properties"]["value"] @@ -310,7 +310,7 @@ async def test_list_enum_multi_select_direct(): async def elicitation_handler(message, response_type, params, ctx): # Verify schema has array with enum pattern - schema = params.requestedSchema + schema = params.requested_schema assert schema["type"] == "object" assert "value" in schema["properties"] value_schema = schema["properties"]["value"] diff --git a/tests/client/test_sampling.py b/tests/client/test_sampling.py index f5edb0c3c..2fc75e311 100644 --- a/tests/client/test_sampling.py +++ b/tests/client/test_sampling.py @@ -85,8 +85,8 @@ async def test_sampling_with_system_prompt(fastmcp_server: FastMCP): def sampling_handler( messages: list[SamplingMessage], params: SamplingParams, ctx: RequestContext ) -> str: - assert params.systemPrompt is not None - return params.systemPrompt + assert params.system_prompt is not None + return params.system_prompt async with Client(fastmcp_server, sampling_handler=sampling_handler) as client: result = await client.call_tool( diff --git a/tests/client/test_sampling_result_types.py b/tests/client/test_sampling_result_types.py index 371048cb7..fc4df87c0 100644 --- a/tests/client/test_sampling_result_types.py +++ b/tests/client/test_sampling_result_types.py @@ -218,7 +218,7 @@ class TestSamplingResultType: tool_result = msg.content break assert tool_result is not None - assert tool_result.isError is True + assert tool_result.is_error is True assert isinstance(tool_result.content[0], TextContent) error_text = tool_result.content[0].text assert "Validation error" in error_text diff --git a/tests/client/test_sampling_tool_loop.py b/tests/client/test_sampling_tool_loop.py index b5d2dd233..4bf5faf02 100644 --- a/tests/client/test_sampling_tool_loop.py +++ b/tests/client/test_sampling_tool_loop.py @@ -201,7 +201,7 @@ class TestAutomaticToolLoop: tool_result = msg.content break assert tool_result is not None - assert tool_result.isError is True + assert tool_result.is_error is True # Content is list of TextContent objects assert isinstance(tool_result.content[0], TextContent) error_text = tool_result.content[0].text @@ -275,7 +275,7 @@ class TestAutomaticToolLoop: tool_result = msg.content break assert tool_result is not None - assert tool_result.isError is True + assert tool_result.is_error is True # Content is list of TextContent objects assert isinstance(tool_result.content[0], TextContent) error_text = tool_result.content[0].text @@ -682,8 +682,8 @@ class TestAutomaticToolLoop: tool_results = cast(list[ToolResultContent], tool_result_message.content) assert len(tool_results) == 2 # One should be success, one should be error - assert any(not r.isError for r in tool_results) - assert any(r.isError for r in tool_results) + assert any(not r.is_error for r in tool_results) + assert any(r.is_error for r in tool_results) async def test_concurrent_tool_result_order_preserved(self): """Test that tool results maintain the same order as tool calls.""" @@ -761,9 +761,9 @@ class TestAutomaticToolLoop: tool_result_message = messages_received[1][-1] tool_results = cast(list[ToolResultContent], tool_result_message.content) assert len(tool_results) == 3 - assert tool_results[0].toolUseId == "call_1" - assert tool_results[1].toolUseId == "call_2" - assert tool_results[2].toolUseId == "call_3" + assert tool_results[0].tool_use_id == "call_1" + assert tool_results[1].tool_use_id == "call_2" + assert tool_results[2].tool_use_id == "call_3" # Check values are correct result_texts = [cast(TextContent, r.content[0]).text for r in tool_results] assert result_texts == ["1", "2", "3"] diff --git a/tests/deprecated/test_import_server.py b/tests/deprecated/test_import_server.py index 8efa2c919..d43382ad6 100644 --- a/tests/deprecated/test_import_server.py +++ b/tests/deprecated/test_import_server.py @@ -555,7 +555,7 @@ async def test_import_conflict_resolution_templates(): async with Client(main_app) as client: # The later imported server should win templates = await client.list_resource_templates() - template_uris = [t.uriTemplate for t in templates] + template_uris = [t.uri_template for t in templates] assert "users://{user_id}/profile" in template_uris assert ( template_uris.count("users://{user_id}/profile") == 1 diff --git a/tests/integration_tests/test_github_mcp_remote.py b/tests/integration_tests/test_github_mcp_remote.py index 10d36efb5..b6190afc7 100644 --- a/tests/integration_tests/test_github_mcp_remote.py +++ b/tests/integration_tests/test_github_mcp_remote.py @@ -64,8 +64,8 @@ class TestGithubMCPRemote: assert isinstance(tool, Tool) assert len(tool.name) > 0 assert tool.description is not None and len(tool.description) > 0 - assert isinstance(tool.inputSchema, dict) - assert len(tool.inputSchema) > 0 + assert isinstance(tool.input_schema, dict) + assert len(tool.input_schema) > 0 async def test_list_resources( self, streamable_http_client: Client[StreamableHttpTransport] diff --git a/tests/prompts/test_prompt.py b/tests/prompts/test_prompt.py index fd392d87a..62fd416a7 100644 --- a/tests/prompts/test_prompt.py +++ b/tests/prompts/test_prompt.py @@ -632,7 +632,7 @@ class TestMessage: msg = Message(img, role="user") assert isinstance(msg.content, ImageContent) assert msg.content.data == "base64data" - assert msg.content.mimeType == "image/png" + assert msg.content.mime_type == "image/png" def test_message_passthrough_audio_content(self): """Test Message passes through AudioContent without JSON serialization.""" @@ -642,7 +642,7 @@ class TestMessage: msg = Message(audio, role="user") assert isinstance(msg.content, AudioContent) assert msg.content.data == "base64audio" - assert msg.content.mimeType == "audio/wav" + assert msg.content.mime_type == "audio/wav" def test_message_image_content_to_mcp_prompt_message(self): """Test that ImageContent round-trips through to_mcp_prompt_message.""" diff --git a/tests/resources/test_function_resources.py b/tests/resources/test_function_resources.py index 2680b42e3..20561a951 100644 --- a/tests/resources/test_function_resources.py +++ b/tests/resources/test_function_resources.py @@ -261,7 +261,7 @@ class TestResourceContentToMcp: assert hasattr(mcp_content, "text") assert mcp_content.text == "hello world" - assert mcp_content.mimeType == "text/html" + assert mcp_content.mime_type == "text/html" assert mcp_content.meta == {"csp": "script-src 'self'"} def test_binary_content_to_mcp(self): @@ -275,18 +275,18 @@ class TestResourceContentToMcp: assert hasattr(mcp_content, "blob") assert mcp_content.blob == "AAEC" # base64 of \x00\x01\x02 - assert mcp_content.mimeType == "application/octet-stream" + assert mcp_content.mime_type == "application/octet-stream" assert mcp_content.meta == {"encoding": "raw"} def test_default_mime_types(self): """Test default mime types are applied correctly.""" text_rc = ResourceContent(content="text") text_mcp = text_rc.to_mcp_resource_contents("resource://test") - assert text_mcp.mimeType == "text/plain" + assert text_mcp.mime_type == "text/plain" binary_rc = ResourceContent(content=b"binary") binary_mcp = binary_rc.to_mcp_resource_contents("resource://test") - assert binary_mcp.mimeType == "application/octet-stream" + assert binary_mcp.mime_type == "application/octet-stream" def test_none_meta(self): """Test that None meta is handled correctly.""" diff --git a/tests/resources/test_resources.py b/tests/resources/test_resources.py index 9d101693c..ad72b6168 100644 --- a/tests/resources/test_resources.py +++ b/tests/resources/test_resources.py @@ -176,7 +176,7 @@ class TestResourceContent: mcp_content = content.to_mcp_resource_contents("resource://test") assert isinstance(mcp_content, mcp_types.TextResourceContents) assert mcp_content.text == "hello" - assert mcp_content.mimeType == "text/plain" + assert mcp_content.mime_type == "text/plain" assert str(mcp_content.uri) == "resource://test" assert mcp_content.meta == {"k": "v"} @@ -188,7 +188,7 @@ class TestResourceContent: mcp_content = content.to_mcp_resource_contents("resource://binary") assert isinstance(mcp_content, mcp_types.BlobResourceContents) assert mcp_content.blob == "AAEC" # base64 of \x00\x01\x02 - assert mcp_content.mimeType == "application/octet-stream" + assert mcp_content.mime_type == "application/octet-stream" class TestResourceResult: diff --git a/tests/resources/test_standalone_decorator.py b/tests/resources/test_standalone_decorator.py index c5dd76ec8..ba555f730 100644 --- a/tests/resources/test_standalone_decorator.py +++ b/tests/resources/test_standalone_decorator.py @@ -165,7 +165,7 @@ class TestResourceDecorator: async with Client(mcp) as client: templates = await client.list_resource_templates() - assert any(t.uriTemplate == "users://{user_id}/profile" for t in templates) + assert any(t.uri_template == "users://{user_id}/profile" for t in templates) result = await client.read_resource("users://123/profile") assert "123" in str(result) diff --git a/tests/server/auth/test_authorization.py b/tests/server/auth/test_authorization.py index 4765c80db..9d4c01d19 100644 --- a/tests/server/auth/test_authorization.py +++ b/tests/server/auth/test_authorization.py @@ -521,7 +521,7 @@ class TestAuthMiddleware: result = await mcp._list_resource_templates_mcp( mcp_types.ListResourceTemplatesRequest() ) - assert [template.uriTemplate for template in result.resourceTemplates] == [ + assert [template.uri_template for template in result.resource_templates] == [ "resource://allowed/{item}" ] diff --git a/tests/server/middleware/test_dereference.py b/tests/server/middleware/test_dereference.py index 0ababd7de..ce4b369c9 100644 --- a/tests/server/middleware/test_dereference.py +++ b/tests/server/middleware/test_dereference.py @@ -32,7 +32,7 @@ class TestDereferenceRefsMiddleware: async with Client(mcp) as client: tools = await client.list_tools() - schema = tools[0].inputSchema + schema = tools[0].input_schema # $defs should be removed — everything inlined assert "$defs" not in schema # The Color enum should be inlined into the request property @@ -49,7 +49,7 @@ class TestDereferenceRefsMiddleware: async with Client(mcp) as client: tools = await client.list_tools() - schema = tools[0].inputSchema + schema = tools[0].input_schema # $defs should still be present assert "$defs" in schema @@ -64,7 +64,7 @@ class TestDereferenceRefsMiddleware: async with Client(mcp) as client: tools = await client.list_tools() - schema = tools[0].inputSchema + schema = tools[0].input_schema assert "$defs" not in schema async def test_does_not_mutate_original_tool(self): @@ -100,9 +100,9 @@ class TestDereferenceRefsMiddleware: tool = tools[0] # Both input and output schemas should be dereferenced - assert "$defs" not in tool.inputSchema - if tool.outputSchema is not None: - assert "$defs" not in tool.outputSchema + assert "$defs" not in tool.input_schema + if tool.output_schema is not None: + assert "$defs" not in tool.output_schema async def test_resource_templates_dereferenced(self): """Middleware dereferences resource template schemas.""" @@ -130,7 +130,7 @@ class TestDereferenceRefsMiddleware: async with Client(mcp) as client: tools = await client.list_tools() - schema = tools[0].inputSchema + schema = tools[0].input_schema # Simple schema should not have $defs regardless assert "$defs" not in schema assert schema["properties"]["a"]["type"] == "integer" diff --git a/tests/server/middleware/test_initialization_middleware.py b/tests/server/middleware/test_initialization_middleware.py index 2e832f724..3a077b367 100644 --- a/tests/server/middleware/test_initialization_middleware.py +++ b/tests/server/middleware/test_initialization_middleware.py @@ -39,7 +39,7 @@ class InitializationMiddleware(Middleware): if hasattr(context.message, "params") and hasattr( context.message.params, "clientInfo" ): - self.client_info = context.message.params.clientInfo + self.client_info = context.message.params.client_info # Store in instance for cross-request access # (session state is not available during on_initialize) @@ -96,7 +96,7 @@ class ClientDetectionMiddleware(Middleware): if tool.annotations is None: tool.annotations = mt.ToolAnnotations() # Mark as read-only for test clients - tool.annotations.readOnlyHint = True + tool.annotations.read_only_hint = True self.tools_modified = True return tools @@ -173,7 +173,7 @@ async def test_client_detection_middleware(): # Check that the tool has the modified annotation tool = tools[0] assert tool.annotations is not None - assert tool.annotations.readOnlyHint is True + assert tool.annotations.read_only_hint is True async def test_multiple_middleware_initialization(): @@ -293,8 +293,8 @@ async def test_middleware_can_access_initialize_result(): assert isinstance(middleware.initialize_result, mt.InitializeResult) # Verify the result contains expected server info - assert middleware.initialize_result.serverInfo.name == "TestServer" - assert middleware.initialize_result.protocolVersion is not None + assert middleware.initialize_result.server_info.name == "TestServer" + assert middleware.initialize_result.protocol_version is not None assert middleware.initialize_result.capabilities is not None diff --git a/tests/server/middleware/test_middleware.py b/tests/server/middleware/test_middleware.py index 0570e31a8..2e4aae369 100644 --- a/tests/server/middleware/test_middleware.py +++ b/tests/server/middleware/test_middleware.py @@ -391,7 +391,7 @@ class TestMiddlewareHooks: templates = await client.list_resource_templates() assert len(templates) == 1 - assert str(templates[0].uriTemplate) == "resource://public/{x}" + assert str(templates[0].uri_template) == "resource://public/{x}" async def test_list_prompts_filtering_middleware(self): """Test that middleware can filter prompts.""" diff --git a/tests/server/middleware/test_tool_injection.py b/tests/server/middleware/test_tool_injection.py index 4e926bd21..983736412 100644 --- a/tests/server/middleware/test_tool_injection.py +++ b/tests/server/middleware/test_tool_injection.py @@ -216,8 +216,8 @@ class TestToolInjectionMiddleware: multiply_tool = next(t for t in tools if t.name == "multiply") assert multiply_tool.description == "Multiply two numbers." - assert "a" in multiply_tool.inputSchema["properties"] - assert "b" in multiply_tool.inputSchema["properties"] + assert "a" in multiply_tool.input_schema["properties"] + assert "b" in multiply_tool.input_schema["properties"] async def test_injected_tool_does_not_conflict_with_base_tool( self, base_server: FastMCP diff --git a/tests/server/providers/local_provider_tools/test_local_provider_tools.py b/tests/server/providers/local_provider_tools/test_local_provider_tools.py index b62290796..c42f80cb7 100644 --- a/tests/server/providers/local_provider_tools/test_local_provider_tools.py +++ b/tests/server/providers/local_provider_tools/test_local_provider_tools.py @@ -123,7 +123,7 @@ class TestToolReturnTypes: content = result.content[0] assert isinstance(content, ImageContent) assert content.type == "image" - assert content.mimeType == "image/png" + assert content.mime_type == "image/png" decoded = base64.b64decode(content.data) assert decoded == b"fake png data" @@ -142,7 +142,7 @@ class TestToolReturnTypes: content = result.content[0] assert isinstance(content, AudioContent) assert content.type == "audio" - assert content.mimeType == "audio/wav" + assert content.mime_type == "audio/wav" decoded = base64.b64decode(content.data) assert decoded == b"fake wav data" @@ -162,7 +162,7 @@ class TestToolReturnTypes: assert isinstance(content, EmbeddedResource) assert content.type == "resource" resource = content.resource - assert resource.mimeType == "application/octet-stream" + assert resource.mime_type == "application/octet-stream" assert hasattr(resource, "blob") blob_data = getattr(resource, "blob") decoded = base64.b64decode(blob_data) @@ -179,12 +179,12 @@ class TestToolReturnTypes: assert isinstance(content1, TextContent) assert content1.text == "Hello" assert isinstance(content2, ImageContent) - assert content2.mimeType == "application/octet-stream" + assert content2.mime_type == "application/octet-stream" assert content2.data == "abc" assert isinstance(content3, EmbeddedResource) assert content3.type == "resource" resource = content3.resource - assert resource.mimeType == "application/octet-stream" + assert resource.mime_type == "application/octet-stream" assert hasattr(resource, "blob") blob_data = getattr(resource, "blob") decoded = base64.b64decode(blob_data) @@ -208,7 +208,7 @@ class TestToolReturnTypes: assert content1.text == "text message" content2 = result.content[1] assert isinstance(content2, ImageContent) - assert content2.mimeType == "image/png" + assert content2.mime_type == "image/png" assert base64.b64decode(content2.data) == b"test image data" content3 = result.content[2] assert isinstance(content3, TextContent) @@ -235,7 +235,7 @@ class TestToolReturnTypes: assert content1.text == "text message" content2 = result.content[1] assert isinstance(content2, AudioContent) - assert content2.mimeType == "audio/wav" + assert content2.mime_type == "audio/wav" assert base64.b64decode(content2.data) == b"test audio data" content3 = result.content[2] assert isinstance(content3, TextContent) @@ -264,7 +264,7 @@ class TestToolReturnTypes: assert isinstance(content2, EmbeddedResource) assert content2.type == "resource" resource = content2.resource - assert resource.mimeType == "application/octet-stream" + assert resource.mime_type == "application/octet-stream" assert hasattr(resource, "blob") blob_data = getattr(resource, "blob") assert base64.b64decode(blob_data) == b"test file data" diff --git a/tests/server/providers/local_provider_tools/test_parameters.py b/tests/server/providers/local_provider_tools/test_parameters.py index 06e14493f..13e5e060e 100644 --- a/tests/server/providers/local_provider_tools/test_parameters.py +++ b/tests/server/providers/local_provider_tools/test_parameters.py @@ -105,7 +105,7 @@ class TestToolParameters: assert result.structured_content is None assert isinstance(result.content, list) assert isinstance(result.content[0], ImageContent) - assert result.content[0].mimeType == "image/png" + assert result.content[0].mime_type == "image/png" assert result.content[0].data == base64.b64encode(b"fake png data").decode() async def test_tool_with_invalid_input(self): diff --git a/tests/server/providers/openapi/test_comprehensive.py b/tests/server/providers/openapi/test_comprehensive.py index 5396767c2..31a54c4b3 100644 --- a/tests/server/providers/openapi/test_comprehensive.py +++ b/tests/server/providers/openapi/test_comprehensive.py @@ -430,7 +430,7 @@ class TestOpenAPIComprehensive: collision_tool = next( tool for tool in tools if tool.name == "collision_test" ) - schema = collision_tool.inputSchema + schema = collision_tool.input_schema properties = schema["properties"] # Should have unique parameter names for colliding parameters @@ -461,7 +461,7 @@ class TestOpenAPIComprehensive: search_tool = next( tool for tool in tools if tool.name == "search_users" ) - schema = search_tool.inputSchema + schema = search_tool.input_schema properties = schema["properties"] # Should have flattened deepObject parameters @@ -681,7 +681,7 @@ class TestOpenAPIComprehensive: # Find create_user tool which uses schema refs create_tool = next(tool for tool in tools if tool.name == "create_user") - schema = create_tool.inputSchema + schema = create_tool.input_schema properties = schema["properties"] # Should have resolved User schema properties @@ -702,7 +702,7 @@ class TestOpenAPIComprehensive: # Check list_users tool - has optional query parameters list_tool = next(tool for tool in tools if tool.name == "list_users") - schema = list_tool.inputSchema + schema = list_tool.input_schema # Query parameters should be optional # (may not appear in required list) # This test just ensures the schema is well-formed @@ -712,7 +712,7 @@ class TestOpenAPIComprehensive: search_tool = next( tool for tool in tools if tool.name == "search_users" ) - search_schema = search_tool.inputSchema + search_schema = search_tool.input_schema # Should have some required parameters assert len(search_schema["properties"]) > 0 diff --git a/tests/server/providers/openapi/test_deepobject_style.py b/tests/server/providers/openapi/test_deepobject_style.py index 1d934ec32..29564f370 100644 --- a/tests/server/providers/openapi/test_deepobject_style.py +++ b/tests/server/providers/openapi/test_deepobject_style.py @@ -206,7 +206,7 @@ class TestDeepObjectStyle: assert surveys_tool is not None # Check that deepObject parameters are included in schema - params = surveys_tool.inputSchema + params = surveys_tool.input_schema properties = params["properties"] # Should have the deepObject parameters @@ -236,7 +236,7 @@ class TestDeepObjectStyle: ) # Check that explode=true parameters are properly structured - params = surveys_tool.inputSchema + params = surveys_tool.input_schema properties = params["properties"] # Target parameter with explode=true should allow individual property access @@ -261,7 +261,7 @@ class TestDeepObjectStyle: ) # Check that explode=false parameters are handled - params = surveys_tool.inputSchema + params = surveys_tool.input_schema properties = params["properties"] # Compact parameter with explode=false should still be present and valid @@ -292,7 +292,7 @@ class TestDeepObjectStyle: assert prefs_tool is not None # Check that nested object structure is preserved - params = prefs_tool.inputSchema + params = prefs_tool.input_schema properties = params["properties"] # Should have path parameter @@ -338,9 +338,9 @@ class TestDeepObjectStyle: # All tools should have valid schemas for tool in tools: - assert tool.inputSchema is not None - assert tool.inputSchema["type"] == "object" - assert "properties" in tool.inputSchema + assert tool.input_schema is not None + assert tool.input_schema["type"] == "object" + assert "properties" in tool.input_schema # Should have some properties - assert len(tool.inputSchema["properties"]) > 0 + assert len(tool.input_schema["properties"]) > 0 diff --git a/tests/server/providers/openapi/test_end_to_end_compatibility.py b/tests/server/providers/openapi/test_end_to_end_compatibility.py index 0680c0d2d..29f15a651 100644 --- a/tests/server/providers/openapi/test_end_to_end_compatibility.py +++ b/tests/server/providers/openapi/test_end_to_end_compatibility.py @@ -114,7 +114,7 @@ class TestEndToEndFunctionality: assert tool.description # Check schema structure - schema = tool.inputSchema + schema = tool.input_schema assert schema["type"] == "object" properties = schema.get("properties", {}) @@ -141,7 +141,7 @@ class TestEndToEndFunctionality: assert len(tools) == 1 tool = tools[0] - schema = tool.inputSchema + schema = tool.input_schema # Both should have collision-resolved parameters properties = schema.get("properties", {}) diff --git a/tests/server/providers/openapi/test_openapi_features.py b/tests/server/providers/openapi/test_openapi_features.py index ac78f1b10..74e9875d5 100644 --- a/tests/server/providers/openapi/test_openapi_features.py +++ b/tests/server/providers/openapi/test_openapi_features.py @@ -163,7 +163,7 @@ class TestParameterHandling: assert search_tool is not None # Check that parameters are included in the tool's input schema - params = search_tool.inputSchema + params = search_tool.input_schema assert params["type"] == "object" properties = params["properties"] @@ -211,7 +211,7 @@ class TestParameterHandling: assert user_post_tool is not None # Check that path parameters are included - params = user_post_tool.inputSchema + params = user_post_tool.input_schema properties = params["properties"] # Check that path parameters are present @@ -316,7 +316,7 @@ class TestRequestBodyHandling: assert create_tool is not None # Check that request body properties are included - params = create_tool.inputSchema + params = create_tool.input_schema properties = params["properties"] # Check that request body properties are present @@ -637,7 +637,7 @@ class TestResourceTemplateMimeType: async with Client(mcp) as mcp_client: templates = await mcp_client.list_resource_templates() assert len(templates) == 1 - assert templates[0].mimeType == "text/plain" + assert templates[0].mime_type == "text/plain" async def test_resource_template_html_mime_type(self, html_spec): """Resource template should reflect text/html from OpenAPI spec.""" @@ -651,7 +651,7 @@ class TestResourceTemplateMimeType: async with Client(mcp) as mcp_client: templates = await mcp_client.list_resource_templates() assert len(templates) == 1 - assert templates[0].mimeType == "text/html" + assert templates[0].mime_type == "text/html" async def test_resource_template_defaults_json_mime_type(self): """Resource template defaults to application/json for JSON responses.""" @@ -702,7 +702,7 @@ class TestResourceTemplateMimeType: async with Client(mcp) as mcp_client: templates = await mcp_client.list_resource_templates() assert len(templates) == 1 - assert templates[0].mimeType == "application/json" + assert templates[0].mime_type == "application/json" class TestResourceMimeType: @@ -741,7 +741,7 @@ class TestResourceMimeType: async with Client(mcp) as mcp_client: resources = await mcp_client.list_resources() assert len(resources) == 1 - assert resources[0].mimeType == "text/plain" + assert resources[0].mime_type == "text/plain" async def test_resource_mime_type_without_schema(self): """Resource with media type but no schema still infers MIME type.""" @@ -774,7 +774,7 @@ class TestResourceMimeType: async with Client(mcp) as mcp_client: resources = await mcp_client.list_resources() assert len(resources) == 1 - assert resources[0].mimeType == "text/plain" + assert resources[0].mime_type == "text/plain" class TestValidateOutput: @@ -981,10 +981,10 @@ class TestValidateOutput: tools = await mcp_client.list_tools() get_user = next(t for t in tools if t.name == "get_user") # With validate_output=False, the outputSchema should be permissive - assert get_user.outputSchema is not None - assert get_user.outputSchema.get("additionalProperties") is True + assert get_user.output_schema is not None + assert get_user.output_schema.get("additionalProperties") is True # Should NOT have specific properties from the original schema - assert "properties" not in get_user.outputSchema + assert "properties" not in get_user.output_schema class TestRedactHeaders: diff --git a/tests/server/providers/openapi/test_parameter_collisions.py b/tests/server/providers/openapi/test_parameter_collisions.py index 09a5a3c5d..104d66398 100644 --- a/tests/server/providers/openapi/test_parameter_collisions.py +++ b/tests/server/providers/openapi/test_parameter_collisions.py @@ -146,7 +146,7 @@ class TestParameterCollisions: assert update_tool is not None # Check that both path and body 'id' parameters are included - params = update_tool.inputSchema + params = update_tool.input_schema properties = params["properties"] # Should have both path ID and body ID (with potential suffixing) @@ -188,7 +188,7 @@ class TestParameterCollisions: assert search_tool is not None # Check that both query and header 'query' parameters are handled - params = search_tool.inputSchema + params = search_tool.input_schema properties = params["properties"] # Should handle the collision somehow (suffixing or other mechanism) @@ -220,6 +220,6 @@ class TestParameterCollisions: # Tools should have valid schemas for tool in tools: - assert tool.inputSchema is not None - assert tool.inputSchema["type"] == "object" - assert "properties" in tool.inputSchema + assert tool.input_schema is not None + assert tool.input_schema["type"] == "object" + assert "properties" in tool.input_schema diff --git a/tests/server/providers/openapi/test_server.py b/tests/server/providers/openapi/test_server.py index af3641ca0..994e3b9e2 100644 --- a/tests/server/providers/openapi/test_server.py +++ b/tests/server/providers/openapi/test_server.py @@ -348,7 +348,7 @@ class TestOpenAPIProviderBasicFunctionality: }, "required": ["name", "active"], } - assert tool.inputSchema == expected_input_schema + assert tool.input_schema == expected_input_schema expected_output_schema = { "type": "object", @@ -360,4 +360,4 @@ class TestOpenAPIProviderBasicFunctionality: "required": ["id", "name", "active"], "title": "User", } - assert tool.outputSchema == expected_output_schema + assert tool.output_schema == expected_output_schema diff --git a/tests/server/providers/proxy/test_proxy_client.py b/tests/server/providers/proxy/test_proxy_client.py index 9a63b9856..4a3a3fd25 100644 --- a/tests/server/providers/proxy/test_proxy_client.py +++ b/tests/server/providers/proxy/test_proxy_client.py @@ -152,10 +152,10 @@ class TestProxyClient: content=TextContent(type="text", text="Hello, world!"), ) ] - assert params.systemPrompt == "You love FastMCP" + assert params.system_prompt == "You love FastMCP" assert params.temperature == 0.5 - assert params.maxTokens == 100 - assert params.modelPreferences == ModelPreferences( + assert params.max_tokens == 100 + assert params.model_preferences == ModelPreferences( hints=[ModelHint(name="gpt-4o")] ) return "" @@ -189,7 +189,7 @@ class TestProxyClient: assert message == "What is your name?" assert "Person" in str(response_type) assert isinstance(params, ElicitRequestFormParams) - assert params.requestedSchema == { + assert params.requested_schema == { "title": "Person", "type": "object", "properties": {"name": {"title": "Name", "type": "string"}}, @@ -388,7 +388,7 @@ class TestProxyClient: ): # Verify the schema is correct - acknowledge should have default=False, not be nullable assert isinstance(params, ElicitRequestFormParams) - schema = params.requestedSchema + schema = params.requested_schema assert schema["properties"]["acknowledge"]["type"] == "boolean" assert schema["properties"]["acknowledge"]["default"] is False diff --git a/tests/server/providers/proxy/test_proxy_server.py b/tests/server/providers/proxy/test_proxy_server.py index 8b19e546f..58fc1a7cc 100644 --- a/tests/server/providers/proxy/test_proxy_server.py +++ b/tests/server/providers/proxy/test_proxy_server.py @@ -479,7 +479,7 @@ class TestTools: async with Client(proxy_server) as client: tools = await client.list_tools() greet_tool = next(t for t in tools if t.name == "greet") - assert "extra" in greet_tool.inputSchema["properties"] + assert "extra" in greet_tool.input_schema["properties"] class TestResources: @@ -546,18 +546,18 @@ class TestResources: assert isinstance(original, TextResourceContents) assert isinstance(proxied, TextResourceContents) assert original.text == proxied.text, f"Content {i} text mismatch" - assert original.mimeType == proxied.mimeType, ( + assert original.mime_type == proxied.mime_type, ( f"Content {i} mimeType mismatch" ) assert original.meta == proxied.meta, f"Content {i} meta mismatch" # Verify the contents are what we expect assert original_result[0].text == "First item" - assert original_result[0].mimeType == "text/plain" + assert original_result[0].mime_type == "text/plain" assert original_result[1].text == '{"key": "value"}' - assert original_result[1].mimeType == "application/json" + assert original_result[1].mime_type == "application/json" assert original_result[2].text == "# Markdown\nContent" - assert original_result[2].mimeType == "text/markdown" + assert original_result[2].mime_type == "text/markdown" async def test_read_resource_returns_none_if_not_found(self, proxy_server): with pytest.raises( @@ -661,15 +661,15 @@ class TestResourceTemplates: assert isinstance(original, TextResourceContents) assert isinstance(proxied, TextResourceContents) assert original.text == proxied.text, f"Content {i} text mismatch" - assert original.mimeType == proxied.mimeType, ( + assert original.mime_type == proxied.mime_type, ( f"Content {i} mimeType mismatch" ) # Verify the contents are what we expect assert original_result[0].text == "Item test123 - First" - assert original_result[0].mimeType == "text/plain" + assert original_result[0].mime_type == "text/plain" assert original_result[1].text == '{"id": "test123", "status": "active"}' - assert original_result[1].mimeType == "application/json" + assert original_result[1].mime_type == "application/json" async def test_proxy_can_overwrite_proxied_resource_template(self, proxy_server): """ @@ -706,7 +706,7 @@ class TestResourceTemplates: async with Client(proxy_server) as client: templates = await client.list_resource_templates() user_template = next( - t for t in templates if t.uriTemplate == "data://user/{user_id}" + t for t in templates if t.uri_template == "data://user/{user_id}" ) assert user_template.name == "overwritten_get_user" @@ -888,7 +888,7 @@ class TestPrompts: # Verify the image content is preserved as ImageContent, not JSON text assert isinstance(proxy_result.messages[1].content, mcp_types.ImageContent) assert proxy_result.messages[1].content.data == "iVBORw0KGgoAAAANSUhEUg==" - assert proxy_result.messages[1].content.mimeType == "image/png" + assert proxy_result.messages[1].content.mime_type == "image/png" async def test_proxy_handles_multiple_concurrent_tasks_correctly( diff --git a/tests/server/sampling/test_sampling_tool.py b/tests/server/sampling/test_sampling_tool.py index 1541e2d92..792161ea3 100644 --- a/tests/server/sampling/test_sampling_tool.py +++ b/tests/server/sampling/test_sampling_tool.py @@ -125,7 +125,7 @@ class TestSamplingToolSDKConversion: assert sdk_tool.name == "search" assert sdk_tool.description == "Search the web." - assert "query" in sdk_tool.inputSchema.get("properties", {}) + assert "query" in sdk_tool.input_schema.get("properties", {}) class TestSamplingToolFromCallableTool: diff --git a/tests/server/tasks/test_progress_dependency.py b/tests/server/tasks/test_progress_dependency.py index e61232fa4..6cc35996a 100644 --- a/tests/server/tasks/test_progress_dependency.py +++ b/tests/server/tasks/test_progress_dependency.py @@ -97,7 +97,7 @@ async def test_progress_status_message_in_background_task(): # Verify statusMessage field is accessible and contains progress info # Should not raise AttributeError - msg = status.statusMessage + msg = status.status_message assert msg is None or msg.startswith("Step") # Wait for completion diff --git a/tests/server/tasks/test_resource_task_meta_parameter.py b/tests/server/tasks/test_resource_task_meta_parameter.py index f22bbf92e..86d36b3a4 100644 --- a/tests/server/tasks/test_resource_task_meta_parameter.py +++ b/tests/server/tasks/test_resource_task_meta_parameter.py @@ -185,7 +185,7 @@ class TestResourceTaskMetaDirectServerCall: # Read inner resource as background task result = await server.read_resource("data://inner", task_meta=TaskMeta()) # Should get CreateTaskResult since we provided task_meta - return f"Created task: {result.task.taskId}" + return f"Created task: {result.task.task_id}" async with Client(server) as client: result = await client.call_tool("outer_tool", {}) @@ -221,7 +221,7 @@ class TestResourceTaskMetaDirectServerCall: @server.tool async def outer_tool() -> str: result = await server.read_resource("item://99", task_meta=TaskMeta()) - return f"Created task: {result.task.taskId}" + return f"Created task: {result.task.task_id}" async with Client(server) as client: result = await client.call_tool("outer_tool", {}) diff --git a/tests/server/tasks/test_task_config.py b/tests/server/tasks/test_task_config.py index 72cdeec45..f1f3eaf9e 100644 --- a/tests/server/tasks/test_task_config.py +++ b/tests/server/tasks/test_task_config.py @@ -265,7 +265,7 @@ class TestPromptModeEnforcement: class TestToolExecutionMetadata: - """Test that ToolExecution.taskSupport is set correctly in tool metadata.""" + """Test that ToolExecution.task_support is set correctly in tool metadata.""" async def test_optional_tool_exposes_task_support(self): """Tools with task enabled should expose taskSupport in metadata.""" @@ -280,7 +280,7 @@ class TestToolExecutionMetadata: tool = next(t for t in tools if t.name == "my_tool") assert isinstance(tool, MCPTool) assert isinstance(tool.execution, ToolExecution) - assert tool.execution.taskSupport == "optional" + assert tool.execution.task_support == "optional" async def test_required_tool_exposes_task_support(self): """Tools with mode=required should expose taskSupport='required'.""" @@ -295,7 +295,7 @@ class TestToolExecutionMetadata: tool = next(t for t in tools if t.name == "my_tool") assert isinstance(tool, MCPTool) assert isinstance(tool.execution, ToolExecution) - assert tool.execution.taskSupport == "required" + assert tool.execution.task_support == "required" async def test_forbidden_tool_has_no_execution(self): """Tools with mode=forbidden should not expose execution metadata.""" diff --git a/tests/server/tasks/test_task_meta_parameter.py b/tests/server/tasks/test_task_meta_parameter.py index 792a2c0f8..e76930637 100644 --- a/tests/server/tasks/test_task_meta_parameter.py +++ b/tests/server/tasks/test_task_meta_parameter.py @@ -263,7 +263,7 @@ class TestTaskMetaDirectServerCall: "inner_tool", {"x": x}, task_meta=TaskMeta() ) # Should get CreateTaskResult since we're in server context - return f"Created task: {result.task.taskId}" + return f"Created task: {result.task.task_id}" async with Client(server) as client: # Call outer_tool which internally calls inner_tool with task_meta diff --git a/tests/server/tasks/test_task_metadata.py b/tests/server/tasks/test_task_metadata.py index 32ce2b849..0d8935d36 100644 --- a/tests/server/tasks/test_task_metadata.py +++ b/tests/server/tasks/test_task_metadata.py @@ -35,7 +35,7 @@ async def test_tasks_get_includes_related_task_metadata(metadata_server: FastMCP # GetTaskResult is returned from response with metadata # Verify the protocol included related-task metadata by checking the response worked - assert status.taskId == task_id + assert status.task_id == task_id assert status.status in ["working", "completed"] diff --git a/tests/server/tasks/test_task_methods.py b/tests/server/tasks/test_task_methods.py index f1ebfd5da..493bc9167 100644 --- a/tests/server/tasks/test_task_methods.py +++ b/tests/server/tasks/test_task_methods.py @@ -45,7 +45,7 @@ async def test_tasks_get_endpoint_returns_status(endpoint_server): # Check status immediately - should be submitted or working status = await task.status() - assert status.taskId == task.task_id + assert status.task_id == task.task_id assert status.status in ["working", "completed"] # Wait for completion @@ -62,8 +62,8 @@ async def test_tasks_get_endpoint_includes_poll_interval(endpoint_server): task = await client.call_tool("quick_tool", {"value": 42}, task=True) status = await task.status() - assert status.pollInterval is not None - assert isinstance(status.pollInterval, int) + assert status.poll_interval is not None + assert isinstance(status.poll_interval, int) async def test_tasks_result_endpoint_returns_result_when_completed(endpoint_server): diff --git a/tests/server/tasks/test_task_mount.py b/tests/server/tasks/test_task_mount.py index fb0a6098a..e85a3c27a 100644 --- a/tests/server/tasks/test_task_mount.py +++ b/tests/server/tasks/test_task_mount.py @@ -553,7 +553,7 @@ class TestMountedTaskMetadata: """Test task metadata exposure for mounted tools.""" async def test_mounted_tool_list_preserves_task_support_metadata(self): - """Mounted tools should preserve execution.taskSupport in tools/list.""" + """Mounted tools should preserve execution.task_support in tools/list.""" child = FastMCP("child") @child.tool(task=True) @@ -574,11 +574,11 @@ class TestMountedTaskMetadata: assert child_mcp_tool.execution is not None assert parent_mcp_tool.execution is not None - assert child_mcp_tool.execution.taskSupport == "optional" - assert parent_mcp_tool.execution.taskSupport == "optional" + assert child_mcp_tool.execution.task_support == "optional" + assert parent_mcp_tool.execution.task_support == "optional" async def test_proxy_tool_preserves_execution_metadata(self): - """ProxyTool.from_mcp_tool should propagate execution.taskSupport (#3569).""" + """ProxyTool.from_mcp_tool should propagate execution.task_support (#3569).""" mcp_tool = MCPTool( name="remote_task_tool", description="A remote tool that supports tasks", @@ -590,7 +590,7 @@ class TestMountedTaskMetadata: result = proxy.to_mcp_tool(name=proxy.name) assert result.execution is not None - assert result.execution.taskSupport == "optional" + assert result.execution.task_support == "optional" class TestMountedTaskConfigModes: @@ -928,7 +928,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.call_tool( "child_add", {"a": 2, "b": 3}, task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -952,7 +952,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.read_resource( "data://child/info", task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -976,7 +976,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.read_resource( "item://child/42", task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -1003,7 +1003,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.call_tool( "c_gc_compute", {"n": 7}, task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -1030,7 +1030,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.read_resource( "doc://c/gc/readme", task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -1054,7 +1054,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.render_prompt( "child_greet", {"name": "World"}, task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) @@ -1081,7 +1081,7 @@ class TestMountedTasksWithTaskMetaParameter: result = await parent.render_prompt( "c_gc_describe", {"topic": "FastMCP"}, task_meta=TaskMeta(ttl=300) ) - return f"task:{result.task.taskId}" + return f"task:{result.task.task_id}" async with Client(parent) as client: result = await client.call_tool("outer", {}) diff --git a/tests/server/tasks/test_task_protocol.py b/tests/server/tasks/test_task_protocol.py index 9c6a88d22..9fd2fd7a6 100644 --- a/tests/server/tasks/test_task_protocol.py +++ b/tests/server/tasks/test_task_protocol.py @@ -61,7 +61,7 @@ async def test_task_notification_sent_after_submission(task_enabled_server): # Verify we can query the task status = await task.status() - assert status.taskId == task.task_id + assert status.task_id == task.task_id async def test_failed_task_stores_error(task_enabled_server): diff --git a/tests/server/tasks/test_task_return_types.py b/tests/server/tasks/test_task_return_types.py index a9fbc5d36..697eb4ae6 100644 --- a/tests/server/tasks/test_task_return_types.py +++ b/tests/server/tasks/test_task_return_types.py @@ -407,7 +407,7 @@ async def media_server(tmp_path): lambda r: ( len(r.content) == 1 and r.content[0].type == "image" - and r.content[0].mimeType == "image/png" + and r.content[0].mime_type == "image/png" ), ), ( @@ -630,7 +630,7 @@ async def mcp_content_server(tmp_path): lambda r: ( len(r.content) == 1 and r.content[0].type == "image" - and r.content[0].mimeType == "image/png" + and r.content[0].mime_type == "image/png" ), ), ( diff --git a/tests/server/test_dependencies.py b/tests/server/test_dependencies.py index f545335eb..0c7858f52 100644 --- a/tests/server/test_dependencies.py +++ b/tests/server/test_dependencies.py @@ -139,10 +139,10 @@ async def test_dependencies_excluded_from_schema(mcp: FastMCP): result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "my_tool") - assert "name" in tool.inputSchema["properties"] - assert "age" in tool.inputSchema["properties"] - assert "config" not in tool.inputSchema["properties"] - assert len(tool.inputSchema["properties"]) == 2 + assert "name" in tool.input_schema["properties"] + assert "age" in tool.input_schema["properties"] + assert "config" not in tool.input_schema["properties"] + assert len(tool.input_schema["properties"]) == 2 async def test_current_context_dependency(mcp: FastMCP): @@ -471,8 +471,8 @@ async def test_connection_dependency_excluded_from_tool_schema(mcp: FastMCP): result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "with_connection") - assert "name" in tool.inputSchema["properties"] - assert "connection" not in tool.inputSchema["properties"] + assert "name" in tool.input_schema["properties"] + assert "connection" not in tool.input_schema["properties"] async def test_sync_tool_context_manager_stays_open(mcp: FastMCP): @@ -592,7 +592,7 @@ async def test_external_user_cannot_override_dependency(mcp: FastMCP): # Verify dependency is NOT in the schema result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "check_permission") - assert "admin" not in tool.inputSchema["properties"] + assert "admin" not in tool.input_schema["properties"] # Normal call - dependency is resolved result = await mcp.call_tool("check_permission", {"action": "read"}) @@ -979,8 +979,8 @@ class TestAuthDependencies: result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "tool_with_token") - assert "name" in tool.inputSchema["properties"] - assert "token" not in tool.inputSchema["properties"] + assert "name" in tool.input_schema["properties"] + assert "token" not in tool.input_schema["properties"] async def test_token_claim_excluded_from_tool_schema(self, mcp: FastMCP): """Test that TokenClaim dependency is excluded from tool schema.""" @@ -998,8 +998,8 @@ class TestAuthDependencies: result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "tool_with_claim") - assert "name" in tool.inputSchema["properties"] - assert "user_id" not in tool.inputSchema["properties"] + assert "name" in tool.input_schema["properties"] + assert "user_id" not in tool.input_schema["properties"] def test_current_access_token_exported_from_all(self): """Test that CurrentAccessToken is exported from __all__.""" @@ -1143,8 +1143,8 @@ class TestSharedDependencies: result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "my_tool") - assert "name" in tool.inputSchema["properties"] - assert "db" not in tool.inputSchema["properties"] + assert "name" in tool.input_schema["properties"] + assert "db" not in tool.input_schema["properties"] async def test_shared_in_resource(self, mcp: FastMCP): """Shared dependencies work in resource functions.""" diff --git a/tests/server/test_dependencies_advanced.py b/tests/server/test_dependencies_advanced.py index 0e9f424a9..8979f403d 100644 --- a/tests/server/test_dependencies_advanced.py +++ b/tests/server/test_dependencies_advanced.py @@ -172,9 +172,9 @@ class TestTransformContextAnnotations: # Both ctx params should be excluded from schema result = await mcp._list_tools_mcp(mcp_types.ListToolsRequest()) tool = next(t for t in result.tools if t.name == "tool_with_multiple_ctx") - assert "name" in tool.inputSchema["properties"] - assert "ctx1" not in tool.inputSchema["properties"] - assert "ctx2" not in tool.inputSchema["properties"] + assert "name" in tool.input_schema["properties"] + assert "ctx1" not in tool.input_schema["properties"] + assert "ctx2" not in tool.input_schema["properties"] async def test_context_in_class_method(self, mcp: FastMCP): """Test Context transformation works with bound methods.""" diff --git a/tests/server/test_icons.py b/tests/server/test_icons.py index 935b4d971..2d60e66ef 100644 --- a/tests/server/test_icons.py +++ b/tests/server/test_icons.py @@ -36,8 +36,8 @@ class TestServerIcons: # Verify that icons and website_url are passed to the underlying server async with Client(mcp) as client: - server_info = client.initialize_result.serverInfo - assert server_info.websiteUrl == "https://example.com" + server_info = client.initialize_result.server_info + assert server_info.website_url == "https://example.com" assert server_info.icons == icons async def test_server_without_icons_and_website_url(self): @@ -45,8 +45,8 @@ class TestServerIcons: mcp = FastMCP(name="TestServer") async with Client(mcp) as client: - server_info = client.initialize_result.serverInfo - assert server_info.websiteUrl is None + server_info = client.initialize_result.server_info + assert server_info.website_url is None assert server_info.icons is None @@ -290,7 +290,7 @@ class TestIconTypes: mcp = FastMCP("TestServer", icons=icons) async with Client(mcp) as client: - server_info = client.initialize_result.serverInfo + server_info = client.initialize_result.server_info assert len(server_info.icons) == 3 assert server_info.icons == icons @@ -319,9 +319,9 @@ class TestIconTypes: mcp = FastMCP("TestServer", icons=icons) async with Client(mcp) as client: - server_info = client.initialize_result.serverInfo + server_info = client.initialize_result.server_info assert server_info.icons[0].src == "https://example.com/icon.png" - assert server_info.icons[0].mimeType is None + assert server_info.icons[0].mime_type is None assert server_info.icons[0].sizes is None diff --git a/tests/server/test_pagination.py b/tests/server/test_pagination.py index 8a53e05d3..89d3ec79e 100644 --- a/tests/server/test_pagination.py +++ b/tests/server/test_pagination.py @@ -166,17 +166,17 @@ class TestServerPagination: # First page result = await client.list_tools_mcp() assert len(result.tools) == 10 - assert result.nextCursor is not None + assert result.next_cursor is not None # Second page - result2 = await client.list_tools_mcp(cursor=result.nextCursor) + result2 = await client.list_tools_mcp(cursor=result.next_cursor) assert len(result2.tools) == 10 - assert result2.nextCursor is not None + assert result2.next_cursor is not None # Third (last) page - result3 = await client.list_tools_mcp(cursor=result2.nextCursor) + result3 = await client.list_tools_mcp(cursor=result2.next_cursor) assert len(result3.tools) == 5 - assert result3.nextCursor is None + assert result3.next_cursor is None async def test_invalid_cursor_returns_error(self) -> None: """Server should return MCP error for invalid cursor.""" @@ -204,7 +204,7 @@ class TestServerPagination: async with Client(server) as client: result = await client.list_tools_mcp() assert len(result.tools) == 25 - assert result.nextCursor is None + assert result.next_cursor is None async def test_pagination_exact_page_boundary(self) -> None: """Test pagination at exact page boundaries.""" @@ -220,12 +220,12 @@ class TestServerPagination: # First page result = await client.list_tools_mcp() assert len(result.tools) == 10 - assert result.nextCursor is not None + assert result.next_cursor is not None # Second (last) page - result2 = await client.list_tools_mcp(cursor=result.nextCursor) + result2 = await client.list_tools_mcp(cursor=result.next_cursor) assert len(result2.tools) == 10 - assert result2.nextCursor is None + assert result2.next_cursor is None class TestPageSizeValidation: @@ -265,7 +265,7 @@ class TestPaginationCycleDetection: cursor: str | None = None, ) -> mcp_types.ListToolsResult: result = await original(cursor=cursor) - result.nextCursor = "stuck" + result.next_cursor = "stuck" return result with patch.object( @@ -294,7 +294,7 @@ class TestPaginationCycleDetection: cursor: str | None = None, ) -> mcp_types.ListPromptsResult: result = await original(cursor=cursor) - result.nextCursor = "stuck" + result.next_cursor = "stuck" return result with patch.object( @@ -321,7 +321,7 @@ class TestPaginationCycleDetection: cursor: str | None = None, ) -> mcp_types.ListResourcesResult: result = await original(cursor=cursor) - result.nextCursor = "stuck" + result.next_cursor = "stuck" return result with patch.object( @@ -348,7 +348,7 @@ class TestPaginationCycleDetection: cursor: str | None = None, ) -> mcp_types.ListResourceTemplatesResult: result = await original(cursor=cursor) - result.nextCursor = "stuck" + result.next_cursor = "stuck" return result with patch.object( @@ -380,7 +380,7 @@ class TestPaginationCycleDetection: result = await original(cursor=cursor) # Cycle through A -> B -> C -> A cursors = ["A", "B", "C"] - result.nextCursor = cursors[call_count % 3] + result.next_cursor = cursors[call_count % 3] call_count += 1 return result @@ -409,7 +409,7 @@ class TestPaginationCycleDetection: cursor: str | None = None, ) -> mcp_types.ListToolsResult: result = await original(cursor=cursor) - result.nextCursor = "" + result.next_cursor = "" return result with patch.object( @@ -439,7 +439,7 @@ class TestPaginationCycleDetection: nonlocal call_count result = await original(cursor=cursor) call_count += 1 - result.nextCursor = f"cursor-{call_count}" + result.next_cursor = f"cursor-{call_count}" return result with ( @@ -469,7 +469,7 @@ class TestPaginationCycleDetection: nonlocal call_count result = await original(cursor=cursor) call_count += 1 - result.nextCursor = f"cursor-{call_count}" + result.next_cursor = f"cursor-{call_count}" return result with ( @@ -499,7 +499,7 @@ class TestPaginationCycleDetection: nonlocal call_count result = await original(cursor=cursor) call_count += 1 - result.nextCursor = f"cursor-{call_count}" + result.next_cursor = f"cursor-{call_count}" return result with ( diff --git a/tests/server/test_server.py b/tests/server/test_server.py index bfc103746..83374362d 100644 --- a/tests/server/test_server.py +++ b/tests/server/test_server.py @@ -365,7 +365,7 @@ class TestMeta: async with Client(mcp) as client: templates = await client.list_resource_templates() template = next( - t for t in templates if t.uriTemplate == "test://template/{id}" + t for t in templates if t.uri_template == "test://template/{id}" ) assert template.meta is not None assert set(template.meta["fastmcp"]["tags"]) == { diff --git a/tests/server/test_tool_annotations.py b/tests/server/test_tool_annotations.py index b7628c5df..e95a08b42 100644 --- a/tests/server/test_tool_annotations.py +++ b/tests/server/test_tool_annotations.py @@ -28,8 +28,8 @@ async def test_tool_annotations_in_tool_manager(): assert len(tools) == 1 assert tools[0].annotations is not None assert tools[0].annotations.title == "Echo Tool" - assert tools[0].annotations.readOnlyHint is True - assert tools[0].annotations.openWorldHint is False + assert tools[0].annotations.read_only_hint is True + assert tools[0].annotations.open_world_hint is False async def test_tool_annotations_in_mcp_protocol(): @@ -52,8 +52,8 @@ async def test_tool_annotations_in_mcp_protocol(): assert len(result.tools) == 1 assert result.tools[0].annotations is not None assert result.tools[0].annotations.title == "Echo Tool" - assert result.tools[0].annotations.readOnlyHint is True - assert result.tools[0].annotations.openWorldHint is False + assert result.tools[0].annotations.read_only_hint is True + assert result.tools[0].annotations.open_world_hint is False async def test_tool_annotations_in_client_api(): @@ -78,8 +78,8 @@ async def test_tool_annotations_in_client_api(): assert tools_result[0].name == "echo" assert tools_result[0].annotations is not None assert tools_result[0].annotations.title == "Echo Tool" - assert tools_result[0].annotations.readOnlyHint is True - assert tools_result[0].annotations.openWorldHint is False + assert tools_result[0].annotations.read_only_hint is True + assert tools_result[0].annotations.open_world_hint is False async def test_provide_tool_annotations_as_dict_to_decorator(): @@ -104,8 +104,8 @@ async def test_provide_tool_annotations_as_dict_to_decorator(): assert tools_result[0].name == "echo" assert tools_result[0].annotations is not None assert tools_result[0].annotations.title == "Echo Tool" - assert tools_result[0].annotations.readOnlyHint is True - assert tools_result[0].annotations.openWorldHint is False + assert tools_result[0].annotations.read_only_hint is True + assert tools_result[0].annotations.open_world_hint is False async def test_direct_tool_annotations_in_tool_manager(): @@ -130,10 +130,10 @@ async def test_direct_tool_annotations_in_tool_manager(): assert len(tools) == 1 assert tools[0].annotations is not None assert tools[0].annotations.title == "Direct Tool" - assert tools[0].annotations.readOnlyHint is False - assert tools[0].annotations.destructiveHint is True - assert tools[0].annotations.idempotentHint is False - assert tools[0].annotations.openWorldHint is True + assert tools[0].annotations.read_only_hint is False + assert tools[0].annotations.destructive_hint is True + assert tools[0].annotations.idempotent_hint is False + assert tools[0].annotations.open_world_hint is True async def test_direct_tool_annotations_in_client_api(): @@ -160,8 +160,8 @@ async def test_direct_tool_annotations_in_client_api(): assert tools_result[0].name == "modify" assert tools_result[0].annotations is not None assert tools_result[0].annotations.title == "Direct Tool" - assert tools_result[0].annotations.readOnlyHint is False - assert tools_result[0].annotations.destructiveHint is True + assert tools_result[0].annotations.read_only_hint is False + assert tools_result[0].annotations.destructive_hint is True async def test_add_tool_method_annotations(): @@ -189,8 +189,8 @@ async def test_add_tool_method_annotations(): assert len(tools) == 1 assert tools[0].annotations is not None assert tools[0].annotations.title == "Create Item" - assert tools[0].annotations.readOnlyHint is False - assert tools[0].annotations.destructiveHint is False + assert tools[0].annotations.read_only_hint is False + assert tools[0].annotations.destructive_hint is False async def test_tool_functionality_with_annotations(): @@ -221,7 +221,7 @@ async def test_tool_functionality_with_annotations(): async def test_task_execution_auto_populated_for_task_enabled_tool(): - """Test that execution.taskSupport is automatically set when tool has task=True.""" + """Test that execution.task_support is automatically set when tool has task=True.""" mcp = FastMCP("Test Server") @mcp.tool(task=True) @@ -235,7 +235,7 @@ async def test_task_execution_auto_populated_for_task_enabled_tool(): assert tools_result[0].name == "background_tool" assert isinstance(tools_result[0], MCPTool) assert isinstance(tools_result[0].execution, ToolExecution) - assert tools_result[0].execution.taskSupport == "optional" + assert tools_result[0].execution.task_support == "optional" async def test_task_execution_omitted_for_task_disabled_tool(): diff --git a/tests/server/test_tool_transformation.py b/tests/server/test_tool_transformation.py index b9812f735..1379e54dc 100644 --- a/tests/server/test_tool_transformation.py +++ b/tests/server/test_tool_transformation.py @@ -277,9 +277,9 @@ async def test_openapi_path_params_not_duplicated_in_description(): assert tool.description == "My endpoint" # Hidden param gone from schema, visible param still present - assert "version" not in tool.inputSchema.get("properties", {}) - assert "user_id" in tool.inputSchema["properties"] + assert "version" not in tool.input_schema.get("properties", {}) + assert "user_id" in tool.input_schema["properties"] assert ( - tool.inputSchema["properties"]["user_id"]["description"] + tool.input_schema["properties"]["user_id"]["description"] == "The user ID" ) diff --git a/tests/server/transforms/test_resources_as_tools.py b/tests/server/transforms/test_resources_as_tools.py index 278d72c25..620a87c76 100644 --- a/tests/server/transforms/test_resources_as_tools.py +++ b/tests/server/transforms/test_resources_as_tools.py @@ -241,7 +241,7 @@ class TestResourcesAsToolsAnnotations: tools = await client.list_tools() tool = next(t for t in tools if t.name == "list_resources") assert tool.annotations is not None - assert tool.annotations.readOnlyHint is True + assert tool.annotations.read_only_hint is True async def test_read_resource_is_read_only(self): """read_resource is annotated as read-only by default.""" @@ -252,7 +252,7 @@ class TestResourcesAsToolsAnnotations: tools = await client.list_tools() tool = next(t for t in tools if t.name == "read_resource") assert tool.annotations is not None - assert tool.annotations.readOnlyHint is True + assert tool.annotations.read_only_hint is True def _deny_all(ctx: AuthContext) -> bool: diff --git a/tests/test_apps.py b/tests/test_apps.py index 39a612c80..45afaf26b 100644 --- a/tests/test_apps.py +++ b/tests/test_apps.py @@ -465,7 +465,7 @@ class TestIntegration: resources = await client.list_resources() assert len(resources) == 1 assert str(resources[0].uri) == "ui://my-app/view.html" - assert resources[0].mimeType == UI_MIME_TYPE + assert resources[0].mime_type == UI_MIME_TYPE async def test_ui_resource_read_preserves_mime_type(self): """Reading a ui:// resource returns content with the correct MIME type.""" @@ -478,7 +478,7 @@ class TestIntegration: async with Client(server) as client: result = await client.read_resource_mcp("ui://my-app/view.html") assert len(result.contents) == 1 - assert result.contents[0].mimeType == UI_MIME_TYPE + assert result.contents[0].mime_type == UI_MIME_TYPE async def test_app_tool_callable(self): """A tool registered with app= is still callable normally.""" diff --git a/tests/test_fastmcp_app.py b/tests/test_fastmcp_app.py index 72d693c7e..86f9eae60 100644 --- a/tests/test_fastmcp_app.py +++ b/tests/test_fastmcp_app.py @@ -882,7 +882,7 @@ class TestAppIntegration: # Call the UI tool through the client and check structured_content result = await client.call_tool_mcp("crm_contact_form", {}) - sc = result.structuredContent + sc = result.structured_content assert sc is not None # Call the backend tool via its hashed address — bypasses namespace diff --git a/tests/tools/test_tool_future_annotations.py b/tests/tools/test_tool_future_annotations.py index d7f5c75e7..2723843ca 100644 --- a/tests/tools/test_tool_future_annotations.py +++ b/tests/tools/test_tool_future_annotations.py @@ -107,7 +107,7 @@ class TestFutureAnnotations: async with Client(fastmcp_server) as client: result = await client.call_tool("returns_image", {}) assert result.content[0].type == "image" - assert result.content[0].mimeType == "image/png" + assert result.content[0].mime_type == "image/png" async def test_async_with_context(self): async with Client(fastmcp_server) as client: diff --git a/tests/tools/tool/test_results.py b/tests/tools/tool/test_results.py index 79e1be485..830d5f1f1 100644 --- a/tests/tools/tool/test_results.py +++ b/tests/tools/tool/test_results.py @@ -83,10 +83,10 @@ class TestToolResultIsError: ) mcp_result = result.to_mcp_result() assert isinstance(mcp_result, CallToolResult) - assert mcp_result.isError is True + assert mcp_result.is_error is True assert isinstance(mcp_result.content[0], TextContent) assert mcp_result.content[0].text == "boom" - assert mcp_result.structuredContent == {"code": 42} + assert mcp_result.structured_content == {"code": 42} def test_default_is_not_error(self): result = ToolResult(content="ok") @@ -269,7 +269,7 @@ class TestSerializeByAlias: "id": "123", "filepath": "/p", } - assert set(tools["get_biofile"].outputSchema["properties"]) == { # type: ignore[index] + assert set(tools["get_biofile"].output_schema["properties"]) == { # type: ignore[index] "id", "filepath", } @@ -292,7 +292,7 @@ class TestSerializeByAlias: result = await client.call_tool("get_biofile", {}) assert result.structured_content == {"_id": "123", "filepath": "/p"} - assert set(tools["get_biofile"].outputSchema["properties"]) == { # type: ignore[index] + assert set(tools["get_biofile"].output_schema["properties"]) == { # type: ignore[index] "_id", "filepath", } @@ -315,7 +315,7 @@ class TestSerializeByAlias: result = await client.call_tool("get_biofile", {}) assert result.structured_content == {"_id": "123"} - assert set(tools["get_biofile"].outputSchema["properties"]) == {"_id"} # type: ignore[index] + assert set(tools["get_biofile"].output_schema["properties"]) == {"_id"} # type: ignore[index] async def test_nested_models_respect_config(self): """serialize_by_alias=False propagates through nested models.""" @@ -364,7 +364,7 @@ class TestSerializeByAlias: # raises if they disagree result = await client.call_tool("get_biofile", {}) - schema_props = set(tools["get_biofile"].outputSchema["properties"]) # type: ignore[index] + schema_props = set(tools["get_biofile"].output_schema["properties"]) # type: ignore[index] assert schema_props == set(result.structured_content) # type: ignore[arg-type] assert result.structured_content == {"result": {"id": "1"}} @@ -391,5 +391,5 @@ class TestSerializeByAlias: tools = {t.name: t for t in await client.list_tools()} result = await client.call_tool("get_model", {}) - schema_props = set(tools["get_model"].outputSchema["properties"]) # type: ignore[index] + schema_props = set(tools["get_model"].output_schema["properties"]) # type: ignore[index] assert schema_props == set(result.structured_content) # type: ignore[arg-type] diff --git a/tests/tools/tool/test_tool.py b/tests/tools/tool/test_tool.py index e84ad3efd..f40860d07 100644 --- a/tests/tools/tool/test_tool.py +++ b/tests/tools/tool/test_tool.py @@ -547,7 +547,7 @@ class TestToolExecutionField: mcp_tool = tool.to_mcp_tool() assert mcp_tool.execution is not None - assert mcp_tool.execution.taskSupport == "optional" + assert mcp_tool.execution.task_support == "optional" def test_tool_without_execution_field(self): """Test that Tool without execution returns None.""" @@ -572,7 +572,7 @@ class TestToolExecutionField: override_execution = ToolExecution(taskSupport="required") mcp_tool = tool.to_mcp_tool(execution=override_execution) assert mcp_tool.execution is not None - assert mcp_tool.execution.taskSupport == "required" + assert mcp_tool.execution.task_support == "required" async def test_function_tool_task_config_still_works(self): """FunctionTool should still derive execution from task_config.""" @@ -585,7 +585,7 @@ class TestToolExecutionField: # FunctionTool sets execution from task_config assert mcp_tool.execution is not None - assert mcp_tool.execution.taskSupport == "optional" + assert mcp_tool.execution.task_support == "optional" def test_tool_execution_required_mode(self): """Test that Tool can store required execution mode.""" @@ -598,7 +598,7 @@ class TestToolExecutionField: mcp_tool = tool.to_mcp_tool() assert mcp_tool.execution is not None - assert mcp_tool.execution.taskSupport == "required" + assert mcp_tool.execution.task_support == "required" def test_tool_execution_forbidden_mode(self): """Test that Tool can store forbidden execution mode.""" @@ -611,4 +611,4 @@ class TestToolExecutionField: mcp_tool = tool.to_mcp_tool() assert mcp_tool.execution is not None - assert mcp_tool.execution.taskSupport == "forbidden" + assert mcp_tool.execution.task_support == "forbidden" diff --git a/tests/utilities/openapi/test_nullable_fields.py b/tests/utilities/openapi/test_nullable_fields.py index ff1881e46..ccdfe8c43 100644 --- a/tests/utilities/openapi/test_nullable_fields.py +++ b/tests/utilities/openapi/test_nullable_fields.py @@ -458,7 +458,7 @@ class TestNullableInputSchemaIntegration: """Test that nullable fields are converted in tool input schemas end-to-end. These tests exercise the full pipeline: OpenAPI spec -> OpenAPIProvider -> - tool.inputSchema, verifying that `nullable: true` doesn't leak through. + tool.input_schema, verifying that `nullable: true` doesn't leak through. """ async def test_nullable_query_param_converted_in_tool_input_schema(self): @@ -496,7 +496,7 @@ class TestNullableInputSchemaIntegration: async with Client(mcp) as mcp_client: tools = await mcp_client.list_tools() assert len(tools) == 1 - schema = tools[0].inputSchema + schema = tools[0].input_schema category_prop = schema["properties"]["category"] assert "nullable" not in category_prop assert category_prop["type"] == ["string", "null"] @@ -545,7 +545,7 @@ class TestNullableInputSchemaIntegration: async with Client(mcp) as mcp_client: tools = await mcp_client.list_tools() assert len(tools) == 1 - schema = tools[0].inputSchema + schema = tools[0].input_schema # Find the bio property — it may be inline or in $defs if "$defs" in schema: diff --git a/tests/utilities/test_types.py b/tests/utilities/test_types.py index 4c818b6af..3d366aa64 100644 --- a/tests/utilities/test_types.py +++ b/tests/utilities/test_types.py @@ -204,7 +204,7 @@ class TestImage: content = img.to_image_content() assert content.type == "image" - assert content.mimeType == "image/png" + assert content.mime_type == "image/png" assert content.data == base64.b64encode(test_data).decode() # Test with data @@ -212,7 +212,7 @@ class TestImage: content = img.to_image_content() assert content.type == "image" - assert content.mimeType == "image/jpeg" + assert content.mime_type == "image/jpeg" assert content.data == base64.b64encode(test_data).decode() def test_to_image_content_error(self, monkeypatch): @@ -327,7 +327,7 @@ class TestAudio: content = audio.to_audio_content() assert content.type == "audio" - assert content.mimeType == "audio/wav" + assert content.mime_type == "audio/wav" assert content.data == base64.b64encode(test_data).decode() # Test with data @@ -335,7 +335,7 @@ class TestAudio: content = audio.to_audio_content() assert content.type == "audio" - assert content.mimeType == "audio/mp3" + assert content.mime_type == "audio/mp3" assert content.data == base64.b64encode(test_data).decode() def test_to_audio_content_error(self, monkeypatch): @@ -359,7 +359,7 @@ class TestAudio: content = audio.to_audio_content(mime_type="audio/custom") assert content.type == "audio" - assert content.mimeType == "audio/custom" + assert content.mime_type == "audio/custom" assert content.data == base64.b64encode(test_data).decode() @@ -442,7 +442,7 @@ class TestFile: resource = file.to_resource_content() assert resource.type == "resource" - assert resource.resource.mimeType == "text/plain" + assert resource.resource.mime_type == "text/plain" # Convert both to strings for comparison assert str(resource.resource.uri) == file_path.resolve().as_uri() if isinstance(resource.resource, BlobResourceContents): @@ -455,7 +455,7 @@ class TestFile: resource = file.to_resource_content() assert resource.type == "resource" - assert resource.resource.mimeType == "application/pdf" + assert resource.resource.mime_type == "application/pdf" # Convert URI to string for comparison assert str(resource.resource.uri) == "file:///resource.pdf" if isinstance(resource.resource, BlobResourceContents): @@ -469,7 +469,7 @@ class TestFile: assert resource.type == "resource" # Should be TextResourceContents for text/plain assert isinstance(resource.resource, TextResourceContents) - assert resource.resource.mimeType == "text/plain" + assert resource.resource.mime_type == "text/plain" assert resource.resource.text == "hello world" def test_to_resource_content_error(self, monkeypatch): @@ -490,7 +490,7 @@ class TestFile: file = File(path=file_path) resource = file.to_resource_content(mime_type="application/custom") - assert resource.resource.mimeType == "application/custom" + assert resource.resource.mime_type == "application/custom" class TestReplaceType: