quota-mcp
Usage & quota tracker for AI subscription accounts (StepFun, Command Code)
Installation
Ajoutez ceci à la configuration MCP de votre client (Claude Desktop : claude_desktop_config.json ; Cursor : .cursor/mcp.json ; VS Code et les autres utilisent la même forme « mcpServers »).
ghcr.io/limitcool/quota-mcp:0.3.2claude mcp add quota-mcp -e 'QUOTA_MCP_MASTER_KEY=<your quota_mcp_master_key>' -e 'QUOTA_MCP_DB=<QUOTA_MCP_DB>' -- docker run -i --rm ghcr.io/limitcool/quota-mcp:0.3.2
{
"mcpServers": {
"quota-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/limitcool/quota-mcp:0.3.2"
],
"env": {
"QUOTA_MCP_MASTER_KEY": "<your quota_mcp_master_key>",
"QUOTA_MCP_DB": "<QUOTA_MCP_DB>"
}
}
}
}
Variables d'environnement
QUOTA_MCP_MASTER_KEYsecret 64 hex chars AES master key for credential encryption (required in production; without it the key is derived from machine traits)QUOTA_MCP_DBSQLite path inside the container (default /data/quota-mcp.db, backed by the /data volume)
Documentation
Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.
Sommaire
English | 简体中文
quota-mcp
A usage & quota tracker for AI subscription accounts. It pulls the balances, subscription expiry dates and rate-limit windows that are scattered across vendor dashboards into one place, and exposes them through both a REST management API and an MCP query surface — point your agent (Hermes, Claude Code, …) at it with one config line and it can answer "how much quota do I have left?" on its own.
Two platforms supported today:
| Platform | Data source | Credential | What you can see |
|---|---|---|---|
StepFun (阶跃星辰, .ai intl / .com China) | platform.stepfun.{ai,com} console Connect RPC | Browser session (Oasis-Token, ~2 h, auto-renewed) + optional plan key | Plan & expiry, 5-hour / weekly / subscription credit windows, access keys under the account, session health |
| Command Code (commandcode.ai) | Undocumented /alpha/* endpoints on api.commandcode.ai | A single Bearer API key | Plan (GOAT/Pro/Max/…), 5-hour / weekly / monthly windows, balances, billing-period request stats |
Highlights:
- Encrypted at rest: credentials are AES-256-GCM encrypted into SQLite (pure-Go driver, no CGO); every endpoint returns masked views only
- StepFun session auto-renewal: a background goroutine checks every 60 s and renews any session whose TTL drops below 20 min. Renewing an expired session gets you a degraded device token — there is a guard that detects this and refuses to persist it
- Dual auth planes: StepFun's plan key (permanent) and console session (quota data) are managed and probed separately; the verdict is driven by the permanent plane
- MCP is read-only: the query surface (list / probe / summarize) is safe to hand to agents; enrol / renew / delete live on the REST side only
- Single binary, zero external services
Quick start
go build -o quota-mcp ./cmd/quota-mcp
# In production set the master key explicitly (64 hex chars). Without it the key is
# derived from machine traits and old ciphertext becomes unreadable after a migration.
export QUOTA_MCP_MASTER_KEY=$(openssl rand -hex 32)
./quota-mcp -db data/quota-mcp.db -listen 127.0.0.1:8780
After startup:
http://127.0.0.1:8780/healthzhealth checkhttp://127.0.0.1:8780/api/stepfun/accountsREST listhttp://127.0.0.1:8780/mcpMCP endpoint
Enrolling accounts
Command Code (two credential planes)
The alpha/API-key plane is the easy one — a permanent Bearer key:
curl -X POST http://127.0.0.1:8780/api/commandcode/accounts \
-H 'Content-Type: application/json' \
-d '{"service":"cc-myname","api_key":"user_xxx","label":"primary"}'
Get the key from commandcode.ai/settings/keys (shown once at creation). The server validates it with whoami first and refuses to store a rejected key.
The internal/session plane mirrors the browser: pass session_text (the whole Cookie: header, a document.cookie dump, or the bare __Secure-commandcode_prod_.session_token value). It is validated against billing/credits and never stored unless it passes. Sessions expire, so refresh them from CookieCloud or by copying the cookie again from DevTools:
curl -X POST http://127.0.0.1:8780/api/commandcode/accounts \
-H 'Content-Type: application/json' \
-d '{"service":"cc-myname","session_text":"__Secure-commandcode_prod_.session_token=eyJ..."}'
When both are stored the API key wins. Each enrol overwrites the credential planes it was given — re-enrolling with only api_key clears any stored session, and vice-versa, so a rotation is never silently skipped.
StepFun (browser session)
Oasis-Token is an HttpOnly cookie, so document.cookie cannot read it — copy it from a request header in DevTools. Paste the whole Cookie: header (or the bare token) to the server:
curl -X POST http://127.0.0.1:8780/api/stepfun/accounts \
-H 'Content-Type: application/json' \
-d '{"service":"ai-412848664332275712","region":"ai","session_text":"Oasis-Token=eyJ...; Oasis-Webid=...","email":"me@example.com"}'
Protocol findings from real-world testing (all handled in code):
- The
.aiOasis-Tokencookie value is two JWTs concatenated (8 segments); the console only accepts the whole value — a single segment gets youtoken is illegal - Timestamp units differ per site:
.aireturns second-level strings,.comreturns milliseconds; the code infers by magnitude .comdevice tokens live only 30 minutes and its RefreshToken returns a degraded token —.comsessions need periodic re-import- Renewing after expiry yields a device token (
mode 1, data plane alwaystoken is illegal), so renewal must happen before expiry; a degradation guard refuses to store such tokens
REST API
GET /api/stepfun/accounts List (masked view)
POST /api/stepfun/accounts Enrol/update (stored only if at least one plane probes OK)
POST /api/stepfun/accounts/{service}/probe Probe (auto-renews once on console auth failure)
POST /api/stepfun/accounts/{service}/renew Force-renew the console session
POST /api/stepfun/accounts/{service}/register?region=ai Register an anonymous device slot (self-test)
DELETE /api/stepfun/accounts/{service} Delete
POST /api/stepfun/probe Probe all (cron-friendly)
GET /api/commandcode/accounts List (masked view)
POST /api/commandcode/accounts Enrol/update (api_key or session_text; stored only if it probes OK)
POST /api/commandcode/accounts/{service}/probe Probe
DELETE /api/commandcode/accounts/{service} Delete
POST /api/commandcode/probe Probe all
MCP surface (for agents)
Two ways to connect — pick either:
1. Streamable HTTP (served on /mcp) — for always-on deployments:
mcp_servers:
quota:
url: http://<your-host>:8780/mcp
2. stdio — for clients that spawn the server themselves (Claude Code, containers, mcp-publisher-style registry installs):
# local binary
quota-mcp -stdio
# or straight from the published image (works with zero setup)
docker run -i --rm -v quota-mcp-data:/data ghcr.io/limitcool/quota-mcp:latest
Works the same way from Claude Code or any other MCP client.
All tools are read-only:
| Tool | Description |
|---|---|
quota_list_accounts | List every account: plan, expiry, remaining quota, session/key status (masked) |
quota_probe_account | Live-probe one account (hits upstream, takes a few seconds) |
quota_probe_all | Serially probe all accounts and refresh the cache |
quota_status | Summary: per-platform counts of serving / limited / invalid / needs-relogin, plus a one-line status per account |
quota_check_alerts | Firing alerts: low quota, upcoming expiry, dead session, rejected key, window exceeded |
quota_report | The scheduled-digest payload: all account numbers + current alerts |
Alerts, expiry warnings & scheduled digest
quota-mcp owns condition detection (it holds the data and runs a 60 s background loop); scheduling and delivery belong to your agent platform. A hermes-style wiring:
1. Threshold & expiry alerts (event-driven, push)
A background evaluator refreshes stale probe data (>5 min), evaluates rules, keeps a
firing/resolved state machine in SQLite (alert_events), and POSTs only the transitions
to a webhook — the same alert never repeats until it clears and fires again.
Rules: credit_low (remaining share below threshold), expiring_soon (subscription/billing
period ending within N days), session_dead (StepFun console session needs re-import),
key_rejected (Command Code key got 401/403), window_limited (rate window exceeded).
QUOTA_MCP_ALERT_WEBHOOK_URL=http://<hermes>:8642/webhooks/quota \
QUOTA_MCP_ALERT_CREDIT_PCT=0.2 \
QUOTA_MCP_ALERT_EXPIRY_DAYS=7 \
./quota-mcp -listen 0.0.0.0:8780
Payload pushed on each transition:
{
"source": "quota-mcp",
"at": "2026-09-21T15:52:30Z",
"fired": [{"kind":"credit_low","provider":"stepfun","service":"ai-…","severity":"warn","title":"订阅额度即将耗尽","detail":"剩余 13%(阈值 20%),2026-10-20 重置"}],
"resolved": []
}
No webhook? No problem — hermes (or anything) can poll instead:
# hermes mcp_servers
mcp_servers:
quota:
url: http://<host>:8780/mcp
then have a hermes cron every 15–30 min call quota_check_alerts and hermes send anything
new. Same for GET /api/alerts?history=20.
2. Scheduled digest (cron)
quota_report (or GET /api/report) returns a stable, agent-friendly payload: every account's
plan / expiry / remaining quota / session state / window usage / request stats, plus current
alerts. Point hermes's existing 09:30 cron at it: one turn calls the tool, composes the message,
and delivers via hermes send. No scheduler is duplicated inside quota-mcp.
3. Environment variables
| Variable | Default | Meaning |
|---|---|---|
QUOTA_MCP_ALERT_CREDIT_PCT | 0.2 | Fires when remaining share drops below this |
QUOTA_MCP_ALERT_EXPIRY_DAYS | 7 | Fires when subscription/billing period ends within N days |
QUOTA_MCP_ALERT_WEBHOOK_URL | — | POST target for alert transitions; empty = record only (pull mode) |
Example (quota_status output — what an agent would read to answer "how much quota is left?"):
{
"stepfun": {
"total": 2, "healthy": 2, "attention": 0,
"accounts": ["ai-4128…: ok (10 models)", "com-3766…: ok (0 models)"]
},
"commandcode": {
"total": 1, "serving": 1, "limited": 0, "key_rejected": 0,
"accounts": ["cc-limitcool: serving GOAT"]
}
}
Project layout
cmd/quota-mcp/ Entrypoint (flags/env config, one port serving both surfaces)
internal/store/ SQLite + AES-256-GCM encryption + schema
internal/stepfun/ StepFun protocol client + account registry + background renewer
internal/commandcode/ Command Code protocol client + account registry
internal/api/ REST management surface (net/http, no framework)
internal/mcpsrv/ MCP query surface (modelcontextprotocol/go-sdk)
internal/alerts/ Alert rules + firing/resolved state machine + webhook push
internal/digest/ Scheduled-digest payload for cron consumers
Security boundary
- Ciphertext goes to the DB only — never to logs, never to responses; every endpoint returns masks
- The REST surface contains writes: bind it to loopback or a private network. To expose it publicly, front it with a reverse proxy + auth and only publish the MCP path
- Losing the master key means every stored credential becomes unreadable — back up
QUOTA_MCP_MASTER_KEY
Releases
Binaries for Linux / macOS / Windows (amd64 + arm64) are attached to each GitHub Release. Grab the latest:
# example: linux amd64
curl -LO https://github.com/limitcool/quota-mcp/releases/latest/download/quota-mcp_linux_amd64
chmod +x quota-mcp_linux_amd64
Docker
Image is published to ghcr.io/limitcool/quota-mcp (amd64 + arm64) on every main push (:main) and tag (:v1.0.0, :latest).
docker run -d --name quota-mcp \
-p 8780:8780 \
-v quota-mcp-data:/data \
-e QUOTA_MCP_MASTER_KEY=$(openssl rand -hex 32) \
ghcr.io/limitcool/quota-mcp:latest
Or with the bundled compose file (QUOTA_MCP_MASTER_KEY is required, put it in .env):
echo "QUOTA_MCP_MASTER_KEY=$(openssl rand -hex 32)" > .env
docker compose up -d
The database lives in the /data volume (QUOTA_MCP_DB=/data/quota-mcp.db). Back up the master key — losing it makes every stored credential unreadable.
License
MIT
Questions fréquentes
Qu'est-ce que quota-mcp ?
Usage & quota tracker for AI subscription accounts (StepFun, Command Code)
Comment installer quota-mcp ?
Il s'exécute sur votre machine. Dans Claude Code : claude mcp add quota-mcp -e 'QUOTA_MCP_MASTER_KEY=<your quota_mcp_master_key>' -e 'QUOTA_MCP_DB=<QUOTA_MCP_DB>' -- docker run -i --rm ghcr.io/limitcool/quota-mcp:0.3.2. Pour les autres clients, collez la configuration JSON de cette page dans leurs réglages MCP.
Faut-il une clé API pour quota-mcp ?
Oui. Il attend QUOTA_MCP_MASTER_KEY, à renseigner dans sa configuration.
quota-mcp est-il open source ?
Oui. Son code est sur GitHub sous licence MIT.
Qui maintient quota-mcp ?
Il est publié par limitcool. AI.tn le référence sans le maintenir ni le recommander.
Issu du registre MCP officiel. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.