A Model Context Protocol server for interacting with FreshRSS feeds via the Fever API
FreshRSS MCP server has 8 tools with basic but incomplete definitions. All tools have names starting with action verbs (list_, get_, mark_) which is correct, but descriptions are generic and lack specificity about WHEN to use each tool vs. alternatives. Parameter descriptions exist but are minimal (1-3 words). No output schemas are documented, the response structure from FreshRSS API is not explained to the LLM. No error guidance, no pagination documented despite tools returning potentially large item lists, no idempotency hints for write operations. Tool composition is reasonable (one action per tool), but parameter names could be more explicit (feed_id, item_id are opaque; no user-friendly alternatives). Average parameter description length is ~15 chars, well below the production baseline of 72 chars. Schemas are present and properly typed, but lack constraints (enums, limits, patterns). No secrets leakage detected (auth via environment variables). Overall, this is a straightforward CRUD wrapper with minimal agent optimization.
Get feed groups
Get items from a specific feed
Get specific items by their IDs
Get unread items
List all feed subscriptions
Mark all items in a feed as read
Mark an item as read
No output schemas documented. LLMs cannot infer what fields get_unread, list_feeds, get_feed_items return, forcing them to guess or make additional calls. The FreshRSSItem interface exists in code but is never exposed to the MCP client.
Tool descriptions are too generic (10-20 chars). 'List all feed subscriptions' and 'Get unread items' lack context: When should I call list_feeds vs. get_feed_items? What structure does list_feeds return? Does it require pagination? Average description length is 25 chars vs. baseline 194.
No pagination support documented. get_feed_items, get_unread, and get_items could return hundreds or thousands of items, blowing the context window. No limit, offset, page, or cursor parameters exposed. Response cap and pagination strategy are invisible to the LLM.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 42 | - | v1 |
Mark an item as unread
Parameter descriptions are minimal (1-3 words). 'Feed ID', 'Item ID to mark as read', 'Array of item IDs to get' do not explain format, constraints, or alternatives. No mention of whether IDs are numeric, strings, or if natural names are accepted. Baseline is 72 chars per parameter.
No error handling guidance. If mark_item_read fails, the LLM has no guidance: Retry? Ask the user? Are errors retryable? The code catches axios errors and throws McpError but provides no classification or recovery hints.
Write operations (mark_item_read, mark_item_unread, mark_feed_read) have no dry-run, confirmation, or destructive hints. An agent could mark an entire feed as read without acknowledgment. No tool annotations present.
No parameter constraints (enums, min/max, regex). feed_id and item_id are free-form strings with no format hints. The LLM has no way to know if IDs should be numeric, prefixed, or of any specific format.
No idempotency hints. mark_item_read and mark_item_unread called twice with the same item_id should be safe, but this is not stated. Agents retry on ambiguous failures, without idempotency guarantees, they risk unintended side effects.