agent-activity

agent-activity

A read-only MCP server that exposes local coding-agent session logs as three tools for introspection of recent work, debugging tool failures, and tracking token usage and estimated cost without parsing log files.

Category
Visit Server

README

agent-activity

A read-only MCP server that exposes your local coding-agent session logs (the JSONL transcripts written by Claude Code at ~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl) as three tools, so you — or an agent — can introspect recent work, debug tool failures, and track token/estimated cost without hand-parsing log files.

Guarantees

  • Read-only. The server only ever reads log files; it never writes to, deletes, or otherwise mutates anything under the log root.
  • Local. All data comes from the filesystem on the machine the server runs on.
  • No network. The server never makes an outbound network call — not for logs, not for pricing data, not for telemetry. Pricing is a local, configurable table (see Cost is an estimate).
  • stdio transport. Standard MCP over stdio, via the official mcp Python SDK (FastMCP).

Tools

list_recent_sessions(limit=20, repo=None)

Recent sessions, most-recently-active first.

  • limit — max sessions to return (default 20, max 200).
  • repo — optional substring filter against the session's repo/cwd.

Returns, per session: session_id, repo, cwd, git_branch, start/ end timestamps, message_count, schema_status ("verified" or "unverified" — whether the log's shape matched what this server expects; degrades gracefully rather than failing on drift), and a usage block (total_tokens, total_cost, cost_status, and a main/sidechain breakdown — see Sidechains).

tail_agent_log(session, limit=100, include_current=False)

The tail of one session's transcript, oldest-first.

  • session — a full session UUID, a unique UUID prefix, or "latest" (see Session resolution).
  • limit — max entries to return (default 100, max 1000).
  • include_current — when resolving "latest", whether to allow it to resolve to the session currently calling this tool (default False).

Returns session_id, repo, and a list of entries, each with type, timestamp, any tool_calls (tool_use_id, tool_name) and tool_results (tool_use_id, is_error), and — for assistant entries that carry usage — a usage block with model, per-entry tokens, and estimated cost.

summarize_tool_calls(session)

Per-tool aggregate for a session: invocation counts, error counts, which calls failed, and total usage.

  • session — a full session UUID, a unique UUID prefix, or "latest" (resolved including the current session — summarizing your own live session is a valid use case here).

Returns session_id, repo, is_live_session, per_tool (per tool name: ok/error/pending/in_progress counts), totals (the same breakdown across all tools, plus rejected), by_source (main vs sidechain totals), failing_calls (each labeled error or rejected), and a session-level usage block (tokens + estimated cost).

All three tools return a structured {"error": ...} dict (never raise) when a session argument is ambiguous ("ambiguous_session", with candidates) or matches nothing ("session_not_found").

Cost is an estimate, not a bill

Session logs record token counts (message.usage) but not dollar cost. Cost is computed by multiplying token counts by a per-model rate table (pricing.py) — order-of-magnitude, hand-maintained figures that will drift as providers change pricing. Treat any cost field as a ballpark to sanity-check spend, not an authoritative bill. Unknown models degrade to cost_status: "unknown" (tokens are still reported) rather than raising.

Override the table with your own by pointing AGENT_ACTIVITY_PRICING_FILE at a JSON file shaped like:

{
  "claude-sonnet-5": {
    "input": 3.00,
    "output": 15.00,
    "cache_write": 3.75,
    "cache_read": 0.30
  }
}

Rates are USD per 1,000,000 tokens. A model listed in the override file fully replaces that model's default entry; models you don't mention keep their built-in defaults.

Sidechains and subagents

Subagent ("sidechain") activity lives in separate sibling files (<session-dir>/subagents/agent-*.jsonl), not inline in the main session file. This server associates those files with their parent session and includes their tool calls and token usage in summarize_tool_calls and list_recent_sessions, but keeps every count and token total tagged main vs sidechain so totals stay decomposable rather than blended.

Sidechain usage is summed only from the sidechain files' own message.usage entries. The parent log's separate rollup fields (toolUseResult.totalTokens / the <usage>...</usage> text tag on the spawning Agent tool's result) are a second, independently-computed aggregate of the same work — summing both would double-count, so those fields are never added into the totals here.

Config

Env var Default Purpose
AGENT_ACTIVITY_LOG_ROOT ~/.claude/projects/ Root directory to scan for */*.jsonl session logs.
AGENT_ACTIVITY_PRICING_FILE (none — built-in table) Path to a JSON pricing-table override (see above).
AGENT_ACTIVITY_CALLER_SESSION_ID (none — falls back to a heuristic) The calling session's own id, if your MCP client can supply it. Used to reliably identify "the current session" for "latest" resolution; without it, the server falls back to a newest-mtime heuristic (documented limitation: can misfire with concurrent sessions).

Install

pip install -e .

This installs the agent-activity console script and its one dependency (mcp).

Run

Any of the following start the same stdio server:

agent-activity
python -m agent_activity
python -m agent_activity.server

The process speaks MCP over stdio (stdin/stdout) — it's meant to be launched by an MCP client, not run interactively.

Register with an MCP client

An example client registration is checked in at .mcp.json:

{
  "mcpServers": {
    "agent-activity": {
      "command": "agent-activity",
      "args": [],
      "env": {
        "AGENT_ACTIVITY_LOG_ROOT": "~/.claude/projects"
      }
    }
  }
}

Point command at the console script (make sure it's on PATH, e.g. by installing into the environment your MCP client uses), or swap it for python with args: ["-m", "agent_activity"] if you'd rather invoke the module directly.

Example tool calls

Once registered, a client can call e.g.:

list_recent_sessions(limit=5)
tail_agent_log(session="latest", limit=50)
summarize_tool_calls(session="latest")

or target a specific session by its full UUID or an unambiguous prefix:

tail_agent_log(session="4140dfe3", limit=200)

How session resolution works

The session argument to tail_agent_log and summarize_tool_calls accepts:

  • a full session UUID — exact match against the log filename stem;
  • a unique UUID prefix — resolves if exactly one discovered session id starts with it; an ambiguous prefix (matches more than one) returns a structured error listing the candidates rather than guessing;
  • "latest" — the most-recently-active session (newest log file mtime). By default this excludes the session currently calling the tool, so tail_agent_log(session="latest") doesn't tail its own still-being-written log; pass include_current=True to opt back in. (summarize_tool_calls resolves "latest" including the current session by default, since summarizing your own live session is a normal thing to want.)

Identifying "the current session" is inherently a heuristic — an MCP server isn't told its caller's session id by the protocol. If the AGENT_ACTIVITY_CALLER_SESSION_ID env var is set, it's used directly (authoritative). Otherwise the server falls back to "the session with the newest file mtime" (optionally scoped to the caller's cwd), which can misfire if two sessions are active at once.

Development

pip install -e .[dev]
pytest tests/ -q

An end-to-end stdio smoke test (spawns the real server as a subprocess, performs the MCP handshake, and calls all three tools against real logs) lives at scripts/smoke_test.py:

python scripts/smoke_test.py

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured