{"record":{"id":"36be9a491ef41a55","repo":"langchain-ai/deepagents","slug":"server-server-name-headers-must-be-a-diction","errorCode":null,"errorMessage":"Server '{server_name}' 'headers' must be a dictionary","messagePattern":"Server '(.+?)' 'headers' must be a dictionary","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":898,"sourceCode":"        if \"url\" not in server_config:\n            error_msg = (\n                f\"Server '{server_name}' with type '{server_type}' \"\n                \"missing required 'url' field\"\n            )\n            raise ValueError(error_msg)\n\n        if \"command\" in server_config:\n            error_msg = (\n                f\"Server '{server_name}' has type '{server_type}' (remote) \"\n                \"but also declares a 'command' field. Remove 'command' or \"\n                'set `\"type\": \"stdio\"`.'\n            )\n            raise ValueError(error_msg)\n\n        headers = server_config.get(\"headers\")\n        if headers is not None and not isinstance(headers, dict):\n            error_msg = f\"Server '{server_name}' 'headers' must be a dictionary\"\n            raise TypeError(error_msg)\n\n        if isinstance(headers, dict):\n            for name, value in headers.items():\n                if not isinstance(value, str):\n                    error_msg = (\n                        f\"Server '{server_name}' header {name!r} must be \"\n                        f\"a string, got {type(value).__name__}\"\n                    )\n                    raise TypeError(error_msg)\n    elif server_type == \"stdio\":\n        if \"command\" not in server_config:\n            error_msg = f\"Server '{server_name}' missing required 'command' field\"\n            raise ValueError(error_msg)\n\n        if \"url\" in server_config:\n            error_msg = (\n                f\"Server '{server_name}' has type 'stdio' but also declares \"\n                \"a 'url' field. Remove 'url' or set \"","sourceCodeStart":880,"sourceCodeEnd":916,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L880-L916","documentation":"MCP server configs of type http/sse accept an optional `headers` dict sent with each request to the remote server. This TypeError is raised by `_validate_server_config` when `headers` is present but is not a dictionary (e.g. a list, string, or null-like non-dict value), preventing an invalid type from reaching the transport layer.","triggerScenarios":"Calling `select_server`, `resolve_and_load_mcp_tools`, or config validation entry points (`_validate_mcp_config_servers`, `_drop_invalid_mcp_config_servers`) with a server entry of type `http`/`sse` whose `headers` key is set to a non-dict value, e.g. `\"headers\": [\"Authorization: Bearer x\"]` or `\"headers\": \"Authorization: ...\"`.","commonSituations":"Config copied from curl examples where headers are written as a list of strings; YAML/JSON authored by hand with headers as an array; merging header snippets incorrectly; a stringified headers block pasted from documentation.","solutions":["Change `headers` in the server config to a dictionary mapping header names to string values, e.g. {\"Authorization\": \"Bearer <token>\"}.","If headers were written as a list of 'Name: value' strings, split each on the first colon and build a dict.","Remove the `headers` key entirely if no custom headers are needed (it is optional).","Run the config through `resolve_and_load_mcp_tools` on a small test config to validate before deploying."],"exampleFix":"// before\n{\"servers\": {\"docs\": {\"type\": \"http\", \"url\": \"https://mcp.example.com\", \"headers\": [\"Authorization: Bearer tok\"]}}}\n// after\n{\"servers\": {\"docs\": {\"type\": \"http\", \"url\": \"https://mcp.example.com\", \"headers\": {\"Authorization\": \"Bearer tok\"}}}}","handlingStrategy":"validation","validationCode":"def validate_server_entry(name: str, cfg: dict) -> None:\n    if cfg.get(\"type\", \"stdio\") in (\"http\", \"sse\"):\n        headers = cfg.get(\"headers\")\n        if headers is not None and not isinstance(headers, dict):\n            raise TypeError(f\"Server '{name}' 'headers' must be a dictionary, got {type(headers).__name__}\")","typeGuard":"def has_dict_headers(cfg: dict) -> bool:\n    h = cfg.get(\"headers\")\n    return h is None or isinstance(h, dict)","tryCatchPattern":null,"preventionTips":["Always author headers as a JSON/YAML object mapping name to string value, never as a list of 'Name: value' strings.","Run `resolve_and_load_mcp_tools` (or the app's /mcp command) against a draft config before committing it.","Keep one canonical server-config schema documented and validated in CI.","Enable config loading errors visibly instead of ignoring dropped servers."],"tags":["mcp","config-validation","typeerror"],"backgroundTag":"mcp-server-config-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}