bytedance/deer-flow · error · HTTPException
MCP server '{name}' uses disallowed stdio command '{command_
Error message
MCP server '{name}' uses disallowed stdio command '{command_name}'. Allowed commands: {allowed}. Configure {_MCP_STDIO_COMMAND_ALLOWLIST_ENV} to extend this list. What it means
400 raised during MCP config validation when a stdio server's command name is not in the allowlist of executable names. The allowlist defaults to known-safe launchers (npx, uvx, uv, etc.) and can be extended via the environment variable DEERFLOW_MCP_STDIO_COMMAND_ALLOWLIST (the constant referenced by _MCP_STDIO_COMMAND_ALLOWLIST_ENV). This confines API-created MCP servers to vetted binaries.
Source
Thrown at backend/app/gateway/routers/mcp.py:608
Local config files can still express arbitrary advanced setups, but the
HTTP API is an untrusted boundary. Restricting stdio commands here reduces
the blast radius of a compromised authenticated browser session.
The command name alone is not a meaningful restriction, so the launcher's
``args`` and ``env`` are screened for the flags and variables that turn an
allowlisted binary into an arbitrary code evaluator.
"""
allowed_commands = _allowed_stdio_commands()
for name, server in request.mcp_servers.items():
transport_type = (server.type or "stdio").lower()
if transport_type != "stdio":
continue
command_name = _stdio_command_name(server.command, server_name=name)
if command_name not in allowed_commands:
allowed = ", ".join(sorted(allowed_commands)) or "<none>"
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' uses disallowed stdio command '{command_name}'. Allowed commands: {allowed}. Configure {_MCP_STDIO_COMMAND_ALLOWLIST_ENV} to extend this list."),
)
exec_flag = _arbitrary_exec_arg(server.args, command=command_name)
if exec_flag is not None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' passes '{exec_flag}' to '{command_name}', which would run arbitrary code. Point the server at a package or module instead."),
)
for env_name in server.env:
if env_name.strip().upper() in _CODE_INJECTING_ENV_VARS:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=(f"MCP server '{name}' sets environment variable '{env_name}', which would run arbitrary code at process startup."),
)
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Switch the command to an allowlisted launcher (e.g. uvx or npx) that fetches/runs your server
- Set DEERFLOW_MCP_STDIO_COMMAND_ALLOWLIST to a comma-separated list including your binary, then restart the Gateway
- Check the error body: it lists the currently allowed commands and the exact env var name
Example fix
# before
{"command": "python", "args": ["server.py"]}
# after (option 1)
{"command": "uvx", "args": ["--from", "./my-server", "my-server"]}
# after (option 2)
# env: DEERFLOW_MCP_STDIO_COMMAND_ALLOWLIST="python" Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = new Set(['npx', 'uvx', 'uv']); // keep in sync with backend defaults + env extension
function assertAllowedCommand(cmd: string) { if (!ALLOWED.has(cmd)) throw new Error(`command '${cmd}' not allowlisted; extend DEERFLOW_MCP_STDIO_COMMAND_ALLOWLIST on the server`); } Type guard
null
Try / catch
try { await putMcpConfig(payload); } catch (e) { if (e.status === 400 && /disallowed stdio command/.test(e.detail)) { const allowed = parseAllowedFromDetail(e.detail); /* switch command or ask operator to extend env */ } throw e; } Prevention
- Prefer allowlisted launchers (npx/uvx) that fetch packages by name
- Record the allowlist env var in each environment's provisioning so dev/prod match
- On 400, read the detail — it enumerates the currently allowed commands
When it happens
Trigger: Submitting command: 'node', 'python', 'docker', or any custom binary not in the default allowlist; deploying a config that worked in an environment with a custom allowlist env var into one without it.
Common situations: Trying to run a MCP server via python server.py instead of an allowlisted launcher; environments where operators extend the allowlist differently across dev/prod; version upgrades that changed the default allowlist contents.
Related errors
- MCP server '{server_name}' command must be a single executab
- MCP server '{name}' passes '{exec_flag}' to '{command_name}'
- MCP server '{server_name}' with stdio transport requires a c
- MCP server '{name}' sets environment variable '{env_name}',
- Cannot set extra config key '{key}' to masked value '***'; p
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/5b54eee13f253b54.
Report an issue: GitHub.