ProxmoxMCP-Plus v0.6.1
This release reduces repeated task polling, bounds tool waiting, adds latency
histograms and offers opt-in independent Proxmox API sessions.
Changes
- Serialize same-job polls within each JobStore. Reuse persisted running state
forjobs.poll_cache_ttlseconds (server default 1; 0 disables the TTL).
Terminal tasks reuse their result. MCP and OpenAPIpoll_job(force=true)bypass
both fast paths. Cache hits preserve history without adding duplicate events.
Existingget_job(refresh=true)calls retain their immediate-backend-refresh
semantics on both MCP and OpenAPI.
Ownership and current persisted state are checked on every call. Retry, cancel,
reconciliation and UPID changes invalidate freshness. Coordination is local to
each store/process; stale-UPID and cross-store retry protections remain intact. - Fix a reproduced cross-store race where a delayed running-task response could
overwrite a newer terminal state. Discard the stale response and retain an
audit event instead of reopening the completed task. - Bound waiting with
mcp.queue_limit(default 64 per target) and
mcp.queue_timeout(default 30 seconds). Overflow and expired waits return
retry-later errors before execution. Cancellation releases queue admission. - Preserve existing metrics and add cumulative, fixed-bucket latency histograms
in seconds. JSON snapshots expose approximate p95/p99; empty or overflowing
quantiles are null. Observe dispatch wait, API-session wait, API requests and
tool execution separately. - Add
proxmox.session_pool_sizeand named-targetsession_pool_size(default 1,
range 1-32). Larger pools own independent clients, sessions and auth objects.
session_pool_timeoutbounds pooled waits (default 30 seconds). Sessions are
leased exclusively; shutdown waits for active requests before closing sessions
and owned tunnels. Partial setup and close failures clean up other sessions.
Uncertain remote mutations are never automatically replayed. - Split job models, SQLite persistence, polling, dispatch admission and execution
policy wrappers into separate modules, preserving existing imports and tool
contracts. No database migration is needed.
Validation
Local Windows/Python 3.13 validation passed 929 tests with four opt-in skips.
All 6,057 runtime statements in 61 modules were covered. Overall branch coverage
was 97.66%; nine critical connection, queue, polling, persistence, policy and
metrics modules had complete branch coverage. CI enforces these gates without
rounding. Fault tests include cancellation, overflow, timeout, disconnects,
partial setup, close errors, cross-store updates and persisted restart.
GET-only live verification is available through
tests/integration/test_readonly_performance.py; destructive integration remains
separately opt-in.
GET-only live verification passed against the local Proxmox test VM, including
eight calling threads and independent sessions. A separate three-run local live
baseline of 16 GET requests per run had median durations of 0.398 seconds with
one session and 0.519 seconds with four. More sessions did not improve this small
workload, so pooling remains opt-in with a default size of one. The VM was
returned to its original saved state after verification.
The reproducible local scripts/benchmark_runtime.py simulation made 100 backend
GETs and 51 audit events for 50 running-task polls with TTL disabled, versus 2 GETs
and 2 events with a long TTL. A 32-request simulation with 10 ms per request had
median durations of 0.337 seconds with one session and 0.085 seconds with four,
over three runs each. These are synthetic results, not production throughput.
Upgrade
Upgrade to proxmox-mcp-plus==0.6.1 or the matching container tag and restart
workers. Preserve SQLite state and legacy OAuth metadata. Independent session
pooling remains opt-in. Tune the new one-second poll TTL and bounded tool waiting
for your workload; use poll_job(force=true) for immediate backend refresh.
See runtime operations for settings,
quantile queries and GET-only integration commands.