{"record":{"id":"21f34381be522e3b","repo":"FoundationAgents/OpenManus","slug":"server-url-is-required","errorCode":null,"errorMessage":"Server URL is required.","messagePattern":"Server URL is required\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"app/tool/mcp.py","lineNumber":53,"sourceCode":"\n\nclass MCPClients(ToolCollection):\n    \"\"\"\n    A collection of tools that connects to multiple MCP servers and manages available tools through the Model Context Protocol.\n    \"\"\"\n\n    sessions: Dict[str, ClientSession] = {}\n    exit_stacks: Dict[str, AsyncExitStack] = {}\n    description: str = \"MCP client tools for server interaction\"\n\n    def __init__(self):\n        super().__init__()  # Initialize with empty tools list\n        self.name = \"mcp\"  # Keep name for backward compatibility\n\n    async def connect_sse(self, server_url: str, server_id: str = \"\") -> None:\n        \"\"\"Connect to an MCP server using SSE transport.\"\"\"\n        if not server_url:\n            raise ValueError(\"Server URL is required.\")\n\n        server_id = server_id or server_url\n\n        # Always ensure clean disconnection before new connection\n        if server_id in self.sessions:\n            await self.disconnect(server_id)\n\n        exit_stack = AsyncExitStack()\n        self.exit_stacks[server_id] = exit_stack\n\n        streams_context = sse_client(url=server_url)\n        streams = await exit_stack.enter_async_context(streams_context)\n        session = await exit_stack.enter_async_context(ClientSession(*streams))\n        self.sessions[server_id] = session\n\n        await self._initialize_and_list_tools(server_id)\n\n    async def connect_stdio(","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/FoundationAgents/OpenManus/blob/52a13f2a57d8c7f6737eefb02ccf569594d44273/app/tool/mcp.py#L35-L71","documentation":"Raised by MCPClient.connect_sse (app/tool/mcp.py:53) when server_url is empty/None. It is a pure input-validation guard executed before any AsyncExitStack or sse_client machinery is set up, so hitting it means no connection attempt was made and no cleanup is needed.","triggerScenarios":"Calling `await mcp.connect_sse('')` or `await mcp.connect_sse(None)`; commonly the result of reading a server URL from config/env (e.g. MCP_SSE_URL unset) and passing it through without a default or check.","commonSituations":"Missing environment variable or empty config entry for the MCP server URL in deployment (env var not exported in the service unit/container); templating bugs producing empty strings; tests constructing the client without wiring a URL.","solutions":["Set the missing URL in config/env (e.g. export MCP_SSE_URL=http://host:port/sse) and confirm it is non-empty before calling.","Validate before connecting: `if not server_url: raise/fallback` in your bootstrap code with a clear config-path-naming message.","If the URL comes from a list of servers, skip/filter empty entries instead of passing them to connect_sse."],"exampleFix":"// before\nurl = os.environ.get('MCP_SSE_URL', '')\nawait mcp.connect_sse(url)\n\n// after\nurl = os.environ.get('MCP_SSE_URL')\nif not url:\n    raise RuntimeError('MCP_SSE_URL is not configured')\nawait mcp.connect_sse(url)","handlingStrategy":"validation","validationCode":"url = os.environ.get('MCP_SSE_URL')\nif not url or not url.startswith(('http://', 'https://')):\n    raise RuntimeError(f'MCP SSE URL misconfigured: {url!r}')\nawait mcp.connect_sse(url, server_id='my-server')","typeGuard":"def is_sse_url(u: str | None) -> bool:\n    return isinstance(u, str) and u.strip().startswith(('http://', 'https://'))","tryCatchPattern":"try:\n    await mcp.connect_sse(url, server_id)\nexcept ValueError as e:\n    if 'Server URL is required' in str(e):\n        fix_config_and_reload()\n    else:\n        raise","preventionTips":["Fail fast at startup on empty MCP URL config with a message naming the env var.","Filter empty entries out of server lists before connecting.","Add config smoke tests that assert every configured MCP URL is a non-empty http(s) string."],"tags":["mcp","validation","configuration","sse"],"backgroundTag":null,"analyzedSha":"52a13f2a57d8c7f6737eefb02ccf569594d44273","analyzedAt":"2026-08-15T02:33:49.993Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}