lmcache-mp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited lmcache-mp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Target audience: operators running vLLM on H100/H200/B200-class GPUs in production who need KV-cache extension beyond HBM and have outgrown the in-process LMCache path. Assumes Kubernetes or bare container deployment.
vllm-cachingvllm-caching covers vLLM's native CPU-offload (--kv-offloading-size, OffloadingConnector) and the in-process LMCacheConnectorV1 (LMCache linked into the vLLM worker). MP mode is structurally different:
Different image pair, different deployment shape, different troubleshooting surface. Hence its own skill.
Ask in order:
→ Native offload (--kv-offloading-size N --kv-offloading-backend native; no HMA flag on vLLM v0.23.0+). Zero extra pods. Use the vllm-caching skill, not this one.
→ In-process LMCacheConnectorV1 (--kv-transfer-config '{"kv_connector":"LMCacheConnectorV1","kv_role":"kv_both"}' + LMCACHE_LOCAL_DISK env vars). Still in vllm-caching skill.
→ MP mode. This skill.
→ NixlConnector or MooncakeConnector. See vllm-caching (and nvidia-nixl for transport-level tuning). MP can layer on top of these via MultiConnector.
Don't reach for MP mode just because it's newest — it adds operational surface (extra DaemonSet, ZMQ network path, two images to keep in sync, version-pin dance). The in-process LMCacheConnectorV1 still works fine for single-pod deployments.
Current stable pair (2026-09-22): vLLM v0.30.0 (2026-09-22) + LMCache v0.5.5 (2026-09-12, still latest). v0.30.0 pins nixl == 1.4.1 (up from 1.3.2); LMCacheMPConnector/SupportsHMA and the lmcache >= 0.3.9 floor are unchanged. Image bundling on v0.30.0 not yet captured — re-run scripts/verify-bundling.sh v0.30.0. The image lags the pair: vllm/vllm-openai:v0.29.0 bundles LMCache 0.5.4 (2026-08-20), verified by container run 2026-09-15 — so "latest vLLM image" and "latest LMCache" are not the same thing, and pip install -U lmcache inside that image moves you off the pair it was built against. v0.19.1 remains the verified-floor bundling example below.
| Component | What you need | Notes |
|---|---|---|
| vLLM | v0.19.0 or newer for LMCacheMPConnector registered in factory.py | Pre-0.19 had only LMCacheConnectorV1. Both connectors coexist in 0.19+. Connector source path stable through v0.25.1. |
| vLLM | v0.20.0+ for cache_salt propagation through MP | PR #39837 added per-user/per-tenant cache isolation. Repo-local fallback adapter has a known bug — see Pitfalls below. |
| vLLM | v0.23.0+ for HMA-by-default | #41847 made disable_hybrid_kv_cache_manager tri-state; combined with LMCache 0.5.x's SupportsHMA declaration this is what unlocks hybrid models in MP mode. |
| LMCache | 0.4.0+ for the MP adapter file (lmcache.integration.vllm.vllm_multi_process_adapter) | Moved into LMCache repo on 2026-01-07 (PR #2360). Earlier versions had it in vLLM. |
| LMCache | 0.4.4+ for vLLM v0.20+/main | vLLM main imports ParallelStrategy symbol that doesn't exist in 0.4.3. Verified against tags v0.4.3 (no class) vs v0.4.4 (has class); still present at v0.5.1. |
| LMCache | 0.5.4 is what the current image ships; 0.5.5 (2026-09-12) is the newest release — the 0.5.2 → 0.5.5 changes are not yet sifted here | 0.5.0 brought P2P KV transfer to MP mode (#3740/#3762), Device-DAX L1 overflow, asymmetric serde (FP16 key / FP8 value), and a wave of renames. 0.5.1 added L2→L1 warm-prefetch (#3827), HiddenStateStore (#3221), an AMD hipFile GDS-L1 backend (#3843), TurboQuant serde for L2, and configurable disk_io_threads. |
| LMCache | 0.5.x required for hybrid-attention models | The SupportsHMA-declaring connector lives in lmcache/integration/vllm/lmcache_mp_connector.py. See the hybrid-model section. |
Renames in 0.5.0 that break old greps and docs: MPCacheEngine → MPCacheServer, GPUKVFormat → EngineKVFormat (gpu_kv_* → engine_kv_*), GPUTransferModule → LMCacheDrivenTransferModule, NonGPUTransferModule → EngineDrivenTransferModule. The CLI was also refactored into multi-subcommand form (#3678).
Verified 2026-09-15 inside vllm/vllm-openai:v0.29.0 (sleep-overridden, exec'd in):
| Package | Version in v0.29.0 image | Import works? | Notes |
|---|---|---|---|
vllm | 0.29.0 | OK | — |
lmcache | 0.5.4 | OK | ParallelStrategy present — the v0.19.1-era ImportError cannot occur here |
nixl | 1.3.2 | OK | — |
mooncake-transfer-engine-cuda13 | 0.3.13.post1 | OK as import mooncake | Distribution now carries a CUDA suffix; the module does not. Querying mooncake-transfer-engine reports NOT INSTALLED for a package that is present |
lmcache CLI | — | /usr/local/bin/lmcache | Server entrypoint ready out of the box |
All four KV-offload connector classes (OffloadingConnector, LMCacheConnectorV1, LMCacheMPConnector, NixlConnector) load through the factory's own thunk. Sixteen connectors are registered at this tag; the four above are the ones to gate on. No pip install at container start is needed.
Earlier floor, kept because anyone pinning that era still meets it: v0.19.1 shipped vllm 0.19.1 / lmcache 0.4.3 / nixl 0.9.0 / mooncake 0.3.10.post1, and its lmcache predates ParallelStrategy.
But: always verify the tag you actually deploy with scripts/verify-bundling.sh <tag>. It builds a sleep-overridden container, runs the import test, prints the version table. ~30 seconds (after pull).
Two containers. The LMCache server is a separate process; vLLM connects over ZMQ to localhost:6555.
# Terminal 1 — LMCache server
docker run --runtime nvidia --gpus all \
--network host --ipc host \
lmcache/standalone:nightly \
/opt/venv/bin/lmcache server \
--l1-size-gb 60 --eviction-policy LRU --max-workers 4 --port 6555
# Terminal 2 — vLLM (connects to LMCache via ZMQ)
docker run --runtime nvidia --gpus all \
--network host --ipc host \
lmcache/vllm-openai:latest-nightly \
Qwen/Qwen3-14B \
--no-enable-prefix-caching \
--kv-transfer-config '{"kv_connector":"LMCacheMPConnector",
"kv_role":"kv_both",
"kv_connector_extra_config":{"lmcache.mp.port":6555}}'Required Docker flags:
--network host — vLLM container needs to reach LMCache on localhost:6555.--ipc host — CUDA IPC shared-memory transfers require shared /dev/shm.--runtime nvidia --gpus all — both containers see GPUs (the LMCache server uses GPU-side IPC even though it doesn't run inference).Flags on the vLLM side that operators forget:
--no-enable-prefix-caching — vLLM's own prefix cache is OFF. LMCache MP handles prefix caching externally.--disable-hybrid-kv-cache-manager is neither required nor wanted (see Pitfall 1); on lmcache ≤ 0.4.x it is required.The canonical pattern is DaemonSet (LMCache) + Deployment (vLLM): one LMCache server per node serves multiple vLLM pods on that node.
An LMCache Kubernetes Operator reconciles an LMCacheEngine custom resource into the DaemonSet + Service + ConfigMap. Current release is `operator-v0.5.0` (2026-06-25) — the version numbering jumped from the old operator-v0.1.1 (2026-05-18) line, so pin deliberately; operator-v0.5.1rc1 (2026-07-20) is a release candidate, not stable. Install via the install.yaml from the release. Prefer it over hand-rolled manifests for new clusters; the hand-written YAML in references/deployment.md remains the manual alternative and shows what the operator generates.
Operator capabilities added in the 0.5 line (LMCache 0.5.1 notes): a mutating webhook that auto-injects the `LMCacheEngine` connection into vLLM pods (#3822), so vLLM Deployments no longer hand-write the status.hostIP plumbing; a configurable hostNetwork field on the CRD (#3849); and optional privileged mode on the engine DaemonSet (#3943).
Example manifests live in the LMCache repo at examples/multi_process/:
lmcache-daemonset.yaml — LMCache server, one per nodevllm-deployment.yaml — vLLM pods that connect to the node-local LMCache via status.hostIPArchitecture details that bite if missed:
status.hostIP. Without hostNetwork, the server's listening port isn't reachable from sibling pods.For the full deployment recipe (sample YAMLs, prereqs, monitoring integration, cleanup), see references/deployment.md.
For the L1+L2 storage architecture (NIXL adapters, fs, mooncake_store, s3, eviction policies), see references/l2-storage.md.
This inverted in the 0.5 line. MP mode now supports hybrid-attention models officially, and the old "don't recommend MP for hybrids" guidance is obsolete. LMCacheMPConnector declares vLLM's SupportsHMA interface (lmcache/integration/vllm/lmcache_mp_connector.py:512, verified at tag v0.5.1), so vLLM keeps its hybrid KV cache manager enabled and exposes multiple KV cache groups — you do not pass --disable-hybrid-kv-cache-manager, and you do not need any HMA-related flag.
Upstream ships per-model recipes (docs/source/mp/hybrid_models.rst, published at https://docs.lmcache.ai/mp/hybrid_models.html) for:
| Model | Attention layout |
|---|---|
| Gemma 2 / 3 / 4, gpt-oss | Interleaved sliding-window + full |
| Qwen3.5 / Qwen3.6, Qwen3-Next and other GDN hybrids | Mamba / Gated-DeltaNet + full |
| DeepSeek-V4-Flash | Sparse-MLA, multiple KV groups |
| GLM 5.1 / 5.2 | Dynamic Sparse Attention, multiple KV groups |
| MiniMax-M3 | Sparse attention + lightning indexer (mixed KV formats in one group) |
Sliding-window + full-attention hybrids need no special configuration — LMCache detects the model's KV cache groups at registration time.
Mamba / GDN hybrids need one model-specific number. vLLM forces a single unified block size N across all KV cache groups so an attention page is at least as large as a Mamba state page; the LMCache server's --chunk-size and vLLM's --max-num-batched-tokens both derive from it, and getting it wrong raises at engine startup. N is model-specific — never assume a value. vLLM prints it once during startup:
INFO ... interface.py:670] Setting attention block size to 784 tokens to
ensure that attention page size is >= mamba page size.Launch vLLM far enough to emit that line (cheap settings, --mamba-cache-mode align --enable-prefix-caching), read N, then stop. The per-model recipe pages carry the rest.
Object-group separation (`--separate-object-groups`, default ON through v0.5.2, OFF from v0.5.3). At registration LMCache buckets a hybrid model's layers into object groups — the unit it stores and retrieves as one object — one per distinct cross-chunk attention window. --no-separate-object-groups collapses every layer into a single full-attention object group (pre-0.5.1 behavior). Upstream documents the flag as transparent to correctness. The default flipped in v0.5.3: on v0.5.3+ the single full-attention group is what you get unless you pass --separate-object-groups, so a config carried over from v0.5.1 silently changes grouping behaviour on upgrade. A community report on LMCache#3106 (2026-07-17, DeepSeek-V4-Pro on vLLM 0.25.1 + LMCache 0.5.1) uses --no-separate-object-groups to work around a ValueError: Size mismatch in the multi-group retrieve path; that report is unverified by this skill, but the flag and its default are confirmed in lmcache/v1/multiprocess/config.py:48.
Still open upstream: LMCache#2845 (the original hybrid tracker) has not been closed even though the docs now claim support — a 2026-07-10 comment asks exactly that. vLLM#38261 (HybridOffloadPlanner) is also still open. Neither blocks the documented path; treat #2845 as a bookkeeping lag, and verify the specific model against its recipe page before production.
Note the in-process LMCacheConnectorV1 did not get this — it does not declare SupportsHMA at vLLM v0.25.1, so hybrids remain broken there (#3106). That distinction is the main reason to choose MP mode for a hybrid model.
--disable-hybrid-kv-cache-manager is a symptom of the fallback connector, not a requirementOn lmcache 0.5.x this flag is not needed — the external package's LMCacheMPConnector declares SupportsHMA, so vLLM keeps the hybrid manager on.
You only see this error when vLLM falls back to its own repo-local copy of the connector (LMCacheMPConnectorUpstream), which still carries the old guard:
RuntimeError: LMCacheMPConnector only works without hybrid kv cache manager.
Please pass --disable-hybrid-kv-cache-manager when starting vllmSource: vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py:80 (verified at vLLM tag v0.25.1). The fix is to make the external `lmcache` import succeed, not to add the flag — run scripts/verify-bundling.sh <tag>. Adding the flag masks a broken install and costs hybrid-model support. On lmcache ≤ 0.4.x the flag genuinely is required.
Always set --no-enable-prefix-caching on the vLLM side when using LMCacheMPConnector. LMCache handles prefix caching externally. Leaving vLLM's own prefix cache on creates double-counting and inconsistent hit reporting.
ParallelStrategy version hazardvLLM main (post-2026-03) imports ParallelStrategy from lmcache.integration.vllm.vllm_multi_process_adapter. This class does not exist in lmcache 0.4.3 (verified against the v0.4.3 tag on 2026-04-26). It was added in 0.4.4.
| vLLM version | Required lmcache |
|---|---|
| v0.19.0, v0.19.1 | 0.4.0+ (works with bundled 0.4.3) |
| v0.20.0 – v0.22.x | 0.4.4+ — verify on the released image |
| v0.23.0 – v0.25.1 | 0.5.x (0.5.1+) — 0.4.x works but forfeits hybrid-model support |
| v0.29.0 | ships 0.5.4, ParallelStrategy present — verified by container run 2026-09-15 |
| main / nightly | 0.5.1+ |
v0.26.x – v0.28.x are not listed because nobody has run the check on them: unverified, not known-bad.
If you mix vLLM main with the v0.19.1 image's bundled 0.4.3, expect:
ImportError: cannot import name 'ParallelStrategy' from
'lmcache.integration.vllm.vllm_multi_process_adapter'Either pin to a matching pair or pip-upgrade lmcache inside the container.
PR #39837 added cache_salt/cache_salts keyword args at the LMCache MP connector call sites, but the repo-local fallback adapter (vllm/distributed/kv_transfer/kv_connector/v1/lmcache_integration/multi_process_adapter.py) still has the old method signatures. The external lmcache package is fine — only the fallback path used when import lmcache.integration.vllm.vllm_multi_process_adapter fails will trip:
TypeError: LMCacheMPSchedulerAdapter.maybe_submit_lookup_request()
got an unexpected keyword argument 'cache_salt'Don't rely on the fallback adapter. Make sure the external lmcache imports successfully (scripts/verify-bundling.sh).
LMCache --l1-size-gb is the total L1 size for that LMCache server, not per-GPU. The LMCache server is a single process. Don't multiply by TP size.
(This is the same direction as vLLM's --kv-offloading-size — total. Opposite of SGLang.)
Defaults (--eviction-policy LRU --eviction-trigger-watermark 0.8 --eviction-ratio 0.2) are fine for bursty traffic. Under sustained pressure, frequent eviction cycles can stutter cache hits. Lower the watermark (0.7) or raise the ratio (0.3) if logs show eviction every few seconds.
--ipc host (Docker) or mounting /dev/shm from the host (K8s) is mandatory. Without it, CUDA IPC shared-memory transfers between vLLM and LMCache pods fail silently or at startup with cryptic errors. The DaemonSet + Deployment example YAMLs show the right volumes/volumeMounts pattern.
The validation method is the same as for native CPU offload — vllm bench serve --dataset-name prefix_repetition, then diff vllm:external_prefix_cache_* Prometheus counters before and after. See vllm-caching for the methodology and right-sizing math (unique_prefix_budget_tokens ≈ l1_size_gib × 1024 × 1024 / kv_bytes_per_token).
Additional MP-specific signals:
{"status":"healthy"} when the engine is initialized. Wire this into K8s liveness/readiness probes.--prometheus-port to override. The MP server publishes its own metrics independent of vLLM's. KV Transfer metrics: GPU_to_CPU_total_bytes=N GPU_to_CPU_total_time=Ts
CPU_to_GPU_total_bytes=M CPU_to_GPU_total_time=UsNon-zero CPU_to_GPU_total_bytes proves the offload path is serving hits back.
Ranked by likelihood:
--no-enable-prefix-caching missing). Both caches racing → worse than either alone.hostNetwork misconfigured, or the vLLM pod scheduled to a node without an LMCache instance, falling through to no-cache or RPC failures./dev/shm.verify-bundling.sh.~/projects/github.com/LMCache/LMCache)docs/source/mp/ in the repo (index.rst, quickstart.rst, deployment.rst, l2_storage.rst, architecture.rst, http_api.rst, observability.rst, tracing_and_debugging.rst)vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py (clone at ~/projects/github.com/vllm-project/vllm)LMCache/LMCache/examples/multi_process/See references/sources.md for verification dates and the inspection ritual.
Last verified: 2026-07-21 (freshen pass — hybrid-model support inverted, LMCache 0.5.x + operator-v0.5.0 versions, HMA pitfall reframed). Runtime bundling re-captured 2026-09-15 on vllm/vllm-openai:v0.29.0: vllm 0.29.0 / lmcache 0.5.4 / nixl 1.3.2 / mooncake 0.3.13.post1, all KV-offload connectors loading. Re-run scripts/verify-bundling.sh <tag> before pinning any other pair.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.