{"record":{"id":"1cf66140f316774f","repo":"HKUDS/DeepTutor","slug":"mcp-stdio-not-allowed","errorCode":"mcp.stdio_not_allowed","errorMessage":"A server you configure yourself must be a remote URL: a stdio server runs a command on the host and stays administrator-only.","messagePattern":"A server you configure yourself must be a remote URL: a stdio server runs a command on the host and stays administrator-only\\.","errorType":"error_code","errorClass":"UserMcpError","httpStatus":400,"severity":"error","filePath":"deeptutor/services/mcp/user_config.py","lineNumber":179,"sourceCode":"        )\n\n\ndef _assert_self_service_allowed(\n    name: str,\n    cfg: MCPServerConfig,\n    *,\n    validate_url: bool = False,\n) -> None:\n    if not _SERVER_NAME_RE.match(name):\n        raise UserMcpError(\"mcp.invalid_name\", f\"Invalid server name {name!r}\")\n    if name.startswith(_RESERVED_NAME_PREFIXES):\n        raise UserMcpError(\n            \"mcp.name_reserved\",\n            f\"{name!r} starts with a reserved tool-name prefix\",\n        )\n    transport = cfg.resolved_type()\n    if transport == \"stdio\" or cfg.command:\n        raise UserMcpError(\n            \"mcp.stdio_not_allowed\",\n            \"A server you configure yourself must be a remote URL: a stdio \"\n            \"server runs a command on the host and stays administrator-only.\",\n        )\n    if transport not in (\"sse\", \"streamableHttp\"):\n        raise UserMcpError(\"mcp.no_transport\", \"Provide an http(s) URL for the server\")\n    if validate_url:\n        ok, error = validate_mcp_url(cfg.url, strict=True)\n        if not ok:\n            raise UserMcpError(\"mcp.blocked_url\", error)\n\n\ndef _read_raw(owner_id: str) -> MCPConfig:\n    \"\"\"The file as stored, *without* the connectability filtering.\n\n    Writes must preserve entries this deployment refuses to connect (a stdio\n    entry left over from a hand edit), or saving one server would silently\n    delete another.","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/mcp/user_config.py#L161-L197","documentation":"Self-service (user-configured) MCP servers must be remote HTTP servers. A stdio server executes an arbitrary command on the host machine, which is an administrator-only security risk, so the loader refuses any user entry whose resolved transport is 'stdio' or that carries a command field.","triggerScenarios":"Passing a config to save_user_server or having an entry in the user MCP config whose resolved_type() returns 'stdio', or any config object with a non-empty cfg.command, regardless of the declared type.","commonSituations":"Copying an administrator-style stdio server entry (command/args/env) from docs or a shared mcp.json into the per-user config; using a config dataclass that defaults command to something non-empty.","solutions":["Switch the server to a remote URL transport (sse or streamableHttp) and remove the command/args/env fields","If you genuinely need a stdio server, ask the administrator to add it to the admin-level MCP config instead of the user config","Check that your config dataclass isn't leaving a stale 'command' attribute set (truthy) even when you intended a URL server"],"exampleFix":"# before\ncfg = McpServerConfig(command=\"npx\", args=[\"-y\", \"some-mcp-server\"])\nawait save_user_server(user_id, \"my-server\", cfg)\n# after\ncfg = McpServerConfig(url=\"https://mcp.example.com/sse\")\nawait save_user_server(user_id, \"my-server\", cfg)","handlingStrategy":"validation","validationCode":"def is_user_configurable(cfg) -> bool:\n    return cfg.resolved_type() not in (\"stdio\",) and not cfg.command and cfg.resolved_type() in (\"sse\", \"streamableHttp\")","typeGuard":null,"tryCatchPattern":"try:\n    await save_user_server(user_id, name, cfg)\nexcept UserMcpError as e:\n    if e.code == \"mcp.stdio_not_allowed\":\n        # fall back to prompting the user for a hosted URL\n        cfg = prompt_for_remote_url()\n    else:\n        raise","preventionTips":["Never offer a command/args form in user-facing MCP UIs","Strip command, args, and env fields before persisting user configs"],"tags":["mcp","security","stdio","transport","config-validation"],"backgroundTag":"mcp-stdio-not-permitted","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}