Xcelsior GPU Cloud

io.github.aabiroPublished by GitHub account aabirov2.0.1Updated Nov 5, 2026

Rent GPUs, launch spot instances and run serverless inference on the Xcelsior marketplace.

VerifiedStreamable HTTPWeb executableCloud & InfrastructureFinanceAI & ML

Overview

AI-generated overview

Xcelsior's hosted GPU marketplace server: lets an assistant compare live GPU rates, rent or cancel instances, run training jobs and serverless inference, and…

What you can do
  • Discover and price hardware: list available GPUs, spot and on-demand rates, tiers, and search marketplace listings by VRAM, region or host reputation
  • Rent and manage compute: prepare and execute instance launches, list and inspect instances, read logs, cancel or terminate, and open SSH or terminal access
  • Run workflows: end-to-end training launches, budget-capped scheduling, multi-stage pipelines, and serverless inference endpoints and jobs
  • Track money: wallet balance and history, invoices, cost estimates, spend envelope, and affordability verdicts before launching
  • Fund and control spending: card top-ups, auto top-up settings, crypto and Lightning deposits, pending verifications, and saved…
When to use it
Useful when someone wants an assistant to find and rent GPU capacity, launch or monitor training and batch jobs, deploy per-token inference, or check and fund what they are spending on Xcelsior without leaving the chat.
Requirements
Remote endpoint at mcp.xcelsior.ca over streamable HTTP with OAuth consent, or the npm package run with npx on Node.js 20.20+ or 22.22+. The stdio package needs an XCELSIOR_ACCESS_TOKEN from the dashboard; headless automation uses a machine client with client credentials. An Xcelsior account with a funded wallet is needed for paid actions.
Before you install
Many tools spend real money in CAD: launching instances, pipelines, serverless endpoints and per-token jobs, card top-ups and auto top-ups that charge a saved card unattended. Cancel, terminate, key deletion and plan revocation change or destroy resources, so use the confirm:false preview first. SSH public keys only, never private keys. Optional PostHog analytics is metadata-only per the README but identifies users by account id.

Installation

In SourceWeft

  1. Open Xcelsior GPU Cloud in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.aabiro%2Fxcelsior/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "xcelsior-gpu-cloud": {
      "type": "http",
      "url": "https://mcp.xcelsior.ca/mcp"
    }
  }
}

README

Xcelsior MCP Server

Hosted Model Context Protocol server for the Xcelsior GPU platform.

Requires Node.js ^20.20.0 or >=22.22.0 (the pinned PostHog MCP beta no longer supports Node 18).

Quick start (local)

bash
cd mcpnpm ciXCELSIOR_MCP_API_URL=http://127.0.0.1:8000 npm run dev

Liveness: GET http://localhost:8770/health Readiness: GET http://localhost:8770/readyz MCP endpoint: http://localhost:8770/mcp

Compare source declarations with production

bash
npx tsx scripts/check-live-surface.ts /path/to/private/token-file

The file contains a bearer token or an agent-key JSON response. The checker authenticates, lists tools, and compares names, annotations and output-schema presence with the customer registry in this checkout. It never invokes a tool handler or prints the token. This gives monorepo-aware coverage when a source scanner cannot discover the registrations; it does not prove handler behavior.

Connecting

The canonical connector URL is https://mcp.xcelsior.ca/mcp.

Default path — OAuth consent (what humans use)

Paste that URL into Claude, ChatGPT, Grok, Copilot Studio, Cursor, or VS Code and press connect. The client discovers everything it needs on its own:

  1. It calls /mcp with no credentials and gets 401 plus WWW-Authenticate: Bearer realm="xcelsior", resource_metadata="…".
  2. It fetches /.well-known/oauth-protected-resource, which names the authorization server and the exact resource identifier.
  3. It identifies itself — by CIMD (preferred: client_id is an HTTPS URL serving the client's own metadata), by RFC 7591 dynamic registration at /oauth/register, or with the pre-provisioned public client xcelsior-connector.
  4. You sign in and approve the requested scopes on Xcelsior's own consent screen. Approval is remembered per client, per scope set, per resource, and is revocable in Settings → AI Agents.
  5. It exchanges the code with S256 PKCE at /oauth/token (application/x-www-form-urlencoded) for a ~1h access token bound to https://mcp.xcelsior.ca/mcp, plus a 30-day refresh token.

No client secret is involved, and nothing has to be pasted by hand.

Automation path — client_credentials

For CI, scripts, and headless agents where no human is present to consent. Create a machine client in Dashboard → Settings → Connect AI Agents, then:

bash
curl -s -X POST https://xcelsior.ca/oauth/token \  -H 'Content-Type: application/x-www-form-urlencoded' \  -d 'grant_type=client_credentials' \  -d 'resource=https://mcp.xcelsior.ca/mcp' \  -d "client_id=$MCP_CLIENT_ID" -d "client_secret=$MCP_CLIENT_SECRET"
json
{  "mcpServers": {    "xcelsior": {      "url": "https://mcp.xcelsior.ca/mcp",      "headers": { "Authorization": "Bearer YOUR_ACCESS_TOKEN" }    }  }}

client_credentials is fully supported and is not going away — it is simply not the front door for a person connecting an assistant.

Resource identifier

https://mcp.xcelsior.ca/mcp — the exact URL a user pastes, path included. Protected-resource metadata, the resource parameter on authorization and token requests, and the aud claim all carry that one value. Tokens issued before the migration carry the bare origin https://mcp.xcelsior.ca and remain valid until 2026-11-30, after which they are rejected like any other wrong-audience token.

Trust surfaces

One codebase, one image, two exposed surfaces (XCELSIOR_MCP_TOOL_PROFILE):

ProfileWhereTools
customer (default)https://mcp.xcelsior.ca/mcp, submitted to directoriesTenant workflows only
operatorSeparate unlisted hostAdds platform-global host and control-plane tools

Operator tools are not registered at all under the customer profile, so they cannot appear in tools/list and cannot be called by name. A token without operator scopes never enumerates them even on the operator host.

Environment

VariableDefaultDescription
XCELSIOR_MCP_API_URLhttp://127.0.0.1:8000Upstream FastAPI base URL
XCELSIOR_MCP_RESOURCE_AUDIENCEhttps://mcp.xcelsior.ca/mcpCanonical RFC 8707 token audience
XCELSIOR_MCP_LEGACY_RESOURCE_AUDIENCEorigin of the abovePre-migration audience, accepted until sunset
XCELSIOR_MCP_LEGACY_AUDIENCE_SUNSET2026-11-30T00:00:00ZWhen the legacy audience stops being accepted
XCELSIOR_MCP_RESOURCE_METADATA_URLderivedWhat the 401 challenge points at
XCELSIOR_MCP_TOOL_PROFILEcustomercustomer or operator
XCELSIOR_MCP_COMPANY_KNOWLEDGE0Register ChatGPT company-knowledge search/fetch
XCELSIOR_MCP_POSTHOG_PROJECT_API_KEYbrowser project key, then disabledPostHog phc_ project key for MCP analytics
XCELSIOR_MCP_POSTHOG_HOSTbrowser host or https://us.i.posthog.comPostHog ingestion host
XCELSIOR_DOCS_URLhttps://docs.xcelsior.caDocumentation corpus for company knowledge
MCP_HOST0.0.0.0Bind address
MCP_PORT8770Listen port
MCP_PATH/mcpHTTP path
MCP_RATE_LIMIT_PER_MIN60Per-token tool call budget

MCP analytics

@posthog/mcp is pinned to 0.11.4 because its pre-1.0 API may change. When a PostHog project key is configured, the server instruments both hosted HTTP and STDIO MCP traffic and emits the standard $mcp_* lifecycle/tool events. The authenticated Xcelsior user_id is used as distinct_id (with OAuth subject and tenant id as machine-principal fallbacks), so calls remain grouped across the hosted service's stateless per-request server instances.

Analytics is metadata-only: Xcelsior removes tool arguments, tool results, and exception messages before send, disables GeoIP and exception fan-out, and does not inject PostHog's context or conversation_id arguments into the reviewed tool schemas. The Streamable HTTP transport uses JSON responses so the SDK can carry its signed Mcp-Session-Id token across replicas. The shared posthog-node client is flushed during graceful shutdown.

If MCP analytics identifies users, production must also set XCELSIOR_POSTHOG_PERSONAL_API_KEY and XCELSIOR_POSTHOG_PROJECT_ID for the privacy-deletion worker. Startup validation rejects identification without those deletion credentials.

Tools (v2)

  • Discovery: list_available_gpus, get_spot_prices, get_pricing_reference, search_marketplace, list_tiers
  • Compute: list_instances, get_instance, get_instance_logs, create_instance, cancel_instance, terminate_instance
  • Billing: get_wallet_balance, estimate_job_cost, list_invoices
  • Guardrails: should_i_run_this (estimate + wallet + optional max_hourly_cad)
  • Workflows: run_training_job, schedule_under_budget
  • Serverless: list_serverless_endpoints, create_serverless_endpoint, run_serverless_job, get_serverless_job_status
  • Monitoring: watch_instance (poll status + telemetry + logs)
  • Diagnostics: explain_instance_placement, simulate_instance_placement, get_instance_timeline, get_active_lease, get_mcp_action_status
  • Operations (tenant): retry_instance, reconcile_instance

Operator profile only: get_scheduler_health, get_host_capacity, list_reconciliation_findings, drain_host, undrain_host, evict_host_workloads, retry_agent_command.

Company knowledge (optional, off by default): search and fetch, with OpenAI's exact schemas, over the documentation site, llms.txt, the pricing table, and live marketplace listings. Every result carries an absolute, human-openable URL and an internal id. Enable with XCELSIOR_MCP_COMPANY_KNOWLEDGE=1; it is deliberately not on for the base directory submission.

Resources: xcelsior://docs/llms, xcelsior://pricing/reference Prompts: cheapest-gpu-now, ca-fine-tune, serverless-inference

create_instance and create_serverless_endpoint always create a server-bound action plan first. confirm:true expresses intent but never replaces approval; execute with the returned plan_id after standing-policy or human approval. A confirmed call without a plan safely prepares a plan and returns approval_required. Host draining never evicts workloads; eviction has its own scope and action plan.

Stdio package (v2)

bash
npx @xcelsior-gpu/mcp

Requires XCELSIOR_ACCESS_TOKEN. See mcp-cli/README.md.

Production deploy

Production promotion is blue/green across ports 8770/8771. Deployment runs readiness, bearer-authenticated protocol initialize, and tools/list against the standby before switching Nginx; a failure leaves the previous MCP serving.

Staging smoke

bash
MCP_CLIENT_ID=... MCP_CLIENT_SECRET=... python3 scripts/mcp_smoke.py

Test with MCP Inspector

bash
npx @modelcontextprotocol/inspector@latest

Point at http://localhost:8770/mcp with your MCP-audience Bearer token.

Source: api/mcp/README.md at commit bedf284

Tools

86

list_available_gpus

List GPUs currently offered by independent hosts on the Xcelsior marketplace, with VRAM, region, available count, and CAD hourly rate. Use when the user asks what hardware is available, or before launching anything, to find a real GPU model and region rather than assuming one. Read-only and free. Inventory is third-party and changes continuously, so a result from earlier in the conversation may already be stale.

Parametersregion

get_spot_prices

Get live interruptible (spot) hourly rates in CAD for each GPU model. Use when the workload can checkpoint and resume, which is most training and batch work — spot is materially cheaper than on-demand and is the right default there. Do not use for a workload that cannot tolerate preemption. Read-only and free; prices are set by competing third-party hosts and move throughout the day.

Takes no parameters.

get_pricing_reference

Get Xcelsior's on-demand hourly rate table in CAD, by GPU model. Use when quoting a price or comparing models, instead of estimating a rate from memory. Read-only and free. This is the reference table, not a quote for a specific host — call estimate_job_cost for what a particular job will actually cost.

Takes no parameters.

search_marketplace

Search live marketplace listings by GPU model, minimum VRAM, region, and host reputation, sorted by price, reputation, region, or VRAM. Use when the user has a constraint to satisfy — a region, a VRAM floor, a trusted host — rather than just wanting to see what exists. Read-only and free. Listings belong to independent hosts and change without notice.

Parametersregionsort_bygpu_modelmin_vram_gbmin_reputation

list_tiers

List Standard, Premium and Dedicated service tiers and their queue and isolation policies. Supply gpu_model to include exact Stripe Prices, the optional GPU-only exclusivity add-on and qualified whole-host GPU counts. Use before choosing a paid launch tier. Read-only and free.

Parametersgpu_modelpricing_mode

get_wallet_balance

Get the account's wallet balance and available credits in CAD. Use before committing to spend, or when the user asks what they have left. Read-only and free.

Parameterscustomer_id

get_wallet_history

List the wallet's transactions — deposits, charges and refunds, newest first, each with an amount and what it was for. Use when a balance is lower than expected, or the user asks where their money went or what they were billed for: get_wallet_balance returns the number and this is the only tool that explains it. For what the balance will do next rather than what it did, use get_spend_envelope, which answers burn rate and runway. Returns one page with `total` and `next_cursor`; pass that cursor as `before` for older transactions, and stop when it is null. Read-only and free.

Parameterslimitbeforecustomer_id

list_funding_options

List the ways this account can add funds, and which are working right now: card, Bitcoin, Lightning and PayPal, with the current BTC rate when crypto is available. Use when a card is declined or the user has none on file, and before telling anyone they must visit the dashboard — the crypto and Lightning rails need no browser at all, so a refused charge is usually not a dead end. A rail can be configured and still be unavailable, so report what `available` says rather than what `enabled` says. Read-only and free; it creates no deposit and moves no money.

Takes no parameters.

create_crypto_deposit

Create a Bitcoin deposit and return the address to send to, the exact BTC amount, and when the quoted rate expires. Use after list_funding_options shows crypto available and the user wants to fund without a card or a browser — this is the whole rail, no dashboard step. It creates a request, it does not move money: nothing is added until the user sends the coins and the network confirms, which get_crypto_deposit reports. Safe to retry with the same idempotency_key; retrying with a different amount under a key already used is refused rather than quietly creating a second deposit. The rate is locked only until it expires, so state the amount and the deadline back to the user. Needs billing:write.

Parametersamount_cadrequiredcustomer_ididempotency_key

get_crypto_deposit

Check a Bitcoin deposit: whether the coins arrived, how many confirmations, and whether the wallet has been credited. Use after create_crypto_deposit to tell the user where their funding is, and prefer it to guessing from get_wallet_balance — an unconfirmed deposit is not a balance yet, and the difference is why the number has not moved. The deposit_id comes from create_crypto_deposit. Read-only and free.

Parametersdeposit_idrequired

create_lightning_deposit

Create a Lightning invoice to add funds, returning the BOLT11 invoice to pay and when it expires. Use when the user wants to fund over Lightning rather than on-chain — it settles in seconds instead of waiting for block confirmations, which is the reason to prefer it. Check list_funding_options first: this rail can be configured and still be down, and it answers 503 when it is. It creates an invoice, it moves nothing until the invoice is paid. Safe to retry with the same idempotency_key; a different amount under a key already used is refused rather than creating a second invoice. Needs billing:write.

Parametersamount_cadrequiredcustomer_ididempotency_key

get_lightning_deposit

Check a Lightning deposit: whether the invoice was paid and whether the wallet has been credited. Use after create_lightning_deposit rather than inferring from get_wallet_balance, which cannot tell an unpaid invoice from a paid one that has not settled. The deposit_id comes from create_lightning_deposit. Read-only and free.

Parametersdeposit_idrequired

get_spend_envelope

How long the balance lasts at the current burn rate, and which instances are consuming it. Returns balance, burn rate per hour, seconds until zero, and a per-instance breakdown. Use before starting long unattended work, when the user asks how long they can keep running, or when deciding whether to top up. Read-only and free. At zero the platform stops running instances automatically with reason 'low_balance' — work is interrupted, not merely billed. If auto-top-up is configured it charges first; check get_wallet_balance for that. This projects the *balance*, not the *work*: nothing here estimates when a job will finish, because instances run until stopped. Treat the runway as 'how long before it stops if nobody acts', not 'whether the job will make it'.

Parameterscustomer_id

estimate_job_cost

Estimate what a GPU job will cost in CAD: hourly rate and projected total for the duration, on-demand by default or spot when the workload can checkpoint. Use when the user asks what something would cost. Read-only and free — it estimates only. If you are about to launch, call should_i_run_this instead, which also checks the balance.

Parametersspotgpu_modelduration_hours

list_invoices

List the account's billing invoices with their periods and amounts in CAD. Use when the user asks what they have been charged or wants a specific invoice. Read-only and free.

Parameterscustomer_id

configure_auto_topup

Set up or change automatic wallet top-ups: when the balance falls below the threshold, the saved card is charged for the amount, without anyone present. Use this when the user wants to stop running out mid-job, or asks to change, pause or stop existing auto top-ups. Call it with enabled=false to turn it off. CHANGES UNATTENDED SPENDING: raising the amount or the threshold means larger or more frequent charges that happen with nobody watching, so state the new numbers back to the user and get their agreement before calling. Lowering them or disabling needs no such care — it only ever reduces what can happen. Every change is recorded on the account, and the response includes the previous settings so you can tell the user exactly what changed. Raising a cap is two calls, lowering one is a single call. When a widening needs approval the response comes back with preview:true, a plan_id and an approval_url instead of a change: send the user to that URL, then call this again passing plan_id and nothing else. The settings are taken from the approved plan rather than the second call, so an approval cannot be spent on different numbers.

Parametersenabledrequiredplan_idamount_cadrequiredthreshold_cadrequiredpayment_method_id

top_up_wallet

Charge a card already saved on the account and credit the wallet. Use this when the user asks to add funds — 'put $20 on my account', 'top me up' — or when a balance check shows they will run out mid-job. Say the amount in CAD; identify the card the way the user did — 'the Visa', 'the one ending 4242' — using card_brand and/or card_last4, or omit both to use their default card. Call list_payment_methods first if you are unsure what is on file. MOVES REAL MONEY: confirm the amount with the user before calling, and never retry a call that timed out without passing the same idempotency key — the charge may already have gone through. If more than one saved card matches, this refuses and lists them rather than guessing; ask which one. If the bank requires verification the card is NOT charged and a link is returned for the user to confirm in a browser — list_pending_verifications shows later whether that was ever done, which a balance check cannot tell you. The wallet is credited when the payment processor confirms, moments later — not when this returns, so do not report a new balance you have not read.

Parametersamount_cadrequiredcard_brandcard_last4idempotency_keypayment_method_id

list_payment_methods

List the cards already saved on the account: brand, last four digits, expiry, and which one is the default. Use when the user asks what is on file, or before a top-up so you can name the card — 'the Visa ending 4242' — rather than guessing. Read-only and free. Cards are added by the user in the dashboard, never here; this reads what is already there and returns no card number and no secret.

Takes no parameters.

get_auto_topup

Show the current automatic top-up settings: whether it is on, the balance that triggers a charge, and how much is charged. Use when the user asks what their auto top-up is set to, before changing it so you can state what is changing, or when a wallet was topped up with nobody present and they want to know why. Read-only and free — configure_auto_topup is what changes them, and calling that to find out the current values would alter the unattended spending you were only trying to read.

Takes no parameters.

list_pending_verifications

List top-ups that stopped because the cardholder's bank wants them to confirm — the money has not moved and the wallet was not credited. Use when a user asks whether a top-up went through, when a balance is lower than they expect after topping up, or when top_up_wallet returned a verification link earlier in the conversation and you need to know whether it was ever followed. A balance check cannot answer this: an unconfirmed charge looks identical to one that was never attempted. Read-only and free, and it returns no credential — completing the challenge happens in a browser, from the link the user was given, and nothing here can finish a payment on their behalf.

Takes no parameters.

list_instances

List the authenticated account's GPU instances, optionally filtered by status, with cursor pagination. Use when the user asks what is running, what they are being billed for, or to find a job_id for another tool. Read-only and free; it does not affect running work.

Parameterslimitcursorstatus

get_instance

Get the full record for one instance by job_id: status, host, GPU, pricing mode, and timestamps. Use when the user asks about a specific job, or after a launch to confirm what was actually allocated. Read-only and free.

Parametersjob_idrequired

get_instance_logs

Get the most recent buffered log lines an instance has printed — its output, stdout and stderr. Use when the user asks what a job is printing, what it is doing right now, or why it failed; the instance id can come from earlier in the conversation rather than from a fresh listing. It returns a snapshot, so call it again for newer output rather than expecting a stream. Read-only and free. If the user asks to be told when the job finishes, or to be notified on completion or failure, that is watch_instance — this tool returns immediately and will not wait for anything.

Parameterslimitjob_idrequired

create_instance

Prepare or execute a server-bound plan to rent a GPU instance. Use when the user has decided to launch; call should_i_run_this first if affordability is unsettled. Called without a plan_id it only *prepares* a plan and returns the canonical spec, a cost estimate, and an approval URL — nothing is allocated and nothing is billed. Execution requires that prepared plan_id plus approval; confirm:true expresses your intent but never substitutes for approval. Executing starts hourly CAD billing against the wallet until the instance is cancelled or terminated.

Parametersnamerequiredtierimageconfirmhost_idplan_idgit_reponum_gpusgpu_modelinit_scriptinteractivepricing_mode+7 more

cancel_instance

Cancel a queued or running instance and stop its hourly billing. Use when the user wants to stop paying for a job — this is the normal way to end work. Call it with confirm:false first: that returns a preview of what will stop and changes nothing, so you do not need get_instance beforehand — the preview comes from the tool that will do the work, which a status read does not. Then call again with confirm:true. Cancelling ends the run: in-flight work not already checkpointed is lost, and the instance cannot be resumed.

Parametersjob_idrequiredconfirm

terminate_instance

Permanently terminate an instance and release its host allocation. Use only when the user explicitly wants the instance destroyed rather than stopped — prefer cancel_instance for ordinary shutdown. Call it with confirm:false first: that returns a preview of exactly what will be destroyed and changes nothing, so you do not need get_instance beforehand — the preview comes from the tool that will do the work, which a status read does not. Then call again with confirm:true. Stops hourly billing immediately, and is irreversible: instance-local state is destroyed and cannot be recovered.

Parametersjob_idrequiredconfirm

register_ssh_key

Register an SSH *public* key on the account — the contents of a .pub file, one line beginning with 'ssh-ed25519', 'ssh-rsa' or 'ecdsa-sha2-'. Use when the user wants a shell on an instance and their key is refused, or before launching work they intend to drive interactively. Never send a private key: if the user pastes one, tell them it is compromised and to generate a new pair, and do not call this tool with it. Free — it moves no money and disturbs no running job — but it creates standing access: anyone holding the matching private key can open a shell on the user's instances and read the data on them, so confirm before adding a key the user did not just name. The key is pushed into running interactive instances, so it takes effect without a relaunch. Registering a key that is already on the account changes nothing and is safe to repeat.

Parametersnamepublic_keyrequired

list_ssh_keys

Show which SSH public keys can currently open a shell on this account's instances, with their fingerprints and when each was added. Use when the user asks what has access, before adding a key so you can say whether it is already there, or when they suspect a key they no longer recognise. Read-only and free. Registering a key is the step that grants shell access, so this is how you show what that has amounted to. Returns the key_id that delete_ssh_key needs — ids are not guessable, so revoking starts here.

Takes no parameters.

delete_ssh_key

Remove an SSH public key, revoking its shell access — including on instances already running, which have the key withdrawn from them. Use when a key belongs to a laptop that is gone, a person who has left, or one the user does not recognise from list_ssh_keys. Call it with confirm:false first for a preview of which key would go. Recoverable only by the person holding the private half: re-registering the same public key restores access, and nobody else can do it for them. Free, and it changes nothing about billing — instances keep running and accruing their hourly cost; only the way in is closed. Anyone connected through that key is disconnected.

Parameterskey_idrequiredconfirm

open_instance_access

Get a way in to a running instance: either the SSH endpoint to connect to, or a single-use ticket for the browser/websocket terminal. Use when the user wants a shell on something already running, after watch_instance reports it reached running. method:'ssh' reads the endpoint and is free; method:'terminal' creates a short-lived ticket that the first connection consumes and cannot be replayed. Read-only with respect to the instance: it never launches, cancels or reconfigures anything, and it does not change what the job costs — the instance goes on billing at its hourly rate whether or not anyone connects. SSH needs a key the account has already registered; if the connection is refused, register_ssh_key is the fix. Not idempotent: every call mints a new single-use ticket and does not return the previous one. Request it once and use it.

Parametersjob_idrequiredmethod

should_i_run_this

Decide whether a proposed GPU job is affordable: estimates cost, reads the wallet balance, checks an optional max_hourly_cad ceiling, and returns an approve/decline verdict with reasons. Use this instead of estimate_job_cost whenever you are about to launch — it answers whether the job *should* run, not merely what it costs. Read-only and free; it never launches anything.

Parametersspotgpu_modelduration_hoursmax_hourly_cad

run_training_job

End-to-end training launch: prepares a launch plan from a git repo and init script, waits for the instance to reach running, and returns connection details plus a log tail. Use when the user wants a repo trained on a GPU in one step rather than orchestrating create + poll themselves. Spends money exactly as create_instance does — the same plan preparation and approval apply — and blocks for up to several minutes while the instance starts. Not idempotent: no idempotency key is sent, so calling it again after a timeout launches a second instance and bills for both. If a call seems to have failed, check list_instances before retrying.

Parametersnamerequiredimageconfirmhost_idgit_repolog_tailnum_gpusgpu_modelinit_scriptpricing_modevram_needed_gbwait_timeout_seconds

schedule_under_budget

Find available capacity at or below a maximum CAD hourly rate and, optionally, launch it. Use when price is the binding constraint and the user has not picked a specific host. Searching is read-only and free; launching spends money through the same plan-and-approval path as create_instance, so nothing is allocated without it. Not idempotent: no idempotency key is sent, so a retry launches a second billed instance. Check list_instances before calling again.

Parametersnameconfirmnum_gpusgpu_modelpricing_modemax_hourly_cadrequiredvram_needed_gb

run_pipeline

Quotes a multi-stage job — train, then evaluate, then serve — as ONE approval covering every stage, with the total committed spend stated before anything runs. Use when the user describes work with steps that depend on each other, instead of launching each and asking three times. Each stage declares what happens if it fails (halt, continue, or retry) and that choice is fixed when the graph is approved. The pipeline cannot spend more than the quoted total: a stage that would exceed it never starts. **Returns as soon as the pipeline is quoted, before it has run or even been approved** — say it is awaiting approval, and check get_pipeline_status before reporting any stage as done. Not idempotent: each call creates another plan awaiting approval, so retrying a call that appeared to fail leaves two plans for the same work.

Parametersnamestagesrequired

revoke_launch_plan

Withdraw a launch plan so it can no longer be approved or executed. Use when the user changes their mind about something you quoted, when a plan was prepared for the wrong spec, or when they say to cancel before anything has started — a plan left sitting is still approvable later by anyone who can approve. Costs nothing and refunds nothing, because nothing has run: it only removes the ability to spend. Safe to call twice; a plan already withdrawn reports it. A plan that has already executed cannot be revoked — the instance it created is stopped with terminate_instance instead. The plan_id comes from whichever tool quoted it: create_instance, run_pipeline or create_image_sweep.

Parametersreasonplan_idrequired

get_pipeline_status

Reports which pipeline stage is running, which finished, and which were skipped and why. Use when a pipeline was started and the user asks how far along it is, or before claiming any stage completed — run_pipeline returns while the work is still ahead of it. Read-only and free.

Parametersplan_idrequired

list_serverless_endpoints

List the account's serverless inference endpoints and their state. Use when the user asks what models they can already call, or to find an endpoint_id before running a job. Read-only and free.

Takes no parameters.

create_serverless_endpoint

Prepare or execute a server-bound plan to create a serverless inference endpoint for a model. Use when the user wants per-token inference with no idle cost, rather than renting a dedicated GPU — prefer this over create_instance for bursty or low-volume inference. confirm:false returns a preview and creates nothing; execution goes through the same plan approval as a GPU launch. Once created, the endpoint bills per million tokens processed and costs nothing while idle.

Parametersnamerequiredregionconfirmplan_idgpu_tiergpu_countmodel_refrequiredmax_workersmin_workersidempotency_key

should_i_run_pel_job

Decide whether serverless inference is affordable before committing to it: estimates token and GPU cost against the wallet balance and returns a verdict. Use before create_serverless_endpoint when deploying a model, and before run_serverless_job on anything large or repeated — deploying an endpoint commits to standing capacity, so the check belongs there too, not only at invocation. Checking the wallet balance directly answers a smaller question: it says what is available, not what this will cost. Read-only and free; it never deploys an endpoint or invokes one.

Parametersgpu_tiermodel_refendpoint_idduration_hoursestimated_input_tokensestimated_output_tokens

run_serverless_job

Enqueue an asynchronous inference job on an existing serverless endpoint and return a job handle. Use when the user wants inference from a model already deployed; create the endpoint first if there is none. Bills per million tokens processed. Not idempotent — calling it twice enqueues two jobs and bills for both, so do not retry a call whose outcome you did not see.

Parametersinputwebhookendpoint_idrequired

get_serverless_job_status

Get the status and, when finished, the result of a serverless inference job. Use to poll a handle returned by run_serverless_job. Read-only and free.

Parametersjob_idrequiredendpoint_idrequired

get_serverless_endpoint

Get one serverless endpoint by id: its model, scaling settings, status and URL. Use when you already hold an endpoint_id and need its configuration — list_serverless_endpoints returns every endpoint on the account, which is the wrong tool once you know which one you mean. For whether it is actually serving traffic rather than how it is configured, use get_serverless_endpoint_health. Read-only and free.

Parametersendpoint_idrequired

get_serverless_endpoint_health

Check whether a serverless endpoint is actually serving: readiness, workers, and recent error state. Use when inference is failing or slow, or before sending a job to an endpoint created a moment ago — a configured endpoint is not a ready one, and this is the difference between them. Prefer it to reading the endpoint record, which reports what was asked for rather than what is running. Read-only and free.

Parametersendpoint_idrequired

list_serverless_endpoint_jobs

List the jobs on one serverless endpoint, newest first. Use when the user asks what is running or what has run on an endpoint, or to find a job_id — get_serverless_job_status answers about a job you can already name, and this is where that name comes from. Read-only and free.

Parameterslimitendpoint_idrequired

cancel_serverless_job

Cancel an inference job that is still running on a serverless endpoint. Use when the user wants to stop work in progress — a job that is taking too long, was submitted by mistake, or is no longer needed. Call it with confirm:false first for a preview. Cancelling stops the job billing for further GPU seconds, and ends the run: whatever it had not yet returned is lost and the job cannot be resumed, so submit a new one instead.

Parametersjob_idrequiredconfirmendpoint_idrequired

delete_serverless_endpoint

Permanently delete a serverless endpoint. Use when the user is finished with a deployed model — prefer cancel_serverless_job if they only want to stop one run. Call it with confirm:false first for a preview. Deleting stops the endpoint's idle cost and cancels jobs still in flight on it, and is irreversible: the endpoint_id stops resolving and a replacement is a new deployment with a new id.

Parametersconfirmendpoint_idrequired

watch_instance

Wait for an instance to reach a phase you name — finished, failed, running — polling its status, telemetry, and recent logs for up to 60 minutes and returning as soon as it gets there. Use when the user asks to be told when something finishes, to be notified when it is done, or to wait for a result, rather than calling get_instance_logs repeatedly and guessing. Read-only: it never cancels or modifies the instance, and abandoning the watch leaves the job running and still billing. The instance keeps accruing hourly cost for as long as it runs, whether or not you are watching.

Parameterscursorjob_idrequiredlog_tailreturn_on_phaseduration_minutespoll_interval_seconds

explain_instance_placement

Explain why the scheduler placed an instance on the host it chose, from persisted placement facts. Use when the user asks why a job landed where it did, or why it did not land somewhere they expected. Read-only and free.

Parametersjob_idrequired

simulate_instance_placement

Answer whether a proposed spec would actually schedule — run it through the real scheduler and get back where it would be placed, or why it would not be, without allocating anything. Use when the user asks whether something is possible, whether it would fit, or whether a combination of GPU model, count, and region can be satisfied at all. Browsing inventory does not answer this: list_available_gpus and search_marketplace show what exists, not whether one host can satisfy four of them in the region asked for. Read-only and free: no capacity is reserved and nothing is billed.

Parametersspecrequired

evaluate_placement_preference

Check what a placement preference would actually get you, before committing to anything. Takes a spec plus constraints — minimum uptime, minimum reputation tier, verified hosts only — and an optional cap on how much more you will pay to satisfy them. Returns the host it would pick and the premium over the cheapest eligible host, or a clear refusal naming the constraint that failed and the best value actually available, so the user can decide whether to relax it. Use whenever a user says they want reliable, verified, or high-uptime capacity: this answers whether that is possible right now and what it costs, rather than quietly placing on something that does not meet it. Differs from simulate_instance_placement, which only answers whether any host is available at all. Read-only and free: nothing is reserved and nothing is billed.

Parametersspecrequiredpreferencerequired

get_instance_timeline

Get the durable attempt timeline for an instance: every scheduling attempt, transition, and failure, in order. Use when a job is stuck or failed and the current status alone does not explain it. Read-only and free.

Parametersjob_idrequired

get_event_history

Get the recorded event history for one instance or host — what actually happened to it and when, from the platform's event log. Use when the user asks why something stopped, what changed overnight, or what a host has been doing; it also covers hosts, which no other tool reads. This is not get_instance_timeline: that explains how a job was *placed* (reserve, command, lease) and this is the record of what happened afterwards, so a placement question goes there and a behaviour question comes here. The entity_id is a job_id from list_instances, or a host_id from get_host_capacity. Read-only and free.

Parameterslimitentity_idrequiredentity_typerequired

list_providers

List the provider accounts this credential can see — normally the caller's own. Use when helping someone who supplies GPUs, before anything else: it is the only source of the provider_id that get_provider_account and get_provider_earnings require, and ids are not guessable. For a caller who is not a provider the list comes back empty, which is itself the answer. Read-only and free.

Parametersstatus

get_provider_account

Show a GPU provider's account and exactly what is blocking their payouts. Returns a `payouts` block: charges_enabled, payouts_enabled, a disabled_reason, and currently_due and past_due — Stripe's list of what the provider still has to supply, such as external_account for a bank account or individual.id_number for identity. Use when someone renting out hardware asks why they have not been paid, what is left to complete, or whether their account is live: name the outstanding items and send them to the earnings page in the browser to finish. Check `checked_live` first — when it is false Stripe was not reachable and the empty lists mean nothing was asked, not that nothing is outstanding. This is the provider side of the marketplace, the person supplying GPUs rather than renting them. Read-only and free; the provider_id comes from list_providers, which returns nothing for an account that supplies no hardware.

Parametersprovider_idrequired

claim_reputation_milestones

Claim every reputation milestone the caller has already earned but not yet collected: it creates a one-time grant per milestone and returns what was awarded with the refreshed score and tier. Use when get_reputation_journey shows milestones ready to claim — each grant adds points and, for the security milestones, a verification badge, which can move the provider into a higher tier and lower the commission they pay. It cannot invent progress: every milestone is re-checked against real account and activity state, so anything not genuinely earned is skipped. Free, and it moves no money. Safe to repeat — already-claimed milestones are skipped rather than granted twice. Touches only the caller's own account, and needs reputation:write.

Takes no parameters.

get_reputation_leaderboard

List the highest-scoring hosts or users on the platform, with their reputation scores. Use when a provider asks where they stand relative to others, or what a competitive score looks like — get_my_reputation gives their number and this gives it a scale. For choosing a host to rent, prefer search_marketplace, which ranks only hardware actually available and can sort and filter by reputation directly. Read-only and free.

Parameterslimitentity_type

get_reputation_history

List the individual reputation events for an entity: what happened, when, and how many points each moved. Use when a provider disputes a score and the four totals from get_reputation_breakdown are not enough to explain it — this is the itemised log those totals are computed from, so it names the specific job or penalty behind a drop. The entity_id is the caller's own provider_id from list_providers or a host_id from get_host_capacity; asking about anyone else is refused. Read-only and free.

Parameterslimitentity_idrequired

request_provider_payout

Settle one completed job and pay the provider their share, creating a Stripe transfer or a PayPal order. Use when a provider asks to be paid for finished work and get_provider_account shows payouts enabled — if it does not, name what is outstanding instead, because this will refuse. Calling it costs nothing: the amount, the platform cut and the tax are computed from the job in the database, not supplied by you, and the destination is the provider's own account. Safe to repeat: settlement is keyed per job, so a retry after a timeout returns the existing settlement rather than paying twice. **Amounts on the stripe rail are integer micros — divide by 1,000,000 for CAD — while the paypal rail returns fields already named _cad.** Reporting a micros figure as dollars overstates it a millionfold. Needs providers:write.

Parametersjob_idrequiredprovider_idrequiredpayment_rail

register_provider

Enrol the caller as a GPU provider so they can be paid for hosting: creates their provider account and starts Stripe Connect onboarding. Use when someone wants to supply hardware and list_providers comes back empty, which means they are not enrolled yet. Free, and it moves no money. Safe to repeat — the provider identity is derived from the credential, so calling again returns the same account rather than a second one. Collect legal_name and province first, and corporation_name for a company. It does not finish onboarding: identity and bank details are entered in the browser, so send them to the earnings page afterwards and use get_provider_account to see what is still outstanding. Needs providers:write, which the default connector does not carry.

Parameterscountryprovincelegal_nameprovider_typegst_hst_numberbusiness_numbercorporation_name

get_paypal_status

Get a provider's PayPal payout onboarding state: whether PayPal is enabled on the platform, how far the provider got, and when they finished. Use when a provider asks about PayPal specifically, or when get_provider_account shows payouts blocked and you need to know whether their PayPal side is the reason — Stripe and PayPal are separate destinations with separate onboarding. The merchant and payer identifiers are deliberately not returned. Read-only and free; the provider_id comes from list_providers.

Parametersprovider_idrequired

get_my_reputation

Get the caller's own reputation score and trust tier. Use when a provider asks how they are rated, why their tier changed, or what their standing is — tier drives the platform commission they pay, their ranking in search, and the pricing premium they can charge, so it is the lever behind earnings rather than a vanity number. Someone who hosts no hardware comes back as a new user with no score, which is itself the answer. Read-only and free.

Takes no parameters.

get_reputation_journey

List the caller's reputation milestones with live progress and how many are ready to claim. Use when a provider asks what to do next to earn more or reach the next tier: this returns concrete steps with real progress against each, so the answer is specific rather than general advice. Progress is computed from actual account and activity state, so a milestone shown as complete is genuinely earned. Read-only and free — claiming a reward is a separate action — that is claim_reputation_milestones, which needs reputation:write and is deliberately outside the default connector's grant.

Takes no parameters.

get_trust_tiers

List every trust tier with its score threshold and what it unlocks — platform commission, search boost and pricing premium. Use when a provider asks what a higher tier is worth or what it takes to reach one, and pair it with get_my_reputation to say how far away they are. The numbers come from the live scoring engine rather than documentation, so quote what this returns instead of any figure you remember. Read-only and free.

Takes no parameters.

get_reputation_breakdown

Explain how a reputation score was arrived at: points from completed jobs, uptime bonus, penalties and decay, derived from the event history. Use when a provider disputes a score or asks why it fell — this separates a penalty from ordinary decay, which are different problems with different fixes. The entity_id is the caller's own provider_id from list_providers or a host_id from get_host_capacity; asking about anyone else is refused. Read-only and free.

Parametersentity_idrequired

get_provider_earnings

Get a provider's aggregate earnings and payout history: what has been earned, what has already been paid out, and what is pending. Use when someone supplying GPUs asks how much they have made, when they were last paid, or why a figure differs from what they expected — earned is not the same as paid, and this separates them. Read-only and free, and it moves no money: requesting a payout is a separate action.

Parametersprovider_idrequired

get_active_lease

Get the current attempt and lease health for an instance — which host holds it and whether the lease is being renewed. Use when an instance appears running but unresponsive, to tell a live job from an abandoned lease. Read-only and free.

Parametersjob_idrequired

get_mcp_action_status

Get the current state of an action plan owned by the authenticated principal, including whether it has been approved. Use after a tool returns approval_required, to check whether the plan is now approved and can be executed. Read-only and free; checking a plan does not approve or execute it.

Parametersplan_idrequired

retry_instance

Retry a failed instance, creating a fresh fenced attempt while preserving the job's identity and history. Use when an instance failed for a transient reason and the user wants it to run again. Requires the instance's expected_version and an idempotency key, so a repeated call cannot produce a second attempt. Starts hourly billing again once the new attempt runs.

Parametersjob_idrequiredidempotency_keyrequiredexpected_versionrequired

reconcile_instance

Force reconciliation of one instance so its recorded state is re-derived from what the host actually reports. Use when an instance's status looks wrong or stale — for example, running in our records but gone on the host. Requires expected_version and an idempotency key. Corrects bookkeeping only: it does not start, stop, or move the workload, and it changes nothing about what the instance is billing.

Parametersjob_idrequiredidempotency_keyrequiredexpected_versionrequired

list_volumes

List the account's persistent volumes: id, name, size, region, status, and what each is attached to. Use when the user asks what storage they have, before creating another one, or to find a volume_id for attach. Read-only and free to call — though the volumes themselves bill per GB-month whether attached or not.

Takes no parameters.

get_volume

Get one volume by id: size, encryption, region, status, and its current attachment. Use when the user asks about a specific volume, or before detaching, to see which instance would lose its filesystem. Read-only and free.

Parametersvolume_idrequired

create_volume

Create a persistent volume that outlives any instance. Use when work must survive a relaunch — checkpoints, datasets, model weights — because an instance's own disk is destroyed with it. Creates storage that bills per GB-month from the moment it exists, attached or not, so size it for what is needed rather than rounding up. Not idempotent: calling it twice creates two volumes, both billed per GB-month. Check list_volumes before retrying.

Parametersnamerequiredregionsize_gbencrypted

attach_volume

Attach a volume to a running instance at a mount path. Use after launching, so the job writes somewhere durable instead of into the container. Free in itself — the volume was already billing — and it changes what the instance can see: a job started before the attach may need restarting to notice the new path. Takes job_id, the instance id list_instances returns; instance_id is a deprecated alias that still works.

Parametersmodejob_idvolume_idrequiredmount_pathinstance_id

detach_volume

Detach a volume from the instance it is mounted on. Use when moving storage to another instance, or before deleting the instance it is attached to. Call it with confirm:false first: that returns a preview naming the instance that would lose its filesystem. Detaching pulls the mount out from under anything writing to it, so unwritten data is lost even though the volume itself is not destroyed — and the volume keeps billing per GB-month either way, so detaching saves nothing.

Parametersconfirmvolume_idrequired

delete_volume

Permanently delete a volume and everything stored on it. Use only when the user says the data is no longer needed — prefer detach_volume when they merely want it off an instance. Call it with confirm:false first for a preview. Stops the per-GB-month billing, and is irreversible: the contents cannot be recovered, so snapshot first if there is any doubt.

Parametersconfirmvolume_idrequired

snapshot_volume

Creates a point-in-time snapshot of a volume, so its current contents can be restored later. Use before anything destructive — a delete, a risky job, a version bump — and when the user wants a checkpoint they can return to. The snapshot is new stored data and bills per GB-month like the volume it came from. Not idempotent: each call creates another snapshot and snapshots are billed for storage. List the volume's snapshots before retrying.

Parametersnamevolume_idrequired

list_volume_snapshots

List a volume's snapshots, with when each was taken. Use before restoring, to choose which capture to go back to, or when the user asks what backups exist — snapshot_volume creates them and this is the only tool that shows them. The snapshot_id for restore_volume_snapshot comes from here and cannot be guessed. Read-only and free.

Parametersvolume_idrequired

restore_volume_snapshot

Roll a volume back to one of its snapshots. Use when the user wants to undo changes on a volume or recover work they have overwritten. Call it with confirm:false first: that returns a preview naming the snapshot and when it was taken, and changes nothing — the age matters, because putting back a week-old capture is a different decision from an hour-old one. Then call again with confirm:true. This REPLACES everything on the volume: anything written since that snapshot is destroyed and cannot be recovered. Detach the volume from a running instance first if it is attached, or the instance keeps writing to what you are replacing. Free to call, and irreversible once confirmed.

Parametersconfirmvolume_idrequiredsnapshot_idrequired

get_artifact_expiry

Show when a job's artifacts will be deleted: each file with its creation time and the date its retention window ends. Use when the user asks how long results are kept, and unprompted after a job finishes — the clock is otherwise invisible, which is how finished work quietly disappears. Read-only and free. Artifacts expire; a volume does not, so copy anything that matters onto one before the window closes.

Parametersjob_idrequired

promote_artifact_to_volume

Copies a finished run's outputs — weights, checkpoints — from artifact storage onto a volume, which has no retention clock. This creates a durable copy — it does not move or delete the originals. Use when a run produced something worth keeping past its expiry, or when the user asks to save results somewhere permanent. The copied data bills per GB-month as volume storage for as long as it is kept, so it is a standing cost rather than a one-off. **Returns as soon as the copy STARTS, not when it finishes.** A large checkpoint takes minutes; say it is running and check get_promotion_status before telling anyone their files are safe. Asking twice for the same job does not copy twice. Returns a promotion_id; the copy is still running when this returns, so pass that id to get_promotion_status before telling the user their files are on the volume.

Parametersjob_idrequiredvolume_idrequiredidempotency_key

get_promotion_status

Reports whether a promotion started by promote_artifact_to_volume has finished, and how much it has copied. Use when you started a promotion and need to know whether the files have actually landed — the promotion tool returns while the copy is still running, so this is what tells you it is safe to say the work is saved. Read-only and free.

Parametersvolume_idrequiredpromotion_idrequired

create_image_sweep

Find out whether one image actually behaves the same on different machines, by running it on several at once and comparing what each container ended up with — package versions, environment, entrypoint. Use when something works on one host and not another, when a result will not reproduce, or when the user asks whether an environment is really identical across nodes; that question cannot be answered from list_instances, which shows what is running but not what is inside it. Not the tool for simply wanting several instances — that is create_instance called N times, and it produces no record to compare across. Spends N times one launch: called without plan_id it only quotes the sweep and returns a plan awaiting approval, and nothing runs until that plan is approved and this tool is called again with plan_id and confirm:true. The approved plan carries the member count, so approving three cannot launch sixty-four. Not idempotent: each call without plan_id creates another plan awaiting approval, so retrying a call that appeared to fail leaves two plans for the same work. Returns a sweep_id once it launches; pass that to get_image_sweep to see whether the members agree.

Parametersnamecountrequiredcommandconfirmplan_idimage_idrequirednum_gpusgpu_modelinteractivevram_needed_gb

create_instance_snapshot

Create a reusable image from a running instance's container, so the exact environment can be launched again later or run across several machines at once. Use when the user wants to keep a working setup, reproduce a result, or prepare an image to sweep — installing packages again on a fresh instance is what this avoids. The image is built on the host in the background and is not usable until it reports ready; list_user_images shows the status. Costs storage while it exists, and taking the same name and tag twice is refused rather than overwriting, so an existing image must be deleted first.

Parameterstagnamerequiredjob_idrequireddescription

list_user_images

List the saved images this account can launch from, with their status, size, and the job each was captured from. Use to find an image_id — create_image_sweep and a snapshot-based launch both need one and it cannot be guessed — or to check whether a snapshot taken earlier has finished building. Read-only and free.

Parametersqlimitscope

delete_user_image

Permanently delete a saved image, stopping its storage cost. Use when the user says an image is no longer needed, or when a snapshot must be retaken under a name that is already taken, since create_instance_snapshot refuses to overwrite. Irreversible through the API: anything that referenced the image — a past sweep, a launch you might want to reproduce — can no longer be launched from it. Check list_user_images first if there is any doubt about which image is which.

Parametersconfirmimage_idrequired

get_image_sweep

Get one sweep: its members, which of them launched, the hosts they landed on, and whether their environments are byte-identical. Use after create_image_sweep to see whether the members agree, and to find which field differs when they do not — the verdict names the differing keys rather than only reporting a mismatch. A member that never reported a fingerprint is unknown, never counted as agreeing. Read-only and free.

Parameterssweep_idrequired

Version history

2
  1. v2.0.1LatestNov 5, 2026
  2. v2.0.0Nov 5, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts