mcp-context-inspector
It's an MCP server (ctxwindow) that records agent-execution metrics and lets you inspect per-session token usage, cost, tool activity, and the full context-window timeline.
Record one agent run's metrics (prompt, model, tokens, latency, trace, context blocks) via
record_session— append-only, returns a newsession_id.Get full session metrics: metadata plus per-prompt tokens, latency, and cost (
get_session_metrics).Get per-turn input/output token and latency breakdowns (
get_token_breakdown).Get tool-call counts grouped by ok/error status (
get_tool_metrics).Replay the ordered tool-call sequence for a session (
get_agent_trace).Estimate USD cost for one session or a recent time window (
get_cost_estimate).List recent sessions to discover session IDs (
get_recent_sessions).Get an ordered, categorized breakdown of everything that entered a session's context window, marking user-visible vs invisible overhead with token estimates (
get_context_timeline).All read tools are read-only/idempotent and scoped to the caller's own sessions (owner token sees all); only
record_sessionwrites.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-context-inspector show me the context timeline for session abc-123"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.

Independent, unaffiliated open-source project. ctxwindow is not built, maintained, or endorsed by Anthropic. "Claude" and "Claude Code" are Anthropic's products; ctxwindow reads their publicly documented OpenTelemetry export and MCP protocol, nothing more.
The package/repo name on disk stays mcp-context-inspector; the product it ships is
called ctxwindow (after its domain, ctxwindow.uk).
Quick start
Live demo, no install: https://ctxwindow.uk
Not yet published to PyPI, so run it from source (Python 3.11+):
git clone https://github.com/sohaibsohail98/mcp-context-inspector
cd mcp-context-inspector && uv run python -m mcp_server.serverWith no MCP_AUTH_TOKEN set, the server generates and prints one on startup, using the
same trust model as a Jupyter server's printed token.
Then sign in at /auth/login (locally or on the live demo) and the page hands you one
command that writes the MCP connection and telemetry config into your own
~/.claude/settings.json (backed up first, merged, never overwritten):
curl -fsSL https://ctxwindow.uk/setup/install?t=<code> | shOn Windows the page's Windows (PowerShell) tab gives you the equivalent
irm "https://ctxwindow.uk/setup/install?os=windows&t=<code>" | iex instead.
The ?t= code is single-use and short-lived, so your real token is never in the command
itself. Close and reopen Claude Code afterward, since env vars only load at process
startup, then run one prompt and check "Test my connection" on the page.
Prefer to wire it up by hand, or connect claude.ai, the Messages API, or Copilot instead? See Usage and Run it locally.
Related MCP server: ai-usage-metrics-mcp
Documentation
Docs site, the full single-page reference (architecture, auth model, storage backends, deploying your own, environment variables, roadmap)
CONTRIBUTING.md, lint, tests, and what a good PR looks like here
LICENSE, MIT
Report a bug or ask a question. For a security issue, please open a private security advisory instead of a public issue.
Why this exists
Most agent observability tools re-show data your own UI already displays. ctxwindow shows something you normally can't see at all: system prompt, tool specs, reasoning, tool calls and results, and the final answer, in the order they actually entered context. Each block is measured against the model's real context window and marked as either visible to the user or invisible overhead. Token counts are honest, labeled estimates, not exact provider usage (see Architecture for why that tradeoff is the right one here).
Anthropic's Claude Code docs page, "Explore the context window", is an interactive simulation of what loads into a session and what each file read costs. It motivated wanting the same visibility for an arbitrary agent loop, not just Claude Code.
The 8 MCP tools
Tool | Returns | Read/write |
| Session metadata + per-prompt tokens/latency/cost | Read |
| Per-turn token/latency breakdown | Read |
| Tool call counts by status | Read |
| Ordered tool-call sequence for one session | Read |
| Estimated cost, one session or a time window | Read |
| Most recent sessions, newest first | Read |
| Full context-window block breakdown | Read |
| Records one agent execution's metrics | Write (append-only) |
Each tool ships explicit MCP annotations (readOnlyHint / destructiveHint /
idempotentHint / openWorldHint), so a client can auto-approve the seven reads and
prompt only for record_session. Nothing here reaches outside this server's own store
(openWorldHint is always false), and record_session only ever inserts a new session —
it never mutates or deletes one.
Plain REST equivalents are exposed under /api/*. Payload shapes are in
Architecture.
Infrastructure
The live deployment (Cloud Run, Firestore, Secret Manager, Artifact Registry, the
Cloudflare custom domain fronting ctxwindow.uk) is defined in
infrastructure/terraform and applied by CI, not by hand.
Every pull request runs terraform plan alongside tflint and checkov; merging to
main runs terraform apply with the freshly built image tag. See
Deploying your own for the shape of it if you're
standing up a separate copy.
Contributing
See CONTRIBUTING.md for lint, tests, and what a good PR looks like
here. Run the suite with uv run pytest and lint with uv run ruff check ..
License
MIT licensed; see LICENSE. Developed alongside
sre-investigation-agent,
the reference chat UI and Bedrock agent this package was extracted from.
Available Tools
8 toolsget_agent_traceARead-onlyIdempotent
The ordered sequence of tool calls for one session -- each entry {name, args, status}.
Use to replay what the agent actually did, in execution order; use get_tool_metrics for aggregate counts.
session_id: id from get_recent_sessions / record_session.
Returns [] for an unknown or non-owned session.
Inputs: session_id (required).
get_context_timelineARead-onlyIdempotent
Ordered, categorized breakdown of everything that entered ONE session's context window.
Each block (system prompt, tool specs, injected context, user turns, reasoning, tool calls/results, final answer) is marked user-visible vs invisible overhead, with cumulative character-based token estimates against the model's real window size. Use for context-window composition analysis; use get_session_metrics for exact provider token usage. The estimates here are character-based, not exact Bedrock counts.
session_id: id from get_recent_sessions / record_session.
Returns [] for an unknown or non-owned session, or one recorded without the optional context_blocks field.
Inputs: session_id (required).
get_cost_estimateARead-onlyIdempotent
Estimated USD cost as a float.
Pass session_id for one session's cost, or period_seconds for the summed cost of your sessions in the last N seconds. Give exactly one; non-owners are scoped to their own sessions. These are estimates from token counts and a static price table, not billed amounts.
session_id: optional session id. period_seconds: optional lookback window in seconds (e.g. 86400 for the last day).
Returns 0.0 for an unknown or non-owned session_id, and for a period with no matching sessions.
Inputs: session_id, period_seconds. Returns: result
get_recent_sessionsARead-onlyIdempotent
List recent sessions, newest first: [{session_id, prompt, model_id, created_at, ...}].
Call this first to discover session_ids for the other get_* tools. Non-owners see only their own sessions; the owner token sees all.
limit: max rows to return (default 10), newest first.
Inputs: limit.
get_session_metricsARead-onlyIdempotent
Full metrics for ONE recorded session: metadata plus per-prompt tokens, latency, and cost.
Use when you have a session_id and need exact provider usage numbers for that session. For the block-by-block token composition of the context window use get_context_timeline instead; for a cost total across many sessions use get_cost_estimate.
session_id: the opaque, case-sensitive id returned by record_session or listed by get_recent_sessions.
Returns {"error": "session not found"} if the id is unknown or not owned by the caller (the two are deliberately indistinguishable).
Inputs: session_id (required).
get_token_breakdownARead-onlyIdempotent
Per-turn input/output token and latency breakdown for one session, in turn order.
Use to see how token usage grew turn-by-turn within a session; use get_session_metrics for session totals.
session_id: id from get_recent_sessions / record_session.
Returns [] for an unknown or non-owned session.
Inputs: session_id (required).
get_tool_metricsARead-onlyIdempotent
Tool-call counts grouped by status (ok / error), for one session or aggregated.
Use for a quick success/failure summary; use get_agent_trace for the ordered call list. Non-owners only ever see their own sessions; the owner token sees everyone's.
session_id: optional. Omit for the aggregate across all your sessions; pass an id for just that session.
Inputs: session_id.
record_sessionA
Append ONE agent execution's metrics to this server's store; returns the new session_id.
This is how a remote agent gets its own runs into the server, rather than only being able to query what the server owner recorded locally. Attributed to the connected identity: your Google account if you signed in via /auth/login, or owner=None for the owner token. NOT idempotent -- each call mints a new session_id. Never updates or deletes an existing session; the get_* tools read what this writes.
prompt: the user prompt that started the run. model_id: the provider model identifier, e.g. "anthropic.claude-3-5-sonnet-20241022-v2:0". loop_result: the run's token / latency / trace payload. Required keys: input_tokens (int), output_tokens (int), total_tokens (int), latency_ms (float), turns (list). Optional: trace (list), context_blocks (list -- omit if you don't have per-block context data; get_context_timeline needs it).
each
turnsitem: input_tokens (int), output_tokens (int), latency_ms (float); optional cache_read_input_tokens / cache_write_input_tokens (int, default 0).each
traceitem: tool (str), args (dict), status (str); optional latency_ms (float, default 0), timestamp (float epoch seconds, default record time).each
context_blocksitem: category (str), label (str), char_count (int), token_estimate (int); optional turn_n (int or null -- null for a pre-conversation block), status (str), content (str).
Example loop_result:
{
"input_tokens": 1200, "output_tokens": 340, "total_tokens": 1540,
"latency_ms": 4210.0,
"turns": [
{"input_tokens": 1200, "output_tokens": 340, "latency_ms": 4210.0,
"cache_read_input_tokens": 800, "cache_write_input_tokens": 0}
],
"trace": [
{"tool": "grep_logs", "args": {"pattern": "ERROR"}, "status": "ok",
"latency_ms": 120.0, "timestamp": 1756400000.0}
]
}
Inputs: prompt (required), model_id (required), loop_result (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each read tool targets a distinct slice of session data—totals, per-turn breakdown, tool-call counts, ordered trace, cost, context timeline, and session discovery—and the descriptions explicitly point to which tool to use. record_session is the only write tool and is clearly separated. No two tools are fungible.
All read tools follow a consistent get_<object>_<metric> snake_case pattern, and the single write tool uses the verb record_session. The naming is predictable and matches each tool's function without mixing conventions.
Eight tools is well-scoped for a session-metrics store: one intake tool, one session-discovery tool, and six focused query/analytics views. Each tool earns its place with no redundancy or bloat.
The server covers the full intended lifecycle: record_session ingests runs, get_recent_sessions discovers session IDs, and the get_* tools provide totals, turn-level detail, tool traces, cost estimates, and context-window composition. Update and delete are deliberately excluded from this append-only metrics store, so there are no obvious dead ends.
Maintenance
Related MCP Connectors
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP observability. Query live traffic, errors, duration, and alerts from your AI agent.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Analytics for MCP servers. Find out which of your tools agents get wrong. MCPulse shows you which tools AI agents retry, which come back empty, and which they never call at all. Two lines inside your own server. It never sees your arguments or your results. getmcpulse.com
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP-native agent evaluation and observability server. Log traces, evaluate output quality with 12 built-in rules (PII detection, prompt injection, cost thresholds), and track agent costs. Real-time dashboard, OTel-compatible spans. Self-hosted, MIT licensed.12115 npm9MIT
- AlicenseAqualityDmaintenanceA MCP server for tracking AI usage metrics and structured logs across applications. Monitor model calls, analyze usage patterns, track costs, and debug AI interactions.54 npmMIT
- AlicenseAqualityFmaintenanceAn MCP server that provides cost and reliability observability for LLM and agent workflows. It records model calls and allows querying and aggregating telemetry data through MCP tools.6MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that gives AI agents observability over their own tool calls, enabling auditing, cost tracking, latency analysis, and alerting.MIT