From bde9515cedfd70d91eb23b71c46305f18a8aaa3c Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 22 Jul 2025 07:48:14 -0400 Subject: [PATCH] fix: handle non-string $ref values in experimental OpenAPI parser (#1217) Co-authored-by: Claude --- .../experimental/utilities/openapi/parser.py | 3 +++ .../experimental/utilities/openapi/schemas.py | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/fastmcp/experimental/utilities/openapi/parser.py b/src/fastmcp/experimental/utilities/openapi/parser.py index 98532c5e7..551555f41 100644 --- a/src/fastmcp/experimental/utilities/openapi/parser.py +++ b/src/fastmcp/experimental/utilities/openapi/parser.py @@ -146,6 +146,9 @@ class OpenAPIParser( """Resolves a reference to its target definition.""" if isinstance(item, self.reference_cls): ref_str = item.ref + # Ensure ref_str is a string before calling startswith() + if not isinstance(ref_str, str): + return item try: if not ref_str.startswith("#/"): raise ValueError( diff --git a/src/fastmcp/experimental/utilities/openapi/schemas.py b/src/fastmcp/experimental/utilities/openapi/schemas.py index 5c8637863..7ccc182ca 100644 --- a/src/fastmcp/experimental/utilities/openapi/schemas.py +++ b/src/fastmcp/experimental/utilities/openapi/schemas.py @@ -93,15 +93,16 @@ def _replace_ref_with_defs( """ schema = info.copy() if ref_path := schema.get("$ref"): - if ref_path.startswith("#/components/schemas/"): - schema_name = ref_path.split("/")[-1] - schema["$ref"] = f"#/$defs/{schema_name}" - elif not ref_path.startswith("#/"): - raise ValueError( - f"External or non-local reference not supported: {ref_path}. " - f"FastMCP only supports local schema references starting with '#/'. " - f"Please include all schema definitions within the OpenAPI document." - ) + if isinstance(ref_path, str): + if ref_path.startswith("#/components/schemas/"): + schema_name = ref_path.split("/")[-1] + schema["$ref"] = f"#/$defs/{schema_name}" + elif not ref_path.startswith("#/"): + raise ValueError( + f"External or non-local reference not supported: {ref_path}. " + f"FastMCP only supports local schema references starting with '#/'. " + f"Please include all schema definitions within the OpenAPI document." + ) elif properties := schema.get("properties"): if "$ref" in properties: schema["properties"] = _replace_ref_with_defs(properties)