From 1c32d3bb5da3b0e86ec29a7fafce1ad43f0b80d2 Mon Sep 17 00:00:00 2001 From: devlikemasta Date: Wed, 16 Sep 2026 19:47:11 +0200 Subject: [PATCH] Add WhatSetter third-party MCP plugin WhatSetter is an AI appointment setter on WhatsApp. The plugin points at WhatSetter's hosted Streamable HTTP MCP server (https://mcp.whatsetter.com/mcp, OAuth 2.1 with DCR and PKCE, nothing to configure) and bundles the whatsetter skill: operating rules, playbooks, and the API's error table. Registers the plugin in .cursor-plugin/marketplace.json and the README table. --- .cursor-plugin/marketplace.json | 5 + README.md | 1 + .../whatsetter/.cursor-plugin/plugin.json | 37 ++++++ third_party/whatsetter/CHANGELOG.md | 10 ++ third_party/whatsetter/LICENSE | 21 ++++ third_party/whatsetter/README.md | 84 +++++++++++++ third_party/whatsetter/assets/logo.png | Bin 0 -> 40162 bytes third_party/whatsetter/mcp.json | 8 ++ .../whatsetter/skills/whatsetter/SKILL.md | 117 ++++++++++++++++++ 9 files changed, 283 insertions(+) create mode 100644 third_party/whatsetter/.cursor-plugin/plugin.json create mode 100644 third_party/whatsetter/CHANGELOG.md create mode 100644 third_party/whatsetter/LICENSE create mode 100644 third_party/whatsetter/README.md create mode 100644 third_party/whatsetter/assets/logo.png create mode 100644 third_party/whatsetter/mcp.json create mode 100644 third_party/whatsetter/skills/whatsetter/SKILL.md diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 98137ca8..bbf843d3 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -407,6 +407,11 @@ "name": "google-cloud-bigquery", "source": "third_party/google-cloud-bigquery", "description": "Explore datasets and tables and run SQL queries." + }, + { + "name": "whatsetter", + "source": "third_party/whatsetter", + "description": "Work WhatsApp leads, conversations, bookings, and campaigns run by the WhatSetter AI setter." } ] } diff --git a/README.md b/README.md index 75c92cf5..18499854 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Official Cursor plugins for popular developer tools, frameworks, and SaaS produc | `daloopa` | [Daloopa](third_party/daloopa/) | Cursor | Integrations | Pull source-linked fundamentals, KPIs, filings, and prices. | | `excalidraw` | [Excalidraw](third_party/excalidraw/) | Cursor | Integrations | Draw and export hand-drawn diagrams from chat. | | `google-cloud-bigquery` | [Google Cloud BigQuery](third_party/google-cloud-bigquery/) | Cursor | Integrations | Explore datasets and tables and run SQL queries. | +| `whatsetter` | [WhatSetter](third_party/whatsetter/) | WhatSetter | Integrations | Work WhatsApp leads, conversations, bookings, and campaigns run by the WhatSetter AI setter. | Author values match each plugin’s `plugin.json` `author.name` (Cursor lists `plugins@cursor.com` in the manifest). ## Repository structure diff --git a/third_party/whatsetter/.cursor-plugin/plugin.json b/third_party/whatsetter/.cursor-plugin/plugin.json new file mode 100644 index 00000000..857308bb --- /dev/null +++ b/third_party/whatsetter/.cursor-plugin/plugin.json @@ -0,0 +1,37 @@ +{ + "name": "whatsetter", + "displayName": "WhatSetter", + "version": "1.0.0", + "minClientVersions": { + "cursor": "3.13.0" + }, + "description": "Work WhatsApp leads, conversations, bookings, and campaigns run by the WhatSetter AI setter.", + "author": { + "name": "WhatSetter", + "email": "contact@whatsetter.com" + }, + "homepage": "https://docs.whatsetter.com/developers/mcp/", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "logo": "assets/logo.png", + "keywords": [ + "whatsetter", + "whatsapp", + "ai setter", + "appointment setting", + "leads", + "conversations", + "bookings", + "campaigns", + "mcp" + ], + "category": "integrations", + "tags": [ + "whatsetter", + "whatsapp", + "sales", + "mcp" + ], + "mcpServers": "./mcp.json", + "skills": "./skills/" +} diff --git a/third_party/whatsetter/CHANGELOG.md b/third_party/whatsetter/CHANGELOG.md new file mode 100644 index 00000000..f6146f0c --- /dev/null +++ b/third_party/whatsetter/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this plugin will be documented here. + +## 1.0.0 — initial release + +- Added the `whatsetter` MCP server pointing at WhatSetter's hosted Streamable HTTP endpoint (`https://mcp.whatsetter.com/mcp`). +- Auth is OAuth 2.1 with Dynamic Client Registration and PKCE, discovered from the server; no key or client ID in the plugin configuration. +- Bundled the `whatsetter` skill: operating rules, playbooks, and the API's error table, so agents read tool results correctly and ask before anything is sent. +- Logo: WhatSetter's brand mark, from the `whatsetter` GitHub organization. diff --git a/third_party/whatsetter/LICENSE b/third_party/whatsetter/LICENSE new file mode 100644 index 00000000..b601fb9a --- /dev/null +++ b/third_party/whatsetter/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 WhatSetter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/whatsetter/README.md b/third_party/whatsetter/README.md new file mode 100644 index 00000000..8b2e50e1 --- /dev/null +++ b/third_party/whatsetter/README.md @@ -0,0 +1,84 @@ +# WhatSetter + +Cursor plugin that connects agents to [WhatSetter](https://whatsetter.com) through WhatSetter's hosted [Model Context Protocol](https://modelcontextprotocol.io/) server. + +WhatSetter is an AI appointment setter on WhatsApp. Read the inbox and the leads it is working, review meetings it booked, import contacts, pause or resume campaigns, and, with explicit approval, send a WhatsApp message from a connected number. + +Official setup: https://docs.whatsetter.com/developers/mcp/ + +## Install + +1. Open **Cursor Settings → Plugins**. +2. Search for **WhatSetter**. +3. Click **Install**, then complete the **Connect to WhatSetter** step (below). + +Or run `/add-plugin whatsetter` in chat. + +## MCP + +```json +{ + "mcpServers": { + "whatsetter": { + "type": "http", + "url": "https://mcp.whatsetter.com/mcp" + } + } +} +``` + +Auth is OAuth 2.1 against WhatSetter with Dynamic Client Registration (DCR) and PKCE, discovered from the server's `WWW-Authenticate` header and `/.well-known/oauth-protected-resource`. Cursor registers itself and opens the **Connect to WhatSetter** page on the first tool call: paste a WhatSetter API key there and approve. Cursor only ever holds a revocable token; the key is checked live and stored encrypted on the WhatSetter server. There is no API key or client ID to configure in the plugin. + +## Before you connect + +You need a WhatSetter workspace at [app.whatsetter.com](https://app.whatsetter.com) and an API key from **Settings → API**. Give the key only the scopes you need; tool calls cannot exceed them. + +| Scope | Lets the agent | +| --- | --- | +| `leads:read` / `leads:write` | Read leads / update their status and tags | +| `conversations:read` | Read the inbox and message history | +| `lists:read` / `lists:write` | List and create contact lists, import contacts | +| `campaigns:read` / `campaigns:write` | List campaigns / pause and resume them | +| `messages:send` | Send WhatsApp messages from a connected number | +| `bookings:read` | Read booked meetings | +| `groups:read` | Read managed WhatsApp groups: members, messages, joins and leaves | +| `webhooks:manage` | Create, delete, and test webhooks | + +A good first key for a daily briefing: `leads:read`, `conversations:read`, `campaigns:read`, `bookings:read`. Add `messages:send` only if the agent may reply on your behalf. + +## What agents can do + +| Category | Capabilities | +| --- | --- | +| Identity | `whoami`: the workspace and the scopes of the key, to start every session | +| Leads | List and search leads, read one lead with its qualification, update status and tags | +| Conversations | List conversations and read the full message history of a lead | +| Messaging | Send a WhatsApp message to a lead the setter has already contacted | +| Lists | List and create contact lists, import contacts (first contact is then made by the campaign, at a safe pace) | +| Campaigns | List campaigns, pause and resume them | +| Bookings | List the meetings booked by the setter, per campaign | +| Groups | List managed WhatsApp groups, their members, messages, joins and leaves | +| Webhooks | List, create, delete, and test webhooks (for example on `lead.qualified`) | + +The hosted server is the source of truth for tool names and schemas. The bundled `whatsetter` skill teaches the agent how to combine the tools and when to stop and ask. + +## Notes + +- Every tool carries `readOnlyHint` / `destructiveHint` annotations, so Cursor can auto-approve reads and always prompts on writes. `send_whatsapp_message` is the only tool that reaches a real person; the skill has the agent show the recipient and the exact text and wait for confirmation. +- Anti-ban rules are enforced by the WhatSetter API, not by a prompt: a number that was never contacted cannot be messaged cold (`lead_not_contacted`), each WhatsApp number has a daily message budget (`quota_exceeded`), and every send carries an idempotency key. +- A message sent through the plugin does not pause the AI setter: it keeps answering the lead and sees the message in the history. +- Sending messages and running campaigns need at least one WhatsApp number connected in the workspace. + +## Docs + +- WhatSetter MCP guide: https://docs.whatsetter.com/developers/mcp/ +- API keys and scopes: https://docs.whatsetter.com/developers/authentication/ +- Anti-ban protections: https://docs.whatsetter.com/dashboard/anti-ban/ +- Upstream plugin repository (Grok CLI and Claude Code manifests): https://github.com/whatsetter/whatsetter-plugin +- Server URL: https://mcp.whatsetter.com/mcp + +Logo is WhatSetter's brand mark on a white tile. + +## License + +MIT diff --git a/third_party/whatsetter/assets/logo.png b/third_party/whatsetter/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..775565ad9fe6e588e0a3ff8b784376853b88bf63 GIT binary patch literal 40162 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 z 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 literal 0 HcmV?d00001 diff --git a/third_party/whatsetter/mcp.json b/third_party/whatsetter/mcp.json new file mode 100644 index 00000000..db302286 --- /dev/null +++ b/third_party/whatsetter/mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "whatsetter": { + "type": "http", + "url": "https://mcp.whatsetter.com/mcp" + } + } +} diff --git a/third_party/whatsetter/skills/whatsetter/SKILL.md b/third_party/whatsetter/skills/whatsetter/SKILL.md new file mode 100644 index 00000000..a9113f18 --- /dev/null +++ b/third_party/whatsetter/skills/whatsetter/SKILL.md @@ -0,0 +1,117 @@ +--- +name: whatsetter +description: Operate a WhatSetter workspace (AI appointment setter on WhatsApp) through the WhatSetter MCP tools. Use when the user mentions WhatSetter or asks about their WhatsApp leads, inbox, replies, campaigns, bookings, lead lists, CRM sync, webhooks or WhatsApp groups. Covers the daily briefing, inbox triage and reply drafts, lead import, qualified leads and booked meetings, pausing and resuming campaigns, CRM write-back and group analytics. Never sends a WhatsApp message without the user's explicit approval. +--- + +# WhatSetter + +WhatSetter runs an AI setter on WhatsApp. Campaigns send the first message to leads imported into lists, the AI qualifies them in conversation and books meetings. You operate that workspace through the `whatsetter` MCP tools. The API behind each tool enforces scopes, rate limits and anti-ban rules. Your job is to use it like a careful human operator. + +## Rules + +1. **Nothing sends without an explicit yes.** `send_whatsapp_message` reaches a real person and cannot be undone. Before calling it, show the lead's name, phone and the exact text, then wait for approval of that message. A draft is not an approval. Approving one message does not cover the next one. For several sends, show the full list and get one explicit approval for that list as shown. +2. **Never message someone new directly.** Sending only works for leads the workspace has already contacted. New contacts go into a list with `import_leads`, and an active campaign sends the first message at a safe pace. On `409 lead_not_contacted`, explain this and offer the import. Never look for a workaround. +3. **Respect the daily budget.** Each WhatsApp number has a daily message quota shared by campaigns, follow-ups and the API. On `429 quota_exceeded`, stop sending on that number, don't retry, and tell the user it resets at midnight UTC. Never pass `humanize: false`. +4. **Don't talk over the AI setter.** In active campaigns the AI answers leads by itself. If a lead's last message is only a few minutes old, the AI is probably handling it: say so instead of drafting. Flag leads who have waited hours with no answer, which usually means a paused campaign or a disconnected number. A message sent through these tools does not pause the AI: it keeps answering the lead afterwards and sees your message in the history. Taking a conversation over for good is done in the dashboard. +5. **WhatSetter is the source of truth.** Names, statuses, messages, bookings and counts come from tool results. Never invent a reply, a booking, a figure or a sent message. When data is missing, say what is missing. +6. **Write like a person on WhatsApp.** Drafts are short plain text, in the language the lead writes in. No markdown, no bullet points, no dashes used as punctuation, no empty compliments. Follow the tone of the conversation so far. + +## First call of every session + +Call `whoami` once. It returns `data.team_id` (the workspace) and `data.key.scopes`. Plan only what those scopes allow. If the user asks for something the key can't do, name the missing scope and tell them to add it in WhatSetter under **Settings → API** (a call without it returns `403 insufficient_scope`). + +## Reading tool results + +- Every result is a JSON envelope: `data` (the payload), `pagination` (`has_more`, `next_cursor`) when the tool lists things, and `_meta` with the API's rate-limit and quota headers (`x-ratelimit-remaining`, `x-quota-remaining`, `x-quota-reset`). Errors come back as `error.code` and `error.message`. +- Results are paginated. Pass `pagination.next_cursor` back as `cursor`, and stop as soon as you have what the question needs. +- Lead and conversation `status`: `new`, `in_progress`, `qualified`, `not_qualified`, `cold`, `unsubscribed`. +- `last_message_direction`: `inbound` means the lead wrote last, `outbound` means the workspace did. `last_message_at` tells how long ago. +- `replied` means the lead has answered at least once. `qualified_at` and `booking_status` show progress toward a meeting. +- `source` tells where a lead came from: `list` (campaign sender), `inbound` (wrote first), `api`, `webhook`, `instagram`, or a social channel when the lead came through a tracked WhatsApp link. +- Messages from `get_conversation_messages` carry `direction`, `text`, `has_media` and `sent_at`. Media content is not available, only the flag. +- A `send_whatsapp_message` result includes `quota.remaining` and `quota.resets_at`. Mention the remaining budget when it is low. + +## Playbooks + +### Daily briefing + +"What's new?", "Give me my morning briefing." + +Read-only. Combine, for the period asked (default: the last 24 hours): + +1. Inbox triage below, without drafts unless asked. +2. Qualified leads: `list_leads` with `status: "qualified"` and `since`. +3. Meetings: `list_bookings` with `since`, canceled ones listed separately. +4. Health: `list_campaigns`, then point out paused campaigns and campaigns without a connected number. + +Finish with two or three suggested next actions and ask before doing any of them. + +### Inbox triage + +"Who is waiting on us?", "Summarize my replies." + +1. `list_conversations`, with `campaign_id` if the user names a campaign. Stay within the time window asked. +2. Open the relevant conversations with `get_conversation_messages`. +3. Sort them into: hot (asks for a price, a call or availability), waiting on us (lead wrote last and nobody answered for hours), booked, stopped (asked to stop or `unsubscribed`), nothing to do. +4. For each one, quote the lead's last words and add one line of context. +5. Draft replies only for hot and waiting conversations, and only if the user wants drafts. Send nothing until rule 1 is met. +6. A lead who asked to stop never gets a draft. Point them out: the platform already stops messaging them. + +### Import leads + +"Import this CSV", "Add these contacts from my CRM." + +1. Normalize every phone to international format (`+33612345678`). If the country is ambiguous, ask instead of guessing. +2. Pick the target list with `list_lists`, or `create_list` if the user wants a new one. +3. Show a preview: row count, three sample rows, rows you could not parse. Get a go before importing, because a list attached to an active campaign starts being contacted. +4. `import_leads` in batches of at most 500. Put useful fields (company, city, offer) in `custom_variables` so campaign messages can use them. +5. Report imported rows, duplicates and invalid rows with their reasons (`invalid_phone`, `duplicate_in_batch`). +6. Remind the user that the campaign sends the first message at the anti-ban pace, not the import itself. + +### Results and bookings + +"How many meetings this week?", "Show me the qualified leads." + +- Qualified leads: `list_leads` with `status: "qualified"` and `since`. +- Meetings: `list_bookings` with `since`. Group by campaign, using `list_campaigns` to turn ids into names. Show date and time in the user's timezone and the attendee's name. +- Bookings with a `canceled_at` value don't count as booked. List them separately. +- Always state the period you counted and whether you read every page. + +### Campaigns + +- Resolve a campaign name to its id with `list_campaigns`. If several campaigns match, ask which one. +- `pause_campaign` stops outbound sending: confirm the campaign name before pausing. `resume_campaign` restarts a paused campaign. +- `409 invalid_state`: only an active campaign can be paused and only a paused one resumed. Draft campaigns are activated in the dashboard. +- `402 plan_limit_reached`: every active campaign slot of the plan is used. Suggest pausing another campaign or upgrading. + +### CRM sync + +- Write back with `update_lead` (`status` and/or `tags`). `tags` replaces the whole list, so read the lead with `get_lead` first and send the merged tags. +- Push events to a CRM or an automation with `create_webhook`: `contact.qualified`, `contact.not_qualified`, `booking.created`, `message.received`, `agent.disconnected`. The endpoint must be HTTPS. +- The signing secret (`whsec_…`) appears once, in the `create_webhook` result. Tell the user to store it right away. +- `test_webhook` delivers a signed test event. `delete_webhook` is permanent: confirm before calling it. + +### WhatsApp groups + +Read-only. Start with `list_groups`, then `get_group` for one group. + +- Members: `list_group_members`. Silent members have no messages, churn shows as `status: "left"`. +- Transcript: `list_group_messages`, filtered by `sender`, `from_agent` or a `since`/`until` window. +- Growth and churn: `list_group_events` with `type` (`join` or `leave`) over a window. +- Always give the window your numbers cover. + +## Errors + +| Code | Meaning | What to do | +|---|---|---| +| `401 invalid_api_key` | The key was revoked or is unknown | Ask the user to reconnect WhatSetter with a valid key | +| `403 insufficient_scope` | The key lacks a scope | Name the scope and have it added in Settings → API | +| `409 lead_not_contacted` | This lead was never contacted | Import into a list; a campaign makes first contact | +| `429 quota_exceeded` | Daily WhatsApp quota reached (on `create_list`: list limit reached) | Stop. The quota resets at midnight UTC. For lists, reuse an existing one | +| `429 rate_limited` | Too many requests this minute | Wait for `Retry-After`, then continue | +| `503 agent_disconnected` | The campaign's WhatsApp number is disconnected | Tell the user to reconnect it in the dashboard. Don't retry | +| `502 send_failed` | The send failed upstream | Check `get_conversation_messages` to confirm nothing went out, then ask the user before trying again | +| `409 invalid_state` | The campaign isn't in the required state | Explain its current status | +| `402 plan_limit_reached` | Active campaign slots are full | Pause another campaign or upgrade | +| `404 not_found` | Wrong id, or it belongs to another workspace | List again and pick the right id | +| `422 validation_error` | Invalid input | Fix the argument and retry |