From 19b7b4019c3d9087c2c426682e78f329bd394fb7 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Fri, 20 Feb 2026 13:46:59 +0530 Subject: [PATCH] Fix: server url extraction from spec_path --- .../mcp_server/mcp_server_manager.py | 3 +-- .../mcp_server/openapi_to_mcp_generator.py | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index e5a2119bc2c..5c72bfbc13f 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -390,8 +390,7 @@ class MCPServerManager: # Use base_url from config if provided, otherwise extract from spec if not base_url: - base_url = get_openapi_base_url(spec) - + base_url = get_openapi_base_url(spec, spec_path) verbose_logger.info( f"Registering OpenAPI tools for server {server.name} with base URL: {base_url}" ) 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 deb0b4f9549..21d39c97d7c 100644 --- a/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py +++ b/litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py @@ -2,8 +2,8 @@ This module is used to generate MCP tools from OpenAPI specs. """ -import json import asyncio +import json import os from pathlib import PurePosixPath from typing import Any, Dict, Optional @@ -80,7 +80,7 @@ async def load_openapi_spec_async(filepath: str) -> Dict[str, Any]: return json.load(f) -def get_base_url(spec: Dict[str, Any]) -> str: +def get_base_url(spec: Dict[str, Any], spec_path: Optional[str] = None) -> str: """Extract base URL from OpenAPI spec.""" # OpenAPI 3.x if "servers" in spec and spec["servers"]: @@ -90,6 +90,20 @@ def get_base_url(spec: Dict[str, Any]) -> str: scheme = spec.get("schemes", ["https"])[0] base_path = spec.get("basePath", "") return f"{scheme}://{spec['host']}{base_path}" + + # Fallback: derive base URL from spec_path if it's a URL + if spec_path and (spec_path.startswith("http://") or spec_path.startswith("https://")): + for suffix in ["/openapi.json", "/openapi.yaml", "/swagger.json", "/swagger.yaml"]: + if spec_path.endswith(suffix): + base_url = spec_path[:-len(suffix)] + verbose_logger.info(f"No server info in OpenAPI spec. Using derived base URL: {base_url}") + return base_url + + if spec_path.split("/")[-1].endswith((".json", ".yaml", ".yml")): + base_url = "/".join(spec_path.split("/")[:-1]) + verbose_logger.info(f"No server info in OpenAPI spec. Using derived base URL: {base_url}") + return base_url + return ""