codex-quota-guard-mcp
# Codex Quota Guard MCP 3.1.1
These docs describe 3.1.1. See [changelog](CHANGELOG.md#311---2026-09-15) for Pro tier pacing and Spark support. Every update pushed to GitHub must increase the package version and synchronize the lockfile, runtime and current documentation.
If Guard is unavailable, report that quota is unverified and continue the user's work; repair Guard when requested and resume checks after recovery. A managed core automatically replaces a saved loopback port denied by the OS, preserving its identity and stored state. Occupied or unauthenticated endpoints are not replaced.
Windows VS Code tasks can now schedule quota resumes through the existing extension IPC owner. See [IPC resume](docs/IPC_RESUME.md). Desktop heartbeat creation and attachment remain unchanged. IPC schedules persist across app closure but run only after the same task reconnects.
Desktop scheduler paths are runtime-only. Guard discovers current Desktop resources at core startup and revalidates on context binding. No saved server path or legacy server environment override is used. The host may provide current CODEX_ELECTRON_RESOURCES_PATH in memory; ambiguous discovery fails closed. Stable MCP capability and task context must pass before monitor availability.
`defer_until_reset.earlyRecovery` reports whether early wake is ready. If false, Codex must resolve the diagnostic and recheck before claiming early recovery; the original timed heartbeat can still be created. Existing defers without an original automation baseline are not automatically adopted: resume manually and create a new defer if still necessary. Reconnect Desktop once to load an updated Guard connector; scheduler rediscovery does not reinstall or stop the shared core.
Quota Guard is a local MCP server that reads the current Codex ChatGPT quota through the official [`codex app-server`](https://learn.chatgpt.com/docs/app-server) interface, admits bounded work segments, and stores redacted checkpoints for resume. It never creates a login, accepts an API key, or reads Codex authentication files.
`quota_status` and `job_preflight` return short action summaries by default (about 1 KB in normal cases). Use `detail="full"` for diagnostics or `detail="compact"` for deduplicated quota data. All modes use the same quota read and policy. See [MCP API](docs/MCP_API.md).
## Security and lifecycle guarantees
- Only the current stable `account.type === "chatgpt"` session is supported. API-key, Bedrock, signed-out, external-token and unstable identities return `CHATGPT_LOGIN_REQUIRED`; no quota percentage is read or cached for them.
- One authenticated `127.0.0.1` core owns SQLite and quota refresh for a Codex profile. Every Codex task gets only a small stdio connector.
- Connectors register an in-memory lease at startup and renew it every 20 seconds, including while the host is idle. This lets pending recovery monitoring restart with Codex before any chat or tool call. A clean disconnect is observed immediately; a crashed connector expires after 60 seconds.
- The core exits about five seconds after the last connector disappears and no request or scheduler dispatch is active. Pending defers do not keep it alive.
- The five-minute early-recovery poll runs only when a connector is alive, a defer is waiting, and the current Codex task supplied a valid scheduler capability.
- There is no Scheduled Task, service, daemon, `launchd`, `systemd`, `wscript`, elevation request, Codex PID scan, browser login, or OAuth fallback.
## Requirements
- Node.js 22.13 or newer (Node 22 and 24 are CI-tested).
- A current Codex installation signed in with ChatGPT.
- PowerShell 7 (`pwsh`) on Windows, used only to apply a private user DACL; elevation is not requested.
Windows 10/11 on physical hardware or in a VM is treated identically. Windows x64 uses x64 Node/Codex; Windows ARM64 uses native ARM64 binaries or Windows' own compatibility layer. The Guard never detects Parallels, VMware, UTM, or the macOS host.
## Install
This project is not published to npm. Install it from its public GitHub checkout:
```powershell
git clone https://github.com/valentine-89/codex-quota-guard-mcp.git
cd codex-quota-guard-mcp
npm ci
npm run check
node scripts/install.mjs
```
Automatic use of an already-banked Codex reset is opt-in. To record standing authorization in the local Guard policy, install with:
```powershell
node scripts/install.mjs --enable-auto-reset
```
This never buys resets or usage credits. It only lets a compatible Codex agent act on a Guard recommendation when a valid banked reset is already reported. The default remains disabled.
The installer preserves unrelated `config.toml` content, creates a private local bearer and runtime settings, and registers the absolute Node executable with `dist/connector.js`. It does not start a persistent process. Restart or reconnect Codex after installation so it opens the new connector.
Guard configuration and state live inside the installed tool at `data/core-<profile hash>/`: `guard.json` holds policy (including automatic reset), `runtime.json` holds private connection settings, and `state.sqlite` holds quota cache, learning, checkpoints, defers and reset recommendations. Each Codex profile has its own directory. Only the MCP registration stays in Codex's `config.toml`. Keep the installation in a writable directory and retain `data/` during future code updates; Git and npm packaging exclude it. Install/uninstall create no configuration backups.
For installations using the old external state directory, close Guard clients and run the **old installation's** `node scripts/uninstall.mjs --purge` before updating its code. Then install this release from the intended installation directory. This is a clean reinstall: old learning, checkpoints, defers, and reset records are deleted. There is no storage migration or fallback. Reapply `--enable-auto-reset` if desired. Review any previously scheduled Guard resume automations separately; deleting local state does not cancel them.
On a Windows machine that also uses WSL, run the installer with Windows Node from `pwsh`; both Windows and WSL tasks then use the Windows-hosted core and the same Windows profile. Native Linux and native macOS each use their own local Node, Codex login and state. See [scheduler diagnostics](docs/TROUBLESHOOTING.md#monitor-unavailable-on-windows-wsl-linux-or-macos) for `monitor.unavailableReason`, capability requirements, and updating the saved server path. The early-recovery monitor accepts a verified Windows named pipe or POSIX Unix-domain socket when Codex supplies the scheduler capability. Do not share credential or state directories across hosts.
## Uninstall
Remove only the MCP registration and stop an authenticated running managed core:
```text
node scripts/uninstall.mjs
```
Also delete the validated Guard-owned private state directory:
```text
node scripts/uninstall.mjs --purge
```
Both modes preserve unrelated Codex configuration and create no removal backup. `--purge` can also finish cleanup after the registration or config file has already been removed, using only the current profile's standard managed directory. Redirected and unrecognized purge paths are rejected.
When asking Codex to uninstall, also have it review any Guard-owned resume automations, old data and configuration backups, and the installation folder. Those items require context and are not automatically deleted by this script. Close or disconnect existing Guard clients before removal.
## MCP use
The public contract has eight tools:
- `quota_status`: call near the beginning of long work with `agentProtocol="auto-reset-v1"`.
- `job_preflight`: call with the same protocol marker and a stable `jobId` before each substantial token-consuming segment.
- `quota_profile`, `checkpoint_create`, `checkpoint_get`, `defer_until_reset`, `defer_automation_attach`, and `resume_prepare` support policy and controlled resume.
- Ordinary schedules call `resume_prepare(trigger="automation")` without `deferId`: quota is revalidated, no Guard wake is consumed/cancelled. Guard recovery schedules must supply the original `deferId`; invalid, early or replayed wakes still exit. Both paths must honor `action` (`continue`, `wait`, `exit`) before preflight.
- Resume output uses only `action`: `continue` permits preflight, `wait` blocks work pending quota recovery, `exit` discards an invalid/early/consumed Guard wake. The old `canResume`, `shouldExit`, and `cancellationBestEffort` fields are removed without aliases. Empty metadata is omitted; non-empty `automationIdsToCancel` still means best-effort cancellation of only those owned IDs. Quota is summarized; use `quota_status(detail="full")` for diagnostics. Update saved caller prompts to this contract.
Do not call the Guard before every shell command, small file read, or trivial edit. No tool accepts credentials, a force-refresh flag, or a model name.
Version 1 requires an auto-reset-aware agent. When enabled, `quota_status.resetCredit.recommendation` is emitted only for a fresh, known account with a valid banked reset, weekly remaining quota at or below Free/Go 5%, Plus 2%, or another recognized plan 1%, and a weekly reset more than 72 hours away. The agent calls the host `consume_usage_reset` tool with the exact returned idempotency key without asking again, then reports the exact result in `quota_status.resetFollowup`. Missing reset-credit data is treated as zero available resets. Cached recommendations are suppressed as soon as the configured reset horizon is reached.
After a definitive reset result, the Guard performs proof-bound rechecks after 3, 5, and 10 additional seconds. It verifies a changed weekly reset epoch or increased remaining percentage. If propagation is still not visible after 18 seconds, the epoch remains consumed and cannot produce another reset recommendation; later ordinary status calls continue bounded revalidation. Duplicate successful follow-ups preserve the consumed or verified state without restarting propagation checks; conflicting late outcomes are rejected.
Weekly-only pacing uses the weekly policy threshold as its reserve, not the five-hour reserve or a fixed percent conversion. With both 5h and weekly windows, each forecast uses its own reserve: the lane's adaptive reserve for 5h, and configured `weeklyOnlyRemainingPercent` for the weekly window. Forecasts are combined by time remaining, not by comparing raw percentages. Included weekly-only jobs may span periodic checks even at 4–10% remaining: check every five minutes above the caution band, every minute within it, or faster when forecast exhaustion is imminent. Pro pacing can extend these intervals when every reported window is healthy; five-hour constraints remain enforced. A detected account, plan (including Plus/Pro), or quota-mode change discards old pacing samples and forecasts, including when switching back; detection uses the next normal fresh quota read, never auth files or forced refresh. Checkpoints and owned wake records are not deleted by this pacing reset.
Ordinary quota refresh remains caller-driven. During active work, `quota_status` and `job_preflight` expose a `checkAgainBy` deadline: primary Pro x5/x20 work gets up to 10/20 minutes with a five-hour window or 30/60 minutes with only a weekly window when every window has at least 50% remaining and burn is low. At 20–49%, these Pro intervals halve. Other healthy weekly-only work gets up to five minutes; near-reserve or high-risk cases retain shorter checks. All Pro deadlines are capped by resets and half the forecast time to reserve. Absent an imminent reserve forecast, `estimatedMinutes` may exceed `maxSegmentMinutes` in every quota mode: a long job is allowed across periodic checks without a split/checkpoint warning solely due to duration. `maxSegmentMinutes` bounds unchecked work, not the entire job; revalidate at the deadline and continue the same job if admitted. Atomic operations still must fit the current admission. Group related small steps under one admission and avoid paired status/preflight calls. The shared refresh lease, backoff and forecast reserve limit still apply. With no request, no new background reader runs.
The installer automatically adds a marked Quota Guard instruction block to the active profile's global `AGENTS.md` (or non-empty `AGENTS.override.md`, which Codex prioritizes). This guides new tasks across all projects to discover and use Guard from the start, including preflight, checkpoint and resume. Personal instructions are preserved; repeated installation updates the same block. Uninstall removes only the marked block from both files. No backup files are retained. Run the installer again when upgrading or changing the global override file, then start a new task to load the guidance. Each separate `CODEX_HOME` needs its own installation. This is agent guidance, not a hard execution gate; explicit user and higher-priority/project instructions can change behavior.
Personalization contains only compact bootstrap rules; admission, freshness, lease, backoff and reset eligibility remain enforced by Guard code. Shared MCP `instructions` contain common action rules, with scheduling/reset details localized to the relevant tools rather than repeated for every tool. Regression tests cap the managed block and shared instructions to prevent prompt growth. The [Codex AGENTS snippet](examples/AGENTS-snippet.md) is detailed reference documentation, not text to add alongside the installed block. Global precedence follows [Codex documentation](https://learn.chatgpt.com/docs/agent-configuration/agents-md).
For a schedulable defer, the Guard returns a complete same-task one-shot `automationRequest` with the fixed `Continue the work.` prompt. Pass it unchanged to the host automation tool and attach only the returned ID; no automation inventory scan, scheduler-documentation lookup, or model-authored prompt is required.
The registered STDIO connector supports the stable MCP `initialize`/`initialized` lifecycle used by Codex by default. The authenticated loopback core also retains MCP `2026-07-28` support for internal clients. Connector startup ensures the core, binds inherited Desktop context when available, and registers a live-client lease. Discovery itself does not read quota. Background quota polling still requires pending recovery and a verified scheduler.
`quota_status.monitor` reports `runtimeMode="shared-http"`, `requiresLiveClientConnection=true`, and `lifecycleMode="codex-bound"`.
Verification has three distinct levels: a healthy authenticated `/health` response proves only that the shared core is running; a successful stable handshake and an eight-tool catalog in a fresh Codex thread prove that Desktop loaded the MCP; a Guard tool call recorded for that same thread proves that the agent used it. Do not infer the latter two from core health or an independent smoke test.
## Verification
```powershell
npm run check
npm run acceptance:install
npm audit
npm pack --dry-run
```
These portable checks run on Node 22/24 for Windows x64/ARM64, Ubuntu x64/ARM64, and macOS Intel/Apple Silicon in CI. `npm run acceptance:live` additionally verifies the currently installed registration and live quota on a signed-in host.
`npm run acceptance:shared` is a maintainer-only Windows desktop acceptance. It requires `CODEX_HOME`, the current real task ID in `QUOTA_PROBE_TASK_ID`, and an inherited desktop scheduler capability; it is not a portable installation check.
Release acceptance is recorded by guest OS. A Windows VM is simply a Windows acceptance result; there are no hypervisor-specific branches.
See [architecture](docs/ARCHITECTURE.md), [security](docs/SECURITY.md), [monitor behavior](docs/MONITOR.md), [Windows and WSL](docs/WINDOWS_AND_WSL.md), [MCP API](docs/MCP_API.md), and [troubleshooting](docs/TROUBLESHOOTING.md).
## Active-work pacing
Quota checks follow the returned deadline during active work, independently of saved checkpoints. Both status and preflight use bounded shared freshness. Honor `canStartSegment`, `validUntil` and `maxSegmentMinutes`; long jobs may span multiple admissions. Save progress before expensive or detached GPU jobs. Idle GPU waiting is not active Codex work.
Forecasts use fresh quota samples and reset on account/plan/bucket changes, quota restoration, reset epochs, errors or long gaps. Healthy Pro primary windows permit longer admissions even at cold start; stale data cannot admit new work. These estimates are advisory and cannot interrupt a model generation. See [MCP API](docs/MCP_API.md) for fields and limits.
Pro capacity is identified as `prolite` (x5) and `pro` (x20, four times x5). Reported percentages are never scaled. `laneId=spark` selects GPT-5.3-Codex-Spark for small work, independently of `secondary` (Luna reserve). Admission does not switch models or combine their quotas. Reuse admission until `checkAgainBy`; `nextRefreshAt` is cache eligibility, not a request to call again. See [Pro and lightweight API rules](docs/MCP_API.md#pro-tiers-and-lightweight-models).
TDQS
Scored across 5 tools
Each tool targets a distinct action: reading quota status, preflight-gating expensive jobs, persisting checkpoints, reading checkpoints, and handling deferral. quota_status and job_preflight both relate to quota state, but their roles as snapshot reader versus execution gate are clear from the descriptions.
All names are lowercase snake_case and readable, but they mix conventions: quota_status and job_preflight are noun_noun, checkpoint_create and checkpoint_get are noun_verb, and defer_until_reset is a verb phrase. The inconsistency is noticeable but not chaotic.
Five tools is well-scoped for a quota-guard server. Each tool covers a necessary part of the workflow without redundancy, and the count feels appropriately minimal rather than padded.
The core lifecycle is covered: status checking, preflight gating, checkpoint persistence/retrieval, and deferral handling. Minor gaps like checkpoint deletion/update, listing checkpoints, or an explicit reset/release action are absent, but they are not essential to the server's stated purpose.