langchain-ai/deepagents · error · ValueError

MCP config must contain 'mcpServers' field. Expected format:

Error message

MCP config must contain 'mcpServers' field. Expected format: {"mcpServers": {"server-name": {...}}}

What it means

After loading and JSON-parsing the config file, `_validate_mcp_config_top_level` requires the top-level object to have an `mcpServers` key holding the server definitions. A JSON file that parses fine but lacks this key raises this ValueError describing the expected shape. The library only recognizes the {"mcpServers": {"server-name": {...}}} format.

Source

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

        raise json.JSONDecodeError(error_msg, exc.doc, exc.pos) from exc


def _validate_mcp_config_top_level(config: dict[str, Any]) -> None:
    """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)

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Rename the top-level key to 'mcpServers' and nest each server dict under it.
  2. If the file is an array of servers, wrap it: {"mcpServers": {name: serverDef, ...}}.
  3. Verify you're loading the intended MCP config file, not another JSON document.

Example fix

// before
{"fs": {"command": "mcp-server-fs"}}
// after
{"mcpServers": {"fs": {"command": "mcp-server-fs"}}}
Defensive patterns

Strategy: validation

Validate before calling

import json
cfg = json.load(open(path))
if "mcpServers" not in cfg:
    raise SystemExit("config must have top-level 'mcpServers' object")

Type guard

def has_mcp_servers(cfg: object) -> bool:
    return isinstance(cfg, dict) and "mcpServers" in cfg

Try / catch

try:
    load_mcp_config(path)
except ValueError as e:
    if "'mcpServers' field" in str(e):
        rewrite_top_level_key(path)
    else:
        raise

Prevention

When it happens

Trigger: Passing a config file whose root is e.g. {"servers": {...}}, a bare array of servers, a Claude-Desktop-style file using a different key, or any JSON object without 'mcpServers' (e.g. a package.json passed by mistake).

Common situations: Using a config exported from another MCP client with a different top-level schema; hand-writing the file and nesting servers directly at the root; pointing the loader at the wrong JSON file entirely.

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/edb437d195816cae. Report an issue: GitHub.