{"record":{"id":"69db9015331efc4d","repo":"langchain-ai/deepagents","slug":"server-server-name-config-must-be-a-dictionary","errorCode":null,"errorMessage":"Server '{server_name}' config must be a dictionary","messagePattern":"Server '(.+?)' config must be a dictionary","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":875,"sourceCode":"\n    Args:\n        server_name: Name of the server.\n        server_config: Server configuration dictionary.\n\n    Raises:\n        TypeError: If config fields have wrong types.\n        ValueError: If required fields are missing or server type is unsupported.\n    \"\"\"\n    if not _SERVER_NAME_RE.fullmatch(server_name):\n        error_msg = (\n            f\"Invalid server name {server_name!r}: server names must contain \"\n            \"only alphanumerics, hyphens, and underscores.\"\n        )\n        raise ValueError(error_msg)\n\n    if not isinstance(server_config, dict):\n        error_msg = f\"Server '{server_name}' config must be a dictionary\"\n        raise TypeError(error_msg)\n\n    server_type = _resolve_server_type(server_config)\n\n    if server_type in _SUPPORTED_REMOTE_TYPES:\n        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)","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L857-L893","documentation":"Each server's config value must be a dict (mapping of connection fields). Anything else (string, list, null) is rejected with TypeError.","triggerScenarios":"Config file where a server entry is a string URL instead of an object, or an empty/null entry; malformed JSON/YAML merging producing non-dict values.","commonSituations":"Hand-edited mcp config like \"fs\": \"npx ...\"; templating errors rendering a server entry as empty; schema drift from another tool's config format.","solutions":["Change the server entry to a dict, e.g. {\"type\": \"stdio\", \"command\": ..., \"args\": [...] }","Validate the parsed config structure before passing it to the library","Fix templating/merge bugs that replace the object with a scalar"],"exampleFix":"// before\n{\"mcpServers\": {\"fs\": \"npx -y @modelcontextprotocol/server-fs\"}}\n// after\n{\"mcpServers\": {\"fs\": {\"type\": \"stdio\", \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-fs\"]}}}","handlingStrategy":"type-guard","validationCode":"def valid_server_entry(entry: object) -> bool:\n    return isinstance(entry, dict)\nconfig = {k: v for k, v in raw.items() if valid_server_entry(v)}","typeGuard":"def is_server_config(value: object) -> bool:\n    return isinstance(value, dict)","tryCatchPattern":"try:\n    tools = await resolve_and_load_mcp_tools(config)\nexcept TypeError as e:\n    if 'must be a dictionary' in str(e):\n        log.error('malformed mcpServers entry: %s', e)\n    raise","preventionTips":["Validate the parsed config against a JSON schema before use","Never hand-write server entries as plain strings; use the object form","Normalize configs from external tools into this library's schema"],"tags":["mcp","validation","configuration"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}