An MCP server that turns Claude into a focused exam coach for a single subject. Drop notes into materials/content/ and past papers into materials/pyqs/. Claude discovers topics from the material, teaches them in any style, quizzes on them, and runs PYQ-pattern practice. SQLite tracks results per topic so weakest ones surface first.
Study Buddy has 8 tools with clear verb-noun naming (list_*, read_*, search_*, discover_*, register_*, archive_*). All tools have descriptions (avg ~80 chars, within baseline). Input schemas are present with type definitions and descriptions for all parameters. However, output schemas are not documented, responses are inferred from code (e.g., list_content returns dicts, search_content returns list of dicts). Error handling is minimal: most tools return plain strings on failure rather than structured error objects with recovery guidance. No tool annotations (readOnlyHint/destructiveHint) despite clear risk distinctions (6 READ_ONLY, 2 WRITE). Parameter descriptions are adequate but lack format/constraint details (e.g., 'folder' accepts 'content'|'pyqs'|'archive' but this is validated in code, not declared in schema). Composition is sound, tools chain well (discover_topics → register_topic → list_topics). No secrets exposed. Path traversal is defended (_safe_path). Overall: solid foundation, but missing output documentation and error guidance that would elevate to 70+.
Archive a topic (mark mastered).
Scan all materials and return ranked candidate topics.
List all files in materials/content/ (your notes, slides, textbook extracts).
List all files in materials/pyqs/ (your previous-year question papers).
List every registered topic with attempts, mastery %, and archived status.
Read a single file by folder + filename. Supports .txt, .md, .pdf, .docx, and images.
Add a topic to the tracker so quiz results can be logged against it.
Output schemas not documented. Tools return dicts/lists but LLMs cannot see field names, types, or structure. E.g., list_content returns [{name, type, size_kb}] but this is inferred from code, not declared in tool definition.
Error handling lacks recovery guidance. Tools return plain strings ('No file named...', 'Unsupported file type...') instead of structured errors with actionable next steps. LLMs cannot distinguish retryable from fatal errors.
Tool annotations missing. 6 tools are READ_ONLY, 2 are WRITE (register_topic, archive_topic), but no readOnlyHint or destructiveHint declared. LLMs cannot infer safety/idempotency without explicit hints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Search across all files in materials/content/.
Parameter constraints not declared in schema. 'folder' parameter accepts only 'content'|'pyqs'|'archive' but is typed as plain string; validation happens in code (_folder_path raises ValueError). Should use enum or pattern constraint in schema.
No pagination support. search_content accepts max_results (1-20, default 5) but list_content and list_pyqs return all files unbounded. If materials/ grows large, responses could bloat context window.