Skip to main content
Glama
nbhson
by nbhson

Universal Agent Recovery

CI npm version npm downloads

Your coding agent crashed at 80% of the task. Who restarts it? This package does.

universal-agent-recovery is an MCP server + independent watchdog (npm package: s-universal-agent-recovery) that automatically detects when a coding agent task is interrupted (crash, timeout, lost session) and resumes it — from the same session when possible, or from a saved checkpoint otherwise.

Agent doing work ── crash ──> watchdog detects ──> resumes from checkpoint
                                        │
                    ┌───────────────────┘
                    ▼
              recovered → agent continues the task

Component

CLI

Role

MCP Server

uar-mcp

Tools for the agent to register tasks, report progress, save checkpoints

Watchdog

uar-watchdog

Independent process that detects interruptions and launches recovery

State dump

uar-state

Read-only JSON snapshot of tasks/leases/retries for debugging

  • Works with OpenCode, Claude Code, and any agent via a generic CLI template adapter.

  • No native dependencies — uses Node's built-in SQLite (node >= 22.5, 22.x only).

  • The watchdog never depends on the agent being alive to perform recovery.

Node version: this package targets Node.js 22.x (>=22.5.0 <23) because storage uses the built-in node:sqlite module, whose behavior can change between major lines. Node 23+/24+ may work but is untested; the (node:xxx) ExperimentalWarning: SQLite is an experimental feature message at startup is expected and harmless.


Quick start

npm install -g s-universal-agent-recovery

1. Register the MCP server in your MCP client

OpenCode — add to ~/.config/opencode/opencode.json (or project opencode.json):

{
  "mcp": {
    "universal-agent-recovery": {
      "type": "local",
      "command": ["uar-mcp"],
      "enabled": true
    }
  }
}

Claude Code:

claude mcp add universal-agent-recovery -- uar-mcp

Any other MCP client — command uar-mcp, transport stdio.

2. Start the watchdog in the background

uar-watchdog

That's it. From now on, whenever the agent calls register_task at the start of significant work, the task is monitored and auto-resumed on interruption.

3. Optional: try the demo

npm run demo   # scripted end-to-end recovery with a mock agent

Related MCP server: Aletheia Token Guard (ATG)

How it works

The agent (via MCP tools) records what it is doing; the watchdog watches the record and recovers when the record goes stale.

                 ┌─────────────────────────┐
                 │   SQLite state store    │
                 │  (shared, WAL mode)     │
                 └──────────┬──────────────┘
        register/heartbeat  │  poll + claim
   ┌────────────────────────┴──────────────────────┐
   │                                               │
MCP Server (uar-mcp)                      Watchdog (uar-watchdog)
- register_task                           - detects stale heartbeat / dead pid
- report_progress / save_checkpoint       - verifies the session still exists
- report_interruption                     - resumes: same session → checkpoint fallback
- mark_completed / cancel_task            - retry budget + backoff + single-owner lock

Recovery lifecycle

  1. Register — agent calls register_task (session id, adapter, working directory).

  2. Progress — agent calls report_progress / save_checkpoint as work proceeds.

  3. Detect — watchdog sees a stale heartbeat (and/or dead pid) → task is INTERRUPTED.

  4. Verify — watchdog checks the session still exists (adapters that support it).

  5. Resume — watchdog launches the agent with the same session id + a self-contained recovery instruction.

  6. Fallback — resume failed? A fresh session is started from the persisted checkpoint.

  7. Verify — recovery succeeded only when the agent resumes making progress or reports completion.

  8. Repeat — until COMPLETED, BLOCKED (retry budget exhausted), or CANCELLED.

Interruption scenarios → when recovery triggers

Scenario

Detected by

Resumed?

Network loss → agent CLI crashes → process dies

isPidAlive check

✅ ≤ ~30s (next poll)

Network loss → CLI hangs, process alive, no pid known

stale heartbeat (RECOVERY_STALE_MS)

✅ after 10 min (default)

Agent retries internally, then exits

dead pid

✅ ≤ ~30s

Agent retries internally, then goes silent with process still alive

heartbeat stale but pid alive

❌ classified IDLE — never resumed (by design)

Agent reports report_interruption before going silent

tool call

✅ immediately (next poll)

Design note: a live process with a stale heartbeat is deliberately classified as IDLE, not INTERRUPTED. From the outside, "running a 15-minute test suite", "stuck waiting for the network", and "waiting for the user to type the next instruction" look identical — so the watchdog only resumes when it can prove the agent is gone (dead pid), or when the agent itself reports the interruption. The agent's own contract: try to recover on your own first, and call report_interruption when you give up — the watchdog then takes over with its own retry budget and backoff.

Task state machine

REGISTERED → RUNNING → INTERRUPTED
     ↓          ↓           ↓
     └──────────┴──→ RECOVERING → RUNNING
                                   ↓
                              COMPLETED
                                   or BLOCKED (exhausted)
                                   or CANCELLED (human)

MCP tools (7)

Tool

Description

register_task

Register a task for monitoring

report_progress

Heartbeat / progress report

save_checkpoint

Persist verified progress (files touched, steps done, next steps)

report_interruption

Report an error or crash

get_task_status

Query full task state + event log

mark_completed

Mark complete — requires evidence of work

cancel_task

Cancel and stop recovery


Configuration

All settings are environment variables (copy .env.example → .env if you use a dotenv loader; both uar-mcp and uar-watchdog must see the same values):

Variable

Default

Description

RECOVERY_DB_PATH

./data/recovery.db

SQLite database shared by MCP + watchdog (must match between the two processes)

RECOVERY_ALLOWED_DIRS

(empty = unrestricted)

Comma-separated root dirs; tasks outside are rejected

RECOVERY_ENABLED

true

Global recovery killswitch

RECOVERY_STALE_MS

600000

Heartbeat considered stale after 10 minutes

RECOVERY_MAX_CONCURRENT

2

Max simultaneous recoveries

RECOVERY_MAX_RUNTIME_MS

3600000

Hard runtime cap per recovery launch

RECOVERY_MAX_ATTEMPTS

5

Retry budget per task

RECOVERY_BACKOFF_BASE_MS

30000

Initial backoff between retries

RECOVERY_BACKOFF_MAX_MS

1800000

Backoff cap

RECOVERY_OWNER_LEASE_MS

300000

Recovery ownership lease

RECOVERY_POLL_MS

30000

Watchdog polling interval

RECOVERY_LOG_LEVEL

info

debug | info | warn | error

RECOVERY_LOG_FILE

(none)

Optional JSON log file

OPENCODE_BIN

opencode

OpenCode binary path

CLAUDE_CODE_BIN

claude

Claude Code binary path

RECOVERY_GENERIC_CLI_RESUME

(empty)

Resume template, e.g. myagent run --resume {session} "{prompt}"

RECOVERY_GENERIC_CLI_NEW

(empty)

New-session template, e.g. myagent run "{prompt}"

Running the watchdog as a service

  • macOS (launchd): copy launchd/com.github.universal-agent-recovery.plist to ~/Library/LaunchAgents/, adjust the paths, then launchctl load ....

  • Linux (systemd): create a user unit running uar-watchdog with the desired RECOVERY_* environment.

  • Windows: use a scheduled task (schtasks /create ... /sc onstart) or a service wrapper.

Windows notes

  • npm shims (opencode.cmd, claude.cmd) cannot be spawned directly by Node. Point the env at the real .exe:

setx OPENCODE_BIN "C:\path\to\nodejs\node_modules\@opencode\cli\bin\opencode.exe"
  • Process-tree cancellation uses taskkill /T /F automatically; tasklist is the process-health fallback.


Supported agents

Agent

Resume flag

Session inspection

Completion detection

Status

OpenCode

--session <id>

session list --format json

No (verified via MCP)

✅ Tier 1 validated

Claude Code

--resume <id> --print

No documented CLI

--output-format json

✅ Tier 1 validated

Generic CLI

Template-driven

No

No

✅ Available


Security

  • Working directories are validated against RECOVERY_ALLOWED_DIRS.

  • Agent processes are launched with argument arrays only (shell: false) — no command injection from task metadata.

  • Credential-like environment variables (*TOKEN*, *SECRET*, *PASSWORD*, *CREDENTIAL*, *API_KEY*, ...) are stripped from agent processes; provider keys agent CLIs need (e.g. ANTHROPIC_API_KEY) are preserved via an explicit allowlist.

  • API keys / tokens are never logged (structured logger redacts secrets).

  • RECOVERY_ENABLED=false is the global killswitch.


Troubleshooting

Symptom

Likely cause

Fix

Task not recovered

RECOVERY_ENABLED=false

Set to true

"Recovery disabled" in logs

Global switch off

RECOVERY_ENABLED=true

Task stuck in RECOVERING

Watchdog died mid-recovery

reconcileStaleOwners() runs every tick; the next watchdog tick recovers it

Agent resumes but task stays INTERRUPTED

Watchdog not running

Start uar-watchdog

Slow agents restarted

RECOVERY_STALE_MS too short

Increase it (default 10 min)

ENOENT spawning the agent

Binary not resolvable

Set OPENCODE_BIN / CLAUDE_CODE_BIN to an absolute .exe path

"SQLite database is locked"

Another uar-mcp / uar-watchdog process holds a long write transaction, or the database lives on a network filesystem (NFS/SMB — WAL mode requires local disk). Steps:

  1. Check for stale processes: ps aux | grep uar- and kill leftovers.

  2. Inspect the current state read-only: uar-state (shows tasks, lease holders, retry counts).

  3. Confirm both processes point at the same RECOVERY_DB_PATH.

  4. Move RECOVERY_DB_PATH to a local disk if it is on a network mount.

"Task 'X' already exists (state: ...)"

Task IDs are unique forever, including terminal states (COMPLETED/CANCELLED/BLOCKED). Use a new ID for a fresh run, or call cancel_task/mark_completed on the existing one.

"Task is BLOCKED; interruption not accepted"

The task exhausted its retry budget (maxAttempts, default 5) or failed with a non-recoverable error class. Inspect lastError / recent events:

uar-state --task <taskId>        # includes the last 50 events

Then either fix the underlying problem and register a new task, or cancel it. There is currently no "unblock" tool — re-registering is intentional friction.

"outside the configured allowed directories"

RECOVERY_ALLOWED_DIRS is set and the task's working directory is outside every root. Add the project root to the comma-separated list (both uar-mcp and uar-watchdog must see the same value).

Config warnings at startup

Invalid numeric env values (e.g. RECOVERY_MAX_ATTEMPTS=-3) and unknown log levels are replaced by defaults with a configuration warning log line at startup — check the logs if behavior doesn't match what you configured.

Debugging snapshot

uar-state                          # pretty JSON of everything
uar-state --db ./data/recovery.db  # explicit database path
uar-state --task my-task           # single task + last 50 events
uar-state --compact | jq '.tasksByState'

The dump is read-only and safe to run while the MCP server and watchdog are live.

Known limitations

  • Claude Code session inspection: no documented non-interactive command to list sessions; an invalid session id falls back to a new session.

  • Session inspection failure vs. missing session: a CLI failure during inspection makes the watchdog defer (never drop session context on a hiccup).

  • Completion detection (OpenCode): no structured output; completion is verified via MCP mark_completed, not process exit.

  • Generic CLI adapter: disabled unless templates are explicitly configured.


Documentation

Document

Content

docs/architecture.md

System architecture and design principles

docs/tool-design.md

MCP tool contracts and schemas

docs/usecase.md

Use cases and scenarios

docs/workflow.md

Recovery workflow details

docs/structure.md

Source code structure guide

Development

npm install
npm run lint        # ESLint
npm run typecheck   # tsc --noEmit
npm test            # unit + integration tests
npm run test:coverage  # same tests + V8 coverage report
npm run build       # compile to dist/

Current coverage (V8): ~76% statements / ~71% branches overall; storage core (src/storage) at ~90% statements. The thinner areas are the adapter binaries' process plumbing (covered mainly by integration tests) and the uar-state CLI (covered at the dumpState function level).

Integration tests against a real OpenCode binary run automatically when the binary exists; the live end-to-end test (needs provider credentials) is opt-in:

UAR_INTEGRATION=1 npm test

Project structure

universal-agent-recovery/
├── bin/                 # CLI shims: uar-mcp, uar-watchdog, uar-state
├── src/
│   ├── core/            # Types, state machine, error classifier, logger
│   ├── storage/         # SQLite, task/event/attempt repositories, leader lock
│   ├── adapters/        # OpenCode, Claude Code, Generic CLI, Mock (testing)
│   ├── mcp/             # MCP server (7 tools, stdio transport) + entry point
│   ├── watchdog/        # Supervisor, monitor, recovery policy, instructions
│   ├── cli/             # uar-state: read-only JSON state dump for debugging
│   └── examples/        # Demo script
├── docs/                # Design documents
├── tests/               # Unit + integration tests
└── launchd/             # macOS launchd plist

License

MIT

Available Tools

7 tools
cancel_taskCancel TaskC

Cancel a task and stop any further recovery attempts for it.

NameRequiredDescriptionDefault
reasonNo
taskIdYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description bears full behavioral burden. It usefully discloses that cancellation stops further recovery attempts, but omits whether cancellation is reversible, what task state results, whether it applies to running vs interrupted tasks, and what permissions or error conditions apply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler. Every phrase contributes either the core action or a behavioral consequence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no annotations, no output schema, and 0% parameter documentation, the description is too thin. It should clarify the resulting task state, reversibility, and the role of the reason parameter to be complete enough for reliable invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description says nothing about either parameter. It does not explain the required taskId or clarify the optional reason parameter, including whether the reason is recorded or affects behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Cancel a task') and adds a distinguishing behavioral detail ('stop any further recovery attempts'), which separates it from siblings like mark_completed and report_interruption. However, it does not explicitly name or contrast those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no indication of when to prefer cancel_task over mark_completed, report_interruption, or other lifecycle siblings, nor does it state prerequisites or exclusions. Usage is only implied by the verb 'Cancel'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_task_statusGet Task StatusB

Get full task status: state, progress, checkpoint, recovery attempts, recent events.

NameRequiredDescriptionDefault
taskIdYes
includeEventsNoInclude recent event log (default true)

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden. It usefully discloses the returned content, including recovery attempts and recent events, and the includeEvents parameter implies an event log. However, it never states that the call is read-only with no side effects, nor anything about cost, pagination, or permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with a colon-delimited field list; zero filler and every phrase conveys information. Ideal density for a simple retrieval tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description's enumeration of returned fields is valuable, and no annotations mean behavior must be inferred from 'Get'. But the required taskId and the includeEvents toggle are left unexplained, so an agent cannot fully understand the call contract from the text alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%: includeEvents has a description and a default, but taskId is undocumented in both schema and description. The description mentions neither parameter, so it adds no meaning over the structured fields and fails to compensate for the undocumented required taskId.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Get') and resource ('task status'), then enumerates the fields returned (state, progress, checkpoint, recovery attempts, recent events). This clearly distinguishes it from the sibling tools, which are all mutation/reporting operations (register_task, report_progress, save_checkpoint, etc.), though it never names them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the agent can infer this is the read-only status lookup among write-oriented siblings, but the description never says when to call it, whether polling is expected, or what alternatives exist. Minimum viable guidance, no exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_completedMark CompletedA

Mark a task completed after verifying the final state. Requires a verification note; completion is never inferred from process exit.

NameRequiredDescriptionDefault
taskIdYes
verificationYesHow completion was verified (tests run, outputs checked, etc.)

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses a useful behavioral rule (completion requires evidence, never inferred from exit codes) but says nothing about irreversibility, resulting task state, permissions, or whether the task can be reopened.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, both front-loaded with the action and the constraint; nothing is wasted or repetitive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A two-parameter mutation tool with no output schema is adequately covered: the agent knows what it needs and the key gating rule. Missing only the post-completion effects (state transition, reversibility).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%: the 'verification' parameter is documented in the schema, while 'taskId' is undocumented anywhere. The description reinforces that verification is mandatory but adds no format or identifier guidance beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('mark a task completed') and adds a precondition that no other sibling performs. It is not confused with report_progress or cancel_task, though it never names those siblings explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'After verifying the final state' states the trigger condition, and 'completion is never inferred from process exit' rules out a tempting wrong usage. It still lacks explicit routing against alternatives such as cancel_task when work is abandoned rather than finished.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

register_taskRegister TaskA

Register a coding-agent task for monitoring and automatic recovery. The agent (or its launcher) calls this when starting a task so the watchdog can resume it after interruptions.

NameRequiredDescriptionDefault
taskIdYesUnique task identifier
adapterIdYesAdapter id, e.g. 'opencode', 'claude-code'
agentTypeNoAgent type label (defaults to adapterId)
sessionIdNoExisting agent session id to resume, when known
processPidNoAgent process id, when launched by the caller
descriptionYesOriginal task description used as recovery context
maxAttemptsNoRecovery attempt budget (default from configuration)
workingDirectoryYesAbsolute working directory the agent runs in

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It usefully discloses that registration enrolls the task in watchdog monitoring and recovery, but omits key traits: whether registering an existing taskId fails or overwrites, idempotency, and whether registration implies any process ownership. These gaps matter for a stateful registration call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero padding, with the action and its monitoring purpose front-loaded before the call-site guidance. Nothing is restated redundantly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter, no-annotation, no-output-schema registration tool, the description covers purpose and trigger but leaves out duplicate-registration behavior and what a caller gets back (task id, status, error). Adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all eight parameters carry inline descriptions, so the schema already does the work. The description adds no additional meaning about required fields, defaults, or how sessionId/processPid affect recovery behavior, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Register') and resource ('a coding-agent task') and adds the purpose ('for monitoring and automatic recovery'), which clearly separates it from siblings like report_progress or save_checkpoint. It stops short of explicitly naming an alternative tool, but the intent is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the trigger ('The agent (or its launcher) calls this when starting a task') and the rationale (so the watchdog can resume it after interruptions), which is a clear use context. It does not cover when-not-to-use, re-registration semantics, or whether a launcher should call it instead of the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

report_interruptionReport InterruptionB

Report an error or interruption for a task. The watchdog verifies and schedules recovery.

NameRequiredDescriptionDefault
errorYesError or interruption description
taskIdYes
exitCodeNoAgent process exit code, when known

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It usefully discloses that a watchdog verifies the report and schedules recovery, but it omits key mutation behavior such as idempotency, permissions, task status changes, and what the caller should expect after submission.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and followed by one behavioral detail. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a reporting/mutation tool with no annotations and no output schema, the description is too thin. It does not explain what 'verifies and schedules recovery' means operationally, whether the task is retried or cancelled, or what response the caller receives.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is moderate at 67%: error and exitCode are documented in the schema, while taskId is self-explanatory. The description loosely maps to the 'error' parameter but adds no meaning beyond the schema and says nothing about exitCode or taskId usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Report') and resource ('error or interruption for a task'), making the tool's core purpose clear. It does not explicitly distinguish itself from siblings such as report_progress, cancel_task, or mark_completed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the purpose: report when a task has an error or interruption. However, the description gives no explicit when-to-use/when-not guidance, no prerequisites, and does not name alternatives such as report_progress or cancel_task.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

report_progressReport ProgressB

Report task progress (acts as a heartbeat). Keeps the watchdog from considering the task stale.

NameRequiredDescriptionDefault
taskIdYes
progressYesWhat has been done so far

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden; it does disclose the important non-obvious behavior that the call resets a stale-task watchdog. It says nothing about how often to call, whether progress overwrites or appends, or what happens if the task is already completed or cancelled.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact clauses with the heartbeat semantics front-loaded right after the purpose. No filler; the parenthetical is slightly awkward but earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-param tool with no output schema, purpose plus heartbeat semantics is the essential core. Missing cadence guidance and the undocumented taskId leave real gaps for what is meant to be a periodic keepalive call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is only 50%: progress is documented in the schema while taskId is undocumented in both places, and the description adds no meaning for either parameter. With a coverage gap, the description should compensate and does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (report task progress) and adds the key framing that it acts as a heartbeat. It is not explicitly contrasted with siblings like save_checkpoint or get_task_status, but the purpose is unambiguous on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The watchdog sentence implies when to call (periodically, to avoid being marked stale), but there is no explicit when-not, no suggested cadence, and no routing away from save_checkpoint or report_interruption, which an agent could easily confuse with this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_checkpointSave CheckpointA

Persist verified progress so a new session can continue the task after a restart. Include concrete details: steps completed, files touched, next steps. Do not paste raw last output.

NameRequiredDescriptionDefault
taskIdYes
detailsNoStructured details: files touched, steps completed, next steps
summaryYesVerified progress summary — what is actually done
verifiedNoWhether this checkpoint reflects verified state (default false)

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so the description carries the burden. It does disclose a real behavioral trait — the checkpoint survives a restart and is meant for a fresh session — which is genuinely useful context. It omits whether saves overwrite a prior checkpoint, whether 'verified' gates anything, and what the call returns, which are material for a persistence tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each earning its place: the purpose first, then content requirements, then a single prohibition. Nothing redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter write with no output schema, the description covers intent, content shape, and a key content exclusion, which is enough to call it correctly. The missing piece is how checkpoints relate to existing ones and to the progress-reporting siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, so the schema already documents summary, details, and verified. The description adds the useful negative constraint ('do not paste raw last output') and enumerates the content expected inside details, but says nothing about taskId or the semantics of the verified flag beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (persist verified progress) plus the reason it exists: letting a new session continue after a restart. It does not explicitly distinguish itself from the sibling report_progress, which is the nearest confusable tool, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose sentence implies the trigger (end of a work segment, before a restart) but never states when to use this versus report_progress or report_interruption. The remaining sentences are content guidance ('include concrete details', 'do not paste raw last output') rather than usage routing.

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.

  1. 7 tool updatesv0.1.4
    • First observedcancel_task
    • First observedget_task_status
    • First observedmark_completed
    • First observedregister_task
    • First observedreport_interruption
    • First observedreport_progress
    • First observedsave_checkpoint

TDQS

A3.5/5.0

Scored across 7 tools

Disambiguation4/5

Each tool maps to a distinct lifecycle action, but report_progress (heartbeat) and save_checkpoint (durable state) are close enough that an agent could misuse one for the other; the descriptions do clarify the difference. register_task vs report_interruption vs mark_completed are clearly separated by intent.

Naming Consistency5/5

All seven tools follow a strict snake_case verb_noun pattern (register_task, report_progress, save_checkpoint, report_interruption, get_task_status, mark_completed, cancel_task). No deviations or mixed conventions.

Tool Count5/5

Seven tools cleanly covers the register→progress→checkpoint→recover→complete/cancel lifecycle without redundancy. Each tool earns its place in the watchdog workflow.

Completeness4/5

Core task lifecycle is fully covered, including recovery and terminal states. Minor gap: no way to enumerate or query multiple tasks (no list_tasks) and no explicit manual recovery trigger, though the watchdog handles recovery automatically.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers