HKUDS/DeepTutor · warning · HTTPException

{error}

Error message

{error}

What it means

Raised by POST /test when the server config declares an SSE/streamableHttp transport but its url fails validate_mcp_url; unlike the save-path equivalent, the raw validation error string is returned directly as the 400 detail (no i18n wrapper).

Source

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

    await manager.reload()
    return {
        "servers": {key: value.model_dump(mode="json") for key, value in updated.servers.items()},
        "status": manager.status(),
    }


@router.post("/test")
async def test_mcp_server(cfg: MCPServerConfig) -> dict[str, Any]:
    transport = cfg.resolved_type()
    if transport is None:
        raise HTTPException(
            status_code=400,
            detail=t("mcp.configure_before_testing"),
        )
    if transport in {"sse", "streamableHttp"}:
        ok, error = validate_mcp_url(cfg.url)
        if not ok:
            raise HTTPException(status_code=400, detail=error)
    return await probe_server(cfg)

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Correct the URL to a full form like http://127.0.0.1:9000/sse and re-test
  2. Read the returned error string — it comes straight from validate_mcp_url and states the precise problem
  3. Confirm the server you meant to test actually exposes an SSE/streamable-HTTP endpoint at that URL

Example fix

// before
await api.post('/mcp/test', { name: 'local', url: 'localhost:9000/sse' });

// after
await api.post('/mcp/test', { name: 'local', url: 'http://localhost:9000/sse' });
Defensive patterns

Strategy: validation

Validate before calling

function isHttpUrl(s: string): boolean {
  try {
    const u = new URL(s);
    return u.protocol === 'http:' || u.protocol === 'https:';
  } catch {
    return false;
  }
}
if (cfg.url && !isHttpUrl(cfg.url)) throw new Error(`Invalid MCP url: ${cfg.url}`);
await api.post('/mcp/test', cfg);

Type guard

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

Try / catch

try {
  await api.post('/mcp/test', cfg);
} catch (e) {
  if (e.status === 400 && typeof e.detail === 'string' && /url/i.test(e.detail)) {
    // e.detail is the raw validator message; fix the url and re-test
  }
}

Prevention

When it happens

Trigger: POST /mcp/test with a body containing a url like '127.0.0.1:9000/sse' (missing scheme) or another malformed/unsupported URL, with the transport resolved to sse or streamableHttp.

Common situations: Quickly testing a locally-running MCP server and forgetting the http:// prefix; copy-paste of endpoints from logs or docs with truncated URLs; testing before checking how the config was saved.

Related errors


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