unslothai/unsloth · warning · HTTPException
Local commands aren't enabled on this server. To allow them,
Error message
Local commands aren't enabled on this server. To allow them, set UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 and restart Unsloth, or use an http:// or https:// URL instead.
What it means
400 raised when the value is not an http(s) URL (scheme check failed) and it contains whitespace — the one-way signal that it's a local command — but stdio MCP is disabled on this server. stdio_mcp_enabled() gates local commands behind UNSLOTH_STUDIO_ALLOW_STDIO_MCP (auto-on for loopback binds, off for 0.0.0.0/Colab), because a stdio MCP server executes a process as the backend user, bypassing the sandbox.
Source
Thrown at studio/backend/routes/mcp_servers.py:103
status_code = 400,
detail = "Enter an http(s):// URL, or a local command whose "
"first token is an executable (not a URL).",
)
return trimmed
parsed = urlparse(trimmed)
if parsed.scheme not in ("http", "https"):
if _looks_like_command(trimmed):
detail = (
"Local commands aren't enabled on this server. To allow them, "
"set UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 and restart Unsloth, or use "
"an http:// or https:// URL instead."
)
else:
detail = (
"MCP server address must start with http:// or https:// "
"(for example https://example.com/mcp)."
)
raise HTTPException(status_code = 400, detail = detail)
if not parsed.netloc:
raise HTTPException(status_code = 400, detail = "url is missing a host")
return trimmed
def _normalize_headers(headers: dict[str, str] | None) -> dict[str, str] | None:
"""Trim header names, drop empties, coerce values to str; None if empty."""
if not headers:
return None
out: dict[str, str] = {}
for raw_key, value in headers.items():
key = str(raw_key).strip()
if key:
out[key] = str(value)
return out or None
def _row_to_response(row: dict) -> McpServerResponse:View on GitHub (pinned to 203007d190)
Solutions
- Use an http(s):// MCP server URL instead — commands are intentionally blocked on network-exposed hosts.
- If this is your own machine and you accept local code execution, set UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 in the backend environment and restart Unsloth.
- Check the bind/host policy: on loopback the flag defaults to 1, so a 403/400 here usually means a network bind or an explicit --disable-tools.
Example fix
# before (backend bound to 0.0.0.0)
client.post('/api/mcp-servers/', json={'url': 'npx -y @modelcontextprotocol/server-memory'})
# 400: local commands aren't enabled
# after
client.post('/api/mcp-servers/', json={'url': 'https://mcp.example.com/sse'})
# or: start backend with UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 on your own machine Defensive patterns
Strategy: validation
Validate before calling
const isUrl = /^https?:\/\//i.test(url.trim());
const looksLikeCommand = /\s/.test(url.trim());
if (!isUrl && looksLikeCommand && !stdioEnabled) throw new Error('Local commands disabled — use an http(s) URL'); Type guard
function acceptableMcpUrl(url, stdioEnabled) { const v = url.trim(); return /^https?:\/\//i.test(v) || (stdioEnabled && !v.split(/\s+/)[0].includes('://')); } Prevention
- Know the deployment posture: network-bound hosts disable stdio MCP by design.
- Keep a remote (http(s)) MCP endpoint as the portable default.
- Set UNSLOTH_STUDIO_ALLOW_STDIO_MCP=1 only on your own loopback machine.
When it happens
Trigger: Creating/updating an MCP server with a command like 'npx -y @modelcontextprotocol/server-filesystem /tmp' while the backend is bound to 0.0.0.0, running in Colab, or with UNSLOTH_STUDIO_ALLOW_STDIO_MCP=0/unset.
Common situations: Deploying Unsloth Studio on a LAN/remote host (where the loopback auto-default doesn't apply) and re-using an MCP command config that worked locally; or hard-disabling tools with --disable-tools.
Related errors
- Unsloth MCP bearer token must be a non-empty value
- Unsloth MCP bearer token must contain ASCII characters only
- command must not be empty
- Enter an http(s):// URL, or a local command whose first toke
- stdio MCP servers are disabled on this host
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/a5d376ffb16e23fc.
Report an issue: GitHub.