Usage & quota tracker for AI subscription accounts (StepFun, Command Code)
About
Usage & quota tracker for AI subscription accounts (StepFun, Command Code)
Security Report
Valid MCP server (2 strong, 0 medium validity signals). No known CVEs in dependencies. Imported from the Official MCP Registry.
5 files analyzed · No issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
What You'll Need
Set these up before or after installing:
Environment variable: QUOTA_MCP_MASTER_KEY
Environment variable: QUOTA_MCP_DB
Documentation
View on GitHubFrom the project's GitHub README.
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
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.