{"record":{"id":"6b45dd6f98d07864","repo":"HKUDS/Vibe-Trading","slug":"transport-mcp-servers-require-a-url","errorCode":null,"errorMessage":"{transport} MCP servers require a url","messagePattern":"(.+?) MCP servers require a url","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/config/schema.py","lineNumber":396,"sourceCode":"            The validated MCP server config instance.\n\n        Raises:\n            ValueError: If required fields are missing for the resolved\n                transport or conflicting fields are provided.\n        \"\"\"\n        transport = self.resolved_transport()\n\n        if transport == \"stdio\":\n            if not self.command.strip():\n                raise ValueError(\"stdio MCP servers require a command\")\n            if self.url.strip() or self.headers:\n                raise ValueError(\"stdio MCP servers do not accept url/headers\")\n            if self.auth is not None:\n                raise ValueError(\"stdio MCP servers do not accept auth (OAuth is HTTP-only)\")\n            return self\n\n        if not self.url.strip():\n            raise ValueError(f\"{transport} MCP servers require a url\")\n        if self.command.strip() or self.args or self.env:\n            raise ValueError(f\"{transport} MCP servers do not accept command/args/env\")\n\n        if self.auth is not None:\n            # The OAuth provider owns the runtime Authorization header; a\n            # hand-set static header alongside it is always a config error.\n            if self.headers:\n                raise ValueError(\n                    \"MCP servers using auth must not also set static headers \"\n                    \"(the OAuth provider owns the Authorization header)\"\n                )\n            # A refresh token must never traverse cleartext.\n            if not self.url.strip().lower().startswith(\"https://\"):\n                raise ValueError(\"OAuth MCP servers require an https url\")\n        return self\n\n\nclass MCPServerConfigOverride(ConfigBase):","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/config/schema.py#L378-L414","documentation":"Raised by validate_transport_config when the resolved transport is sse or streamableHttp but the url field is empty. HTTP transports are entirely url-driven, so a blank url cannot proceed.","triggerScenarios":"An entry with type: sse/streamableHttp and no url, or a url of only whitespace; env-var templating that yields an empty string.","commonSituations":"Type set but url line accidentally deleted; secrets interpolation failing silently to ''; overriding a server at runtime and dropping url.","solutions":["Set the full endpoint url, e.g. url: https://mcp.example.com/sse.","Verify any ${VAR} interpolation in the url resolves to a non-empty value.","Ensure the url starts with https:// if auth is configured (plain http is otherwise accepted but discouraged)."],"exampleFix":"# before\nmcp_servers:\n  remote:\n    type: streamableHttp\n\n# after\nmcp_servers:\n  remote:\n    type: streamableHttp\n    url: https://mcp.example.com/mcp","handlingStrategy":"validation","validationCode":"def http_mcp_has_url(entry: dict) -> bool:\n    if entry.get('type') in ('sse', 'streamableHttp'):\n        return bool(str(entry.get('url', '')).strip())\n    return True","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check that ${VAR} interpolation in urls resolves before deploy","Add a config smoke-test that instantiates MCPServerConfig for every entry"],"tags":["mcp","config","http-transport","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}