Authenticated remote MCP server on Cloudflare Workers that exposes a private GitHub-hosted Obsidian vault (read and create/overwrite notes, never deletes) to claude.ai and Claude Code.
Vault MCP demonstrates solid fundamentals: all 5 tools have clear verb-noun names (list_, read_, write_, delete_, search_), descriptions between 80-180 chars, and complete Zod schemas with typed parameters. Tool descriptions accurately convey purpose and state-changing intent (write_note, delete_note). Parameters are well-described with examples ('user_profile/identity.md'). However, output schemas are not documented, callers cannot see what fields to expect from responses. Error handling is present but generic (VaultError wrapping). No tool annotations (readOnlyHint, destructiveHint) despite clear risk profiles. search_notes correctly constrains limit (1-30, default 10) following pagination best practices.
Delete an existing note by its repo-relative path. Markdown files only. Recorded as a git commit (revertable); never touches non-note files.
List note (markdown) paths in the vault. Optionally scope to a subdirectory.
Read the raw markdown of a single note by its repo-relative path.
Search notes by content (indexed) and filename. Returns matching paths with snippets.
Create a new note or overwrite an existing one at a repo-relative path. Markdown files only.
Output schemas not documented. Tool responses return ToolResult with text content, but callers cannot see what fields or structure to expect. LLMs cannot plan downstream operations or extract structured data.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). write_note and delete_note are clearly destructive; list_notes, read_note, search_notes are read-only. Annotations help agents reason about safety and retry logic.
Error messages are generic ('Vault operation failed'). No recovery guidance. When a note is not found or a write fails, the LLM receives no actionable next step.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 69 | 2026-07-28+ | v2 |
search_notes returns snippets as plain text blocks. No structured hit objects with path, score, or fragment metadata. LLMs must parse markdown to extract paths.
No confirmation or dry-run pattern for delete_note. Irreversible operations should support a confirmation step to prevent accidental deletions by agents.