This is an educational MCP server (masterclass lessons) with 9 tools spread across 4 lesson modules. All tools have basic descriptions and input schemas are visible in the code. However, there are significant gaps in schema completeness, parameter documentation, and error handling. Tool names follow verb-noun conventions adequately. The server operates via STDIO only, which limits deployment scenarios. Output schemas are not documented. Error handling is minimal, most tools return simple success messages or bare file-not-found strings without recovery guidance. The codebase shows good structure for teaching purposes but lacks production-grade robustness.
Error messages are bare strings with no recovery guidance. 'There is no note called {name}.' does not tell the LLM what to do next (search for similar names? list available notes? etc.).
Recommendations
Document output schemas for all tools. For read_note, specify: {type: 'string', description: 'File contents as plain text'}. For get_learning_insights, specify the multi-line format or return structured JSON: [{approach, worked_count, total_count, success_rate, confidence}, ...]. For save_* tools, return {success: boolean, message: string, timestamp: string, resource_id?: string} so agents can chain calls.
Add input parameter constraints. For read_note, validate filename: no path separators, no dots (prevent ../), length 1-255 chars, alphanumeric + underscore. For search_memory, limit 'term' to 1-100 chars. For record_experience, validate 'task' and 'approach' as 1-500 chars each (prevent token bombs). Use JSON Schema 'pattern', 'minLength', 'maxLength', 'enum' fields, AND repeat in descriptions for LLM visibility.
Add recovery guidance to error responses. Instead of 'There is no note called ideas.txt.', return 'Note not found: ideas.txt. Available notes: [list]. Try a different name or create_note() first.' Call an internal list_notes() helper to return available options. This teaches the LLM the recovery path.
Sanitize file paths in read_note. Use pathlib.Path(NOTES / name).resolve() and assert it is within NOTES to prevent traversal. Return: 'Invalid filename: contains path separators or escapes' if detection fails. Same for save_* operations.
Separate read_memory and search_memory output. Return JSON: {memories: [{topic, insight, saved_at}, ...], total_count: N, limit: 50, offset: 0} so agents can parse and paginate programmatically. Offer optional limit and offset parameters.
Score history
Overall score trend
↑ 50 points across a rubric change (v1 → v2)
50/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-22
D
50
2026-07-28+
v2
2026-03-09
F
0
-
v1
writesource verified57/100
Save research findings so another agent can read them later.
No input validation. read_note accepts any filename string, including path traversal attempts ('../../etc/passwd'). Missing permission checks and sanitization.
Tool descriptions are inconsistent in length and detail. save_research (19 chars) and save_draft (41 chars) are too brief; get_learning_insights (95 chars) is better. Some describe the intent ('Remember one insight') rather than the effect ('Appends insight to persistent JSON memory').
State mutation on save operations is not idempotent-friendly. Calling save_research twice with different findings overwrites the first; no version history or diff support. Agents retrying on ambiguous failures will silently replace data.
save_researchsave_draftsave_memory
Add a note_available or list_notes discovery tool so agents can explore the notes folder without guessing filenames. Similarly, add list_memories tool.
For save_research and save_draft, add an 'append' boolean parameter (default false) so agents can accumulate findings rather than overwrite. Or return a confirmation prompt: 'Research already saved. Overwrite? [yes/no]'. This prevents silent data loss on retry.
Document which tools are idempotent and which are not. Tools like read_note, read_memory, search_memory are safe to retry (GET-like). Tools like save_research, save_memory, record_experience mutate state; mark as destructive/non-idempotent in annotations so agents know not to blindly retry.
Add timestamp to all write operations. return {success: true, message: 'Saved', saved_at: '2025-07-28T14:32:00Z'} so agents can track ordering and detect race conditions in multi-agent scenarios.
Explain parameter relationships in descriptions. For record_experience, note: 'The "notes" parameter is optional and typically used to explain why the approach failed or succeeded. Pass empty string if not needed.' This prevents LLMs from overthinking optional params.