HKUDS/DeepTutor · error · HTTPException

mcp.server_error

Error message

mcp.server_error

What it means

Validation error from _validate_servers: the server entry declares an SSE or streamable HTTP transport (has a url), but that URL fails validate_mcp_url — typically missing a scheme, using a disallowed scheme, or being malformed. The error message embeds the specific validation error.

Source

Thrown at deeptutor/api/routers/mcp_settings.py:52

router = APIRouter(dependencies=[Depends(require_admin)])


class MCPSettingsPayload(BaseModel):
    servers: dict[str, MCPServerConfig] = Field(default_factory=dict)


def _validate_servers(config: MCPConfig) -> None:
    for name, cfg in config.servers.items():
        transport = cfg.resolved_type()
        if transport is None:
            raise HTTPException(
                status_code=400,
                detail=t("mcp.configure_command_or_url", name=name),
            )
        if transport in {"sse", "streamableHttp"}:
            ok, error = validate_mcp_url(cfg.url)
            if not ok:
                raise HTTPException(
                    status_code=400, detail=t("mcp.server_error", name=name, error=error)
                )


@router.get("")
async def get_mcp_settings() -> dict[str, Any]:
    config = load_mcp_config()
    manager = get_mcp_manager()
    await manager.ensure_started()
    return {
        "servers": {name: cfg.model_dump(mode="json") for name, cfg in config.servers.items()},
        "status": manager.status(),
    }


@router.put("")
async def update_mcp_settings(payload: MCPSettingsPayload) -> dict[str, Any]:
    try:

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Fix the URL to include a full valid scheme and host, e.g. https://example.com/mcp/sse
  2. Read the embedded {error} in the 400 detail — it states exactly what validate_mcp_url rejected
  3. Confirm the transport type matches the URL field usage (stdio servers use command, remote servers use url)
  4. Test the URL with curl to confirm the endpoint is reachable and correctly formed

Example fix

// before
{"servers": {"remote": {"name": "remote", "url": "example.com/mcp/sse"}}}

// after
{"servers": {"remote": {"name": "remote", "url": "https://example.com/mcp/sse"}}}
Defensive patterns

Strategy: validation

Validate before calling

function isValidMcpUrl(url: string): boolean {
  try {
    const u = new URL(url);
    return u.protocol === 'http:' || u.protocol === 'https:';
  } catch {
    return false;
  }
}
if (transport === 'sse' || transport === 'streamableHttp') {
  if (!isValidMcpUrl(cfg.url)) throw new Error(`Invalid MCP url: ${cfg.url}`);
}

Type guard

function isHttpUrl(s: string): s is string {
  return /^https?:\/\/.+/.test(s);
}

Try / catch

try {
  await api.put('/mcp', { servers });
} catch (e) {
  if (e.status === 400 && e.detail?.includes('server_error')) {
    // fix the reported server's url and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: PUT mcp settings or upsert with a server whose resolved transport is 'sse' or 'streamableHttp' and whose url is e.g. 'localhost:8080/sse' (no scheme), 'ftp://...', or an unparsable string.

Common situations: Copying an MCP endpoint from docs and dropping the https:// prefix; mixing up the fields (putting the URL into a command field or vice versa); proxy/firewall environments where developers hand-edit URLs and introduce typos.

Related errors


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