Real-time context budget tracking for any AI coding agent.
Plug into Claude Code, Cursor, or any MCP-compatible tool and get:
- 📊 Live token budget bar per agent run
- 🔁 Loop detection (when an agent calls the same tool 3× in a row)
⚠️ Warning / critical alerts before context overflow- 🗄️ Full run history stored in PostgreSQL
- 📈 Budget timeline for every run
- 🔴 BullMQ alert queue for async threshold notifications
- 🔄 Run diff engine — compare two agent runs side by side
No cloud. No telemetry. Runs entirely on your machine.
ContextPulse is a transparent MCP server. You call its tracking tools from your agent's workflow. It counts tokens using tiktoken, updates a live budget in memory, persists everything to PostgreSQL, and fires alerts when thresholds are crossed.
Your agent → calls cp_track_tool_call → ContextPulse counts tokens
→ updates live budget
→ warns at configurable thresholds (70% / 90% by default, model-calibrated — see below)
→ detects loops
→ saves to DB
→ queues BullMQ alert jobs The contextpulse dashboard connects over WebSocket and visualizes everything in real time.
brew services start postgresql@16
# or Docker
docker run -d --name contextpulse-db -e POSTGRES_DB=contextpulse -p 5432:5432 postgres:16brew services start redis
# or Docker
docker run -d --name contextpulse-redis -p 6379:6379 redis:7{
"mcpServers": {
"contextpulse": {
"command": "npx",
"args": ["-y", "contextpulse-mcp"],
"env": {
"DATABASE_URL": "postgresql://apple@localhost:5432/contextpulse"
}
}
}
}{
"mcpServers": {
"contextpulse": {
"command": "npx",
"args": ["-y", "contextpulse-mcp"],
"env": {
"DATABASE_URL": "postgresql://localhost:5432/contextpulse"
}
}
}
}The DB schema is created automatically on first run.
cp_start_session → get sessionId cp_start_run → get runId (optionally pass baselineOverheadTokens — see Accuracy & limitations) cp_track_tool_call → after every tool call (pass tool name, args, output) cp_get_budget → check current budget at any time cp_get_run_summary → full run summary with timeline cp_end_run → clean up
{
"toolCallId": "a1b2c3...",
"inputTokens": 142,
"outputTokens": 87,
"totalTokens": 229,
"budget": {
"used": 14820,
"limit": 200000,
"percentUsed": 7.41,
"warningThresholdPct": 60,
"criticalThresholdPct": 85
},
"budgetStatus": "ok",
"alert": null
}When budget hits the warning threshold (60% by default for Claude models — see Accuracy & limitations):
{
"budgetStatus": "warning",
"alert": "warning"
}| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
postgresql://apple@localhost:5432/contextpulse |
PostgreSQL connection string |
REDIS_URL |
redis://localhost:6379 |
Redis connection for BullMQ |
MODEL |
claude-sonnet-4-6 |
Model in use. Picks the default CONTEXT_LIMIT / thresholds below from a per-model profile (see Accuracy & limitations). |
CONTEXT_LIMIT |
model-derived, else 200000 |
Token limit per session. Set this to override the model's default. |
WARNING_THRESHOLD_PCT |
model-derived, else 70 |
Warning alert threshold (%). Set this to override the model's default. |
CRITICAL_THRESHOLD_PCT |
model-derived, else 90 |
Critical alert threshold (%). Set this to override the model's default. |
LOOP_DETECTION_THRESHOLD |
3 |
Same tool calls before loop alert |
CONTEXT_LIMIT / WARNING_THRESHOLD_PCT / CRITICAL_THRESHOLD_PCT always win if set explicitly. Otherwise ContextPulse picks defaults from MODEL — currently claude, gpt, and gemini have profiles in src/config/index.ts; anything else falls back to 200k / 70% / 90%. Edit that file directly if your model isn't covered or the numbers don't match your plan.
Be aware of two gaps before you treat the reported percentage as exact:
Token counts are an approximation. ContextPulse counts tokens with tiktoken's cl100k_base encoding, which is OpenAI's tokenizer, not Claude's — there's no public Claude tokenizer to use instead. It will drift from what Claude actually bills, especially on code. Treat percentUsed as a trend signal ("am I climbing toward the wall") rather than an exact remaining-token count.
This proxy can't see everything in the context window. ContextPulse only counts tokens that flow through cp_track_tool_call. It has no visibility into your agent's system prompt, other MCP servers' tool schemas, or any server-side context injection — all of which can be substantial (a single MCP server's tool definitions alone can run tens of thousands of tokens). So the tracked total is a floor, not the full picture.
Two ways to close the gap a bit:
baselineOverheadTokensoncp_start_run— pass a rough estimate of what's already spent before the first tracked call (system prompt + other tool schemas), and it's added to the running total from the start.- Per-model thresholds —
claudeprofiles default to tighter thresholds (60% / 85%) than the generic default (70% / 90%) specifically to hedge against this blind spot. TuneWARNING_THRESHOLD_PCT/CRITICAL_THRESHOLD_PCTfurther if you find alerts firing early or late for your setup.
cp_sessions -- one row per coding session
cp_runs -- one row per agent task
cp_tool_calls -- every intercepted tool call
cp_budget_snapshots -- token usage timeline per run
contextpulse-mcp/
src/
mcp/ ← MCP tool handlers
context/ ← token counting + budget engine
alerts/ ← BullMQ queue + worker
diff/ ← run diff engine
db/ ← PostgreSQL schema + queries contextpulse/ ← dashboard repo
app/dashboard/
- contextpulse — Real-time Next.js dashboard for this server
MIT