{"record":{"id":"405858b60cec64d0","repo":"HKUDS/Vibe-Trading","slug":"stdio-mcp-servers-do-not-accept-auth-oauth-is-htt","errorCode":null,"errorMessage":"stdio MCP servers do not accept auth (OAuth is HTTP-only)","messagePattern":"stdio MCP servers do not accept auth \\(OAuth is HTTP-only\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/config/schema.py","lineNumber":392,"sourceCode":"    def validate_transport_config(self) -> \"MCPServerConfig\":\n        \"\"\"Validate transport-specific MCP server configuration.\n\n        Returns:\n            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\")","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/config/schema.py#L374-L410","documentation":"Raised by validate_transport_config when a stdio MCP server carries an auth (OAuth) block. OAuth is HTTP-only in this schema: stdio child processes have no HTTP layer for token exchange, so auth on stdio is always a config error.","triggerScenarios":"An entry with command set plus an auth: {client_id, refresh_token, ...} block, typically copied from an OAuth HTTP broker server config.","commonSituations":"Copying a live-broker OAuth server template into a stdio wrapper entry; assuming auth applies globally rather than per-transport.","solutions":["Delete the auth block from the stdio server entry.","If OAuth is required, configure the server as HTTP (type: sse or streamableHttp) with an https url and the auth block."],"exampleFix":"# before\nmcp_servers:\n  local:\n    command: ./server\n    auth:\n      client_id: abc\n\n# after\nmcp_servers:\n  local:\n    command: ./server","handlingStrategy":"validation","validationCode":"def stdio_without_auth(entry: dict) -> bool:\n    if entry.get('type') == 'stdio' or entry.get('command'):\n        return entry.get('auth') is None\n    return True","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember auth is HTTP-only in this schema","Keep OAuth templates separate from stdio templates"],"tags":["mcp","config","oauth","stdio","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}