diff --git a/pyproject.toml b/pyproject.toml index 991203674..fec290757 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,6 +103,11 @@ fallback-version = "0.0.0" [tool.pytest.ini_options] asyncio_mode = "auto" # filterwarnings = ["error::DeprecationWarning"] +filterwarnings = [ + # Suppress OAuth in-memory token storage warnings in tests + # Tests intentionally use ephemeral storage; this warning is for end users + "ignore:Using in-memory token storage:UserWarning", +] timeout = 5 env = [ "FASTMCP_TEST_MODE=1", diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index b58645579..2a6b1a04b 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -1,7 +1,6 @@ from __future__ import annotations import inspect -import warnings from collections.abc import Callable from dataclasses import dataclass from typing import ( @@ -9,7 +8,6 @@ from typing import ( Annotated, Any, Generic, - Literal, TypeAlias, get_type_hints, ) @@ -21,7 +19,6 @@ from mcp.types import Tool as MCPTool from pydantic import Field, PydanticSchemaGenerationError from typing_extensions import TypeVar -import fastmcp from fastmcp.server.dependencies import get_context from fastmcp.utilities.components import FastMCPComponent from fastmcp.utilities.json_schema import compress_schema @@ -173,7 +170,7 @@ class Tool(FastMCPComponent): tags: set[str] | None = None, annotations: ToolAnnotations | None = None, exclude_args: list[str] | None = None, - output_schema: dict[str, Any] | Literal[False] | NotSetT | None = NotSet, + output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: ToolResultSerializerType | None = None, meta: dict[str, Any] | None = None, enabled: bool | None = None, @@ -216,7 +213,7 @@ class Tool(FastMCPComponent): description: str | NotSetT | None = NotSet, tags: set[str] | None = None, annotations: ToolAnnotations | NotSetT | None = NotSet, - output_schema: dict[str, Any] | Literal[False] | NotSetT | None = NotSet, + output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: ToolResultSerializerType | None = None, meta: dict[str, Any] | NotSetT | None = NotSet, transform_args: dict[str, ArgTransform] | None = None, @@ -255,7 +252,7 @@ class FunctionTool(Tool): tags: set[str] | None = None, annotations: ToolAnnotations | None = None, exclude_args: list[str] | None = None, - output_schema: dict[str, Any] | Literal[False] | NotSetT | None = NotSet, + output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: ToolResultSerializerType | None = None, meta: dict[str, Any] | None = None, enabled: bool | None = None, @@ -269,17 +266,8 @@ class FunctionTool(Tool): if isinstance(output_schema, NotSetT): final_output_schema = parsed_fn.output_schema - elif output_schema is False: - # Handle False as deprecated synonym for None (deprecated in 2.11.4) - if fastmcp.settings.deprecation_warnings: - warnings.warn( - "Passing output_schema=False is deprecated. Use output_schema=None instead.", - DeprecationWarning, - stacklevel=2, - ) - final_output_schema = None else: - # At this point output_schema is not NotSetT and not False, so it must be dict | None + # At this point output_schema is not NotSetT, so it must be dict | None final_output_schema = output_schema # Note: explicit schemas (dict) are used as-is without auto-wrapping diff --git a/src/fastmcp/tools/tool_transform.py b/src/fastmcp/tools/tool_transform.py index efbd1fb8c..afa3d30d9 100644 --- a/src/fastmcp/tools/tool_transform.py +++ b/src/fastmcp/tools/tool_transform.py @@ -1,7 +1,6 @@ from __future__ import annotations import inspect -import warnings from collections.abc import Callable from contextvars import ContextVar from dataclasses import dataclass @@ -13,7 +12,6 @@ from pydantic import ConfigDict from pydantic.fields import Field from pydantic.functional_validators import BeforeValidator -import fastmcp from fastmcp.tools.tool import ParsedFunction, Tool, ToolResult, _convert_to_content from fastmcp.utilities.components import _convert_set_default_none from fastmcp.utilities.json_schema import compress_schema @@ -371,7 +369,7 @@ class TransformedTool(Tool): transform_fn: Callable[..., Any] | None = None, transform_args: dict[str, ArgTransform] | None = None, annotations: ToolAnnotations | NotSetT | None = NotSet, - output_schema: dict[str, Any] | Literal[False] | NotSetT | None = NotSet, + output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: Callable[[Any], str] | NotSetT | None = NotSet, meta: dict[str, Any] | NotSetT | None = NotSet, enabled: bool | None = None, @@ -486,15 +484,6 @@ class TransformedTool(Tool): final_output_schema = tool.output_schema else: final_output_schema = tool.output_schema - elif output_schema is False: - # Handle False as deprecated synonym for None (deprecated in 2.11.4) - if fastmcp.settings.deprecation_warnings: - warnings.warn( - "Passing output_schema=False is deprecated. Use output_schema=None instead.", - DeprecationWarning, - stacklevel=2, - ) - final_output_schema = None else: final_output_schema = cast(dict | None, output_schema) diff --git a/tests/client/test_sse.py b/tests/client/test_sse.py index 914b505a2..7110d5cfd 100644 --- a/tests/client/test_sse.py +++ b/tests/client/test_sse.py @@ -94,10 +94,13 @@ async def nested_sse_server(): from starlette.applications import Starlette from starlette.routing import Mount + from fastmcp.server.http import create_sse_app from fastmcp.utilities.http import find_available_port server = create_test_server() - sse_app = server.sse_app(path="/mcp/sse/", message_path="/mcp/messages") + sse_app = create_sse_app( + server=server, message_path="/mcp/messages", sse_path="/mcp/sse/" + ) # Nest the app under multiple mounts to test URL resolution inner = Starlette(routes=[Mount("/nest-inner", app=sse_app)])