Pingen hybrid mail MCP server — physical letters, mass-mailing batches, Swiss eBill
Strong tool definitions with comprehensive descriptions and proper schemas. All 19 tools have clear, action-oriented names (verb_noun pattern) and detailed descriptions (100-300 chars, well above 20-char minimum). Input schemas are complete with typed parameters and descriptions. Tool annotations (readOnlyHint, openWorldHint) are present. Key strengths: two-phase confirmation patterns for irreversible operations (send, delete, cancel), bulk operation support, and clear billing impact warnings. Weaknesses: output schemas not explicitly documented in source; some parameter descriptions could be more prescriptive about constraints (e.g., enum values for delivery_product are listed in descriptions but not as formal JSON Schema enums); error handling guidance is minimal.
Cancel a batch or multiple batches. Two-phase confirmation required. Cancellation may fail if already submitted to the printer. Supports bulk mode via ids[].
Upload a multi-recipient PDF and create a batch draft. The PDF must contain all recipient letters — each page or section maps to one recipient. Performs the two-step signed-URL upload then creates with auto_send=false. Batch starts in "validating" status. Send with pingen_batch_send after status is "valid".
Get a batch by UUID. Optionally include the letter objects within the batch (include_letters=true). Returns batch status, file info, delivery settings, and statistics.
List mass-mailing batches in your organisation. Batches are multi-letter PDFs where one PDF contains multiple recipients. Supports status filter and pagination.
Submit a batch (or multiple batches) for postal delivery. BILLING IMPACT: triggers real postal delivery for all letters in the batch(es). Two-phase confirmation required. Bulk mode: provide ids[] to send multiple batches with one confirmation.
Output schemas not documented in source code. Tool descriptions mention what is returned (e.g., 'Returns paginated letter objects', 'Returns full details'), but the actual response structure is not visible in the provided code. LLMs cannot plan downstream tool calls or extract specific fields without knowing the response schema.
Enum constraints for delivery_product, print_mode, print_spectrum, and status are documented in descriptions as free-form strings (e.g., 'cheap, fast, premium, registered') rather than formal JSON Schema enums. LLMs may hallucinate invalid values; formal enums are self-documenting and machine-parseable.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 65 | 2026-07-28+ | v2 |
Create and submit a Swiss eBill (electronic invoice) to the SIX eBill network. BILLING IMPACT: real SIX eBill submission. Two-phase confirmation required: Phase 1 — call without confirm_token to get a summary + confirm_token. Phase 2 — call again with confirm_token to execute.
Get a single eBill by UUID. Returns full details including status, file info, and submission timestamps.
List Swiss eBill submissions in your organisation. eBills are electronic invoices delivered via the SIX eBill network to the recipient's e-banking system. Supports status filter and pagination.
Calculate the price for sending a letter with given delivery and print settings. Returns the estimated cost in CHF (or organisation billing currency). Call this BEFORE pingen_letter_send to show the agent/user the cost and include it in the confirmation summary.
Cancel a letter or multiple letters. Two-phase confirmation required. Cancellation may fail if the letter is already submitted to the printer (status "sending" or later). Supports bulk mode via ids[].
Upload a PDF and create a letter draft in Pingen. Performs the two-step file upload (signed S3 URL) then creates the letter with auto_send=false (draft). The letter starts in "validating" status — Pingen verifies the PDF and address position. Check status with pingen_letter_get, see issues with pingen_letter_list_issues. Send with pingen_letter_send after status is "valid".
Soft-delete a letter or multiple letters from your Pingen view. DESTRUCTIVE: removes the letter from your data view subject to data retention policy. Two-phase confirmation required. Supports bulk mode via ids[].
Edit an existing letter draft (status must be "validating" or "valid"). Modify address position, delivery product, print settings, or metadata. Cannot edit letters already sent or cancelled.
Get a single letter by UUID. Returns full details including status, delivery product, print settings, file URL, and timestamps.
List letters in your Pingen organisation with optional filters. Returns paginated letter objects with status, file info, and delivery details. Use status filter to find letters in a specific state (e.g. "valid" = ready to send, "delivered" = confirmed delivery).
List issue events for a specific letter. Use this when a letter status is "invalid" to understand why (e.g. "file_too_many_pages", "address_invalid", "address_not_found"). Returns event objects with code, name, and details.
Submit a letter (or multiple letters in bulk) for postal delivery. BILLING IMPACT: triggers real postal delivery at CHF 0.97+/letter. Two-phase confirmation required: Phase 1 — call without confirm_token to get a summary + confirm_token. Phase 2 — call again with the same arguments plus confirm_token to execute. Bulk mode: provide ids[] instead of id to send multiple letters with one confirmation. Recommended: call pingen_letter_calculate_price first to verify the cost and include it in the Phase 1 summary.
Get a single organisation by UUID. Returns full details including billing balance, plan, and account status. Use this to check billing balance before sending letters.
List all organisations accessible to the authenticated Pingen account. Returns organisation UUIDs, names, and billing information.
Error handling is minimal. The toolError() wrapper catches exceptions and returns a message, but does not categorize errors as retryable, user-fixable, or fatal. LLMs receive no guidance on whether to retry, ask the user, or abort. No recovery hints (e.g., 'Try pingen_letter_list_issues() to see why validation failed').
Mutually exclusive parameters (id vs ids in send/cancel/delete tools) are documented in descriptions but not enforced at the schema level. JSON Schema oneOf or conditional validation would prevent LLMs from passing both parameters simultaneously.
No documented rate limits, timeout guidance, or retry strategies. Tools calling external Pingen API may hang or fail; agents need explicit timeout and backoff guidance to avoid blocking.