Xcelsior GPU Cloud

io.github.aabiro由 GitHub 账号 aabiro 发布v2.0.1更新于 Nov 5, 2026

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

已验证Streamable HTTP可网页运行云端与基础设施金融AI 与机器学习

概览

AI 生成的概览

Xcelsior 的托管 GPU 市场服务器:让助手比较实时 GPU 价格、租用或取消实例、运行训练任务与无服务器推理,并管理钱包支出。

可以做什么
  • 发现与比价硬件:列出可用 GPU、竞价与按需价格、服务层级,并按显存、区域或主机信誉搜索市场列表
  • 租用与管理算力:准备并执行实例启动、列出和查看实例、读取日志、取消或销毁实例,并获取 SSH 或终端访问方式
  • 运行工作流:端到端训练启动、按预算上限调度、多阶段流水线,以及无服务器推理端点和任务
  • 跟踪费用:钱包余额与流水、发票、成本估算、余额消耗预测,以及启动前的可负担性判断
  • 充值与控制支出:银行卡充值、自动充值设置、加密货币与闪电网络充值、待验证充值,以及已保存的支付方式
  • 管理 SSH 密钥:注册公钥、查看指纹并撤销访问权限
适用场景
适合希望让助手查找并租用 GPU 算力、启动或监控训练与批处理任务、部署按 token 计费的推理,或在对话中查看并充值 Xcelsior 支出的场景。
运行要求
可通过 mcp.xcelsior.ca 的 streamable HTTP 远程端点配合 OAuth 授权使用,也可用 npx 运行 npm 包,需要 Node.js 20.20+ 或 22.22+。stdio 包需要仪表盘生成的 XCELSIOR_ACCESS_TOKEN;无人值守自动化使用带客户端凭据的机器客户端。付费操作需要已充值的 Xcelsior 账户。
安装前请注意
许多工具会实际花费加元:启动实例、流水线、无服务器端点和按 token 计费的任务、银行卡充值,以及无人值守时自动扣款的自动充值。取消、销毁、删除密钥和撤销计划会更改或销毁资源,请先用 confirm:false 预览。只提交 SSH 公钥,切勿提交私钥。可选的 PostHog 分析按 README 仅收集元数据,但会以账户 ID 标识用户。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Xcelsior GPU Cloud,将其添加到工作区。
  2. 连接 所需的 凭据。它们会被私密存储,绝不会在公开页面上展示。
  3. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.aabiro%2Fxcelsior/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。 客户端会在首次连接时完成 OAuth 登录。

{
  "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.

来源:api/mcp/README.md,提交 bedf284

工具

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.

输入参数region

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.

无需输入参数。

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.

无需输入参数。

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.

输入参数regionsort_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.

输入参数gpu_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.

输入参数customer_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.

输入参数limitbeforecustomer_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.

无需输入参数。

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.

输入参数amount_cad必填customer_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.

输入参数deposit_id必填

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.

输入参数amount_cad必填customer_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.

输入参数deposit_id必填

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'.

输入参数customer_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.

输入参数spotgpu_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.

输入参数customer_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.

输入参数enabled必填plan_idamount_cad必填threshold_cad必填payment_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.

输入参数amount_cad必填card_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.

无需输入参数。

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.

无需输入参数。

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.

无需输入参数。

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.

输入参数limitcursorstatus

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.

输入参数job_id必填

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.

输入参数limitjob_id必填

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.

输入参数name必填tierimageconfirmhost_idplan_idgit_reponum_gpusgpu_modelinit_scriptinteractivepricing_mode另有 7 个

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.

输入参数job_id必填confirm

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.

输入参数job_id必填confirm

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.

输入参数namepublic_key必填

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.

无需输入参数。

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.

输入参数key_id必填confirm

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.

输入参数job_id必填method

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.

输入参数spotgpu_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.

输入参数name必填imageconfirmhost_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.

输入参数nameconfirmnum_gpusgpu_modelpricing_modemax_hourly_cad必填vram_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.

输入参数namestages必填

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.

输入参数reasonplan_id必填

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.

输入参数plan_id必填

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.

无需输入参数。

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.

输入参数name必填regionconfirmplan_idgpu_tiergpu_countmodel_ref必填max_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.

输入参数gpu_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.

输入参数inputwebhookendpoint_id必填

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.

输入参数job_id必填endpoint_id必填

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.

输入参数endpoint_id必填

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.

输入参数endpoint_id必填

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.

输入参数limitendpoint_id必填

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.

输入参数job_id必填confirmendpoint_id必填

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.

输入参数confirmendpoint_id必填

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.

输入参数cursorjob_id必填log_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.

输入参数job_id必填

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.

输入参数spec必填

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.

输入参数spec必填preference必填

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.

输入参数job_id必填

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.

输入参数limitentity_id必填entity_type必填

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.

输入参数status

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.

输入参数provider_id必填

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.

无需输入参数。

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.

输入参数limitentity_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.

输入参数limitentity_id必填

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.

输入参数job_id必填provider_id必填payment_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.

输入参数countryprovincelegal_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.

输入参数provider_id必填

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.

无需输入参数。

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.

无需输入参数。

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.

无需输入参数。

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.

输入参数entity_id必填

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.

输入参数provider_id必填

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.

输入参数job_id必填

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.

输入参数plan_id必填

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.

输入参数job_id必填idempotency_key必填expected_version必填

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.

输入参数job_id必填idempotency_key必填expected_version必填

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.

无需输入参数。

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.

输入参数volume_id必填

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.

输入参数name必填regionsize_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.

输入参数modejob_idvolume_id必填mount_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.

输入参数confirmvolume_id必填

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.

输入参数confirmvolume_id必填

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.

输入参数namevolume_id必填

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.

输入参数volume_id必填

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.

输入参数confirmvolume_id必填snapshot_id必填

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.

输入参数job_id必填

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.

输入参数job_id必填volume_id必填idempotency_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.

输入参数volume_id必填promotion_id必填

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.

输入参数namecount必填commandconfirmplan_idimage_id必填num_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.

输入参数tagname必填job_id必填description

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.

输入参数qlimitscope

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.

输入参数confirmimage_id必填

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.

输入参数sweep_id必填

版本历史

2
  1. v2.0.1最新Nov 5, 2026
  2. v2.0.0Nov 5, 2026

评分

已满足适用检查项的 100%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分