How to set GPU budget caps over remote MCP
An MCP client can start a budgeted rental or Job only after the owner approves a live quote and, when a budgeted agent key is used, after the owner approves that key. max_spend_usd, max_hours, and idle_minutes are budget limits the owner chooses, not GPU sale prices. The MCP guide says CloudGPU’s servers destroy the instance when one of the limits that rental carries is reached, and a GPU spend cap does not pay for storage.
Preconditions
The owner authorizes the MCP connection first. Remote Streamable HTTP is https://cloudgpu.app/mcp. Local stdio is the published cloudgpu-mcp 0.16.3 package. Setup is in the MCP guide. After authorization, read the tool list that session returns. Local and remote tool sets differ. Remote orchestration does not read local files or provide local SSH transfers. If a name below is missing, skip it.
Call get_account and list_instances before a new allocation. Reuse a compatible running rental when the remaining caps still cover the work. A row from list_gpus is not proof that a cap configuration has been accepted for a particular task. compare_compute_costs, when listed, compares billed GPU cost for explicit candidates. It does not approve a cap or start a GPU.
Read GET /v1/public/compute-capabilities before relying on storage or Job output collection. On 2026-11-15 that document reported storage true, automatic_output_collection true, and full_disk_restore false. It does not list budget-cap fields.
Owner limits and key limits
A static page or an account login is not an approval. On remote MCP, the owner checks spending limits on the OAuth approval page in the MCP guide. Connecting an account or adding funds does not approve a paid task.
On local stdio, when connect_account is listed, pass the spending limit the owner chooses, then finish_connect only after they approve the link. The 0.16.3 schema fields are agent_name, spend_limit_usd, max_concurrent, and expires_in_days. max_concurrent defaults to 1 and accepts 1 through 10. expires_in_days defaults to 30 and accepts 1 through 90. spend_limit_usd is the key total the owner chooses. The schema accepts 1 through 10000. That range is a field constraint, not a GPU price and not the number to copy.
{
"agent_name": "<name the owner will recognize>",
"spend_limit_usd": "<example key spending limit the owner approved>",
"max_concurrent": 1,
"expires_in_days": 30
}
The agent guide says that key is refused on CloudGPU’s servers when a job or instance would take its total spend over spend_limit_usd (403 key_budget_exceeded). Unfinished jobs and instances count at their max_spend_usd. Finished ones count at what they cost. Every request with this key must set max_spend_usd (400 max_spend_required when it is missing). The same key is refused at max_concurrent running jobs or instances (429 key_concurrency_exceeded), and when it has expired or been revoked (401). The agent guide says the token poll returns expired_token after 10 minutes. finish_connect follows the expires_in value on the connect response. A higher key limit is a new owner approval. It does not change caps already set on a running rental.
Local stdio also has CLOUDGPU_MAX_SPEND_USD and CLOUDGPU_MAX_HOURS. The MCP guide documents them as the ceiling on what the assistant may set, with defaults 50 and 24. Those defaults are not GPU sale prices and are not the values to send. The 0.16.3 client refuses a max_spend_usd or max_hours above the configured ceiling before the request is sent. Remote MCP does not apply those environment variables. CLOUDGPU_READ_ONLY=1 registers only the look-up tools, so the create tools are absent.
Quote, then attach the caps
Show the owner the quote before any create. Billing terms come from that quote: minute or started-hour, preauthorization, and the minimum. The pricing page is the billing source. This page does not restate amounts. The budget must cover the minimum on the quote. within_budget on a server quote compares the estimate with max_budget_usd. The agent guide says that flag does not mean the task can start.
estimate_cost is the quote create_instance accepts. In cloudgpu-mcp 0.16.3 its quote_id is a local id of the form q_ plus 12 hex characters. The client keeps that wrapper for 15 minutes, then rejects it and tells you to call estimate_cost again. quote_compute is a separate five-minute server quote. Its description says to pass that quote_id to run_job. Pass each id only to the tool that issued it.
The agent guide sets a server quote’s expires_at 5 minutes after the quote is issued. billing_quote_id in the 0.16.3 Job schema is described as expiring after five minutes. Those server clocks are not the 15-minute local wrapper. create_instance fails when the billing quote stored inside the local wrapper has expired, even if the wrapper’s own 15 minutes have not elapsed. The recovery is another estimate_cost and a new approval.
Read billing_increment_seconds, minimum_charge_usd, preauthorized_usd, and billing_description on the estimate_cost result. suggested_max_spend_usd, when present, is not the owner’s approval and is not a GPU sale price. Set user_confirmed to true only after the owner approves that quote and the caps.
{
"quote_id": "<quote_id from that estimate_cost>",
"user_confirmed": true,
"max_spend_usd": "<example budget cap the owner approved>",
"max_hours": "<example hour cap the owner approved>",
"idle_minutes": 60
}
max_spend_usd and max_hours in that call are the example budget limits the owner chooses. idle_minutes 60 is the schema default, not a value the owner must copy. The schema allows 0, which turns the idle limit off, or an integer from 10 through 1440. Installing packages and downloading models count as idle, so the owner can set a higher value on this create call when that work needs longer than the default. max_spend_usd and max_hours still apply when idle is turned off. The 0.16.3 client sends max_minutes as the ceiling of max_hours times 60. The MCP input is max_hours, not max_minutes. create_instance also refuses the call when max_spend_usd is below the minimum stored from estimate_cost.
On local stdio, create_instance does not take billing_quote_id or billing_accepted. After user_confirmed is true, the client attaches the billing quote that estimate_cost stored. If the session schema lists those fields, pass billing_quote_id only when the response you just received contains it, and set billing_accepted to true only after the owner accepts that quote’s minimum and billing period. create_instance is not idempotent. The local client deletes the quote_id when the call takes it, so the same id cannot be sent again. The agent guide says POST /v1/gpu/instances has no idempotency key and the same request sent twice can start two machines. If the call times out, use list_instances and look for an instance already created with that GPU before calling create_instance again.
run_job uses the same max_spend_usd and max_hours fields. It does not take idle_minutes. Pass quote_id from quote_compute when that tool is listed. For a whole-hour source, the MCP guide says the Job also needs billing_quote_id and billing_accepted true, from estimate_cost or POST /v1/gpu/billing-quote, in addition to the compute quote. Omit billing_quote_id when the response does not contain it. Send a stable idempotency_key and the same body on retry. If you omit the key, 0.16.3 generates one and returns it. Keep that returned value. The same key with a different body is 409 idempotency_key_reused in the agent guide. A new key is a new Job.
{
"quote_id": "<quote_id from quote_compute>",
"billing_quote_id": "<billing_quote_id only when the quote response contains it>",
"billing_accepted": true,
"user_confirmed": true,
"max_spend_usd": "<example budget cap the owner approved>",
"max_hours": "<example hour cap the owner approved>",
"idempotency_key": "<stable key for this submission>",
"command": "<the command the owner approved>"
}
Set billing_accepted to true in that Job body only after the owner accepts the billing quote. Leave the field and billing_quote_id out when the response has no billing_quote_id.
When a cap is reached
The MCP guide says every instance the MCP server rents carries max_spend_usd, max_hours, and, by default, a 60-minute idle limit. CloudGPU checks them every minute and destroys the instance when one is reached, whether or not the client is still connected. The agent guide uses the same destroy wording for max_minutes, max_spend_usd, and idle_minutes on POST /v1/gpu/instances. The 60-minute figure is that documented default, not a second cap the owner has to copy.
For a Job, max_spend_usd and max_hours are the limits the servers enforce. The agent guide says stopping means the command finished, or a limit or a cancel was hit, and the GPU is being destroyed. failed with time_limit_reached or spend_limit_reached is a limit. needs_attention means CloudGPU stopped the job because it could not confirm the state of its GPU after an error. It is not retried automatically. Do not resubmit it with a new key. A lost response or an ambiguous state does not authorize another allocation. Poll the original Job or instance id.
Downloads and setup count against the same caps. Idle time includes installing packages and downloading models. A cap reached during that work destroys the instance, or fails the Job at the limit, and does not keep the partial download as a new rental. Cancellation, budget exhaustion, or storage failure can prevent output collection. GPU release still proceeds, and that failure does not authorize another allocation. Saving the files is a separate step in How to save GPU results over remote MCP.
402 insufficient_balance means the balance does not cover required_starting_balance. Ask the owner to add funds. Do not retry the create until it does. request_top_up, when listed, returns a payment link for the owner. Payment is not approval of the quote.
Reuse the same rental
Reuse the same instance_id only while list_instances or get_status shows it running and the next command stays inside the original max_spend_usd, max_hours, and idle_minutes. get_status reports the auto-shutdown limits. cloudgpu-mcp 0.16.3 has no tool that changes those three fields on a running instance. Do not keep an idle GPU running only to consume time that was already authorized. Copyable lookup steps for that running rental are in How to reuse a running GPU over remote MCP.
run_job and prepare_job_rerun provision separately. prepare_job_rerun reads parameters from a successful Job. It does not start a GPU, and it does not reuse the old quote or the old idempotency key. A new Job needs a fresh quote and a new approval. Server batches, when run_server_job_batch is listed, keep a spending and time limit on each child. The MCP guide is the batch reference. Storage charges stay outside those GPU caps.
Storage is separate
GPU caps do not pay for storage or for retaining files. Leave accept_storage_charges false unless the owner has agreed to paid storage. A budget-limited agent key cannot consent to paid storage. quote_storage_budget and confirm_storage_budget, when listed, move wallet funds only after a separate owner approval. They are not part of max_spend_usd.
Read get_storage when it is listed. Otherwise use authenticated GET /v1/storage. The parameter walkthrough for keeping files is How to save GPU results over remote MCP.
Exceptions
An expired server quote does not start a GPU. Call estimate_cost or quote_compute again, show the new quote, and wait for another approval. Do not treat the 15-minute local quote_id wrapper as a substitute for the five-minute server quote.
create_instance is not idempotent. run_job is retried only with the same idempotency_key and the same body. A cap reached mid-download still ends that rental or Job. Collection can fail and the GPU can still be released. A budget-limited agent key cannot consent to paid storage while the docs still say so.
Related
Rent, reuse, and release boundaries are in the rent-and-reuse guide. Quotes and Jobs are in GPU Jobs for AI agents and the quote and reuse note. A ComfyUI start path that already includes these cap fields is How to run ComfyUI over remote MCP. Tool rules are in AGENTS.md. Enforcement wording is in the MCP guide and the agent guide.
Questions and answers
Are the cap numbers GPU sale prices?
No. max_spend_usd, max_hours, and idle_minutes are limits the owner chooses for that rental or Job. They are not the GPU sale price. The live quote supplies the billing increment, the minimum, and the preauthorization. The pricing page is the billing source. The documented local defaults for CLOUDGPU_MAX_SPEND_USD and CLOUDGPU_MAX_HOURS are ceilings on what local stdio will send, not prices to copy into the create call.
Do the caps pay for storage?
No. max_spend_usd bounds GPU spend for that Job or instance. Storage has its own eligibility, quota, retention, and charges. Read get_storage when it is listed, or authenticated GET /v1/storage. Leave accept_storage_charges false unless the owner agrees. A budget-limited agent key cannot consent to paid storage.
What if the quote expires before create?
An expired quote does not start a GPU. The agent guide sets expires_at on a server quote to 5 minutes after issue, and quote_compute is a five-minute server quote. The local stdio quote_id from estimate_cost is a separate wrapper that cloudgpu-mcp 0.16.3 rejects after 15 minutes, and create_instance also refuses when the billing quote stored in that wrapper has expired. Call the quote tool again and wait for a new approval. create_instance is not idempotent.
Can the agent raise caps on a running rental?
No. cloudgpu-mcp 0.16.3 has no tool that changes max_spend_usd, max_hours, or idle_minutes on a running instance. Reuse that instance_id only while it is running and the work stays inside the original caps. A higher key limit is a new owner approval through connect_account, and that approval does not raise the caps already set on a running rental. run_job and prepare_job_rerun provision separately and need a fresh quote and approval.