From 31f96876062ff09a8178ee2a23b18b2295225b1f Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Wed, 13 Aug 2025 20:52:05 -0400 Subject: [PATCH] Remove unnecessary asserts (#1484) --- .github/workflows/run-static.yml | 1 + docs/python-sdk/fastmcp-cli-run.mdx | 12 +++--- docs/python-sdk/fastmcp-server-auth-auth.mdx | 10 ++--- docs/python-sdk/fastmcp-server-context.mdx | 42 +++++++++---------- .../fastmcp-utilities-components.mdx | 14 +++---- src/fastmcp/cli/run.py | 5 --- .../experimental/server/openapi/routing.py | 2 - .../experimental/server/openapi/server.py | 2 - src/fastmcp/server/auth/auth.py | 3 +- src/fastmcp/server/context.py | 3 +- src/fastmcp/utilities/components.py | 3 +- src/fastmcp/utilities/json_schema_type.py | 6 ++- 12 files changed, 50 insertions(+), 53 deletions(-) diff --git a/.github/workflows/run-static.yml b/.github/workflows/run-static.yml index 30451ba18..0b172865d 100644 --- a/.github/workflows/run-static.yml +++ b/.github/workflows/run-static.yml @@ -77,6 +77,7 @@ jobs: # Check if docs.json content changed (ignoring formatting) if ! jq --sort-keys . docs/docs.json.orig | diff -q - <(jq --sort-keys . docs/docs.json) > /dev/null 2>&1; then echo "❌ docs.json content has changed!" + echo "" echo "Run `just api-ref-all` to regenerate the SDK docs, then commit the changes. Note: you may need to install `just` (https://github.com/casey/just)" exit 1 fi diff --git a/docs/python-sdk/fastmcp-cli-run.mdx b/docs/python-sdk/fastmcp-cli-run.mdx index 4aaf9995d..0e48d7e93 100644 --- a/docs/python-sdk/fastmcp-cli-run.mdx +++ b/docs/python-sdk/fastmcp-cli-run.mdx @@ -53,7 +53,7 @@ Import a MCP server from a file. - The server object (or result of calling a factory function) -### `run_with_uv` +### `run_with_uv` ```python run_with_uv(server_spec: str, python_version: str | None = None, with_packages: list[str] | None = None, with_requirements: Path | None = None, project: Path | None = None, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, show_banner: bool = True) -> None @@ -76,7 +76,7 @@ Run a MCP server using uv run subprocess. - `show_banner`: Whether to show the server banner -### `create_client_server` +### `create_client_server` ```python create_client_server(url: str) -> Any @@ -92,7 +92,7 @@ Create a FastMCP server from a client URL. - A FastMCP server instance -### `create_mcp_config_server` +### `create_mcp_config_server` ```python create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None] @@ -102,7 +102,7 @@ create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None] Create a FastMCP server from a MCPConfig. -### `import_server_with_args` +### `import_server_with_args` ```python import_server_with_args(file: Path, server_or_factory: str | None = None, server_args: list[str] | None = None) -> Any @@ -120,7 +120,7 @@ Import a server with optional command line arguments. - The imported server object -### `run_command` +### `run_command` ```python run_command(server_spec: str, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, server_args: list[str] | None = None, show_banner: bool = True, use_direct_import: bool = False) -> None @@ -141,7 +141,7 @@ Run a MCP server or connect to a remote one. - `use_direct_import`: Whether to use direct import instead of subprocess -### `run_v1_server` +### `run_v1_server` ```python run_v1_server(server: FastMCP1x, host: str | None = None, port: int | None = None, transport: TransportType | None = None) -> None diff --git a/docs/python-sdk/fastmcp-server-auth-auth.mdx b/docs/python-sdk/fastmcp-server-auth-auth.mdx index fcc2a5667..b576b6515 100644 --- a/docs/python-sdk/fastmcp-server-auth-auth.mdx +++ b/docs/python-sdk/fastmcp-server-auth-auth.mdx @@ -107,7 +107,7 @@ the authorization servers that issue valid tokens. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -116,7 +116,7 @@ verify_token(self, token: str) -> AccessToken | None Verify token using the configured token verifier. -#### `get_routes` +#### `get_routes` ```python get_routes(self) -> list[Route] @@ -129,7 +129,7 @@ Subclasses can override this method to add additional routes by calling super().get_routes() and extending the returned list. -### `OAuthProvider` +### `OAuthProvider` OAuth Authorization Server provider. @@ -140,7 +140,7 @@ authorization flows, token issuance, and token verification. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -158,7 +158,7 @@ to our existing load_access_token method. - AccessToken object if valid, None if invalid or expired -#### `get_routes` +#### `get_routes` ```python get_routes(self) -> list[Route] diff --git a/docs/python-sdk/fastmcp-server-context.mdx b/docs/python-sdk/fastmcp-server-context.mdx index cc3c79237..fc6219fef 100644 --- a/docs/python-sdk/fastmcp-server-context.mdx +++ b/docs/python-sdk/fastmcp-server-context.mdx @@ -111,7 +111,7 @@ Read a resource by URI. - The resource content as either text or bytes -#### `log` +#### `log` ```python log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -127,7 +127,7 @@ Send a log message to the client. - `extra`: Optional mapping for additional arguments -#### `client_id` +#### `client_id` ```python client_id(self) -> str | None @@ -136,7 +136,7 @@ client_id(self) -> str | None Get the client ID if available. -#### `request_id` +#### `request_id` ```python request_id(self) -> str @@ -145,7 +145,7 @@ request_id(self) -> str Get the unique ID for this request. -#### `session_id` +#### `session_id` ```python session_id(self) -> str @@ -162,7 +162,7 @@ the same client session. - for other transports. -#### `session` +#### `session` ```python session(self) -> ServerSession @@ -171,7 +171,7 @@ session(self) -> ServerSession Access to the underlying session for advanced usage. -#### `debug` +#### `debug` ```python debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -180,7 +180,7 @@ debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, An Send a debug log message. -#### `info` +#### `info` ```python info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -189,7 +189,7 @@ info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any Send an info log message. -#### `warning` +#### `warning` ```python warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -198,7 +198,7 @@ warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Send a warning log message. -#### `error` +#### `error` ```python error(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -207,7 +207,7 @@ error(self, message: str, logger_name: str | None = None, extra: Mapping[str, An Send an error log message. -#### `list_roots` +#### `list_roots` ```python list_roots(self) -> list[Root] @@ -216,7 +216,7 @@ list_roots(self) -> list[Root] List the roots available to the server, as indicated by the client. -#### `send_tool_list_changed` +#### `send_tool_list_changed` ```python send_tool_list_changed(self) -> None @@ -225,7 +225,7 @@ send_tool_list_changed(self) -> None Send a tool list changed notification to the client. -#### `send_resource_list_changed` +#### `send_resource_list_changed` ```python send_resource_list_changed(self) -> None @@ -234,7 +234,7 @@ send_resource_list_changed(self) -> None Send a resource list changed notification to the client. -#### `send_prompt_list_changed` +#### `send_prompt_list_changed` ```python send_prompt_list_changed(self) -> None @@ -243,7 +243,7 @@ send_prompt_list_changed(self) -> None Send a prompt list changed notification to the client. -#### `sample` +#### `sample` ```python sample(self, messages: str | list[str | SamplingMessage], system_prompt: str | None = None, include_context: IncludeContext | None = None, temperature: float | None = None, max_tokens: int | None = None, model_preferences: ModelPreferences | str | list[str] | None = None) -> ContentBlock @@ -256,25 +256,25 @@ completion from the client. The client must be appropriately configured, or the request will error. -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: None) -> AcceptedElicitation[dict[str, Any]] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T]) -> AcceptedElicitation[T] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: list[str]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T] | list[str] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation @@ -303,7 +303,7 @@ type or dataclass or BaseModel. If it is a primitive type, an object schema with a single "value" field will be generated. -#### `get_http_request` +#### `get_http_request` ```python get_http_request(self) -> Request @@ -312,7 +312,7 @@ get_http_request(self) -> Request Get the active starlette request. -#### `set_state` +#### `set_state` ```python set_state(self, key: str, value: Any) -> None @@ -321,7 +321,7 @@ set_state(self, key: str, value: Any) -> None Set a value in the context state. -#### `get_state` +#### `get_state` ```python get_state(self, key: str) -> Any diff --git a/docs/python-sdk/fastmcp-utilities-components.mdx b/docs/python-sdk/fastmcp-utilities-components.mdx index e18484bec..c7494f52f 100644 --- a/docs/python-sdk/fastmcp-utilities-components.mdx +++ b/docs/python-sdk/fastmcp-utilities-components.mdx @@ -55,7 +55,7 @@ Create a copy of the component. - `key`: The key to use for the copy. -#### `enable` +#### `enable` ```python enable(self) -> None @@ -64,7 +64,7 @@ enable(self) -> None Enable the component. -#### `disable` +#### `disable` ```python disable(self) -> None @@ -73,7 +73,7 @@ disable(self) -> None Disable the component. -#### `copy` +#### `copy` ```python copy(self) -> Self @@ -82,7 +82,7 @@ copy(self) -> Self Create a copy of the component. -### `MirroredComponent` +### `MirroredComponent` Base class for components that are mirrored from a remote server. @@ -93,7 +93,7 @@ to create a local version you can modify. **Methods:** -#### `enable` +#### `enable` ```python enable(self) -> None @@ -102,7 +102,7 @@ enable(self) -> None Enable the component. -#### `disable` +#### `disable` ```python disable(self) -> None @@ -111,7 +111,7 @@ disable(self) -> None Disable the component. -#### `copy` +#### `copy` ```python copy(self) -> Self diff --git a/src/fastmcp/cli/run.py b/src/fastmcp/cli/run.py index 9a0a47971..900110021 100644 --- a/src/fastmcp/cli/run.py +++ b/src/fastmcp/cli/run.py @@ -80,9 +80,6 @@ async def import_server(file: Path, server_or_factory: str | None = None) -> Any logger.error("Could not load module", extra={"file": str(file)}) sys.exit(1) - assert spec is not None - assert spec.loader is not None - module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) @@ -102,8 +99,6 @@ async def import_server(file: Path, server_or_factory: str | None = None) -> Any ) sys.exit(1) - assert server_or_factory is not None - # Handle module:object syntax if ":" in server_or_factory: module_name, object_name = server_or_factory.split(":", 1) diff --git a/src/fastmcp/experimental/server/openapi/routing.py b/src/fastmcp/experimental/server/openapi/routing.py index ca7ebdb94..092b2445b 100644 --- a/src/fastmcp/experimental/server/openapi/routing.py +++ b/src/fastmcp/experimental/server/openapi/routing.py @@ -110,8 +110,6 @@ def _determine_route_type( # Tags don't match, continue to next mapping continue - # We know mcp_type is not None here due to post_init validation - assert route_map.mcp_type is not None logger.debug( f"Route {route.method} {route.path} mapped to {route_map.mcp_type.name}" ) diff --git a/src/fastmcp/experimental/server/openapi/server.py b/src/fastmcp/experimental/server/openapi/server.py index 101427375..9df9b046f 100644 --- a/src/fastmcp/experimental/server/openapi/server.py +++ b/src/fastmcp/experimental/server/openapi/server.py @@ -163,8 +163,6 @@ class FastMCPOpenAPI(FastMCP): # Determine route type based on mappings or default rules route_map = _determine_route_type(route, route_maps) - # TODO: remove this once RouteType is removed and mcp_type is typed as MCPType without | None - assert route_map.mcp_type is not None route_type = route_map.mcp_type # Call route_map_fn if provided diff --git a/src/fastmcp/server/auth/auth.py b/src/fastmcp/server/auth/auth.py index 2dd316793..3c2f3f59d 100644 --- a/src/fastmcp/server/auth/auth.py +++ b/src/fastmcp/server/auth/auth.py @@ -135,6 +135,8 @@ class RemoteAuthProvider(AuthProvider): the authorization servers that issue valid tokens. """ + resource_server_url: AnyHttpUrl + def __init__( self, token_verifier: TokenVerifier, @@ -169,7 +171,6 @@ class RemoteAuthProvider(AuthProvider): Subclasses can override this method to add additional routes by calling super().get_routes() and extending the returned list. """ - assert self.resource_server_url is not None return create_protected_resource_routes( resource_url=self.resource_server_url, diff --git a/src/fastmcp/server/context.py b/src/fastmcp/server/context.py index 8a3901830..07a867d3e 100644 --- a/src/fastmcp/server/context.py +++ b/src/fastmcp/server/context.py @@ -188,7 +188,8 @@ class Context: Returns: The resource content as either text or bytes """ - assert self.fastmcp is not None, "Context is not available outside of a request" + if self.fastmcp is None: + raise ValueError("Context is not available outside of a request") return await self.fastmcp._mcp_read_resource(uri) async def log( diff --git a/src/fastmcp/utilities/components.py b/src/fastmcp/utilities/components.py index 8306b1e67..a0c4468ac 100644 --- a/src/fastmcp/utilities/components.py +++ b/src/fastmcp/utilities/components.py @@ -117,7 +117,8 @@ class FastMCPComponent(FastMCPBaseModel): def __eq__(self, other: object) -> bool: if type(self) is not type(other): return False - assert isinstance(other, type(self)) + if not isinstance(other, type(self)): + return False return self.model_dump() == other.model_dump() def __repr__(self) -> str: diff --git a/src/fastmcp/utilities/json_schema_type.py b/src/fastmcp/utilities/json_schema_type.py index 62577402b..b6ba9266a 100644 --- a/src/fastmcp/utilities/json_schema_type.py +++ b/src/fastmcp/utilities/json_schema_type.py @@ -449,7 +449,8 @@ def _create_pydantic_model( ) -> type: """Create Pydantic BaseModel from object schema with additionalProperties.""" name = name or schema.get("title", "Root") - assert name is not None # Should not be None after the or operation + if name is None: + raise ValueError("Name is required") sanitized_name = _sanitize_name(name) schema_hash = _hash_schema(schema) cache_key = (schema_hash, sanitized_name) @@ -507,7 +508,8 @@ def _create_dataclass( """Create dataclass from object schema.""" name = name or schema.get("title", "Root") # Sanitize name for class creation - assert name is not None # Should not be None after the or operation + if name is None: + raise ValueError("Name is required") sanitized_name = _sanitize_name(name) schema_hash = _hash_schema(schema) cache_key = (schema_hash, sanitized_name)