MCP server for managing marketing campaigns and sending campaign emails in a CRM system
Two tools with basic descriptions and schemas, but multiple critical gaps limit production readiness. Tool names follow verb-noun convention (create_campaign, send_campaign_email), which is positive. Descriptions exist but are generic and lack LLM-optimized context. Parameter descriptions are present but minimal. No enum constraints on the 'type' parameter despite being a constrained field. No documented output schemas. Error handling is absent, both tools lack recovery guidance. The 'type' parameter in create_campaign explicitly states 'One of: loyalty, referral, re-engagement' in the description, but this should be enforced as an enum in the schema, not just text. No indication of idempotency, pagination, or result limiting. Security concerns: database credentials are injected via environment variables (good), but no validation or sanitization is visible in the tool implementations. The send_campaign_email function has a TODO comment ('TODO: Send email via MCP'), indicating incomplete implementation.
Create a marketing campaign. Args: name: The name of the campaign. type: The type of the campaign. One of: loyalty, referral, re-engagement description: The description of the campaign. Returns: The ID of the created campaign.
Send a campaign email. Args: campaign_id: The ID of the campaign. customer_id: The ID of the customer. subject: The subject of the email. body: The body of the email. Returns: A confirmation that the email was sent.
Incomplete implementation: send_campaign_email has a TODO comment and does not actually send emails, it only inserts records into a database. This breaks the contract promised by the tool description.
Schema mismatch: send_campaign_email's schema declares campaign_id as type 'string', but the function signature expects UUID. This will cause runtime failures when agents pass string IDs.
Missing enum constraint on 'type' parameter in create_campaign. Description text says 'One of: loyalty, referral, re-engagement', but this is not enforced as a JSON Schema enum. LLMs may hallucinate invalid values like 'seasonal' or 'promotional'.
No output schema documentation. Both tools return strings, but LLMs do not know the format, structure, or what fields are available for downstream composition. create_campaign returns an ID but format is undocumented. send_campaign_email returns a confirmation string but structure is undefined.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 42 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 42 | - | v1 |
No error handling or recovery guidance. If campaign_id doesn't exist or type is invalid, functions will fail with database errors. No tool provides guidance on what to do next (e.g., 'Try search_campaigns() first').
send_campaign_email is a destructive operation (sends email) with no confirmation step or dry-run support. No idempotency guarantee. If an LLM retries on ambiguous failure, users may receive duplicate emails.
Minimal parameter descriptions. 'The ID of the campaign' and 'The ID of the customer' do not explain expected format (UUID vs integer string?), valid ranges, or lookup strategy. LLMs may pass invalid IDs without guidance.
No input validation visible in tool implementations. No SQL injection prevention (though parameterized queries help), no type coercion guards, no constraint enforcement before database calls.