vastai-mcp
# vastai-mcp
[Polski](README.pl.md)
Vast.ai GPU cloud marketplace and instance management MCP server.
Wraps the Vast.ai REST API (`https://console.vast.ai/api/v0`) so an LLM agent can search the GPU marketplace, rent machines, manage lifecycle, run commands, and inspect billing.
## Table of contents
- [Tools](#tools)
- [Environment variables](#environment-variables)
- [Wiring it up](#wiring-it-up)
- [Local run](#local-run)
## Tools
| Tool | Parameters | Description |
|------|------------|-------------|
| `search_offers` | `query: Dict[str, Any]` | Search the GPU marketplace (POST /bundles/) |
| `search_benchmarks` | `gpu_name: Optional[str] = None` | GPU benchmark data (GET /benchmarks/) |
| `search_templates` | `select_filters: Optional[Dict] = None` | Search user and public templates (GET /template/) |
| `get_gpu_metrics` | `gpu_name, verified, datacenter` | Current supply/demand/pricing snapshot |
| `get_gpu_trends` | `gpu_names, window_hours=24, step` | Historical price/supply time-series |
| `list_instances` | `label: Optional[str] = None` | List user's instances (GET /instances/) |
| `get_instance` | `instance_id: int` | Instance details (GET /instances/{id}/) |
| `create_instance` | `offer_id, image/template_hash_id, disk, runtype, env, onstart, price, ...` | Rent a GPU (PUT /asks/{offer_id}/) |
| `manage_instance` | `instance_id, action: Literal[...], label?` | start/stop/label/reboot/recycle |
| `destroy_instance` | `instance_id: int` | Permanently destroy (DELETE /instances/{id}/) |
| `change_bid` | `instance_id, price: float` | Change spot bid price |
| `show_instance_logs` | `instance_id, tail=1000` | Request instance logs |
| `execute_command` | `instance_id, command: str` | Run a remote command |
| `get_current_user` | none | Current account + credit balance |
| `raw_request` | `method, path, params?, body?` | Escape hatch for any other endpoint |
| `register_ssh_key` | `name, public_key_path` | Register a local public key on the Vast.ai account (POST /ssh/) |
| `list_ssh_keys` | none | List registered SSH keys (GET /ssh/) |
| `get_instance_ssh_info` | `instance_id` | Resolve `ssh_host`/`ssh_port` + ready-to-run `ssh` command |
| `ssh_exec` | `instance_id, command, key_path?, user="root", timeout=30` | Run a command over SSH (paramiko) |
| `ssh_transfer` | `direction: Literal["upload","download"], instance_id, local_path, remote_path, key_path?, user="root"` | SFTP upload/download between local disk and instance |
The `query` body for `search_offers` follows the Vast.ai filter operator convention: each field maps to `{eq, neq, gt, lt, gte, lte, in, notin}`. Example:
```json
{
"gpu_name": {"in": ["RTX 4090"]},
"num_gpus": {"gte": 1},
"reliability": {"gte": 0.99},
"verified": {"eq": true},
"rentable": {"eq": true},
"type": "ondemand",
"limit": 5
}
```
## Environment variables
| Variable | Required | Description |
|----------|----------|-------------|
| `VASTAI_MCP_API_KEY` | yes | Vast.ai API key (https://cloud.vast.ai/manage-keys/) |
| `VASTAI_MCP_SSH_KEY_PATH` | no | Default path to your SSH **private** key, used by `ssh_exec` and `ssh_transfer` when `key_path` is not passed per-call |
## Wiring it up
Only requirement: `uv` (https://docs.astral.sh/uv/). Nothing else to install.
### Claude Code
```
claude mcp add vastai-mcp -e VASTAI_MCP_API_KEY=<value> -- uvx --from git+https://github.com/dam2452/vastai-mcp.git vastai-mcp
```
### Claude Desktop / other MCP client
```json
{
"mcpServers": {
"vastai-mcp": {
"command": "uvx",
"args": ["--from", "git+https://github.com/dam2452/vastai-mcp.git", "vastai-mcp"],
"env": { "VASTAI_MCP_API_KEY": "<value>" }
}
}
}
```
After pushing a new version: `uv cache clean` and restart the client.
## Local run
```
uv run --directory . vastai-mcp
```
Tests (manual):
```
uv run --directory . --with pytest pytest test/
```
TDQS
Scored across 20 tools
Each tool targets a distinct resource and action: search_offers/search_benchmarks/search_templates operate on different datasets, get_gpu_metrics vs get_gpu_trends differ by snapshot vs history, and instance tools are clearly separated (list/get/create/manage/destroy). Even potentially similar tools like execute_command and ssh_exec are explicitly differentiated by stopped vs running instance state.
All tools follow a consistent verb_noun snake_case pattern (search_offers, list_instances, create_instance, destroy_instance, ssh_exec, ssh_transfer). The naming is predictable and consistent, with no camelCase or mixed conventions.
20 tools is at the upper end of 'well-scoped' but appropriate for a full Vast.ai API surface covering marketplace search, instance CRUD, SSH operations, metrics, and user info. The count feels justified given the breadth of features, though slightly heavy compared to a typical 3-15 tool server.
The surface covers the main GPU rental workflow: search offers, create/read/delete instances, manage state, run commands, transfer files, and fetch metrics. Minor gaps like volume management exist, but the raw_request escape hatch covers any missing endpoint, preventing dead ends.