HKUDS/DeepTutor · error · UserMcpError

mcp.blocked_url

mcp.blocked_url

Error message

error

What it means

When validate_url=True, the candidate server URL is passed to validate_mcp_url(url, strict=True); if it fails (non-http(s) scheme, unreachable host, loopback/private address, or otherwise blocked), the returned error message is wrapped in a UserMcpError with code mcp.blocked_url.

Source

Thrown at deeptutor/services/mcp/user_config.py:189

        raise UserMcpError("mcp.invalid_name", f"Invalid server name {name!r}")
    if name.startswith(_RESERVED_NAME_PREFIXES):
        raise UserMcpError(
            "mcp.name_reserved",
            f"{name!r} starts with a reserved tool-name prefix",
        )
    transport = cfg.resolved_type()
    if transport == "stdio" or cfg.command:
        raise UserMcpError(
            "mcp.stdio_not_allowed",
            "A server you configure yourself must be a remote URL: a stdio "
            "server runs a command on the host and stays administrator-only.",
        )
    if transport not in ("sse", "streamableHttp"):
        raise UserMcpError("mcp.no_transport", "Provide an http(s) URL for the server")
    if validate_url:
        ok, error = validate_mcp_url(cfg.url, strict=True)
        if not ok:
            raise UserMcpError("mcp.blocked_url", error)


def _read_raw(owner_id: str) -> MCPConfig:
    """The file as stored, *without* the connectability filtering.

    Writes must preserve entries this deployment refuses to connect (a stdio
    entry left over from a hand edit), or saving one server would silently
    delete another.
    """
    path = user_mcp_path(owner_id)
    if not path.exists():
        return MCPConfig()
    try:
        return MCPConfig.model_validate(json.loads(path.read_text(encoding="utf-8")))
    except (OSError, json.JSONDecodeError, ValueError):
        return MCPConfig()

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Use a publicly reachable https:// URL for the server
  2. If you need a local server for development, run with validate_url disabled (admin/local mode) or expose it via a tunnel the validator permits
  3. Check the exact reason inside the error message returned by validate_mcp_url — it names the specific rule that failed

Example fix

# before
await save_user_server(user_id, "local", McpServerConfig(url="http://localhost:8080/sse", type="sse"), validate_url=True)
# after
await save_user_server(user_id, "prod", McpServerConfig(url="https://mcp.example.com/sse", type="sse"), validate_url=True)
Defensive patterns

Strategy: try-catch

Validate before calling

from deeptutor.services.mcp import validate_mcp_url

ok, reason = validate_mcp_url(cfg.url, strict=True)
if not ok:
    show_error(reason)

Try / catch

try:
    await save_user_server(user_id, name, cfg, validate_url=True)
except UserMcpError as e:
    if e.code == "mcp.blocked_url":
        show_error(f"URL rejected: {e.message}")
    else:
        raise

Prevention

When it happens

Trigger: Calling _assert_self_service_allowed with validate_url=True (via load_user_mcp_config or save_user_server) where cfg.url is non-http(s), points at localhost/private networks, or violates the strict SSRF rules in validate_mcp_url.

Common situations: Pointing a user MCP server at a local development server (http://localhost:3000/sse), an internal IP, or leaving a placeholder URL; strict mode is enabled during interactive 'add server' flows.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/2c140240a56b61b1. Report an issue: GitHub.