Skip to content

HTTP API and MCP

vidx serve exposes every index under a directory. Base path /v1; JSON in, JSON or Server-Sent Events out; the OpenAPI document is at /v1/openapi.json.

Method Path Purpose
GET /healthz liveness, version, known indexes
GET /metrics Prometheus text
GET, POST /v1/indexes list, create ({"id": "name"})
GET /v1/indexes/{id} status: videos, counts, sizes
GET, POST /v1/indexes/{id}/videos list; add sources ({"sources": [...], "policy": "..."}) → 202 job
GET /v1/indexes/{id}/videos/{vid}/timeline?level=chapter\|scene\|shot segments
GET /v1/indexes/{id}/videos/{vid}/transcript?t0&t1&kind=transcript\|ocr\|description spans
POST /v1/indexes/{id}/search hybrid search
POST /v1/indexes/{id}/ask agentic answer; SSE with Accept: text/event-stream
POST /v1/indexes/{id}/view labelled frame grid (PNG)
GET /v1/indexes/{id}/blobs/{key} thumbnails, grids
GET, DELETE /v1/jobs/{job} job status (SSE with Accept: text/event-stream); cancel
POST /v1/mcp, /v1/indexes/{id}/mcp MCP (streamable HTTP, JSON-RPC 2.0)

Authentication is Authorization: Bearer <key> (or X-API-Key) when server.api_keys is set; server.daily_cost_cap_usd caps each key's provider spend per day (429 past it).

Streaming an answer

curl -N -H 'Accept: text/event-stream' -H 'Content-Type: application/json' \
  -d '{"question": "what is regret matching?", "budget": {"max_tool_calls": 6}}' \
  http://127.0.0.1:8080/v1/indexes/dataset/ask

Events (event: names the type): status, tool_call, tool_result, token, citation (video_id, t0, t1, kind), done (partial, reason, usage).

MCP

Point an MCP client at POST /v1/mcp. Tools: search, list_videos, timeline, get_transcript, get_ocr, get_descriptions, view (returns an image), describe (when a VLM role is bound), index_state, and ask (VideoIndex's own agent).

{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
 "params": {"name": "search", "arguments": {"query": "strawberry", "k": 5}}}