From 6ad8ee4ab02970db7e255d1069eaa29dcd4d8cf0 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 9 Oct 2026 09:02:34 +0800 Subject: [PATCH] fix(mcp): satisfy type discipline in YAML parser --- .../mcp_server/openapi_to_mcp_generator.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py b/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py index cccc489c569..4b0e093f32d 100644 --- a/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py +++ b/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py @@ -179,7 +179,7 @@ def load_openapi_spec(filepath: str) -> Mapping[str, Any]: def _parse_openapi_spec(text: str) -> Mapping[str, Any]: """Parse JSON or YAML OpenAPI documents into a mapping.""" try: - parsed: Any = json.loads(text) + parsed_json: Final[Any] = json.loads(text) except json.JSONDecodeError: import yaml from yaml.nodes import ScalarNode @@ -191,8 +191,10 @@ def _parse_openapi_spec(text: str) -> Mapping[str, Any]: return super().compose_node(parent, index) def flatten_mapping(self, node: object) -> None: - node_values = getattr(node, "value", ()) - if any(key_node.tag == "tag:yaml.org,2002:merge" for key_node, _ in node_values): + if any( + key_node.tag == "tag:yaml.org,2002:merge" + for key_node, _ in getattr(node, "value", ()) + ): raise yaml.YAMLError("YAML merge keys are not supported") super().flatten_mapping(node) @@ -206,11 +208,14 @@ def _parse_openapi_spec(text: str) -> Mapping[str, Any]: _NoMergeSafeLoader.construct_yaml_int, ) - parsed = yaml.load(text, Loader=_NoMergeSafeLoader) + parsed_yaml: Final[Any] = yaml.load(text, Loader=_NoMergeSafeLoader) + if not isinstance(parsed_yaml, dict): + raise TypeError("OpenAPI spec must be a JSON or YAML object") + return parsed_yaml - if not isinstance(parsed, dict): + if not isinstance(parsed_json, dict): raise TypeError("OpenAPI spec must be a JSON or YAML object") - return parsed + return parsed_json async def load_openapi_spec_async(filepath: str, *, max_bytes: int | None = None) -> dict[str, Any]: