MCP server for cross-session context handoffs in Claude Code
eywa-mcp has two tools with complete input schemas and descriptions, but the descriptions lack depth for LLM optimal selection. Both tools have clear names starting with action verbs (eywa_get, eywa_extract), but descriptions are moderately detailed (183 and 206 chars respectively) and lack explicit guidance on when to call them vs. alternatives. Input schemas are present with all parameters typed, but parameter descriptions could be more prescriptive about constraints. No output schema documentation is visible, the tools return TextContent with unstructured text responses, which is problematic for agent composition. Error handling is present in the implementation (TypeErrors, ValueErrors, FileNotFound), but error messages are generic and do not guide recovery. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are declared, even though eywa_get is read-only and eywa_extract is clearly destructive/state-changing.
Extract a handoff from the current session (or a specified session). Called at end of session to persist a handoff document. Extracts key decisions, insights, and open threads via the Anthropic Claude model configured by `EYWA_CLAUDE_MODEL` (default: `sonnet`) using the Claude Agent SDK. - No args: auto-detects current session via PID tracing + mtime. - With session_id: extracts that specific session. Examples: - eywa_extract() - eywa_extract(session_id="1b2f6f6b-65a6-42ff-aca7-34889b422799")
Retrieve past session handoffs for context continuity. Called at session start or when you need context about past work. - No query: returns 3 most recent substantial sessions. - With query: keyword-matches against past sessions, returns top matches. Examples: - eywa_get() - eywa_get(query="sorbent reasoning tokens") - eywa_get(query="river mcp", days_back=30, max_handoffs=5)
No output schema documentation. Both tools return unstructured TextContent with free-text responses. LLMs cannot reliably parse the results or extract structured fields for downstream calls. No documented fields, no pagination, no result-count guarantee.
Missing tool annotations. eywa_get is read-only (no side effects) and eywa_extract is destructive (writes handoff documents, modifies state). No readOnlyHint or destructiveHint declared, forcing LLMs to infer intent from descriptions alone.
Descriptions lack explicit recovery guidance. eywa_get mentions 'no query returns 3 recent sessions' and 'with query keyword-matches', but does not state what happens if no sessions match, or how to interpret empty results. eywa_extract says 'auto-detects current session via PID tracing', but does not explain what 'detection failed' means or how to resolve it.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 68 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 41 | - | v1 |
Parameter descriptions lack format/constraint detail. 'days_back' defaults to 14 with no min/max bounds stated. 'max_handoffs' defaults to 3, max 5, but the description does not explain why the cap exists or what happens if you request 6. 'session_id' is described as 'Session UUID' but no format pattern (UUID v4, hyphenated, etc.) is given.
Error responses are generic and do not guide next steps. _handle_eywa_get catches TypeError/ValueError and returns 'Invalid arguments: {exc}', no hint about which parameter was invalid or what valid values are. _handle_eywa_extract returns 'Session detection failed: {error}' but does not suggest calling eywa_get() to list available sessions.
No pagination support. eywa_get returns 'top matches' but does not declare a total_count or next_cursor. If there are 100+ sessions, the LLM cannot iterate through results. The description says max_handoffs defaults to 3, but does not document what to do if results are truncated.
eywa_extract has an implicit dependency on eywa_get (to discover sessions), but this is not documented in either tool's description. An LLM might try to extract a non-existent session UUID without first calling eywa_get() to list available sessions.