MinerU API Server#
mineru-api is a FastAPI/uvicorn HTTP server that exposes MinerU's document-parsing pipeline over a REST API. The server is defined in mineru/cli/fast_api.py and launched via the mineru-api CLI entry point.
Server Startup & Port Configuration#
The main() Click command accepts:
| Option | Default | Notes |
|---|---|---|
--host | 127.0.0.1 | Set to 0.0.0.0 / :: for public binding |
--port | 8000 | Any free integer port |
--reload | off | Dev-mode auto-reload; incompatible with spawn launch |
--enable-vlm-preload | false | Preloads the VLM model at startup |
API docs are served at /docs by default; set MINERU_API_ENABLE_FASTAPI_DOCS=0 to disable .
Concurrency Control#
A process-level asyncio.Semaphore gates all active parse jobs . The limit is read from the environment variable MINERU_API_MAX_CONCURRENT_REQUESTS, falling back to DEFAULT_MAX_CONCURRENT_REQUESTS = 3 . On macOS the limit is hardcoded to 1 . The current limit is advertised in every /health response so that routers can calibrate concurrency without additional configuration.
Task Lifecycle#
Requests are handled through AsyncTaskManager :
POST /file_parse— synchronous: submits a task and blocks until completion .POST /tasks— async: returns HTTP 202 with atask_idimmediately .GET /tasks/{task_id}— polls task status .GET /tasks/{task_id}/result— fetches result once completed .
Completed task state and output files are retained for MINERU_API_TASK_RETENTION_SECONDS (default 24 h) and swept by a background cleanup loop every MINERU_API_TASK_CLEANUP_INTERVAL_SECONDS (default 5 min) .
Health Check Protocol#
GET /health is the primary liveness and compatibility signal .
Healthy response (HTTP 200):
{
"status": "healthy",
"version": "<semver>",
"protocol_version": 2,
"queued_tasks": 0,
"processing_tasks": 1,
"max_concurrent_requests": 3,
"processing_window_size": 64
}
Unhealthy (HTTP 503): returned when AsyncTaskManager.is_healthy() is False — triggered when the dispatcher task exits unexpectedly, the cleanup loop crashes, or last_worker_error is non-None .
The client validates two fields before routing any task :
status == "healthy"— node is up and the task manager is running.protocol_version == API_PROTOCOL_VERSION(2) — client and server are version-compatible .
This version check makes /health a compatibility gate, not just a liveness probe. A version mismatch raises a hard error rather than silently routing to an incompatible server.
Multi-Instance Deployment with mineru-router#
mineru-router (defined in mineru/cli/router.py) is the load balancer that coordinates one or more mineru-api instances.
Router defaults: host 127.0.0.1, port 8002 .
Worker sources#
Workers can be remote or local:
- Remote workers: passed via
--upstream-url. - Local GPU workers: launched as subprocesses via
--local-gpus auto|none|0,1,2— onemineru-apiprocess per GPU, each on a dynamically allocated port . Port collisions are prevented by pre-reserving all ports before spawning .
Health monitoring & automatic restart#
The router polls every worker's /health endpoint every 2 seconds (WORKER_REFRESH_INTERVAL_SECONDS) . After 5 consecutive failures (WORKER_HEALTH_FAILURE_RESTART_THRESHOLD), it restarts the local worker . This means recovery from a fatal worker crash takes up to ~10 seconds once /health starts returning 503.
Known gap: If a vLLM
EngineCoredies inside_process_taskbut does not setlast_worker_error, the/healthendpoint continues returning 200 and the router never triggers a restart. This is tracked in issue #5171 and addressed by PR #5188.
Load balancing#
acquire_submission_server selects the least-loaded healthy worker using a utilization score (queued + processing + pending_assignments) / max_concurrent_requests, with local workers preferred over remote and randomization applied before sorting to avoid deterministic hotspots . The router reads max_concurrent_requests and processing_window_size from each worker's /health payload so it can correctly cap in-flight submissions per worker.
Process-level concurrency isolation#
For long-running services, a common pattern is deploying multiple mineru-api instances each with MINERU_API_MAX_CONCURRENT_REQUESTS=1 behind mineru-router. This bounds memory accumulation to a single document's lifetime per process and allows individual worker restarts without affecting the pool .
Key Files#
| File | Purpose |
|---|---|
mineru/cli/fast_api.py | FastAPI app, AsyncTaskManager, all API endpoints, main() CLI |
mineru/cli/api_client.py | HTTP client helpers, LocalAPIServer, health validation |
mineru/cli/router.py | mineru-router load balancer, WorkerPool, health monitor |
mineru/cli/api_protocol.py | API_PROTOCOL_VERSION, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_PROCESSING_WINDOW_SIZE |