diff --git a/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py b/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py index e5cb6a0098d..48a3cb89543 100644 --- a/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py +++ b/litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py @@ -172,10 +172,20 @@ async def filter_tools( if not query or not query.strip(): return available_tools - # Router should be built on startup - if not, something went wrong + # Lazy-build router from available_tools if not already initialized if self.tool_router is None: - verbose_logger.warning("Router not initialized - was build_router_from_mcp_registry() called on startup?") - return available_tools + verbose_logger.info( + "Router not pre-built, building from available_tools on first call" + ) + try: + self._build_router(available_tools) + except Exception as e: + verbose_logger.error(f"Failed to lazy-build router: {e}") + return available_tools + + if self.tool_router is None: + verbose_logger.warning("Router still None after build attempt") + return available_tools # Run semantic filtering try: diff --git a/litellm/proxy/hooks/mcp_semantic_filter/hook.py b/litellm/proxy/hooks/mcp_semantic_filter/hook.py index fc9349c2a42..21ef3485a27 100644 --- a/litellm/proxy/hooks/mcp_semantic_filter/hook.py +++ b/litellm/proxy/hooks/mcp_semantic_filter/hook.py @@ -224,6 +224,8 @@ async def async_pre_call_hook( tool_names_csv = self._get_tool_names_csv(filtered_tools) _metadata_variable_name = self._get_metadata_variable_name(data) + if _metadata_variable_name not in data: + data[_metadata_variable_name] = {} data[_metadata_variable_name]["litellm_semantic_filter_stats"] = filter_stats data[_metadata_variable_name]["litellm_semantic_filter_tools"] = tool_names_csv