MCP server for PurelyMail email service management
This server exhibits significant quality gaps across naming, descriptions, parameter documentation, and schema completeness. While tool names follow verb_noun convention reasonably well (create_user, delete_user, list_users, etc.), the descriptions are extremely terse, most are under 20 characters, violating the critical baseline that descriptions must be 10 - 1024 characters with substantive guidance. Parameters almost universally lack type definitions in visible schemas; most tools have required=[] despite having required parameters. Input schemas are auto-generated from OpenAPI but appear incomplete in the data provided. Error handling is present but generic ('Error: ' prefix). No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are visible. The server dynamically generates tools from an OpenAPI spec (createToolsFromSpec), which is a maintenance win but masks schema quality issues, we cannot verify schemas are being properly translated. No pagination guidance is visible for list_* tools. No output schemas are documented. No parameter relationships or constraints are described. This reads as a thin wrapper over a third-party API with minimal agent-optimization work.
Adds a domain, assuming it passes DNS checks.
Returns current account credit, as a BigDecimal string with precision 64.
Creates a new app password.
Creates or updates a password reset method (either phone or email).
Routing rule must not have the same user/prefix as any other existing rules for the domain.
Creates a new user.
Deletes an app password.
Descriptions are universally terse and uninformative. 15 of 19 tools have descriptions under 20 characters ('Deletes a user.', 'Creates a new user.', etc.). These lack WHEN to use the tool, prerequisites, consequences, or context that would guide LLM selection.
Input schemas have required=[] for most tools despite having required parameters (e.g., userName is logically required for get_user, but required=[]). This allows LLMs to omit necessary parameters, causing runtime errors. The schema validation is inverted.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 30 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Deletes a domain, and all dependent settings and users.
Deletes a password reset method.
Deletes an existing routing rule
Deletes a user.
Gets the DNS record value of the Purelymail ownership proof record, required to add a domain
Retrieves details of a user.
Lists domains accessible to an account, possibly including shared domains.
Lists all password reset methods for a user.
Lists all routing rules active under your account
Lists all users under your account (up to 1000).
Modifies a user.
Updates settings for an existing owned domain.
Parameters lack type descriptions in many cases. For example, domainName is described only as 'The domain name for the user' but does not specify format, constraints, or examples. Parameters named 'type' (in create_or_update_password_reset_method) lack descriptions altogether or are minimal ('The reset method type (email or phone)').
No output schemas are documented. LLMs have no idea what fields to expect from tool responses (e.g., does list_users return an array of user objects, or a paginated result with count and items?). This blocks downstream tool chaining and forces LLMs to guess field names.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are present. LLMs cannot distinguish safe reads (list_users, get_user) from destructive writes (delete_user, delete_domain) without reading descriptions. This is especially critical for destructive ops where a single mistake ends a user or domain.
List tools (list_users, list_routing_rules, list_domains, list_password_reset_methods) have no pagination parameters (limit, offset, page_size, cursor) and no mention of result limits. The tool description for list_users states '(up to 1000)', but this is buried in the description, not formalized as a parameter or output contract.
Error handling is generic. The CallToolRequestSchema handler catches errors and returns {isError: true, text: 'Error: ' + message}. There is no categorization (retryable vs. user-fixable vs. fatal), no recovery guidance (e.g., 'User not found. Try list_users() to find available users.'), and no validation of input before the call.
No dry-run or confirmation step for destructive operations. delete_user, delete_domain, delete_routing_rule, and delete_app_password have no confirmation mechanism. An agent error or prompt injection could permanently delete user accounts or entire domains without recourse.
Tools generated from OpenAPI spec are not verified for quality. The createToolsFromSpec function in openapi-fetch-generator.ts infers tool definitions from the API spec, but the transformation logic is not visible. This masks whether schemas are being properly translated, enum constraints enforced, or parameter descriptions preserved.