Drive the user's e-ink reader: send long-form text, decks, and tappable choices to the device instead of the chat window, and read back their taps.
Strong tool naming (all verb-first: send_, await_, get_, resume_) and comprehensive parameter descriptions. All 6 tools have clear, detailed descriptions (100-200 chars). Input schemas are well-structured with proper types and enums. However, output schemas are not explicitly documented in the source code, responses are inferred from implementation. Error handling is present but lacks recovery guidance. No tool annotations (readOnlyHint/destructiveHint) despite clear risk classifications. Missing idempotency guarantees for write operations.
Block until the drill finishes or times out. Returns the full report (items, attempts, timing, requests for help) or progress if still running. Supports MCP Tasks extension for non-blocking async.
Block until the user taps a choice, quick action, or marks text for explanation. Returns the tap label, kind, and optional context anchors. Supports MCP Tasks extension for non-blocking async.
Query the current state of a reader session: connection status, document version, reading position, pending taps, and drill progress.
Resume a drill that was parked by a quick action or explain request. Returns the updated progress.
Hand the device a complete multiple-choice drill (deck). The device runs the loop: score taps, show feedback, turn pages. Returns initial drill state and connection info.
Send markdown content to the reader. Append mode concatenates with existing content; replace mode clears and starts fresh. Returns delivery status including connection state and pending taps.
Output schemas not documented. Tool descriptions state what is returned (e.g., 'Returns delivery status including connection state and pending taps') but formal response schemas are absent from tool definitions. LLMs cannot plan downstream calls without knowing response structure.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Tools are marked with Risk classifications (WRITE, READ_ONLY) in comments but not exposed via MCP tool annotations. Agents cannot distinguish safe reads from destructive writes without parsing descriptions.
Blocking await tools (await_reader_choice, await_drill_report) lack Multi-Round-Trip Request (MRTR) support. Descriptions mention 'Supports MCP Tasks extension for non-blocking async' but no evidence of Tasks extension negotiation or result input_required pattern in code.
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | A | 84 | 2025-06-18+ | v2 |
Error responses lack recovery guidance. Code returns JSON errors (e.g., 'error: unauthorized', 'error: invalid code') but does not guide LLM on next steps. Pattern: 'User not found. Try search_users()' is absent.
Idempotency not guaranteed for write operations. send_to_reader and send_drill modify state but lack idempotency keys or deduplication. Agents retrying on ambiguous failures risk duplicate sends.