langchain-ai/deepagents · error · TypeError

Server '{server_name}' 'headers' must be a dictionary

Error message

Server '{server_name}' 'headers' must be a dictionary

What it means

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.

Source

Thrown at libs/code/deepagents_code/mcp_tools.py:898

        if "url" not in server_config:
            error_msg = (
                f"Server '{server_name}' with type '{server_type}' "
                "missing required 'url' field"
            )
            raise ValueError(error_msg)

        if "command" in server_config:
            error_msg = (
                f"Server '{server_name}' has type '{server_type}' (remote) "
                "but also declares a 'command' field. Remove 'command' or "
                'set `"type": "stdio"`.'
            )
            raise ValueError(error_msg)

        headers = server_config.get("headers")
        if headers is not None and not isinstance(headers, dict):
            error_msg = f"Server '{server_name}' 'headers' must be a dictionary"
            raise TypeError(error_msg)

        if isinstance(headers, dict):
            for name, value in headers.items():
                if not isinstance(value, str):
                    error_msg = (
                        f"Server '{server_name}' header {name!r} must be "
                        f"a string, got {type(value).__name__}"
                    )
                    raise TypeError(error_msg)
    elif server_type == "stdio":
        if "command" not in server_config:
            error_msg = f"Server '{server_name}' missing required 'command' field"
            raise ValueError(error_msg)

        if "url" in server_config:
            error_msg = (
                f"Server '{server_name}' has type 'stdio' but also declares "
                "a 'url' field. Remove 'url' or set "

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Change `headers` in the server config to a dictionary mapping header names to string values, e.g. {"Authorization": "Bearer <token>"}.
  2. If headers were written as a list of 'Name: value' strings, split each on the first colon and build a dict.
  3. Remove the `headers` key entirely if no custom headers are needed (it is optional).
  4. Run the config through `resolve_and_load_mcp_tools` on a small test config to validate before deploying.

Example fix

// before
{"servers": {"docs": {"type": "http", "url": "https://mcp.example.com", "headers": ["Authorization: Bearer tok"]}}}
// after
{"servers": {"docs": {"type": "http", "url": "https://mcp.example.com", "headers": {"Authorization": "Bearer tok"}}}}
Defensive patterns

Strategy: validation

Validate before calling

def validate_server_entry(name: str, cfg: dict) -> None:
    if cfg.get("type", "stdio") in ("http", "sse"):
        headers = cfg.get("headers")
        if headers is not None and not isinstance(headers, dict):
            raise TypeError(f"Server '{name}' 'headers' must be a dictionary, got {type(headers).__name__}")

Type guard

def has_dict_headers(cfg: dict) -> bool:
    h = cfg.get("headers")
    return h is None or isinstance(h, dict)

Prevention

When it happens

Trigger: 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: ..."`.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/36be9a491ef41a55. Report an issue: GitHub.