DEV Community

Diya
Diya

Posted on

I built an MCP server that tracks your Claude Code context budget in real time📎

Every developer using Claude Code or Cursor has hit this wall: the agent starts looping, responses get worse, and then — context overflow. You had no warning. You had no visibility. You just lost the whole session.

I built ContextPulse to fix that.

What is ContextPulse?

ContextPulse is a framework-agnostic MCP server that sits between your AI coding agent and your tools. It intercepts every tool call, counts tokens in real time, tracks your context budget, and fires alerts before you hit the wall.

It ships in two repos:

  • contextpulse-mcp — the MCP server + NestJS REST API + WebSocket gateway + BullMQ alert queue
  • contextpulse — the Next.js real-time dashboard

The problem it solves

Current observability tools (Langfuse, LangSmith, Phoenix) are framework-first and show you cost after the run. They don't tell you during the run that you're at 87% context and one tool call away from overflow.

And nobody in open source lets you compare two agent runs side by side to see what changed after a prompt edit.

ContextPulse does both.

Features

Phase 1 — MCP server core

  • Intercepts tool calls via the MCP protocol
  • Counts tokens using tiktoken (cl100k_base)
  • Stores everything in PostgreSQL — sessions, runs, tool calls, budget snapshots, alerts
  • Fires warnings at 70% and critical alerts at 90% context usage
  • Detects loops: when the same tool is called 3× in a row

Phase 2 — Real-time dashboard

  • NestJS REST API: GET /api/runs, /api/runs/:id, /api/runs/:id/tool-calls, /api/runs/:id/alerts
  • WebSocket gateway (Socket.io) pushes live events to the dashboard
  • Next.js 15 dashboard with live budget bar, tool call waterfall, alert feed, event log

Phase 3 — BullMQ alert queue + loop graph

  • BullMQ async alert worker: processes budget and loop alerts without blocking the MCP server
  • Optional webhook delivery via ALERT_WEBHOOK_URL
  • Loop detection frequency chart — highlights tools called above the loop threshold in red

Phase 4 — Run diff engine

  • GET /api/diff?runA=<id>&runB=<id> compares two runs
  • Returns token delta, tool call delta, budget winner, new loops introduced, loops resolved
  • Full diff UI in the dashboard: side-by-side stat cards, delta table, tool-by-tool breakdown

Tech stack

TypeScript · NestJS · Next.js 15 · PostgreSQL · Redis
BullMQ · WebSocket (Socket.io) · MCP SDK · tiktoken · Zod · Tailwind
Enter fullscreen mode Exit fullscreen mode

Quick start

1. Start PostgreSQL

createdb contextpulse
Enter fullscreen mode Exit fullscreen mode

2. Clone and run the MCP server

git clone https://github.com/DIYA73/contextpulse-mcp
cd contextpulse-mcp
npm install
cp .env.example .env
npm run dev:api   # NestJS API on port 3000
npm run dev:mcp   # MCP server on stdio
Enter fullscreen mode Exit fullscreen mode

3. Add to Claude Code

// ~/.claude/settings.json
{
  "mcpServers": {
    "contextpulse": {
      "command": "npx",
      "args": ["tsx", "/path/to/contextpulse-mcp/src/proxy/server.ts"],
      "env": {
        "DATABASE_URL": "postgresql://localhost:5432/contextpulse"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Run the dashboard

git clone https://github.com/DIYA73/contextpulse
cd contextpulse
npm install
echo "NEXT_PUBLIC_API_URL=http://localhost:3000" > .env.local
npm run dev   # Dashboard on port 3001
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3001 — you'll see the live dashboard.

Using it in your agent

cp_start_session   → get sessionId
cp_start_run       → get runId
cp_track_tool_call → call after every tool call
cp_get_budget      → check live budget anytime
cp_get_run_summary → full run summary with timeline
cp_end_run         → clean up
Enter fullscreen mode Exit fullscreen mode

Example response from cp_track_tool_call:

{
  "toolCallId": "a1b2c3...",
  "inputTokens": 142,
  "outputTokens": 87,
  "totalTokens": 229,
  "budget": {
    "used": 14820,
    "limit": 200000,
    "percentUsed": 7.41
  },
  "budgetStatus": "ok",
  "alert": null
}
Enter fullscreen mode Exit fullscreen mode

When budget hits 90%:

{
  "budgetStatus": "critical",
  "alert": "critical"
}
Enter fullscreen mode Exit fullscreen mode

The run diff engine

This is the feature I haven't seen anywhere else in open source.

After changing your prompt or agent config, you can compare two runs side by side:

GET /api/diff?runA=<uuid>&runB=<uuid>
Enter fullscreen mode Exit fullscreen mode

The response tells you:

  • Which run used fewer tokens (and by how much %)
  • Which tools appeared only in one run
  • New loops introduced in Run B
  • Loops that were resolved from Run A
  • Per-tool token delta

The dashboard shows it as a full diff UI with a summary sentence like:

"Run B used 12,400 fewer tokens (23% more efficient). Run B resolved 1 loop: read_file."

What I learned building this

Context engineering is the real bottleneck. Not model capability. The GitHub MCP server alone costs 42,000–55,000 tokens in tool definitions before you type a single prompt. Tracking this in real time changed how I think about agent design.

BullMQ graceful fallback matters. The alert queue degrades to console logging when Redis isn't available. This made the MCP server safe to use without Redis — alerts still fire, they just aren't queued.

TypeScript strict mode with exactOptionalPropertyTypes catches real bugs. The BullMQ + ioredis version conflict (two different Redis class definitions) only showed up clearly because of strict typing.

Repos

If this is useful to you, a ⭐ on GitHub goes a long way. And if you build something on top of it, I'd love to see it.

Top comments (0)