{"record":{"id":"a4c9f14b4467a18b","repo":"langchain-ai/deepagents","slug":"server-server-name-cannot-combine-auth-oauth","errorCode":null,"errorMessage":"Server '{server_name}' cannot combine 'auth: oauth' with an 'Authorization' header.","messagePattern":"Server '(.+?)' cannot combine 'auth: oauth' with an 'Authorization' header\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":955,"sourceCode":"        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\n    both on the same server is rejected to keep the filter semantics\n    unambiguous. An empty list is rejected because it would silently strip\n    every tool from the server (`allowedTools`) or be a no-op\n    (`disabledTools`) — both are almost certainly user errors; omit the field\n    instead.\n\n    Args:","sourceCodeStart":937,"sourceCodeEnd":973,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L937-L973","documentation":"`auth: oauth` manages credentials itself (token storage and refresh), and supplying a static `Authorization` header alongside it creates two competing sources of credentials for the same request. `_validate_server_config` raises this ValueError when an http/sse server sets `auth: oauth` while its `headers` contain a case-insensitive `Authorization` key.","triggerScenarios":"An http/sse server entry has both `\"auth\": \"oauth\"` and a headers dict containing `Authorization` (any casing, e.g. `authorization` or `AUTHORIZATION`), validated via `select_server`, `resolve_and_load_mcp_tools`, or the batch validators.","commonSituations":"Adding `auth: oauth` to a server that already used a static bearer token in headers; migrating from token auth to OAuth without deleting the old header; a shared config template that ships both options.","solutions":["Remove the `Authorization` entry from `headers` and rely on `auth: oauth` for credentials.","Or remove `\"auth\": \"oauth\"` and keep the static Authorization header for token-based auth.","Note the check is case-insensitive, so renaming to `authorization` or `AUTHORIZATION` will not bypass it.","Re-run `resolve_and_load_mcp_tools` after the fix to confirm validation passes."],"exampleFix":"// before\n{\"api\": {\"type\": \"http\", \"url\": \"https://mcp.example.com\", \"auth\": \"oauth\", \"headers\": {\"Authorization\": \"Bearer tok\"}}}\n// after\n{\"api\": {\"type\": \"http\", \"url\": \"https://mcp.example.com\", \"auth\": \"oauth\"}}","handlingStrategy":"validation","validationCode":"def validate_no_auth_header_conflict(name: str, cfg: dict) -> None:\n    if cfg.get(\"auth\") == \"oauth\":\n        names = {str(k).lower() for k in (cfg.get(\"headers\") or {})}\n        if \"authorization\" in names:\n            raise ValueError(f\"Server '{name}' cannot combine 'auth: oauth' with an 'Authorization' header.\")","typeGuard":"def auth_and_headers_compatible(cfg: dict) -> bool:\n    if cfg.get(\"auth\") != \"oauth\":\n        return True\n    names = {str(k).lower() for k in (cfg.get(\"headers\") or {})}\n    return \"authorization\" not in names","tryCatchPattern":"try:\n    tools = resolve_and_load_mcp_tools(config)\nexcept ValueError as e:\n    if \"cannot combine 'auth: oauth'\" in str(e):\n        name = extract_server_name(str(e))\n        headers = config[\"servers\"][name].get(\"headers\", {})\n        headers = {k: v for k, v in headers.items() if k.lower() != \"authorization\"}\n        config[\"servers\"][name][\"headers\"] = headers\n        tools = resolve_and_load_mcp_tools(config)\n    else:\n        raise","preventionTips":["Pick one credential source per server: either `auth: oauth` or a static Authorization header, never both.","When migrating a token-header server to OAuth, delete the Authorization header in the same change.","The check is case-insensitive — renaming the header will not bypass it.","Document per-server auth mode in your config to prevent template drift."],"tags":["mcp","config-validation","auth","oauth","http-headers"],"backgroundTag":"mcp-server-config-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}