Custom MCP Marketing Server for BandhanAI. Exposes tools over stdio transport for creating marketing campaigns and recording campaign email sends, scoped by tenant organization ID.
This server exposes 2 tools with basic functionality but significant quality gaps. Tool names are appropriately action-based (create_campaign, send_campaign_email), but descriptions lack depth and actionability. Parameter schemas are present with type definitions, but descriptions are minimal (e.g., 'The campaign name.' is only 18 chars, below the 20-char floor). Error handling is reactive (raises ValueError, RuntimeError) but does not guide the LLM toward recovery. The server performs tenant scoping via environment variables (ORG_ID), which is a security best practice, but this is not documented in tool descriptions. Response documentation is absent, the agent cannot predict output structure or plan downstream tool chains. create_campaign returns a UUID string, send_campaign_email returns a success message, but neither output schema is formally documented.
Create a marketing campaign.
Record a campaign email send. This tool records the email in the campaigning_emails table. The actual email delivery is handled separately via the Gmail MCP server (GMAIL_SEND_EMAIL).
Parameter descriptions below 20-character floor. 'The campaign name.' (18 chars), 'Optional campaign description.' (29 chars), 'Email subject line.' (18 chars), 'Email body content (HTML).' (25 chars) lack actionable context for LLM parameter selection.
Output schemas not documented. create_campaign returns 'str: The UUID of the newly created campaign' but the LLM cannot plan downstream tool calls (e.g., to send_campaign_email) without knowing the exact field name and structure. send_campaign_email returns 'str: Success message with subject and customer ID' but format is opaque.
Enum validation done in code, not in schema. 'type' parameter for create_campaign allows ['loyalty', 'referral', 're-engagement', 'at risk', 'new customer', 'champion', 'about to sleep', 'lost', 'potential loyalist'] but enum constraint is not declared in JSON Schema, only enforced at runtime. Status parameter in send_campaign_email has similar issue.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 42 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 30 | - | v1 |
Error handling does not guide recovery. Errors like 'Invalid campaign type: {type}. Must be one of {allowed_types}' or 'ORG_ID environment variable not set' are informative for humans but lack LLM recovery hints (e.g., 'Try calling list_campaign_types() to see valid options' or 'Ensure the MCP server is configured with ORG_ID in the environment').
Tenant scoping via ORG_ID not documented in tool descriptions. The server enforces multi-tenant isolation, but agents have no visibility into this requirement. If ORG_ID is missing, both tools fail with a generic RuntimeError. Agents cannot understand that they need to pass ORG_ID or configure it upstream.
send_campaign_email has undocumented multi-step lookup logic. The function queries crm table, then customers table, then attempts external Supabase connection mapping, but the agent cannot predict which data source will be consulted or what fields are expected. The fallback behavior is opaque.
Parameter naming ambiguity in send_campaign_email. 'campaign_id' is a string UUID, but the type definition does not clarify whether it must be a valid UUID or just any string. Without explicit format validation in schema or description, agents may pass invalid IDs.
No pagination or result limits declared. While these tools do not return large result sets, the output format is undocumented, if create_campaign fails to return a valid UUID, the agent will not know how to interpret the error or retry.