{"record":{"id":"c3bf68332d402f30","repo":"langchain-ai/deepagents","slug":"server-server-name-uses-stdio-transport-auth","errorCode":null,"errorMessage":"Server '{server_name}' uses stdio transport; 'auth: oauth' is only valid for http/sse transports.","messagePattern":"Server '(.+?)' uses stdio transport; 'auth: oauth' is only valid for http/sse transports\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":948,"sourceCode":"            f\"Server '{server_name}' has unsupported transport type '{server_type}'. \"\n            \"Supported types: stdio, sse, http\"\n        )\n        raise ValueError(error_msg)\n\n    auth = server_config.get(\"auth\")\n    if auth is not None:\n        if auth != \"oauth\":\n            msg = (\n                f\"Server '{server_name}' has unsupported auth value \"\n                f\"{auth!r}. Only 'oauth' is supported.\"\n            )\n            raise ValueError(msg)\n        if server_type == \"stdio\":\n            msg = (\n                f\"Server '{server_name}' uses stdio transport; \"\n                \"'auth: oauth' is only valid for http/sse transports.\"\n            )\n            raise ValueError(msg)\n        header_names = {name.lower() for name in (server_config.get(\"headers\") or {})}\n        if \"authorization\" in header_names:\n            msg = (\n                f\"Server '{server_name}' cannot combine 'auth: oauth' \"\n                \"with an 'Authorization' header.\"\n            )\n            raise ValueError(msg)\n\n    _validate_tool_filter_fields(server_name, server_config)\n\n\ndef _validate_tool_filter_fields(\n    server_name: str,\n    server_config: dict[str, Any],\n) -> None:\n    \"\"\"Validate optional `allowedTools` / `disabledTools` fields.\n\n    Both fields, when present, must be non-empty lists of strings. Setting","sourceCodeStart":930,"sourceCodeEnd":966,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L930-L966","documentation":"`auth: oauth` performs browser-based OAuth and only makes sense for remote transports (http/sse) that can redirect through an authorization flow. stdio servers are local subprocesses with no HTTP surface, so `_validate_server_config` raises this ValueError when `auth: oauth` is combined with a stdio server.","triggerScenarios":"A server entry resolving to type `stdio` includes `\"auth\": \"oauth\"`, e.g. `{\"type\": \"stdio\", \"command\": \"npx\", \"args\": [...], \"auth\": \"oauth\"}`, validated through `select_server`, `resolve_and_load_mcp_tools`, or the config validators.","commonSituations":"Copy-pasting a remote-server entry (which used oauth) and converting it to a local command without dropping `auth`; adding auth globally to all servers in a config; misunderstanding that stdio servers handle their own auth via env vars/secrets.","solutions":["Remove the `auth` field from the stdio server entry.","If OAuth is genuinely needed, the server must be remote: set `\"type\": \"http\"` or `\"sse\"` with a `url` and keep `auth: oauth`.","Pass credentials to a local stdio server via `env` (e.g. {\"API_KEY\": \"...\"}) per the server's own requirements.","Validate the corrected entry with `resolve_and_load_mcp_tools` before reloading."],"exampleFix":"// before\n{\"local\": {\"type\": \"stdio\", \"command\": \"npx\", \"args\": [\"-y\", \"mcp-server\"], \"auth\": \"oauth\"}}\n// after\n{\"local\": {\"type\": \"stdio\", \"command\": \"npx\", \"args\": [\"-y\", \"mcp-server\"], \"env\": {\"API_KEY\": \"...\"}}}","handlingStrategy":"validation","validationCode":"def validate_auth_transport(name: str, cfg: dict) -> None:\n    if cfg.get(\"type\", \"stdio\") == \"stdio\" and cfg.get(\"auth\") is not None:\n        raise ValueError(f\"Server '{name}' uses stdio transport; 'auth: oauth' is only valid for http/sse transports.\")","typeGuard":"def auth_matches_transport(cfg: dict) -> bool:\n    stype = cfg.get(\"type\", \"stdio\")\n    auth = cfg.get(\"auth\")\n    return auth is None or (auth == \"oauth\" and stype in (\"http\", \"sse\"))","tryCatchPattern":"try:\n    tools = resolve_and_load_mcp_tools(config)\nexcept ValueError as e:\n    if \"only valid for http/sse transports\" in str(e):\n        name = extract_server_name(str(e))\n        config[\"servers\"][name].pop(\"auth\", None)  # stdio servers manage their own auth\n        tools = resolve_and_load_mcp_tools(config)\n    else:\n        raise","preventionTips":["OAuth applies only to remote (http/sse) servers; never add `auth` to stdio entries.","Give local stdio servers credentials via `env` per the server's own requirements.","When converting a remote entry to a local command, strip auth fields in the same edit.","Avoid blanket config merges that copy `auth` onto every server."],"tags":["mcp","config-validation","auth","oauth","stdio"],"backgroundTag":"mcp-server-config-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}