A URL shortener MCP server built with Express, Prisma, TypeScript, and SQLite
Strong tool naming (verb_noun pattern throughout) and comprehensive descriptions (avg 180 chars, well within 10-1024 range). All 8 tools have clear, actionable descriptions explaining WHAT, WHEN, and consequences. Input schemas present with types and descriptions for all parameters. However, output schemas are not explicitly documented in the source code, LLMs cannot see what fields to expect from responses. Error handling is minimal; no recovery guidance or actionable error messages visible. Missing tool annotations (readOnlyHint, destructiveHint) despite clear risk classifications. Descriptions are good but could be more concise (some exceed 200 chars). No pagination parameters visible for list_urls despite potentially large result sets.
Shorten multiple URLs in a single call (max 20). Returns per-URL results including any errors. Each successful result includes estimatedTokensSaved — the per-substitution token savings if you later reference the slug instead of the long URL.
Delete all shortened URLs owned by the authenticated user. This is permanent and cannot be undone. Returns the count of deleted URLs.
Delete a single shortened URL by slug. This is permanent and cannot be undone.
Get aggregate statistics for all shortened URLs owned by the authenticated user, including total URLs, total clicks, and estimated tokens saved.
Retrieve a single shortened URL record by slug, including click count and metadata. Returns the full URL object.
Output schemas not documented. LLMs cannot see what fields responses contain (e.g., does get_url return click_count, createdAt, expiresAt?). Forces agents to guess structure and risks failed downstream tool calls.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk classifications. delete_url and delete_all_urls marked DESTRUCTIVE but lack destructiveHint annotation to guide agent caution.
list_urls lacks pagination parameters (limit, offset, page_size). No indication of result cap. Large URL collections could blow context window without pagination support.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 67 | <=2025-11-25 | v2 |
List all shortened URLs owned by the authenticated user. Supports sorting by createdAt, expiresAt, or clicks in ascending or descending order.
Search shortened URLs by tag and/or longUrl substring. At least one of tag or longUrl must be provided. Returns matching URL records.
Create a new shortened URL and return only the short URL. Optionally provide a TTL or expiry date. If no slug is provided, an AI-suggested slug will be used. Use get_url or list_urls if you need the full URL record. Token savings are only realised when the slug is reused in future context; single-use URLs cost more context than pasting the original inline. Set tag to a brief note about the URL's purpose (e.g. 'auth API docs', 'PR #42') — this lets you retrieve it later via search_urls without needing to remember the slug or keep the context in the conversation.
Error handling not visible in tool definitions. No recovery guidance (e.g., 'slug already exists, try search_urls to find it'). Agents cannot self-correct on failures.
delete_all_urls has empty input schema (no parameters). Description warns 'permanent and cannot be undone' but lacks confirmation/dry-run pattern to prevent accidental invocation.