PostStack MCP server demonstrates solid definition quality with well-structured tool naming, comprehensive descriptions following the 'what/when/returns' pattern, and complete JSON Schema input specifications. All 11 tools follow verb_noun naming conventions (create_*, list_*, get_*, verify_*, update_*, delete_, check_*, revoke_*). Descriptions average ~180 characters and explicitly state use cases and return structures. However, output schemas are not formally documented in code, responses are shaped via helper functions (shapeDomain, respond) but schema definitions are not visible in the provided source. All parameters have type definitions and descriptions. Error handling is present but limited, most tools lack recovery guidance or actionable error messages. Security considerations are addressed (API key injection, destructive operation warnings) but no explicit permission gating or audit trails visible. Tool composition is clean, single responsibility per tool, IDs flow through chains correctly.
Check whether a from-address is safe to send from RIGHT NOW. When to use: BEFORE sending agent-generated content from a non-default domain. Combines DNS verification (DKIM/SPF/DMARC), 30-day bounce + complaint rates, and the standard deliverability warnings (no plain-text body, link-domain mismatch, oversized HTML, etc.) into one response. Returns: { from, domain, domain_verified, dkim, spf, dmarc, return_path, volume_30d, bounce_rate, complaint_rate, warnings[] }. Example: { from: "Acme <hi@acme.io>" }
Generate a new PostStack API key. The full key is returned ONCE in this response and cannot be retrieved again. When to use: agent needs to provision credentials for a new integration. Pick "sending_access" for send-only keys (recommended for app servers) or "full_access" for management. Returns: shaped key including the secret string — display it once and tell the user to store it securely. Example: { name: "Backend prod", permission: "sending_access" }
Add a new sending domain to PostStack. When to use: a customer is onboarding a new sending domain. The response includes DNS records (SPF, DKIM, DMARC, return-path) the user must configure before verify_domain succeeds. Returns: shaped domain with dnsRecords[] and pending status. Example: { name: "send.acme.io", region: "eu-west-1" }
Permanently delete a sending domain (irreversible — historical email records remain). When to use: a domain is being decommissioned. Confirm with the user first since future sends from any matching from-address will fail. Returns: { success: boolean }. Example: { id: 42 }
Output schemas not explicitly documented. Tools use helper functions (shapeDomain, respond) to structure responses, but the actual schema definitions are not visible in provided source code. LLMs cannot reliably predict response structure for planning.
Error handling lacks actionable recovery guidance. Tools return errors but do not tell LLMs what to do next (e.g., 'Domain verification failed, ensure DNS records are propagated, then call verify_domain again'). Generic errors offer no recovery path.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | 2025-06-18+ | v2 |
Get an API key's metadata (the secret is never returned after creation). When to use: confirm a key's permission, mode or last-used timestamp before revoking. Returns: shaped key without secret. Example: { id: 17 }
Get domain details including DNS records and verification status. When to use: read DNS records to display, or check whether the domain is verified before sending. Returns: shaped domain (status, dnsRecords[], tracking flags, verifiedAt). Example: { id: 42 }
List API keys (only the prefix is returned, never the full secret). When to use: audit which keys exist, find a key id to revoke. Returns: { keys: [{ id, name, keyPrefix, permission, mode, ... }] }. Example: { per_page: 50 }
List sending domains. When to use: choose which domain to send from, or audit which domains are verified. Returns: { domains: [...] } — array of shaped domains with status and tracking flags. Example: { per_page: 50 }
Permanently revoke an API key — all subsequent requests using it will fail. When to use: a key has leaked or is no longer needed. Confirm with the user — irreversible. Returns: { success: boolean }. Example: { id: 17 }
Update domain settings (tracking, TLS, inbound, BIMI, sending stream). When to use: toggle tracking on/off, switch TLS modes, enable inbound webhook receiving + catch-all routing, set BIMI logo, or pin a domain to a specific sending stream. Returns: shaped domain with updated settings. Example: { id: 42, click_tracking: false, tls_mode: "enforced", inbound_enabled: true }
Trigger DNS verification for a domain. When to use: user has configured DNS records (SPF/DKIM/DMARC/return-path) and wants PostStack to re-check them. Returns the new status — "verified" means sending is unblocked. Returns: shaped domain with updated status and per-record verified flags. Example: { id: 42 }
Destructive operations (delete_domain, revoke_api_key) lack confirmation/dry-run patterns. Descriptions warn users to confirm, but no tool-level confirmation step exists. An LLM could delete a domain irreversibly without explicit user approval.
Permission/scope declarations missing. Tools do not declare what permissions they require (e.g., 'read:domains', 'write:domains', 'delete:domains'). No audit trail visibility in tool definitions.
Parameter constraints not fully specified. Some parameters (e.g., 'name' in create_domain) lack length/pattern constraints. 'region' is enum-constrained to 'eu-west-1' only (single value), this could be clearer as text ('EU-only platform currently'). 'page' and 'per_page' parameters lack min/max bounds.
Tool descriptions include example usage patterns but could benefit from explicit dependency hints. E.g., 'create_domain returns pending status, call verify_domain after DNS configuration' is stated, but 'check_deliverability' does not mention that it requires an existing, verified domain.