vram-mcp
by sushiHex
README.md
# vram-mcp
Give your AI agents a shared view of GPU memory. Through
[MCP](https://modelcontextprotocol.io), they can inspect what's using VRAM,
make room for [Ollama](https://ollama.com) models, and see which sessions are
already relying on them.
Each client runs its own server; sessions under the same OS user share claims,
reservations, pending-operation records, and an audit log. Capacity and process
readings apply to one configured GPU. Claimed or recently busy models are
protected from eviction by default.
## Get started
Use **Python 3.10+**, a running **Ollama** instance, and an **NVIDIA GPU with
drivers** for memory readings. Windows and Linux are tested. Without
`nvidia-smi` or NVML, model operations and claims still work, but some readings
are unavailable.
Run vram-mcp on the machine hosting Ollama and the GPU. Changing
`OLLAMA_BASE_URL` redirects model requests; GPU and process inspection always
remain local. On a multi-GPU host, set `VRAM_MCP_GPU_INDEX` in every client's
server environment to select the same device; the default is GPU index `0`.
### Connect your client
With [uv](https://docs.astral.sh/uv/getting-started/installation/) and Git
installed, choose your client below. `uvx` fetches vram-mcp from GitHub into an
isolated environment; no source checkout is needed.
**[Claude Code](https://code.claude.com/docs/en/mcp):**
```sh
claude mcp add vram --scope user -- uvx --from git+https://github.com/sushiHex/vram-mcp vram-mcp
```
**[Codex](https://learn.chatgpt.com/docs/extend/mcp?surface=cli):**
```sh
codex mcp add vram -- uvx --from git+https://github.com/sushiHex/vram-mcp vram-mcp
```
**[Hermes](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp)** — merge into `~/.hermes/config.yaml`:
```yaml
mcp_servers:
vram:
command: uvx
args: ["--from", "git+https://github.com/sushiHex/vram-mcp", "vram-mcp"]
```
<details>
<summary>Claude Desktop and other clients using mcpServers JSON</summary>
Merge this entry into your client's MCP configuration:
```json
{
"mcpServers": {
"vram": {
"command": "uvx",
"args": ["--from", "git+https://github.com/sushiHex/vram-mcp", "vram-mcp"]
}
}
}
```
If the client cannot find `uvx`, use its absolute executable path. In JSON,
Windows paths need escaped backslashes, such as `C:\\tools\\uvx.exe`.
</details>
Reconnect your client after registration. It launches the server over stdio;
running `vram-mcp` by hand waits for MCP input. Prefer a local installation?
See [installing from source](docs/configuration.md#installing-from-source).
### Make your first check
Ask your agent:
> Check GPU memory with vram-mcp. Show what's loaded, who is using it, and how
> much room is left. Report any unavailable readings.
The agent should call `vram_status()` and `list_claims()`. Status includes a
readable `summary`, the selected GPU, loaded models, available process details,
and `observations` metadata. Check each observation's `status`; `unavailable`
means the corresponding value is unknown, rather than empty or zero.
`list_claims()` also shows capacity reserved for training or other non-Ollama
work.
## Agent workflow
These examples are **MCP tool calls** made inside a connected client, not shell
commands or a Python API. Use a descriptive session label for `owner` and `by`,
such as `codex:review`, so another agent can identify your work.
1. **Inspect before changing memory.** Call `vram_status()` and `list_claims()`.
Model names are canonicalized consistently: a bare final name such as
`llama3` becomes `llama3:latest`; comparison is case-insensitive, and
Ollama's default registry/library prefix is removed.
2. **Claim a model before relying on it.** Replace the example model below
with one already installed in Ollama. Continue only if the claim succeeds,
and save its returned `claim_id`.
```text
claim(model="llama3:latest", owner="codex:review", purpose="Review local code")
```
3. **Make room when needed.** `ensure_free(gb=8, by="codex:review")` unloads
unprotected models largest-first. Choose the target for your workload and
check `outcome`, `free_mb`, `declined`, `reserved_mb`, and `observations`.
It does not evict when selected-GPU capacity or Ollama residency is unknown.
Reaching the target does not give you ownership of that space.
4. **Load and check.** Call
`warm(model="llama3:latest", keep_alive="10m", by="codex:review")` when needed.
Inspect `outcome`, `reason`, and `observations`. `succeeded` means residency
was reconciled after the request; `refused` means no Ollama request was sent;
`failed` means Ollama definitively rejected it; and `unknown` means the
request may still be running and includes `pending_until`. Do not retry a
same-model mutation until that pending window ends. Warm admission is also
serialized across models sharing the selected GPU. A model that was already
resident has zero incremental residency cost (`reason="already_resident"`).
Loading successfully does not guarantee full GPU residency. Run inference
through your usual Ollama client.
5. **Renew and release.** Claims expire after one hour by default. Call
`renew(claim_id="<returned claim_id>")` before expiry for longer work and
`release(claim_id="<returned claim_id>")` when finished, including if loading
fails. Releasing a claim does not unload the model; claim expiry and Ollama's
`keep_alive` are separate.
For training or diffusion, use `reserve(gb=8, owner="codex:training",
purpose="LoRA training")` to declare capacity, then renew/release its `claim_id`
in the same way. A reservation records intent; it does not allocate memory.
Validation rejects invalid requests: capacities, TTLs, and trend windows
must be finite and positive; model, owner, purpose, and caller labels must be
nonblank; `warm` accepts a positive Ollama duration or `-1` for indefinite
residency. Use `unload()` rather than a zero `keep_alive`.
**Coordination is cooperative.** Direct Ollama calls can bypass it. `force=True`
on `unload`, `ensure_free`, or `warm` overrides claims, busy protection, or
reservation admission; use it only after resolving competing work. It does not
bypass an unreadable coordination ledger or another pending mutation.
`busy=null` means unknown and does not block eviction on its own. See
[coordination details](docs/coordination.md).
## Understand the readings
| `pressure.state` | Meaning |
| --- | --- |
| `ok` | No pressure detected in the available readings. |
| `tight` | Less than 1 GiB is free on the selected GPU. |
| `degraded` | Ollama placed part of a model on the CPU; expect slower inference. |
| `thrashing` | Unexplained non-local memory meets the spill threshold and, when free VRAM is known, exceeds it. Driver paging is suspected. |
Missing required telemetry produces `pressure.state="unknown"`. Read
`pressure.coverage` and top-level `observations` to see which evidence was
available. Driver-spill detection is best effort and requires non-local memory
that can be attributed to the selected GPU; adapter-aggregated Windows counters
do not establish that. CPU offload is tracked separately. Disabling auditing
stops history detection and trend sampling, but does not disable current GPU or
process observations.
Use `history()` to investigate a model disappearing and `trend(hours=1)` to
review memory changes. Trends are sampled when `vram_status()` reads the GPU;
there is no background sampler. See [diagnostics](docs/coordination.md#diagnostics).
## Tools
The client's MCP schema provides full arguments and defaults.
| Tool | Purpose |
| --- | --- |
| `vram_status` | Inspect GPU memory, models, claims, activity, and pressure. |
| `list_loaded` | List resident models and their claim/busy details. |
| `ensure_free` | Try to reach a free-memory target by unloading unprotected models. |
| `unload` | Evict a named model, respecting claims and recent activity. |
| `warm` | Load a model for a chosen `keep_alive`, checking reservations. |
| `claim`, `reserve` | Declare model use or capacity needed for other GPU work. |
| `renew`, `release` | Extend or end your claim or reservation. |
| `list_claims` | See active model claims and capacity reservations. |
| `history`, `trend` | Review recorded actions, observed changes, and memory samples. |
| `advise` | Get configuration suggestions; no settings are changed. |
## Guides
| Guide | Read it for |
| --- | --- |
| [Configuration](docs/configuration.md) | Source installation, environment variables, and connection troubleshooting. |
| [Coordination and diagnostics](docs/coordination.md) | Claims, reservations, protection limits, pressure, and audit history. |
## Development
```sh
git clone https://github.com/sushiHex/vram-mcp.git
cd vram-mcp
python -m venv .venv
```
Activate with `source .venv/bin/activate` on Linux or
`.\.venv\Scripts\Activate.ps1` in PowerShell, then run:
```sh
python -m pip install -e ".[dev]"
python -m pytest -q
```
Tests use mocked GPU, process, and HTTP calls; no GPU or Ollama daemon is needed.
CI covers Python 3.10–3.14 on Windows and Linux. Current model management targets
Ollama and NVIDIA; AMD/Intel telemetry and vLLM/llama.cpp management are future
work.
## License
MIT — see [LICENSE](LICENSE). Companion project:
[hardline-mcp](https://github.com/sushiHex/hardline-mcp) for agent messaging.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessUnresponsive