FIREFIGHTER
Schedules GPU jobs on AMD GPUs, including mixed-vendor machines, and reads AMD GPU utilization through rocm-smi.
Governs Docker containers and docker run/docker pull commands, including GPU containers, so containerized agent workloads are queued and network transfers are scheduled.
Supports scheduling GPU jobs on Intel GPUs and mixed-vendor GPU placement alongside NVIDIA and AMD cards.
Detects Kubernetes pods as external workloads and accounts for their resource use in the dynamic CPU/RAM/VRAM reserve so agent jobs yield to them.
Schedules GPU jobs on NVIDIA GPUs, places jobs on the admitted card, and reads GPU utilization through nvidia-smi.
The problem
Run three or four agents at once and each one decides on its own to train a model, run an eval sweep, build a Docker image or render something. They all grab the same GPU. VRAM runs out (CUDA out-of-memory, or silent spill into system RAM on Windows), two trainings slow each other to a crawl, your game stutters, audio crackles, and nobody knows who's using what or for how long.
Related MCP server: agent-bus-mcp
What firefighter does
๐ค You always come first. It watches your keyboard and mouse, fullscreen apps, games (3D-engine use), and every process it didn't start: Docker containers, Kubernetes pods, local model servers, your own apps. It keeps a dynamic reserve of CPUs, RAM and VRAM for you that grows within half a second when you sit down or start a game and gives capacity back slowly when you leave.
๐๏ธ Agents take turns instead of fighting. Heavy work waits in a queue. A GPU job starts only when its VRAM need fits, and that need is learned from the command's past runs. Projects that have used the least go first (least attained service), with a 45-minute cap on any wait.
๐น A market maker, not a bidding war. Agents don't bid against each other. firefighter posts prices for three tiers: spot (leftovers, โ price), normal, and urgent (2ร, only when you're waiting on the result). Every reply an agent already gets ends with one line: when each tier would start, what it costs against the agent's budget, the odds the GPU is busy over the next 2 hours, a quiet hour to aim for, and a
do:with the one recommended action. The advice never tells an agent to outbid anyone, so the whole market costs about 60 tokens and there's no bidding war to win.๐ก๏ธ Fallbacks for careless or rogue agents. Heavy processes an agent starts outside firefighter are found and adopted anyway: idle priority, billed 1.5ร, preempted first. That makes skipping the queue strictly worse than using it. Other guards cover queue flooding (per project and in total), new project names that try to get a fresh budget (all new projects share one small daily pool), chronic under-estimates (ร1.25), VRAM hoarding (ร3), lease overruns (ร2, preempted first), leases over 24 h, extensions after a short backfill, and one agent cancelling or re-bidding another agent session's job (you, from a terminal or editor, can manage any job). Text an agent sends (plans, names) is stripped of control characters before other agents or your terminal see it.
๐ซก Graceful for the agent. When you need the machine back, the job's own client says why, and the job gets the whole grace period (60 s) to save and exit (checkpoint protocol). On macOS/Linux a job still running 10 s before the deadline gets SIGINT (Ctrl+C) before SIGTERM; on Windows it keeps the full grace period, then is stopped. It's requeued under the same id and the agent is told why and that there's nothing to resubmit.
โธ๏ธ Polite preemption. The ladder goes: shrink the job's CPU set โ cooperative pause at a step boundary โ suspend (for jobs that ignore the pause) โ checkpoint-and-exit with automatic requeue when you need the memory back โ kill, but only when RAM is critical.
๐ Network too. Downloads and uploads (
docker pull, pip/npm/cargo installs,git clone, model and dataset downloads; detected automatically, or--net) take turns, wait while you're using the link (a call, a stream:network.human_busy_pct), and pause while you game.๐งฎ Any machine. Any number of GPUs from any vendor (NVIDIA, AMD, Intel; mixed is fine), any CPU count (Windows processor groups past 64 included), any RAM size. Each GPU job is placed on the card it was admitted on, in that vendor's own numbering. On mixed machines a job goes to the NVIDIA cards unless it says otherwise (
--gpu-vendor amd|intel|any). Every PC runs its own firefighter; nothing goes over the network.๐ Set and forget.
setupstarts the guard at logon and, for every agent it finds installed, registers the MCP server and adds a short rule block to its global instructions, so every new session (including T3 Code threads) already knows the protocol: Claude Code, Codex, Gemini CLI, Antigravity, Cursor, Grok Build, OpenCode, Kimi CLI and Kimi Code, Pi, Muse Code, fx, Kiro, Windsurf/Devin, Copilot CLI, Amp, Qwen Code, Crush, Cline, Goose and Droid. Each in its own format;uninstallremoves all of it.
Install (one command)
Windows (PowerShell):
irm https://raw.githubusercontent.com/JoshWright22/FIREFIGHTER/main/scripts/install.ps1 | iexmacOS / Linux:
curl -fsSL https://raw.githubusercontent.com/JoshWright22/FIREFIGHTER/main/scripts/install.sh | shThe installer checks the release checksum, puts one ~8 MB binary on your PATH, and runs firefighter setup.
With Go 1.23+:
go install github.com/JoshWright22/firefighter/cmd/firefighter@latest && firefighter setup.
Requirements: Windows 10/11, macOS 12+ or Linux, on x64 or arm64. No admin rights needed. For
GPU numbers you need nvidia-smi (NVIDIA driver) or rocm-smi (AMD). On Linux, idle detection
uses GNOME, KDE or another freedesktop ScreenSaver desktop, or xprintidle; headless machines
count you as "present".
What install changes (each config file gets a one-time *.firefighter.bak backup first):
What | Where |
Binary |
|
Autostart | Task Scheduler task |
Agent rules | a marked block in |
MCP server |
|
State |
|
Verify: open a new terminal and run firefighter status. Remove: firefighter uninstall undoes
autostart, the rule blocks and the MCP entries. Then delete the binary and, if you want to forget
budgets and history, the state folder.
Use
firefighter run --gpu --minutes 40 --vram 10 --name "nanoGPT train" -- python train.py
firefighter run --gpu --urgent --minutes 10 -- python eval.py # you're waiting on it: 2x
firefighter run --gpu --spot --minutes 120 -- python sweep.py # can wait: 1/3 price
firefighter run --minutes 5 -- npm run build # long CPU work
firefighter run --gpu --minutes 20 -- docker run --gpus all my/eval # containers are governed too
id=$(firefighter run --detach --gpu --minutes 90 -- python sweep.py) && firefighter wait "$id"
firefighter quote --gpu --minutes 30 --vram 8 # the market, no side effects
firefighter bid <id> 10 # make a waiting job urgent (5 = normal)
firefighter status # who's on stage until when, the queue, budgets
firefighter plan "eval sweep" --when tonight --minutes 120 --gpu 90 --vram 12
firefighter extend <id> 15 # running long? say sorun waits for a turn, then runs your command in your own environment (venv, conda, uv, nvm and
docker all just work), passes its output and exit code through, and ends with a receipt:
โ 3f2a91c0 nanoGPT train waiting #2, starts ~14:05 (in 22m): GPU turn queue
gpu 40m: start ~22m, cost ~42 of 212 (urgent ~6m ~84) (spot ~70m ~14) | busy 15/60/120m 92/35/12% | quiet 02:00 (usually 8% busy) | do: queue it at normal (starts ~22m); keep working meanwhile
โ nanoGPT train: spotlight's yours (lease 40 min, budget left 212.0)
โ nanoGPT train: curtain call, ok (exit 0) in 37.2 min (declared 40), waited 6.1, charged 31.4 machine-min, peak 3.1 GB RAM / 9.4 GB VRAMMCP tools (one-line text replies plus structuredContent): firefighter_submit,
firefighter_wait, firefighter_status (which also gives quotes), firefighter_job (extend,
urgent/normal, cancel) and firefighter_plan. firefighter_config is listed only when you allow
agents to change the policy.
How it decides (and how to change it)
Zero config gives you the researched defaults below. You can swap each part by name, live, with
firefighter config set <key> <value>. Agents can read the policy through the firefighter_config
MCP tool, and can change it only if you set guard.agents_can_configure true.
Stage | Default | What it does | Swap with |
You | dynamic reserve | Four states: away, present, active and game. The reserve grows within one 0.5 s tick and gives back 1 CPU every 15 s, RAM after 60 s and VRAM after 120 s. Jobs are pinned to the CPUs outside your reserve (Windows and Linux; macOS uses background QoS instead). A state with |
|
Order |
| The project with the least use goes first, with a 12 h half-life (Tiresias, Slurm fair share). A 45-minute wait cap overrides it. |
|
Market |
| Price per machine-minute = tier (spot โ
, normal 1, urgent 2) ร congestion ร 1.25 for projects whose jobs habitually overrun. Congestion is 0.5 ร 8^u, where u is how committed the resource is over the next hour: 0.5 idle, about 1.4 at half load, 4 when full. The price is locked when the job is granted; overruns pay ร2 and adopted work ร1.5 on top. Urgent buys at most 30 min of queue lead under |
|
Budget |
| Steady refill of 240 machine-minutes a day (10 an hour), banked up to 2 days (Karma, OSDI '23). The first project on a machine starts full. Later new projects start at the median usage and draw their start and first day's refill from one pool all new projects share (120 a day), so inventing names doesn't mint budget or jump the queue. While a project's budget is empty, its waiting and running jobs are spot. |
|
Charge | DRF | One machine-minute is all of the GPU, VRAM, RAM or CPUs for one minute (Dominant Resource Fairness). Idle VRAM is charged ร3 (ESX idle tax), overruns ร2, and chronic under-estimates ร1.25. | built in |
Admission | learned peaks | A job's need is the larger of its declared size and 1.2 ร its learned peak, checked against what's left on one GPU after your reserve and the unclaimed needs of jobs already there. Each card takes turns on its own ( |
|
Preemption | ladder | See the ladder below. |
|
Guard | on | Heavy processes an agent CLI (Claude Code, Codex, Gemini, Grok, OpenCode, Kimi, Copilot, Amp, Qwen, Aider, Goose, Cline and more) starts outside firefighter get adopted: spot band, idle priority, charged. IDE terminals are never adopted. Each project is capped at 20 open jobs. Agents can read the policy but can't change it unless you allow it, and even then only |
|
Presets: balanced (default), gamer, throughput, fair โ firefighter config set preset gamer.
Band | Who | Preempted by |
0 ยท headliner | you, plus everything not run by firefighter (apps, games, Docker, k8s) | nothing |
1 ยท opener | short CPU jobs (โค 3 min) | you |
2 ยท main set | in-budget GPU and long jobs (the market) | you |
3 ยท afterparty | over budget, | anything |
4 ยท harvester | optional idle-GPU program (Salad, BOINC, Folding@home) | anything |
The preemption ladder
Steps run in order, and each one fires only if the trigger is still there:
CPU set. Jobs always live outside your CPU reserve (Windows, Linux).
Cooperative pause (GPU jobs, while your state holds the GPU): firefighter creates the file at
FIREFIGHTER_PAUSE_FILE. A job that honors it createsFIREFIGHTER_PAUSED_FILEand sleeps until the pause file is gone.Suspend: if the job hasn't acknowledged within 10 s (or, where per-process GPU counters exist, acknowledged but kept computing), it's suspended. It stays suspended while you need the GPU. Past 60 s, if the memory it holds is what you're short of, it's stopped and requeued (it ignored the pause, so it can't checkpoint).
--evict neverjobs stay suspended until you're done.Checkpoint: when RAM or VRAM (per card) stays under your reserve for 20 s, or when a spot job has run its 10-minute minimum and an in-budget job is waiting on what it holds, firefighter lifts any pause and creates
FIREFIGHTER_CHECKPOINT_FILE. The job gets 60 s to save and exit. On Unix it then gets a SIGTERM, and 10 s later it's killed. A job that exits with 75, or exits at all after the request, is put back in line under the same id.--evict forcejobs are killed at once (and put back in line the same way).Kill: if available RAM drops under 3%, one job is killed at once, even mid-grace, and the next only after 5 s (memory takes a moment to come back).
Victims are picked so one eviction fixes the problem: first jobs whose memory covers the shortfall,
then the highest band (spot, past their lease, adopted), then the heaviest. One eviction at a time.
--evict never jobs are only ever touched when RAM is critical. CUDA can't be checkpointed from outside on Windows
or macOS, so the job has to cooperate. firefighter protocol prints a short Python helper you
call once per step.
Per-OS support
Windows | macOS | Linux | |
Your input | GetLastInputInfo | IOHIDSystem idle time | GNOME/Mutter, freedesktop ScreenSaver (KDE, Wayland), xprintidle |
Games and fullscreen | fullscreen foreground window (not merely maximized), 3D-engine use per process, exclusive apps | exclusive apps only (add your games to | exclusive apps only ( |
GPU / VRAM | any vendor: nvidia-smi, plus DXGI + GPU counters for AMD/Intel (no vendor tool needed) | unified memory (counted as RAM) | nvidia-smi, rocm-smi or amdgpu sysfs; outside VRAM holders count as load only while the card is busy |
Job priority | idle CPU, idle GPU scheduling, very low memory and I/O priority | nice 19 + background QoS | nice 19, SCHED_IDLE, idle I/O class, on every thread |
CPU reserve | affinity (CPU Sets past 64 CPUs) | QoS | affinity |
No orphans | Job Object, kill on close | process group | process group |
CLI reference
Command | What it does |
| Wait for a turn, run, receipt. Flags: |
| Block until the job ends (following requeues); prints the receipt and log tail. Exits with the job's exit code, or 124 on timeout |
| The market for a job, no side effects |
| Change a job's tier, lease, or cancel it |
| The human's state and reserve, the market, running and waiting jobs, budgets, plans |
| Govern a process that's already running |
| Announce or remove planned work |
| Every key is in |
| The pause/checkpoint helper |
| Install, remove, run or stop the guard, MCP server |
Files in the state folder: firefighter.toml (your settings), state.json (budgets, learned
history, receipts, the hour-of-week occupancy), STATUS.md (a status snapshot rewritten every 15 s
for agents that read files), daemon.log, logs/<id>.log (detached jobs, kept 7 days),
signals/ (pause and checkpoint files), daemon.json and daemon.lock.
Editors and agent apps
Every agent
setupfinds (see the list above, T3 Code's providers included): MCP and the rules are wired up automatically.Claude Code plugin: a live status-line entry,
/firefighter, and a guard that sends heavy Bash commands back to the agent to rerun through the queue:/plugin install firefighter --marketplace JoshWright22/FIREFIGHTERVS Code, Cursor, Windsurf extension: a live status bar item (the
.vsixis on every release).Anything else:
firefighter statuslinegives one line for any status bar (Claude Code'sstatusLine, tmux, starship), andfirefighter eventsstreams NDJSON for editor plugins. There's also a local HTTP API. See docs/integrations.md.
How it compares
firefighter | worker-q | load-lock / agent-task-queue | gpulease / gpu-arbiter | KAI-Scheduler / Kueue / Slurm | |
Runs on Windows, macOS and Linux | โ | partial (Windows, Linux) | โ macOS/Linux | โ Linux | Linux clusters |
Protects the human at the keyboard | โ dynamic reserve, game detection | partial: static reserve, manual gaming mode | โ | gpu-arbiter: Steam games | โ |
GPU, CPU and RAM together | โ DRF | โ | โ slots | โ GPU only | โ |
Any mix of GPUs, pinned per card | โ NVIDIA/AMD/Intel | โ | โ | NVIDIA | โ |
Agent protocol (MCP + rules in agent instructions) | โ automatic, ~20 agents | partial (Claude only) | load-lock โ ~10 CLIs | partial | โ |
Market information for every agent | โ quotes, busy odds | partial: ETAs | โ | โ | โ |
Catches agents that skip the queue | โ adoption | partial: tags it | โ | gpulease: adopts, no limits | n/a |
Preemption ladder (pause โ suspend โ checkpoint โ kill) | โ | partial: requeue | โ | partial | โ |
One-command install, no cluster | โ | partial | โ | โ | โ |
Prior art was surveyed in Nov 2026 (about 65 projects read in full); nothing found does more than about half of this, and none on all three OSes. Details: docs/research.md.
FAQ
How do I stop several Claude Code or Codex agents from fighting over my GPU? Install
firefighter. New sessions read the rule block and register the MCP server, so they queue GPU work
through firefighter run or firefighter_submit and wait their turn.
Why do I get CUDA out of memory when two AI agents train at once? Each agent sees the whole card free and starts its own job, so together they ask for more VRAM than the card has. firefighter starts a GPU job only when its VRAM need fits on one card next to what's already running and your reserve; the need is learned from that command's past runs.
Can several AI agents share one GPU? Yes. They take turns, or run side by side when the card
has room (gpu.max_jobs per card). With more than one GPU, each card takes jobs on its own and a job
goes to the least busy card that fits.
Is there an MCP server for queuing GPU jobs? firefighter mcp, registered for every agent setup
finds. Tools: firefighter_submit, firefighter_wait, firefighter_status, firefighter_job,
firefighter_plan.
Will it slow down my games? It's designed to do the opposite. Fullscreen apps and 3D-engine use
switch you to the "game" state (on macOS and Linux, list your games in reserve.exclusive_apps).
Running GPU jobs get a cooperative pause; jobs that ignore it are suspended. If your game then needs
the memory a job holds, that job checkpoints (or, if it ignored the pause, is stopped) and requeues.
No new GPU jobs start until you're done.
Does it work with Docker and Kubernetes? Containers you run yourself count as your load and are
protected by the reserve. firefighter run -- docker run ... labels the container so firefighter can
pin, pause and stop it like any other job.
What if an agent ignores the rules? If an agent CLI starts something that stays heavy for 60 seconds outside firefighter, it gets adopted. It's put on idle priority, charged to its project, and evicted first under pressure.
Can agents cheat the market? Prices are posted, not auctioned, so there's no bidding game. A bid
of 10 costs double and buys at most 30 minutes of lead. Budgets belong to projects, so running more
jobs doesn't buy more turns. Runtimes are checked against each command's history. Agents can read
the policy but not change it unless you set guard.agents_can_configure. An agent with shell
access could still edit firefighter's files directly. firefighter is a referee for cooperative
agents, not a security boundary.
Does it need an NVIDIA GPU? No. It reads NVIDIA (nvidia-smi plus Windows GPU counters) and AMD (rocm-smi). On Apple silicon it schedules unified memory as RAM. Without a GPU it still schedules CPU and RAM.
Research
docs/how-it-works.md maps every paper's idea to the code that uses it, with the numbers, and lists what isn't implemented and why. The policy comes from a survey of about 40 repos and 30 papers. Among them: DRF (NSDI '11), Tiresias (NSDI '19), Themis (NSDI '20), Gavel (OSDI '20), Karma (OSDI '23), PerfIso (ATC '18), PilotFish (ATC '22), lottery and stride scheduling (OSDI '94), BOINC, KAI-Scheduler, AgentCgroup and AIOS. The full report with sources is in docs/research.md.
Testing
go test ./... runs the unit tests and an end-to-end suite. The suite builds the binary, starts a
real daemon, and scripts the human, memory pressure and a GPU through FIREFIGHTER_FAKE_FILE. It
covers GPU turns that never overlap, VRAM admission, game pause and resume, RAM-pressure checkpoint
and requeue, cancel, quotes and re-bids, adoption of rogue processes, daemon restart, the MCP server,
and setup/uninstall. CI runs it on Windows (x64 and ARM), macOS and Linux (x64 and ARM) VMs, then
tests both one-command installers.
Security notes
The guard,
setupand both installers refuse to run as administrator or root: any agent of yours can read the token and write its files, so anything elevated would lend those rights to every agent. It runs as you, binds only 127.0.0.1, and keeps its folder private (0700/0600 on Unix).It only acts on what a job's own client started (the caller is identified by its exact TCP connection, not by what it claims; only that client can start the job), on containers labeled for that job, and on processes adopted by you or, for its own session's work only, by an agent. Ancestry and ownership checks ignore reused pids. "You" means a caller whose unbroken process chain reaches a terminal window (Windows Terminal, iTerm, GNOME Terminal, ...; or sshd) with no agent CLI, script runtime (node) or IDE in between (
guard.human_hosts,guard.agent_hosts). The terminal must be installed by an administrator: the program and every folder above it owned by the system (root on macOS/Linux; TrustedInstaller, SYSTEM or Administrators on Windows), or a real sshd session started by root (a Linux text-console login, whose parent is init, doesn't count: an agent's detached process ends up there too). A terminal installed just for your user (a kitty or WezTerm download, Scoop, an app you dragged into /Applications, a Nix profile) doesn't count. The desktop shell, a classic console started from it, tmux and screen don't count either (an agent can open those silently); from them, add--forcefor other projects' jobs and foradopt. Anything else, including detached helpers and agents hosted in node or an IDE, is an agent session limited to its own work and its project; from an IDE terminal, add--forceto manage another project's job. An agent that opens a window in a terminal you already have running (wt.exe,open -a Terminal, a silentssh localhost) passes for you there too. These are guardrails against accidents, not a boundary against a hostile agent with your shell.firefighter_submitruns a command as you, outside an agent's own sandbox; its MCP annotations say so, so hosts can ask for approval as they do for a shell.Releases are built by GitHub Actions with SHA-pinned actions, the Go toolchain from go.mod, a locked npm toolchain for the extension, and least-privilege tokens, and carry signed build provenance. The installers check it automatically when the GitHub CLI is installed and signed in; by hand:
gh attestation verify firefighter_windows_amd64.zip --repo JoshWright22/FIREFIGHTER.Any agent can stop the guard (it's your process; it could kill it anyway). It comes back on the next firefighter call, and the new guard thaws anything the old one had suspended.
Not a sandbox: an agent with your shell can do anything you can. firefighter makes the polite path the cheap one and catches the careless one; it doesn't contain a hostile one.
Windows: a job's whole process tree is in a job object, so nothing it starts outlives it by accident. Shared build servers on the
guard.keep_alivelist (MSBuild nodes, VBCSCompiler, ...) are spared when the job ends normally; if its client is killed, they go with it.
Available Tools
5 toolsfirefighter_jobB
Change your job: extend (minutes = more lease), urgent / normal (tier, while waiting), cancel.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Job id | |
| action | Yes | extend | urgent | normal | cancel | |
| minutes | No | For extend |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden. It does add real behavioral context beyond structured fields: extend adds lease minutes, urgent/normal changes the job's tier while it waits. But it says nothing about whether cancel is destructive or reversible, what happens to a job already running, permission requirements, or error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short, front-loaded sentence with no filler; every clause maps to an action. The telegraphic phrasing ('tier, while waiting') is terse to the point of being cryptic, but it is not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations and no output schema, the definition covers what each action does at a high level and the parameters are fully documented in the schema. It falls short on consequences, state preconditions, and return behavior, which an agent would want before invoking a job-changing operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description genuinely adds meaning: it explains that minutes applies only to extend and translates the action values urgent/normal into a tier change. That clarification of conditional parameter relevance goes beyond the flat enum-free schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description says 'Change your job' and enumerates four actions (extend, urgent, normal, cancel), which gives a rough sense of a job-control tool. However, it never states what a 'job' is or what the overall effect of the call is, and it does not distinguish this tool from siblings like firefighter_wait or firefighter_plan. The intent is inferable but vague.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Parenthetical hints imply when each action applies: extend when more lease time is needed, urgent/normal to change tier 'while waiting', cancel to abort. That is implicit usage guidance per action, but there is no explicit when-not, no mention of prerequisites (e.g. must the job be in a waiting state?), and no routing to alternative sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firefighter_planB
Announce heavy work later so others plan around it (reserves nothing). done=true removes your project's plans.
| Name | Required | Description | Default |
|---|---|---|---|
| at | No | HH:MM or now | |
| done | No | Remove | |
| what | No | What | |
| gpu_pct | No | GPU % | |
| minutes | No | Minutes | |
| project | No | Project | |
| vram_gb | No | VRAM GB |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose two important behaviours: the plan reserves nothing, and done=true deletes the project's plans (a broader blast radius than a single record). It omits confirmation of idempotency, permissions, and what happens when all seven optional parameters are omitted. Useful but incomplete for an unannotated mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core purpose before the done=true deletion caveat. No wasted words, though the terseness edges toward under-specification rather than elegant brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a seven-parameter, unannotated tool with no output schema, the description leaves major gaps: what a 'plan' is, default values, which parameters are meaningful together, and what the call returns. It never states that all parameters are optional or what an empty call does. An agent could invoke it correctly only by guessing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is nominally 100%, so the baseline of 3 applies, but the schema descriptions are extremely thin ('What', 'Remove', 'Project'), adding little real meaning. The description does clarify done=true's effect at project scope and implies 'at' is a time-of-day or 'now'. Nothing explains how at, minutes, gpu_pct, and vram_gb interact.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: announcing future heavy work so others can plan around it, plus a removal mode via done=true. The parenthetical 'reserves nothing' implicitly separates it from firefighter_submit, though it never names that sibling directly. The dual create/delete behaviour in one tool slightly blurs the single stated purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It says the tool is for announcing work 'later', and that done=true removes plans, but gives no explicit when-to-use versus firefighter_submit, firefighter_job, or firefighter_wait, and no exclusion or prerequisite guidance. Routing is left entirely to inference from the tool names. An agent could easily confuse this with actually submitting work.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firefighter_statusARead-only
The shared machine in a few lines: the human, what runs until when, the queue, budgets, plans, do:. Pass minutes (and gpu) to also price a job without queuing it.
| Name | Required | Description | Default |
|---|---|---|---|
| gpu | No | ...on the GPU | |
| minutes | No | Price a job of this runtime | |
| project | No | Your project (folder name) | |
| vram_gb | No | ...needing this VRAM |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only annotations, it discloses the important behavior that pricing does not enqueue a job. It also sets expectations for a short, multi-section response, though operational details such as pricing freshness or data scope are not covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences front-load the status purpose and then introduce the optional pricing behavior without procedural filler. The telegraphic phrasing is efficient, but fragments such as "the human" and "do:" sacrifice some readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An agent can make a basic status call or request a non-queuing quote, and the description supplies some output expectations despite the lack of an output schema. However, opaque output terminology, incomplete parameter interactions, and no explicit sibling routing leave notable gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already describes all four parameters, the description adds the useful interaction that minutes, optionally with gpu, enables a pricing mode without submission. It does not similarly explain how project or vram_gb affect the status result or quote.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies two clear functions: a brief overview of the shared machine and an optional job-price estimate. It lists useful status contents and distinguishes pricing from queuing, although cryptic terms such as "the human" and "do:" reduce precision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for a basic status call and explicitly explains when to supply minutes and gpu for pricing. The phrase "without queuing it" helps distinguish this from submission, but it does not name sibling tools or explain when to prefer firefighter_job or firefighter_plan.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firefighter_submitADestructive
Queue heavy work (GPU, or CPU over ~1 min) on this shared machine. Returns one line: job id, start estimate, cost, do: (next step). Then call firefighter_wait. Runs the command as you, outside any agent sandbox, with your network and files: only submit what you'd run in your own shell.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | Yes | Absolute working directory | |
| gpu | No | Needs the GPU | |
| net | No | Network-heavy (downloads, uploads); known installers and downloads are detected | |
| name | No | '<project> <what>' | |
| spot | No | Leftover time only; 1/3 price, paused first | |
| ram_gb | No | Peak RAM GB, if known | |
| urgent | No | Only when the human waits on the result; 2x price | |
| command | Yes | Shell command | |
| minutes | Yes | High-end runtime guess; a lease, billed 2x past 1.25x | |
| vram_gb | No | Peak VRAM GB, if known | |
| gpu_vendor | No | GPUs the job can use: nvidia, amd, intel or any (default NVIDIA if present) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and openWorldHint=true, and the description adds meaningful context beyond them: the command runs as the user, outside any agent sandbox, with the user's network and files, plus an explicit caution to only submit what you'd run in your own shell. It also discloses the return shape ('one line: job id, start estimate, cost, do: (next step)'), so the agent knows what comes back and what to do next.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the core purpose and threshold, then sequencing, then the safety-critical caveat last. No filler, and each sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter destructive job-submission tool with no output schema, the description covers purpose, when to submit, sequencing, execution environment, and the shape of the response. It leaves unstated what happens on failure or how to poll progress outside of firefighter_wait, but the essentials for calling it safely are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter including cost modifiers (spot, urgent, minutes lease) is already documented in the schema. The description adds no parameter-level meaning beyond that; its remaining content concerns execution environment and return value, not argument semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Queue heavy work') and scopes it precisely with the inclusion threshold ('GPU, or CPU over ~1 min') and the shared-machine context. It is clearly distinguishable from siblings by naming firefighter_wait as the immediate follow-up.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete use condition (heavy work: GPU, or CPU over ~1 min) and an explicit next step ('Then call firefighter_wait'), which routes the agent correctly after submission. It stops short of stating when not to use it (e.g. short CPU work, or when firefighter_plan/status is the better starting point), so it is not fully explicit about alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
firefighter_waitARead-only
Wait up to ~45 s on a job. One line, short if nothing changed; receipt and log tail when done.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Job id | |
| timeout_s | No | Seconds, max 50 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, the description discloses the blocking behavior, the approximate maximum wait, and two distinct return shapes ('one line, short if nothing changed' versus 'receipt and log tail when done'). It stops short of saying what is returned if the timeout elapses without a state change.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact clauses with the wait scope front-loaded and the outcome variants second; there is no filler and every clause conveys information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully sketches the return values, and it covers the timeout dimension. The main remaining gap is the timeout-expiry case, which an agent would need to interpret the 'short if nothing changed' result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented; the description only reinforces timeout_s with '~45 s', and that figure is slightly at odds with the schema's stated max of 50. Baseline 3 applies since the schema carries the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Wait ... on a job') plus a rough duration, so an agent knows this blocks until progress or completion. It does not, however, explicitly contrast itself with siblings like firefighter_status or firefighter_job, which also inspect a job.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'Wait up to ~45 s on a job' implies the use case (blocking until a job advances or finishes) versus one-shot polling, but there is no explicit when-to-use/when-not guidance or named alternative among the siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
firefighter_job - First observed
firefighter_plan - First observed
firefighter_status - First observed
firefighter_submit - First observed
firefighter_wait
TDQS
Scored across 5 tools
Each tool covers a distinct phase of the job lifecycle: submit queues work, wait blocks for completion, status reports the machine, job mutates an existing job, and plan announces future intent. The only mild overlaps are wait vs. status (both surface job state) and status's pricing mode vs. submit, but the descriptions make the boundaries clear enough.
All tools share a consistent firefighter_ prefix, giving a predictable namespace. The suffixes mix verbs (submit, wait) with nouns (status, job, plan), so the pattern isn't a pure verb_noun scheme, but it is readable and internally coherent.
Five tools is well-scoped for a shared-machine job queue: submit, wait, inspect, modify, and plan. Each tool maps to a real user need with no filler.
The surface covers the full lifecycle: queue, poll, inspect, mutate (extend/tier/cancel), and pre-announce plans. Minor gaps existโno explicit way to list your own jobs or fetch full logs on demand (logs surface only via wait's tail), but agents can work around this with status and repeated waits.
Maintenance
Related MCP Connectors
HiveCompute MCP Server โ decentralized inference router for AI agents
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
Real-time chat hub for AI agents โ Claude Code, Cursor, Cline, Codex over MCP or REST.
AI cloud for agents: launch GPUs, run jobs that stop their own billing, schedule runs.
Related MCP Servers
- AlicenseBqualityDmaintenanceagent-mq is a message queue that enables AI coding agents to communicate with each other across sessions and machines. Agents can send messages, delegate tasks, and coordinate work โ all through MCP tools. Supports Claude Code, Cursor, Codex, OpenClaw, and any MCP-compatible tool. UUID-based authentication with per-user data isolation. Self-hostable with Docker.72MIT
- AlicenseNot gradedqualityCmaintenanceA local MCP server that connects AI coding agents (Claude Code, Codex, Cursor, etc.) on the same machine via a shared message bus, enabling them to chat, delegate tasks, and collaborate privately without cloud or internet.73 npmMIT
- AlicenseAqualityAmaintenanceEnables AI agents to delegate scoped tasks across multiple providers like Codex, Claude Code, and Antigravity through a single local MCP server, with quota monitoring, notifications, and remote control via messaging apps.132Apache 2.0
- AlicenseNot gradedqualityAmaintenanceMCP server that turns multiple home computers into a fleet for AI coding agents, enabling task delegation and LAN-based execution with local models.1Apache 2.0