langchain-ai/deepagents · error · TypeError

'mcpServers' field must be a dictionary

Error message

'mcpServers' field must be a dictionary

What it means

The config contains an `mcpServers` key, but `_validate_mcp_config_top_level` additionally requires it to be a dictionary mapping server names to server config objects. If the value is any other JSON type (string, array, number, null) this TypeError is raised.

Source

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

    """Validate top-level MCP configuration fields.

    Args:
        config: Parsed MCP config dictionary.

    Raises:
        TypeError: If top-level fields have wrong types.
        ValueError: If required top-level fields are missing.
    """
    if "mcpServers" not in config:
        error_msg = (
            "MCP config must contain 'mcpServers' field. "
            'Expected format: {"mcpServers": {"server-name": {...}}}'
        )
        raise ValueError(error_msg)

    if not isinstance(config["mcpServers"], dict):
        error_msg = "'mcpServers' field must be a dictionary"
        raise TypeError(error_msg)

    if not config["mcpServers"]:
        error_msg = "'mcpServers' field is empty - no servers configured"
        raise ValueError(error_msg)


def _validate_mcp_config_servers(config: dict[str, Any]) -> None:
    """Validate every server in an MCP configuration.

    Args:
        config: Parsed MCP config dictionary.
    """
    for server_name, server_config in config["mcpServers"].items():
        _validate_server_config(server_name, server_config)


def _drop_invalid_mcp_config_servers(
    config: dict[str, Any],

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Convert the value to an object keyed by server name: {"mcpServers": {"fs": {"command": "mcp-server-fs"}}}.
  2. If the value is a JSON array of server objects, index each one by its name field when rebuilding the object.
  3. Replace null/placeholder values with a real server map or an empty object (then add servers).

Example fix

// before
{"mcpServers": [{"name": "fs", "command": "mcp-server-fs"}]}
// after
{"mcpServers": {"fs": {"command": "mcp-server-fs"}}}
Defensive patterns

Strategy: type-guard

Validate before calling

cfg = json.load(open(path))
servers = cfg.get("mcpServers")
if not isinstance(servers, dict):
    raise SystemExit("'mcpServers' must be an object keyed by server name")

Type guard

def is_server_map(cfg: object) -> bool:
    return isinstance(cfg, dict) and isinstance(cfg.get("mcpServers"), dict)

Try / catch

try:
    load_mcp_config(path)
except TypeError as e:
    if "'mcpServers' field must be a dictionary" in str(e):
        convert_list_to_map(path)
    else:
        raise

Prevention

When it happens

Trigger: Config like {"mcpServers": ["fs", "git"]} (list of names), {"mcpServers": "fs"} (string), or {"mcpServers": null}; also files where the servers were written as an array of objects instead of a keyed object.

Common situations: Converting a list of servers from another tool without converting to a keyed object; a script that overwrote mcpServers with a serialized string; template placeholders left as null.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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