agent-activity
agent-activity is a read-only MCP server that exposes local Claude Code session logs for introspection, debugging, and cost tracking — without hand-parsing JSONL files.
List recent sessions (list_recent_sessions): Browse up to 200 recent coding-agent sessions (newest first), optionally filtered by repository substring. Each session includes ID, repo/cwd, git branch, timestamps, message count, schema status, and token/cost usage split by main vs. sidechain activity.
Tail session transcripts (tail_agent_log): Retrieve the last N entries (up to 1000) from a session's log in chronological order, showing entry types, timestamps, tool calls (with outcomes: ok/error/pending), tool results, and per-entry token/cost usage. Sessions can be resolved by full UUID, unique prefix, or the keyword "latest".
Summarize tool call activity (summarize_tool_calls): Get an aggregate breakdown of tool usage for a session — per-tool counts by outcome (ok/error/pending/in_progress), overall totals, main vs. sidechain split, failing/rejected calls, and session-level token and cost estimates. Works on live sessions, labeling active pending calls as in_progress.
Key properties:
Read-only: never writes or modifies log files
Local only: reads from
~/.claude/projects/by default, no outbound network callsCost estimation: built-in per-model pricing table, overrideable via custom JSON; reports
"unknown"for unfamiliar modelsSidechain/subagent support: includes and tags subagent activity without double-counting
Graceful error handling: returns structured
{"error": ...}dicts instead of exceptions for ambiguous or missing sessions
Click on "Install 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., "@agent-activityshow my recent sessions"
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.
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
mcpPython SDK (FastMCP).
Related MCP server: log-mcp
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, cwd=None)
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 (defaultFalse).cwd— optional exact working-directory path; scopes"latest"resolution and current-session detection to sessions from that directory.
Returns session_id, repo, schema_status (as in
list_recent_sessions), and a list of entries, each with type,
timestamp, any tool_calls (tool_use_id, tool_name, and outcome
— ok/error/pending, joined against the whole session so a call's
outcome is known even when its result entry falls outside the returned
tail) 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, cwd=None)
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).cwd— optional exact working-directory path; scopes"latest"resolution and current-session detection to sessions from that directory.
Returns session_id, repo, schema_status (as in
list_recent_sessions), 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 |
|
| Root directory to scan for |
| (none — built-in table) | Path to a JSON pricing-table override (see above). |
| (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 |
Install
This project uses uv. With uv installed
(curl -LsSf https://astral.sh/uv/install.sh | sh), from the repo root:
uv syncThis creates a locked virtual environment (.venv/) from the committed
uv.lock, pins the interpreter via .python-version, and installs the
agent-activity package plus its one runtime dependency (mcp).
Fallback (no uv):
pip install -e .still works and installs theagent-activityconsole script and itsmcpdependency — it just isn't locked or interpreter-pinned.
Run
Any of the following start the same stdio server (via uv, no manual activation needed):
uv run agent-activity
uv run python -m agent_activity
uv run python -m agent_activity.serverIf you've activated the environment (or installed with pip install -e .),
you can drop the uv run prefix and invoke agent-activity /
python -m agent_activity directly.
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": "uv",
"args": ["run", "--directory", "/absolute/path/to/agent-activity-mcp-server", "agent-activity"],
"env": {
"AGENT_ACTIVITY_LOG_ROOT": "~/.claude/projects"
}
}
}
}uv run resolves the project (and its locked environment) from a working
directory, so set --directory to the absolute path of this repo — MCP
clients launch the command from an arbitrary cwd. This form doesn't require
the console script to be on PATH.
Alternatively, if you've installed the package into the environment your MCP
client uses (e.g. via pip install -e .), point command directly at the
agent-activity console script (with args: []), or use python with
args: ["-m", "agent_activity"] to invoke the module.
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, sotail_agent_log(session="latest")doesn't tail its own still-being-written log; passinclude_current=Trueto opt back in. (summarize_tool_callsresolves"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
uv sync installs the dev dependencies (the dev dependency group, which
includes pytest) alongside the runtime deps. Run the tests with:
uv sync
uv run pytest tests/ -qAn 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:
uv run python scripts/smoke_test.pyAvailable Tools
3 toolslist_recent_sessionsA
List recent coding-agent sessions, newest first.
Discovers session logs under the configured log root (default
~/.claude/projects/) and returns up to limit sessions
(default 20, max 200), most-recently-active first. Each entry
includes the session id, repo/cwd, git branch, start/end
timestamps, message count, schema-verification status, and a
token/cost usage rollup (total tokens, estimated cost, cost
status, and the main-vs-sidechain split). Pass repo to filter
to sessions whose cwd/repo directory name contains that substring.
Read-only; never writes to or modifies the underlying log files.
| Name | Required | Description | Default |
|---|---|---|---|
| repo | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description fully discloses the tool's read-only nature, default behavior, and the fields it returns. It also mentions the configurable log root, providing complete behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose. While efficient, a slight rephrasing could reduce redundancy (e.g., 'newest first' repeated), but it remains clear and concise overall.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with an existing output schema, the description covers all necessary aspects: purpose, behavior, parameters, and read-only guarantee. It is complete and leaves no ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds substantial meaning beyond the schema (which has 0% description coverage). It explains the repo parameter's filtering behavior and the limit parameter's default and maximum value, making the parameters clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists recent coding-agent sessions, newest first, with specific details on log root, limit, and fields returned. It distinguishes itself from siblings (summarize_tool_calls and tail_agent_log) by its unique purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool (to list recent sessions) and notes it is read-only. However, it does not explicitly mention when not to use it or provide alternatives, though the sibling tools are sufficiently distinct.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_tool_callsA
Summarize a session's tool calls: per-tool outcomes, failures, usage.
session accepts a full session UUID, a unique UUID prefix, or
"latest" (resolved including the current session, since
summarizing "my own" live session is a valid use case here).
Returns per-tool invocation counts broken down by outcome
(ok / error / pending / in_progress), overall
totals, a main/sidechain split (tool calls made by
subagents are included and tagged, never blended in untagged),
the list of failing calls (each labeled error or rejected
for permission denials), and the session's total token/cost
usage. If this session is currently live (the most recently
active discovered session), its trailing pending calls are
labeled in_progress instead of pending. If session is
ambiguous or matches no session, returns a structured
{"error": ...} dict instead of raising. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| session | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully discloses behavior: read-only, handles live sessions, returns structured errors, splits main/sidechain, and labels pending vs in-progress. This is comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but every sentence adds value; it is front-loaded with the overall purpose. A slightly more concise phrasing could be used, but overall well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema or annotations, the description covers input, behavior, and output structure (including error handling). It is complete for an agent to understand and use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% coverage (no description for the session parameter), but the tool description provides extensive detail on the parameter's meaning and acceptable values, fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool summarizes a session's tool calls with per-tool outcomes, failures, usage. It distinguishes from siblings (list_recent_sessions, tail_agent_log) by its specific focus on summarizing tool calls.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains how to specify the session (full UUID, prefix, 'latest') and covers the live session case. However, it does not explicitly state when not to use this tool or compare with siblings for alternative usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tail_agent_logA
Return the tail of a session's transcript, oldest-first.
session accepts a full session UUID, a unique UUID prefix, or
the keyword "latest". By default "latest" excludes the
session currently calling this tool (so it never tails its own
still-being-written log); pass include_current=True to opt in.
Returns up to limit entries (default 100, max 1000) in
chronological order. Each entry reports its type and timestamp;
assistant entries list any tool(s) called and, for entries
carrying usage, per-entry token counts and estimated cost;
tool-result entries report each result's tool_use_id and
whether it was an error. If session is ambiguous (a prefix
matching multiple sessions) or matches no session, returns a
structured {"error": ...} dict instead of raising. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| session | Yes | ||
| include_current | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so description carries full burden. Discloses read-only nature, error handling (returns dict instead of raising), default/max limit, chronological order, parameter behavior (prefix, 'latest', self-exclusion), and return format details. Comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured, starting with purpose then detailing parameters and error handling. Each sentence adds value, but length is appropriate for the complexity. Slightly verbose but no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations and no output schema, description covers input, behavior, error handling, and return contents. Includes safety note (Read-only) and all parameter nuances. Fully sufficient for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage, so description compensates fully. Describes session parameter (UUID, prefix, 'latest', default behavior), limit (default 100, max 1000), and include_current (opt-in). All three parameters are clearly documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool returns the tail of a session transcript oldest-first. Distinguishes from siblings: list_recent_sessions lists sessions, summarize_tool_calls summarizes calls, while this tool specifically retrieves transcript entries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explains when to use (get recent log entries) and special behavior like 'latest' keyword and exclusion of current session. Implicitly differentiates from siblings but could be more explicit about when not to use or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.1.0- First observed
list_recent_sessions - First observed
summarize_tool_calls - First observed
tail_agent_log
TDQS
Each tool has a clearly distinct purpose: listing sessions, summarizing tool calls within a session, and tailing session transcripts. There is no overlap or ambiguity.
All tool names follow a consistent verb_noun snake_case pattern (list_recent_sessions, summarize_tool_calls, tail_agent_log), making them predictable and clear.
Three tools is slightly low but appropriate for the narrow domain of inspecting agent sessions. The set covers the essential operations without superfluous tools.
The tool surface covers listing sessions, inspecting tool calls, and viewing transcripts. A minor gap is the lack of a dedicated 'get session details' tool, but the list tool returns metadata, and summary/tail provide depth.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Read-only MCP server for turva.dev, an agent-readiness audit and advisory service.
MCP server exposing the Backtest360 engine API as tools for AI agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceLocal-first dashboard + MCP server that parses Claude Code and Codex JSONL files into a SQLite cost / token tracker. Per-MCP and per-tool breakdown, session drill-down, dedup by request_id; never talks to vendor APIs51001MIT
- AlicenseAqualityDmaintenanceMCP server for log file analysis. Gives LLMs the ability to efficiently analyze large log files without loading them into context.799MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that reads local OpenClaw session files to provide token usage and cost data without any network calls or authentication.MIT
- FlicenseNot gradedqualityAmaintenanceLocal MCP server that lets your AI coding agent query its own cross-tool project history - file/command freshness, past test failures, cost & token spend, cache status, and session handoff - over stdio, 100% local, no telemetry.42-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/patrickdaj/agent-activity-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server