Content Saver MCP Server + Next.js Web UI for saving notes, links, searching content, and managing saved items with AI-powered enrichment
This MCP server has 6 tools with defined input schemas and descriptions, but exhibits significant quality gaps across naming, parameter validation, and output documentation. Tool descriptions are present but generic (avg ~100 chars). Parameter descriptions are minimal. Critically, NO output schemas are documented for any tool, violating a hard baseline of production-grade tools. Error handling is present but not recovery-focused. The server lacks idempotency guarantees, pagination metadata, and chaining IDs despite handling collections. Per-tool scores average 42, reflecting widespread structural issues rather than isolated problems.
Delete a saved item by its ID. Returns success confirmation or error if ID not found.
List recently saved items. Returns items from the last N days, ordered newest to oldest.
Save a URL/link with optional title, comment, and tags. Prevents duplicates for the same URL.
Save a text note with optional title and tags. Tags should be provided by the AI client.
Search saved items using query text, tags, and/or date range. Returns both notes and links.
Update an existing item (note or link) by its ID. Supports partial updates - only provided fields will be changed.
NO output schemas documented for any of 6 tools. LLMs cannot predict response structure, plan downstream calls, or extract required fields. This violates a critical baseline: '100% of A+ tools have documented return types'.
'search' tool accepts free-form 'query' parameter with no format constraints or examples. Description states 'searches title, body, URL' but does not clarify: Is it regex? Substring? AND/OR logic? Returns 'both notes and links' but does not specify pagination, total count, or result limit. Agents cannot estimate result size.
'list_recent' accepts 'limit' parameter with no range constraint (e.g. 1-100). Description states default days=7 but does not specify max result count or pagination. If an LLM passes limit=10000, server behavior is undefined. Violates 'Specify minimum and maximum for numeric parameters'.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 46 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 40 | - | v1 |
No pagination metadata in return. If 'search' or 'list_recent' return 20+ items, LLM cannot fetch next page. Baselines require 'paginated-result' pattern with offset/limit and total count. Large result sets will blow context window.
Error handling in CallToolRequestSchema returns generic '{"content": [{"type": "text", "text": "Error: <message>"}], "isError": true}'. Does not categorize errors as retryable vs. user-fixable vs. fatal. Does not provide recovery guidance (e.g. 'Try search_users()' or 'This operation cannot be retried'). Violates 'recovery-guide' pattern.
'delete_item' and 'update_item' are irreversible operations. No confirmation step, dry-run, or warning in description that operation is destructive and non-recoverable. Violates 'confirmation-request' pattern for high-risk tools. Description for 'delete_item' is 65 chars; could include explicit warning.
Parameter 'tags' across 3 tools (save_note, save_link, update_item) is described as 'Optional array of tags' with no guidance on: tag format, max length, allowed characters, max count per item, or examples. LLMs will guess, some may pass HTML, special chars, or 1000+ tags, breaking downstream systems.
Parameter descriptions are minimal. 'title' is 'Optional title for the note' (28 chars), no max length, no format hint. 'body' is 'Required body text' (18 chars), what is max size? Can it contain HTML? Baselines require 'LLM-optimized descriptions (50-200 chars)'.
'search' parameters 'dateFrom' and 'dateTo' are described as ISO 8601 format but no validation shown in code. If an LLM passes '2024-13-45' or 'yesterday', behavior is undefined. Baselines require: 'Specify the expected format, range, and allowed values directly in parameter description.'
'update_item' parameter 'url' is described as 'New URL for links only (optional, ignored for notes)'. But no validation shown: must it be a valid HTTP(S) URL? What about relative URLs? Description implies conditional behavior but does not define when error vs. silent ignore occurs.