MCP server for Gmail operations including reading emails, sending emails, and token refresh
Three tools with basic schemas and descriptions, but significant gaps in parameter documentation, error handling, and output schema clarity. get_recent_emails and send_email have reasonable descriptions (50-80 chars), but refresh_token lacks context on when/why to use it. Parameters are typed but lack detailed constraints, ranges, or format guidance. No output schemas documented. Error handling is minimal, responses are JSON strings rather than structured objects. No tool annotations (readOnlyHint, destructiveHint). Naming is acceptable (verb_noun pattern), but descriptions fall short of LLM-optimized guidance (target 50-200 chars per pattern:tool-description).
Get the most recent emails from Gmail
Refresh the access token using the refresh token
Send an email using Gmail
refresh_token lacks actionable description. Current: 'Refresh the access token using the refresh token' (56 chars). Does not explain WHEN to call it, what triggers expiry, or what the LLM should do with the returned token. Should state: 'Refresh an expired access token. Call this when Gmail API returns a 401 Unauthorized error. Returns new access_token and expires_at timestamp.'
No output schemas documented for any tool. LLMs cannot plan downstream calls or extract required fields. get_recent_emails should document: returns array of {id, from, subject, snippet, date, unread}. send_email should document: returns {message_id, thread_id, status}. refresh_token should document: returns {access_token, expires_at, expires_in, status, error?}.
Parameter descriptions lack constraints and format guidance. max_results has no min/max bounds (should be 1-100). html_body marked optional but no guidance on when to use vs body. cc/bcc are arrays but no limit on recipients. Descriptions should state: 'max_results: integer, 1-100 (default 10)', 'html_body: optional HTML string, max 10MB, overrides plain text if provided'.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 57 | <=2025-11-25 | v2 |
Error handling returns raw JSON strings instead of structured error objects. refresh_token returns json.dumps({"error": "...", "status": "error"}), this is a string, not a typed response. Should return structured {status: 'error', code: 'REFRESH_FAILED', message: '...', retryable: true}. Current approach forces LLM to parse JSON text, which is error-prone.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). get_recent_emails should have readOnlyHint=true. send_email should have destructiveHint=true (irreversible). refresh_token should have idempotentHint=true (safe to retry). These hints guide agent planning and error recovery.