{"record":{"id":"8ec6c3b99631ac3d","repo":"langchain-ai/deepagents","slug":"server-server-name-has-type-stdio-but-also-d","errorCode":null,"errorMessage":"Server '{server_name}' has type 'stdio' but also declares a 'url' field. Remove 'url' or set `\"type\": \"http\"` (or `\"sse\"`) for a remote server.","messagePattern":"Server '(.+?)' has type 'stdio' but also declares a 'url' field\\. Remove 'url' or set `\"type\": \"http\"` \\(or `\"sse\"`\\) for a remote server\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":919,"sourceCode":"            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 \"\n                '`\"type\": \"http\"` (or `\"sse\"`) for a remote server.'\n            )\n            raise ValueError(error_msg)\n\n        if \"args\" in server_config and not isinstance(server_config[\"args\"], list):\n            error_msg = f\"Server '{server_name}' 'args' must be a list\"\n            raise TypeError(error_msg)\n\n        if \"env\" in server_config and not isinstance(server_config[\"env\"], dict):\n            error_msg = f\"Server '{server_name}' 'env' must be a dictionary\"\n            raise TypeError(error_msg)\n    else:\n        error_msg = (\n            f\"Server '{server_name}' has unsupported transport type '{server_type}'. \"\n            \"Supported types: stdio, sse, http\"\n        )\n        raise ValueError(error_msg)\n\n    auth = server_config.get(\"auth\")\n    if auth is not None:\n        if auth != \"oauth\":","sourceCodeStart":901,"sourceCodeEnd":937,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L901-L937","documentation":"A `stdio` server is a local subprocess launched with `command`/`args`, while `url` only applies to remote transports (http/sse). Declaring both is contradictory, so `_validate_server_config` raises this ValueError to force an unambiguous transport choice.","triggerScenarios":"A server entry resolving to type `stdio` contains a `url` key — e.g. `{\"type\": \"stdio\", \"command\": \"npx\", \"args\": [...], \"url\": \"https://...\"}` — validated via `select_server`, `resolve_and_load_mcp_tools`, or the batch config validators.","commonSituations":"Copying a config template that kept `url` when switching between remote and local forms; adding `url` 'just in case' alongside command config; a server that moved from remote hosting to a local binary without cleaning up the old fields; merged config files from two setups.","solutions":["Remove the `url` field from the stdio server entry if it should run locally.","Alternatively set `\"type\": \"http\"` (or `\"sse\"`) and keep `url`, removing `command`/`args` if the server is remote.","Ensure only one transport shape remains: (type http/sse + url) or (type stdio/omitted + command).","Re-run `resolve_and_load_mcp_tools` to confirm the fixed entry validates."],"exampleFix":"// before\n{\"fs\": {\"type\": \"stdio\", \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"], \"url\": \"https://mcp.example.com\"}}\n// after\n{\"fs\": {\"type\": \"stdio\", \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"]}}","handlingStrategy":"validation","validationCode":"def validate_no_transport_mixing(name: str, cfg: dict) -> None:\n    stype = cfg.get(\"type\", \"stdio\")\n    if stype == \"stdio\" and \"url\" in cfg:\n        raise ValueError(f\"Server '{name}' has type 'stdio' but also declares a 'url' field\")","typeGuard":"def has_single_transport_shape(cfg: dict) -> bool:\n    stype = cfg.get(\"type\", \"stdio\")\n    if stype in (\"http\", \"sse\"):\n        return \"url\" in cfg and \"command\" not in cfg\n    if stype == \"stdio\":\n        return \"command\" in cfg and \"url\" not in cfg\n    return False","tryCatchPattern":"try:\n    tools = resolve_and_load_mcp_tools(config)\nexcept ValueError as e:\n    if \"but also declares a 'url' field\" in str(e):\n        name = extract_server_name(str(e))\n        config[\"servers\"][name].pop(\"url\", None)  # keep local stdio form\n        tools = resolve_and_load_mcp_tools(config)\n    else:\n        raise","preventionTips":["Decide the transport first: local binary (stdio + command) or remote URL (http/sse + url); never include both field sets.","When converting a remote server to local (or vice versa), delete the obsolete fields in the same edit.","Avoid 'just in case' fields in server configs.","Schema-validate config files with a JSON Schema that forbids cross-field combinations."],"tags":["mcp","config-validation","stdio","conflicting-fields"],"backgroundTag":"mcp-server-config-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}