Skip to main content
Glama
README.md
# minimax-remaining-mcp

> MCP 服务器:让 AI 代理知道 **MiniMax Token Plan** 套餐还剩多少额度,
> 以及什么时候该暂停自己以避免触发限流。

适配 **DeepSeek Harness (DSH)**、Claude Desktop、Cursor 等所有兼容 MCP 协议的客户端。

```
┌──────────────┐    stdio    ┌──────────────────────┐   HTTPS   ┌──────────────┐
│   AI 代理   │ ──────────► │  minimax-remaining-  │ ────────► │  MiniMax     │
│ (DSH 等)    │ ◄────────── │         mcp          │ ◄──────── │   Web API    │
└──────────────┘             └──────────┬───────────┘           └──────────────┘
                                        │
                                        ▼
                                 ┌─────────────┐
                                 │  Camoufox   │  一次性手动登录
                                 │  (Firefox)  │  → 持久化会话 cookie
                                 └─────────────┘
```

## 项目背景

MiniMax 网页控制台的 "5h 限额 / 61% 已用 / 2h56m 后重置" 面板其实由
两个 HTTP 接口驱动:

1. `/v1/api/openplatform/coding_plan/remains?GroupId=…` — 5 小时固定窗口的
   剩余百分比 + 倒计时
2. `/backend/account/token_plan_credit` — 套餐池(周维度)的累计额度

两个接口都不接受网页 UI 上的 `api_key`(长得像 `sk-cp-...`)作为
Bearer Token —— 用它会返回 `base_resp = {2062, "no active token plan"}`。
**唯一可行的方案是使用网页会话 cookie**(真实浏览器登录后的 `_token`)。
本项目用 Camoufox 维持一个持久化的 Firefox profile,让 cookie 在
MCP 服务器重启之间保留下来。

## 5 小时固定窗口(不是滚动窗口)

按 MiniMax 官方文档:

> 套餐内额度受 **5 小时固定窗口**和周窗口控制;未使用完的套餐内额度
> **不会结转**到下一个计费周期。

所以窗口边界是**固定**的时钟时段(典型为 CST 00:00 10:00 / 15:00 / 20:00
等),而不是从你的首次请求开始滚动。如果你在窗口切换前几秒查询,返回
的会是**下一个**窗口的数据。响应里的 `interval_start_iso` /
`interval_end_iso` 字段会告诉你具体是哪一段。

## 一行安装

```bash
# 方式 1:从 PyPI 安装(推荐)
pip install minimax-remaining-mcp
# 或
uv pip install minimax-remaining-mcp
# 或
uvx minimax-remaining-mcp    # 不安装直接运行

# 方式 2:从 GitHub 安装(无需 PyPI 账号)
pip install git+https://github.com/yang-cc/minimax-remaining-mcp.git

# 方式 3:本地开发模式
git clone https://github.com/yang-cc/minimax-remaining-mcp.git
cd minimax-remaining-mcp
uv venv .venv --python 3.12
uv pip install -e .
```

## 一次性登录

由于没有 Bearer Token 路径,需要先在 Camoufox 里手动登录一次:

```text
# 1. 启动服务器
python -m minimax_remaining_mcp.server
# 2. 在 MCP 客户端里调用:
minimax_login(timeout_seconds=600)
```

Camoufox 浏览器会弹出并打开 MiniMax 登录页。请手动完成
Cloudflare / CAPTCHA 验证、登录账号,直到浏览器进入 API Keys 页面。
服务器会自动检测到 `_token` cookie 并把会话持久化到 `data/cookies.json`。

## 🔌 DeepSeek Harness (DSH) 集成

DSH 通过 `@deepseek-ai/dsh-mcp-client` 加载 MCP 服务器。在
`~/.dsh/profiles/web/cordis.patch.yml` 里追加下面这段(**注意 package
名是 `minimax-remaining-mcp`,但 Python 模块路径是
`minimax_remaining_mcp.server`**):

```yaml
- insert:
  - id: minimax-remaining-mcp
    name: '@deepseek-ai/dsh-mcp-client'
    config:
      serverName: minimax
      transport: stdio
      command: <repo>/.venv/Scripts/python.exe   # 或 uv 环境的 python
      args: ['-u', '-m', 'minimax_remaining_mcp.server']
      env:
        # 暂停阈值:5h 剩余低于 30% 时触发代理暂停
        MINIMAX_PAUSE_THRESHOLD_REMAINING_PCT: '30'
        # 储存目录(可选,默认 ./data)
        # MINIMAX_DATA_DIR: E:\\codex_dir\\.dsh\\state\\minimax-remaining-mcp
      failOnStartupError: false
      toolCallTimeoutMs: 180000
```

### DSH 集成要点

| 注意点 | 说明 |
|---|---|
| **`-u` 参数** | 让 Python stdio 不带缓冲,DSH 控制台能立刻看到 MCP 服务器日志。 |
| **Python 解释器路径** | 取决于安装方式:<br>• `pip install` → 用系统 Python 或 venv 中的 python<br>• `uv pip install -e .` → `<repo>/.venv/Scripts/python.exe`<br>• `uv tool install` → `uv tool run minimax-remaining-mcp` 也行,但 stdio 缓冲需要 `-u` |
| **首次启动需要登录** | DSH 启动 MCP 服务器时如果 `data/cookies.json` 不存在,调用 `minimax_login()` 会弹出浏览器窗口。 |
| **重启 DSH** | 修改 `cordis.patch.yml` 后必须重启 DSH 才会生效。 |
| **`failOnStartupError: false`** | 推荐设为 `false`,这样即使首次启动时 cookie 还没准备好,DSH 也不会立即报错。 |
| **持久化目录隔离** | 多个项目共用同一个 DSH 时,建议每个项目用不同的 `MINIMAX_DATA_DIR`,避免 cookie 互相覆盖。 |

### DSH 中的典型用法

DSH 启动后,会调用 `minimax_status()` 来判断剩余额度。你可以训练代理在
每次 MiniMax API 调用前先调用一次 `minimax_status()`,观察 `should_pause`
字段:

```text
remaining_percent_5h < 30  → should_pause=true → 代理应停下来或转做其他事
remaining_percent_5h >= 30 → should_pause=false → 可以继续调用
```

更彻底的方案是调用 `minimax_wait_for_quota()`,它会**阻塞**直到额度恢复
到阈值之上(默认 `MINIMAX_PAUSE_THRESHOLD_REMAINING_PCT`),省去代理自己
写轮询逻辑。

## 工具一览

| 工具 | 用途 |
|------|------|
| `minimax_status()` | 网页面板的全部数字:5h 剩余/已用 %、倒计时、套餐累计。低于阈值时设置 `should_pause=true`。 |
| `minimax_window()` | 仅返回代理本地的 5h 观测窗口状态(**与 MiniMax 的固定窗口是分开的**,仅用于代理自节流)。 |
| `minimax_consume(delta=N)` | 把本地窗口消费计数器加 N。每次 MiniMax API 调用后调用一次。 |
| `minimax_wait_for_quota(target_pct=None, poll_seconds=60)` | **阻塞**到 5h 剩余百分比 ≥ `target_pct`。关闭 MCP 连接可中断。 |
| `minimax_login(timeout_seconds=600)` | 弹出 Camoufox 浏览器窗口用于手动登录。 |
| `minimax_smoke()` | 快速 Camoufox 健康检查(打开 example.com)。 |
| `minimax_info()` | 静态配置 + 最近一次会话元数据。 |
| `minimax_clear(confirm=True)` | 清空 cookies / session / window 状态。 |

### ⚠️ 首次冷启动(Camoufox)会比较慢

`minimax_smoke()` 和 `minimax_login()` 第一次启动 Camoufox 时,需要解压
持久化的 Firefox profile、初始化 sqlite 数据库、加载扩展等,通常需要
**30-90 秒**(视磁盘速度而定)。**这是 Camoufox 冷启动的正常表现,不是
bug**——后续启动会复用 `data/profile/` 里的缓存,秒级完成。

如果首次调用超过了你的 MCP 客户端 `toolCallTimeoutMs`(DSH 默认 180s)
而被中止,**重试一次即可看到结果**。如果你预计会频繁冷启动(例如在
CI 里跑),可以把对应 MCP 客户端的 `toolCallTimeoutMs` 调到 300000(5
分钟)。

### `minimax_status()` 响应示例

实际诊断输出(当 5h 窗口已耗尽、应触发暂停时):

![minimax_status 示例输出](remaining_example.png)

下面是规范化后的 JSON 结构:

```jsonc
{
  "ok": true,
  "source": "coding_plan",
  "remaining_percent_5h": 76,             // 5h 窗口剩余 %
  "used_percent_5h": 24,                 // 5h 窗口已用 %
  "seconds_until_reset_human": "4h21m35s",
  "interval_end_iso": "2026-08-25T12:00:00+00:00",
  "interval_status_text": "active",      // active | exhausted | inactive
  "remaining_percent_weekly": 100,
  "seconds_until_weekly_reset_human": "5d08h42m",
  "total_credits": 14000,                // 套餐累计(周维度)
  "used_credits": 3188,
  "remaining_credits": 10812,
  "user_name": "...",
  "group_id": "...",
  "should_pause": false,                 // 低于阈值时为 true
  "model_remains": [
    { "model_name": "general",  "interval_remaining_percent": 76, "interval_status": 1 },
    { "model_name": "video",    "interval_remaining_percent": 100, "interval_status": 3 }
  ]
}
```

## 暂停阈值语义

`MINIMAX_PAUSE_THRESHOLD_REMAINING_PCT=30` 的意思是 **当 5h 窗口的剩余
百分比 < 30% 时暂停**(即已用超过 70%)。对比的是 `remaining_percent_5h`,
**不是**套餐累计的 `remaining_credits` —— 这两者是独立指标。

## 持久化文件

所有状态以纯 JSON 储存在 `data/`(已被 `.gitignore` 屏蔽):

```
data/
├── cookies.json                # Camoufox 会话 cookie
├── session.json                # 最近一次登录元数据
├── window.json                 # 代理本地的 5h 观测窗口
├── last_usage.json             # 最近一次成功的 API 响应(缓存)
└── profile/                    # Camoufox 持久化 Firefox profile(~150 MB)
```

如果 `coding_plan/remains` 返回 401/403,完整响应体会写到
`data/last_coding_plan_failure.json` 方便排查 —— 在怀疑服务挂了之前先
看这个文件。

## 环境变量

全部可选,默认值见下表。

| 变量 | 默认 | 说明 |
|------|------|------|
| `MINIMAX_PAUSE_THRESHOLD_REMAINING_PCT` | `30` | 5h 剩余低于此值时暂停。 |
| `MINIMAX_WINDOW_SECONDS` | `18000` | 代理本地窗口长度(5h)。 |
| `MINIMAX_HEADFUL_ON_LOGIN` | `1` | 登录时强制显示浏览器窗口。 |
| `MINIMAX_CAMOUFOX_OS` | auto | `windows` / `macos` / `linux`。 |
| `MINIMAX_CAMOUFOX_LOCALE` | `zh-CN` | 浏览器语言。 |
| `MINIMAX_HTTP_TIMEOUT` | `15` | API 请求超时(秒)。 |
| `MINIMAX_DATA_DIR` | `./data` | cookies / session 储存目录。 |
| `MINIMAX_WEB_URL` | `https://platform.minimaxi.com` | 覆盖控制台基础 URL。 |
| `MINIMAX_USAGE_API_URL` | `…/backend/account/token_plan_credit` | 套餐池 endpoint。 |
| `MINIMAX_REMAINS_API_URL` | `…/v1/api/openplatform/coding_plan/remains` | 5h 窗口 endpoint。 |
| `MINIMAX_REMAINS_API_URL_FALLBACK` | `api.minimaxi.com/...` | 主 endpoint 失败时使用。 |
| `MINIMAX_LOGIN_HINT_URL` | `…/user-center/basic-information/interface-key` | 登录落地页。 |

## 本地开发 & 调试

```bash
# 启动 MCP 服务器(stdio 模式)
.venv\Scripts\python.exe -u -m minimax_remaining_mcp.server
# 或(Windows)
run.bat

# 直接探测 coding_plan 接口(无需 MCP / 浏览器)
.venv\Scripts\python.exe probe_coding_plan.py

# 检查持久化状态
cat data/cookies.json | head -c 200
cat data/session.json
cat data/last_coding_plan_failure.json   # 如果存在
```

## 打包发布到 PyPI(维护者用)

```bash
# 安装打包工具
pip install build twine

# 在项目根目录构建 wheel + sdist
python -m build
# → dist/minimax_remaining_mcp-0.1.0-py3-none-any.whl
# → dist/minimax_remaining_mcp-0.1.0.tar.gz

# 检查产物
twine check dist/*

# 上传到 PyPI(需要先 `twine login` 或用 token)
twine upload dist/*
# 或:uv publish dist/*
```

发布后任何人可以:

```bash
pip install minimax-remaining-mcp
uv pip install minimax-remaining-mcp
uvx minimax-remaining-mcp    # 临时运行
```

## 限制

- **没有 Bearer-key 路径。** MiniMax 目前没有为 Coding Plan API 发放订阅
  密钥;网页控制台上的 `api_key` 当作 Bearer 用会返回 `2062 "no active
  token plan"`。唯一可行的是会话 cookie。
- **Cloudflare / CAPTCHA 需手动完成。** 首次登录必须由真人完成。
  本项目不接入任何打码服务。
- **5h 窗口是 CST 固定时段。** 在窗口切换前查询,会拿到下一个窗口的数据。
  `interval_start_iso` / `interval_end_iso` 告诉你具体是哪一段。
- **套餐累计(`remaining_credits`)不会结转。** 它是周维度的累计池,
  不会随 5h 窗口重置而清零。

## 许可证

MIT — 详见 `LICENSE`。

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation4/5

Tools are mostly distinct: minimax_status queries live MiniMax quota, minimax_window returns local tracking state, and consume/wait/login/clear/info each target a single operation. The only realistic confusion is minimax_window vs minimax_status, since both concern the 5h window, but the descriptions explicitly separate local no-API state from server-reported state.

Naming Consistency4/5

All tools share the minimax_ prefix and split sensibly into noun-style read tools (window, status, info) and verb-style actions (login, consume, clear, wait_for_quota, smoke). It is not a uniform verb_noun pattern, but the convention is predictable and easy to parse.

Tool Count5/5

Eight tools is a well-scoped size for a quota-management server. Each tool earns its place: authentication, live status, local consumption tracking, blocking wait, state reset, health check, and configuration/session info.

Completeness5/5

The toolset covers the full lifecycle: authenticate, check live quota, track local usage, pause until reset, inspect config, and wipe state. There are no obvious missing operations for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues