universal-mcp-applications 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. universal_mcp/applications/ahrefs/README.md +51 -0
  2. universal_mcp/applications/ahrefs/__init__.py +1 -0
  3. universal_mcp/applications/ahrefs/app.py +2291 -0
  4. universal_mcp/applications/airtable/README.md +22 -0
  5. universal_mcp/applications/airtable/__init__.py +1 -0
  6. universal_mcp/applications/airtable/app.py +479 -0
  7. universal_mcp/applications/apollo/README.md +44 -0
  8. universal_mcp/applications/apollo/__init__.py +1 -0
  9. universal_mcp/applications/apollo/app.py +1847 -0
  10. universal_mcp/applications/asana/README.md +199 -0
  11. universal_mcp/applications/asana/__init__.py +1 -0
  12. universal_mcp/applications/asana/app.py +9509 -0
  13. universal_mcp/applications/aws-s3/README.md +0 -0
  14. universal_mcp/applications/aws-s3/__init__.py +1 -0
  15. universal_mcp/applications/aws-s3/app.py +552 -0
  16. universal_mcp/applications/bill/README.md +0 -0
  17. universal_mcp/applications/bill/__init__.py +1 -0
  18. universal_mcp/applications/bill/app.py +8705 -0
  19. universal_mcp/applications/box/README.md +307 -0
  20. universal_mcp/applications/box/__init__.py +1 -0
  21. universal_mcp/applications/box/app.py +15987 -0
  22. universal_mcp/applications/braze/README.md +106 -0
  23. universal_mcp/applications/braze/__init__.py +1 -0
  24. universal_mcp/applications/braze/app.py +4754 -0
  25. universal_mcp/applications/cal-com-v2/README.md +150 -0
  26. universal_mcp/applications/cal-com-v2/__init__.py +1 -0
  27. universal_mcp/applications/cal-com-v2/app.py +5541 -0
  28. universal_mcp/applications/calendly/README.md +53 -0
  29. universal_mcp/applications/calendly/__init__.py +1 -0
  30. universal_mcp/applications/calendly/app.py +1436 -0
  31. universal_mcp/applications/canva/README.md +43 -0
  32. universal_mcp/applications/canva/__init__.py +1 -0
  33. universal_mcp/applications/canva/app.py +941 -0
  34. universal_mcp/applications/clickup/README.md +135 -0
  35. universal_mcp/applications/clickup/__init__.py +1 -0
  36. universal_mcp/applications/clickup/app.py +5009 -0
  37. universal_mcp/applications/coda/README.md +108 -0
  38. universal_mcp/applications/coda/__init__.py +1 -0
  39. universal_mcp/applications/coda/app.py +3671 -0
  40. universal_mcp/applications/confluence/README.md +198 -0
  41. universal_mcp/applications/confluence/__init__.py +1 -0
  42. universal_mcp/applications/confluence/app.py +6273 -0
  43. universal_mcp/applications/contentful/README.md +17 -0
  44. universal_mcp/applications/contentful/__init__.py +1 -0
  45. universal_mcp/applications/contentful/app.py +364 -0
  46. universal_mcp/applications/crustdata/README.md +25 -0
  47. universal_mcp/applications/crustdata/__init__.py +1 -0
  48. universal_mcp/applications/crustdata/app.py +586 -0
  49. universal_mcp/applications/dialpad/README.md +202 -0
  50. universal_mcp/applications/dialpad/__init__.py +1 -0
  51. universal_mcp/applications/dialpad/app.py +5949 -0
  52. universal_mcp/applications/digitalocean/README.md +463 -0
  53. universal_mcp/applications/digitalocean/__init__.py +1 -0
  54. universal_mcp/applications/digitalocean/app.py +20835 -0
  55. universal_mcp/applications/domain-checker/README.md +13 -0
  56. universal_mcp/applications/domain-checker/__init__.py +1 -0
  57. universal_mcp/applications/domain-checker/app.py +265 -0
  58. universal_mcp/applications/e2b/README.md +12 -0
  59. universal_mcp/applications/e2b/__init__.py +1 -0
  60. universal_mcp/applications/e2b/app.py +187 -0
  61. universal_mcp/applications/elevenlabs/README.md +88 -0
  62. universal_mcp/applications/elevenlabs/__init__.py +1 -0
  63. universal_mcp/applications/elevenlabs/app.py +3235 -0
  64. universal_mcp/applications/exa/README.md +15 -0
  65. universal_mcp/applications/exa/__init__.py +1 -0
  66. universal_mcp/applications/exa/app.py +221 -0
  67. universal_mcp/applications/falai/README.md +17 -0
  68. universal_mcp/applications/falai/__init__.py +1 -0
  69. universal_mcp/applications/falai/app.py +331 -0
  70. universal_mcp/applications/figma/README.md +49 -0
  71. universal_mcp/applications/figma/__init__.py +1 -0
  72. universal_mcp/applications/figma/app.py +1090 -0
  73. universal_mcp/applications/firecrawl/README.md +20 -0
  74. universal_mcp/applications/firecrawl/__init__.py +1 -0
  75. universal_mcp/applications/firecrawl/app.py +514 -0
  76. universal_mcp/applications/fireflies/README.md +25 -0
  77. universal_mcp/applications/fireflies/__init__.py +1 -0
  78. universal_mcp/applications/fireflies/app.py +506 -0
  79. universal_mcp/applications/fpl/README.md +23 -0
  80. universal_mcp/applications/fpl/__init__.py +1 -0
  81. universal_mcp/applications/fpl/app.py +1327 -0
  82. universal_mcp/applications/fpl/utils/api.py +142 -0
  83. universal_mcp/applications/fpl/utils/fixtures.py +629 -0
  84. universal_mcp/applications/fpl/utils/helper.py +982 -0
  85. universal_mcp/applications/fpl/utils/league_utils.py +546 -0
  86. universal_mcp/applications/fpl/utils/position_utils.py +68 -0
  87. universal_mcp/applications/ghost-content/README.md +25 -0
  88. universal_mcp/applications/ghost-content/__init__.py +1 -0
  89. universal_mcp/applications/ghost-content/app.py +654 -0
  90. universal_mcp/applications/github/README.md +1049 -0
  91. universal_mcp/applications/github/__init__.py +1 -0
  92. universal_mcp/applications/github/app.py +50600 -0
  93. universal_mcp/applications/gong/README.md +63 -0
  94. universal_mcp/applications/gong/__init__.py +1 -0
  95. universal_mcp/applications/gong/app.py +2297 -0
  96. universal_mcp/applications/google-ads/README.md +0 -0
  97. universal_mcp/applications/google-ads/__init__.py +1 -0
  98. universal_mcp/applications/google-ads/app.py +23 -0
  99. universal_mcp/applications/google-calendar/README.md +21 -0
  100. universal_mcp/applications/google-calendar/__init__.py +1 -0
  101. universal_mcp/applications/google-calendar/app.py +574 -0
  102. universal_mcp/applications/google-docs/README.md +25 -0
  103. universal_mcp/applications/google-docs/__init__.py +1 -0
  104. universal_mcp/applications/google-docs/app.py +760 -0
  105. universal_mcp/applications/google-drive/README.md +68 -0
  106. universal_mcp/applications/google-drive/__init__.py +1 -0
  107. universal_mcp/applications/google-drive/app.py +4936 -0
  108. universal_mcp/applications/google-gemini/README.md +25 -0
  109. universal_mcp/applications/google-gemini/__init__.py +1 -0
  110. universal_mcp/applications/google-gemini/app.py +663 -0
  111. universal_mcp/applications/google-mail/README.md +31 -0
  112. universal_mcp/applications/google-mail/__init__.py +1 -0
  113. universal_mcp/applications/google-mail/app.py +1354 -0
  114. universal_mcp/applications/google-searchconsole/README.md +21 -0
  115. universal_mcp/applications/google-searchconsole/__init__.py +1 -0
  116. universal_mcp/applications/google-searchconsole/app.py +320 -0
  117. universal_mcp/applications/google-sheet/README.md +36 -0
  118. universal_mcp/applications/google-sheet/__init__.py +1 -0
  119. universal_mcp/applications/google-sheet/app.py +1941 -0
  120. universal_mcp/applications/hashnode/README.md +20 -0
  121. universal_mcp/applications/hashnode/__init__.py +1 -0
  122. universal_mcp/applications/hashnode/app.py +455 -0
  123. universal_mcp/applications/heygen/README.md +44 -0
  124. universal_mcp/applications/heygen/__init__.py +1 -0
  125. universal_mcp/applications/heygen/app.py +961 -0
  126. universal_mcp/applications/http-tools/README.md +16 -0
  127. universal_mcp/applications/http-tools/__init__.py +1 -0
  128. universal_mcp/applications/http-tools/app.py +153 -0
  129. universal_mcp/applications/hubspot/README.md +239 -0
  130. universal_mcp/applications/hubspot/__init__.py +1 -0
  131. universal_mcp/applications/hubspot/app.py +416 -0
  132. universal_mcp/applications/jira/README.md +600 -0
  133. universal_mcp/applications/jira/__init__.py +1 -0
  134. universal_mcp/applications/jira/app.py +28804 -0
  135. universal_mcp/applications/klaviyo/README.md +313 -0
  136. universal_mcp/applications/klaviyo/__init__.py +1 -0
  137. universal_mcp/applications/klaviyo/app.py +11236 -0
  138. universal_mcp/applications/linkedin/README.md +15 -0
  139. universal_mcp/applications/linkedin/__init__.py +1 -0
  140. universal_mcp/applications/linkedin/app.py +243 -0
  141. universal_mcp/applications/mailchimp/README.md +281 -0
  142. universal_mcp/applications/mailchimp/__init__.py +1 -0
  143. universal_mcp/applications/mailchimp/app.py +10937 -0
  144. universal_mcp/applications/markitdown/README.md +12 -0
  145. universal_mcp/applications/markitdown/__init__.py +1 -0
  146. universal_mcp/applications/markitdown/app.py +63 -0
  147. universal_mcp/applications/miro/README.md +151 -0
  148. universal_mcp/applications/miro/__init__.py +1 -0
  149. universal_mcp/applications/miro/app.py +5429 -0
  150. universal_mcp/applications/ms-teams/README.md +42 -0
  151. universal_mcp/applications/ms-teams/__init__.py +1 -0
  152. universal_mcp/applications/ms-teams/app.py +1823 -0
  153. universal_mcp/applications/neon/README.md +74 -0
  154. universal_mcp/applications/neon/__init__.py +1 -0
  155. universal_mcp/applications/neon/app.py +2018 -0
  156. universal_mcp/applications/notion/README.md +30 -0
  157. universal_mcp/applications/notion/__init__.py +1 -0
  158. universal_mcp/applications/notion/app.py +527 -0
  159. universal_mcp/applications/openai/README.md +22 -0
  160. universal_mcp/applications/openai/__init__.py +1 -0
  161. universal_mcp/applications/openai/app.py +759 -0
  162. universal_mcp/applications/outlook/README.md +20 -0
  163. universal_mcp/applications/outlook/__init__.py +1 -0
  164. universal_mcp/applications/outlook/app.py +444 -0
  165. universal_mcp/applications/perplexity/README.md +12 -0
  166. universal_mcp/applications/perplexity/__init__.py +1 -0
  167. universal_mcp/applications/perplexity/app.py +65 -0
  168. universal_mcp/applications/pipedrive/README.md +284 -0
  169. universal_mcp/applications/pipedrive/__init__.py +1 -0
  170. universal_mcp/applications/pipedrive/app.py +12924 -0
  171. universal_mcp/applications/posthog/README.md +132 -0
  172. universal_mcp/applications/posthog/__init__.py +1 -0
  173. universal_mcp/applications/posthog/app.py +7125 -0
  174. universal_mcp/applications/reddit/README.md +135 -0
  175. universal_mcp/applications/reddit/__init__.py +1 -0
  176. universal_mcp/applications/reddit/app.py +4652 -0
  177. universal_mcp/applications/replicate/README.md +18 -0
  178. universal_mcp/applications/replicate/__init__.py +1 -0
  179. universal_mcp/applications/replicate/app.py +495 -0
  180. universal_mcp/applications/resend/README.md +40 -0
  181. universal_mcp/applications/resend/__init__.py +1 -0
  182. universal_mcp/applications/resend/app.py +881 -0
  183. universal_mcp/applications/retell/README.md +21 -0
  184. universal_mcp/applications/retell/__init__.py +1 -0
  185. universal_mcp/applications/retell/app.py +333 -0
  186. universal_mcp/applications/rocketlane/README.md +70 -0
  187. universal_mcp/applications/rocketlane/__init__.py +1 -0
  188. universal_mcp/applications/rocketlane/app.py +4346 -0
  189. universal_mcp/applications/semanticscholar/README.md +25 -0
  190. universal_mcp/applications/semanticscholar/__init__.py +1 -0
  191. universal_mcp/applications/semanticscholar/app.py +482 -0
  192. universal_mcp/applications/semrush/README.md +44 -0
  193. universal_mcp/applications/semrush/__init__.py +1 -0
  194. universal_mcp/applications/semrush/app.py +2081 -0
  195. universal_mcp/applications/sendgrid/README.md +362 -0
  196. universal_mcp/applications/sendgrid/__init__.py +1 -0
  197. universal_mcp/applications/sendgrid/app.py +9752 -0
  198. universal_mcp/applications/sentry/README.md +186 -0
  199. universal_mcp/applications/sentry/__init__.py +1 -0
  200. universal_mcp/applications/sentry/app.py +7471 -0
  201. universal_mcp/applications/serpapi/README.md +14 -0
  202. universal_mcp/applications/serpapi/__init__.py +1 -0
  203. universal_mcp/applications/serpapi/app.py +293 -0
  204. universal_mcp/applications/sharepoint/README.md +0 -0
  205. universal_mcp/applications/sharepoint/__init__.py +1 -0
  206. universal_mcp/applications/sharepoint/app.py +215 -0
  207. universal_mcp/applications/shopify/README.md +321 -0
  208. universal_mcp/applications/shopify/__init__.py +1 -0
  209. universal_mcp/applications/shopify/app.py +15392 -0
  210. universal_mcp/applications/shortcut/README.md +128 -0
  211. universal_mcp/applications/shortcut/__init__.py +1 -0
  212. universal_mcp/applications/shortcut/app.py +4478 -0
  213. universal_mcp/applications/slack/README.md +0 -0
  214. universal_mcp/applications/slack/__init__.py +1 -0
  215. universal_mcp/applications/slack/app.py +570 -0
  216. universal_mcp/applications/spotify/README.md +91 -0
  217. universal_mcp/applications/spotify/__init__.py +1 -0
  218. universal_mcp/applications/spotify/app.py +2526 -0
  219. universal_mcp/applications/supabase/README.md +87 -0
  220. universal_mcp/applications/supabase/__init__.py +1 -0
  221. universal_mcp/applications/supabase/app.py +2970 -0
  222. universal_mcp/applications/tavily/README.md +12 -0
  223. universal_mcp/applications/tavily/__init__.py +1 -0
  224. universal_mcp/applications/tavily/app.py +51 -0
  225. universal_mcp/applications/trello/README.md +266 -0
  226. universal_mcp/applications/trello/__init__.py +1 -0
  227. universal_mcp/applications/trello/app.py +10875 -0
  228. universal_mcp/applications/twillo/README.md +0 -0
  229. universal_mcp/applications/twillo/__init__.py +1 -0
  230. universal_mcp/applications/twillo/app.py +269 -0
  231. universal_mcp/applications/twitter/README.md +100 -0
  232. universal_mcp/applications/twitter/__init__.py +1 -0
  233. universal_mcp/applications/twitter/api_segments/__init__.py +0 -0
  234. universal_mcp/applications/twitter/api_segments/api_segment_base.py +51 -0
  235. universal_mcp/applications/twitter/api_segments/compliance_api.py +122 -0
  236. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +255 -0
  237. universal_mcp/applications/twitter/api_segments/dm_events_api.py +140 -0
  238. universal_mcp/applications/twitter/api_segments/likes_api.py +159 -0
  239. universal_mcp/applications/twitter/api_segments/lists_api.py +395 -0
  240. universal_mcp/applications/twitter/api_segments/openapi_json_api.py +34 -0
  241. universal_mcp/applications/twitter/api_segments/spaces_api.py +309 -0
  242. universal_mcp/applications/twitter/api_segments/trends_api.py +40 -0
  243. universal_mcp/applications/twitter/api_segments/tweets_api.py +1403 -0
  244. universal_mcp/applications/twitter/api_segments/usage_api.py +40 -0
  245. universal_mcp/applications/twitter/api_segments/users_api.py +1498 -0
  246. universal_mcp/applications/twitter/app.py +46 -0
  247. universal_mcp/applications/unipile/README.md +28 -0
  248. universal_mcp/applications/unipile/__init__.py +1 -0
  249. universal_mcp/applications/unipile/app.py +829 -0
  250. universal_mcp/applications/whatsapp/README.md +23 -0
  251. universal_mcp/applications/whatsapp/__init__.py +1 -0
  252. universal_mcp/applications/whatsapp/app.py +595 -0
  253. universal_mcp/applications/whatsapp-business/README.md +34 -0
  254. universal_mcp/applications/whatsapp-business/__init__.py +1 -0
  255. universal_mcp/applications/whatsapp-business/app.py +1065 -0
  256. universal_mcp/applications/wrike/README.md +46 -0
  257. universal_mcp/applications/wrike/__init__.py +1 -0
  258. universal_mcp/applications/wrike/app.py +1583 -0
  259. universal_mcp/applications/youtube/README.md +57 -0
  260. universal_mcp/applications/youtube/__init__.py +1 -0
  261. universal_mcp/applications/youtube/app.py +1696 -0
  262. universal_mcp/applications/zenquotes/README.md +12 -0
  263. universal_mcp/applications/zenquotes/__init__.py +1 -0
  264. universal_mcp/applications/zenquotes/app.py +31 -0
  265. universal_mcp_applications-0.1.1.dist-info/METADATA +172 -0
  266. universal_mcp_applications-0.1.1.dist-info/RECORD +268 -0
  267. universal_mcp_applications-0.1.1.dist-info/WHEEL +4 -0
  268. universal_mcp_applications-0.1.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,23 @@
1
+ # WhatsappApp MCP Server
2
+
3
+ An MCP Server for the WhatsappApp API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the WhatsappApp API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `search_contacts` | Search WhatsApp contacts by name or phone number. |
13
+ | `list_messages` | Get WhatsApp messages matching specified criteria with optional context. |
14
+ | `list_chats` | Get WhatsApp chats matching specified criteria. |
15
+ | `get_chat` | Get WhatsApp chat metadata by JID. |
16
+ | `get_direct_chat_by_contact` | Get WhatsApp chat metadata by sender phone number. |
17
+ | `get_contact_chats` | Get all WhatsApp chats involving the contact. |
18
+ | `get_last_interaction` | Get most recent WhatsApp message involving the contact. |
19
+ | `get_message_context` | Get context around a specific WhatsApp message. |
20
+ | `send_message` | Send a WhatsApp message to a person or group. For group chats use the JID. |
21
+ | `send_file` | Send a file such as a picture, raw audio, video or document via WhatsApp to the specified recipient. For group messages use the JID. |
22
+ | `send_audio_message` | Send any audio file as a WhatsApp audio message to the specified recipient. For group messages use the JID. If it errors due to ffmpeg not being installed, use send_file instead. |
23
+ | `download_media` | Download media from a WhatsApp message and get the local file path. |
@@ -0,0 +1 @@
1
+ from .app import WhatsappApp
@@ -0,0 +1,595 @@
1
+ from typing import Any
2
+
3
+ import requests
4
+ from universal_mcp.applications import BaseApplication
5
+ from universal_mcp.exceptions import NotAuthorizedError
6
+ from universal_mcp.integrations import AgentRIntegration
7
+ from universal_mcp_whatsapp.whatsapp import (
8
+ WHATSAPP_API_BASE_URL,
9
+ )
10
+ from universal_mcp_whatsapp.whatsapp import (
11
+ download_media as whatsapp_download_media,
12
+ )
13
+ from universal_mcp_whatsapp.whatsapp import (
14
+ get_chat as whatsapp_get_chat,
15
+ )
16
+ from universal_mcp_whatsapp.whatsapp import (
17
+ get_contact_chats as whatsapp_get_contact_chats,
18
+ )
19
+ from universal_mcp_whatsapp.whatsapp import (
20
+ get_direct_chat_by_contact as whatsapp_get_direct_chat_by_contact,
21
+ )
22
+ from universal_mcp_whatsapp.whatsapp import (
23
+ get_last_interaction as whatsapp_get_last_interaction,
24
+ )
25
+ from universal_mcp_whatsapp.whatsapp import (
26
+ get_message_context as whatsapp_get_message_context,
27
+ )
28
+ from universal_mcp_whatsapp.whatsapp import (
29
+ list_chats as whatsapp_list_chats,
30
+ )
31
+ from universal_mcp_whatsapp.whatsapp import (
32
+ list_messages as whatsapp_list_messages,
33
+ )
34
+ from universal_mcp_whatsapp.whatsapp import (
35
+ search_contacts as whatsapp_search_contacts,
36
+ )
37
+ from universal_mcp_whatsapp.whatsapp import (
38
+ send_audio_message as whatsapp_audio_voice_message,
39
+ )
40
+ from universal_mcp_whatsapp.whatsapp import (
41
+ send_file as whatsapp_send_file,
42
+ )
43
+ from universal_mcp_whatsapp.whatsapp import (
44
+ send_message as whatsapp_send_message,
45
+ )
46
+
47
+
48
+ class WhatsappApp(BaseApplication):
49
+ """
50
+ Base class for Universal MCP Applications.
51
+ """
52
+
53
+ def __init__(self, integration: AgentRIntegration | None = None, **kwargs) -> None:
54
+ super().__init__(name="whatsapp", integration=integration, **kwargs)
55
+ self.base_url = WHATSAPP_API_BASE_URL
56
+ self._api_key: str = integration.client.api_key if integration else None
57
+
58
+ def get_api_key(self) -> str:
59
+ return self._api_key
60
+
61
+ @property
62
+ def api_key(self) -> str:
63
+ """Gets the API key from the integration, triggering authentication if needed."""
64
+ if self._api_key:
65
+ return self._api_key
66
+ self._api_key = self.get_api_key()
67
+ return self._api_key
68
+
69
+ def _authenticator(self):
70
+ """
71
+ Triggers WhatsApp authentication flow when no integration is available.
72
+ Raises NotAuthorizedError with authorization URL when authentication is needed.
73
+ """
74
+
75
+ # Try WhatsApp authentication
76
+ auth_result = self._authenticate_whatsapp()
77
+ if auth_result[0] is True:
78
+ return True
79
+ elif isinstance(auth_result[1], str):
80
+ # auth_result contains the authorization URL message
81
+ raise NotAuthorizedError(auth_result[1])
82
+ else:
83
+ # WhatsApp authentication failed but no URL provided
84
+ raise NotAuthorizedError(
85
+ "WhatsApp authentication failed. Please check your configuration."
86
+ )
87
+
88
+ def _authenticate_whatsapp(self) -> tuple[bool, str]:
89
+ """
90
+ Authenticate with WhatsApp API when no integration is available.
91
+ Makes a POST request to the auth endpoint.
92
+ """
93
+ try:
94
+ # Use the API key from the integration
95
+ user_id = self.api_key
96
+ if not user_id:
97
+ raise ValueError("No API key available from integration")
98
+
99
+ auth_url = f"{self.base_url}/api/auth"
100
+
101
+ response = requests.post(
102
+ auth_url,
103
+ headers={"Content-Type": "application/json"},
104
+ json={"user_id": user_id},
105
+ timeout=60,
106
+ )
107
+
108
+ if response.status_code == 200:
109
+ result = response.json()
110
+ if result.get("status") == "qr_required":
111
+ qr_url = f"{self.base_url}/api/qr?user_id={user_id}"
112
+ return (
113
+ False,
114
+ f"Please ask the user to visit the following url to authorize WhatsApp: {qr_url}. Render the url in proper markdown format with a clickable link.",
115
+ )
116
+ elif result.get("status") == "connected":
117
+ return (True, "User already authenticated")
118
+ else:
119
+ # Return QR URL even when auth fails, so user can try to authenticate
120
+ qr_url = f"{self.base_url}/api/qr?user_id={user_id}"
121
+ return (
122
+ False,
123
+ f"Please ask the user to visit the following url to authorize WhatsApp: {qr_url}. Render the url in proper markdown format with a clickable link.",
124
+ )
125
+
126
+ except Exception:
127
+ # Return QR URL when there's an exception, so user can try to authenticate
128
+ user_id = self.api_key
129
+ if user_id:
130
+ qr_url = f"{self.base_url}/api/qr?user_id={user_id}"
131
+ return (
132
+ False,
133
+ f"Please ask the user to visit the following url to authorize WhatsApp: {qr_url}. Render the url in proper markdown format with a clickable link.",
134
+ )
135
+ else:
136
+ return (False, "No API key available from integration")
137
+
138
+ def search_contacts(
139
+ self,
140
+ query: str,
141
+ ) -> list[dict[str, Any]]:
142
+ """
143
+ Search WhatsApp contacts by name or phone number.
144
+
145
+ Args:
146
+ query (string): Search term to match against contact names or phone numbers
147
+
148
+ Returns:
149
+ List[Dict[str, Any]]: Retrieved collection
150
+
151
+ Raises:
152
+ ValueError: Raised when required parameters are missing.
153
+
154
+ Tags:
155
+ whatsapp.contacts, important
156
+ """
157
+ if query is None:
158
+ raise ValueError("Missing required parameter 'query'.")
159
+
160
+ # Trigger authentication
161
+ self._authenticator()
162
+
163
+ user_id = self.api_key
164
+ contacts = whatsapp_search_contacts(query, user_id)
165
+ return contacts
166
+
167
+ def list_messages(
168
+ self,
169
+ after: str | None = None,
170
+ before: str | None = None,
171
+ sender_phone_number: str | None = None,
172
+ chat_jid: str | None = None,
173
+ query: str | None = None,
174
+ limit: int = 20,
175
+ page: int = 0,
176
+ include_context: bool = True,
177
+ context_before: int = 1,
178
+ context_after: int = 1,
179
+ ) -> list[dict[str, Any]]:
180
+ """
181
+ Get WhatsApp messages matching specified criteria with optional context.
182
+
183
+ Args:
184
+ after (string): Optional ISO-8601 formatted string to only return messages after this date
185
+ before (string): Optional ISO-8601 formatted string to only return messages before this date
186
+ sender_phone_number (string): Optional phone number to filter messages by sender
187
+ chat_jid (string): Optional chat JID to filter messages by chat
188
+ query (string): Optional search term to filter messages by content
189
+ limit (integer): Maximum number of messages to return (default 20)
190
+ page (integer): Page number for pagination (default 0)
191
+ include_context (boolean): Whether to include messages before and after matches (default True)
192
+ context_before (integer): Number of messages to include before each match (default 1)
193
+ context_after (integer): Number of messages to include after each match (default 1)
194
+
195
+ Returns:
196
+ List[Dict[str, Any]]: Retrieved collection
197
+
198
+ Raises:
199
+ ValueError: Raised when required parameters are missing.
200
+
201
+ Tags:
202
+ whatsapp.messages, important
203
+ """
204
+ # Trigger authentication
205
+ self._authenticator()
206
+
207
+ user_id = self.api_key
208
+ messages = whatsapp_list_messages(
209
+ after=after,
210
+ before=before,
211
+ sender_phone_number=sender_phone_number,
212
+ chat_jid=chat_jid,
213
+ query=query,
214
+ limit=limit,
215
+ page=page,
216
+ include_context=include_context,
217
+ context_before=context_before,
218
+ context_after=context_after,
219
+ user_id=user_id,
220
+ )
221
+ return messages
222
+
223
+ def list_chats(
224
+ self,
225
+ query: str | None = None,
226
+ limit: int = 20,
227
+ page: int = 0,
228
+ include_last_message: bool = True,
229
+ sort_by: str = "last_active",
230
+ ) -> list[dict[str, Any]]:
231
+ """
232
+ Get WhatsApp chats matching specified criteria.
233
+
234
+ Args:
235
+ query (string): Optional search term to filter chats by name or JID
236
+ limit (integer): Maximum number of chats to return (default 20)
237
+ page (integer): Page number for pagination (default 0)
238
+ include_last_message (boolean): Whether to include the last message in each chat (default True)
239
+ sort_by (string): Field to sort results by, either "last_active" or "name" (default "last_active")
240
+
241
+ Returns:
242
+ List[Dict[str, Any]]: Retrieved collection
243
+
244
+ Raises:
245
+ ValueError: Raised when required parameters are missing.
246
+
247
+ Tags:
248
+ whatsapp.chats, important
249
+ """
250
+ # Trigger authentication
251
+ self._authenticator()
252
+
253
+ user_id = self.api_key
254
+ chats = whatsapp_list_chats(
255
+ query=query,
256
+ limit=limit,
257
+ page=page,
258
+ include_last_message=include_last_message,
259
+ sort_by=sort_by,
260
+ user_id=user_id,
261
+ )
262
+ return chats
263
+
264
+ def get_chat(
265
+ self,
266
+ chat_jid: str,
267
+ include_last_message: bool = True,
268
+ ) -> dict[str, Any]:
269
+ """
270
+ Get WhatsApp chat metadata by JID.
271
+
272
+ Args:
273
+ chat_jid (string): The JID of the chat to retrieve
274
+ include_last_message (boolean): Whether to include the last message (default True)
275
+
276
+ Returns:
277
+ Dict[str, Any]: Retrieved chat metadata
278
+
279
+ Raises:
280
+ ValueError: Raised when required parameters are missing.
281
+
282
+ Tags:
283
+ whatsapp.chat, important
284
+ """
285
+ if chat_jid is None:
286
+ raise ValueError("Missing required parameter 'chat_jid'.")
287
+
288
+ # Trigger authentication
289
+ self._authenticator()
290
+
291
+ user_id = self.api_key
292
+ chat = whatsapp_get_chat(chat_jid, include_last_message, user_id)
293
+ return chat
294
+
295
+ def get_direct_chat_by_contact(
296
+ self,
297
+ sender_phone_number: str,
298
+ ) -> dict[str, Any]:
299
+ """
300
+ Get WhatsApp chat metadata by sender phone number.
301
+
302
+ Args:
303
+ sender_phone_number (string): The phone number to search for
304
+
305
+ Returns:
306
+ Dict[str, Any]: Retrieved chat metadata
307
+
308
+ Raises:
309
+ ValueError: Raised when required parameters are missing.
310
+
311
+ Tags:
312
+ whatsapp.chat, important
313
+ """
314
+ if sender_phone_number is None:
315
+ raise ValueError("Missing required parameter 'sender_phone_number'.")
316
+
317
+ # Trigger authentication
318
+ self._authenticator()
319
+
320
+ user_id = self.api_key
321
+ chat = whatsapp_get_direct_chat_by_contact(sender_phone_number, user_id)
322
+ return chat
323
+
324
+ def get_contact_chats(
325
+ self,
326
+ jid: str,
327
+ limit: int = 20,
328
+ page: int = 0,
329
+ ) -> list[dict[str, Any]]:
330
+ """
331
+ Get all WhatsApp chats involving the contact.
332
+
333
+ Args:
334
+ jid (string): The contact's JID to search for
335
+ limit (integer): Maximum number of chats to return (default 20)
336
+ page (integer): Page number for pagination (default 0)
337
+
338
+ Returns:
339
+ List[Dict[str, Any]]: Retrieved collection
340
+
341
+ Raises:
342
+ ValueError: Raised when required parameters are missing.
343
+
344
+ Tags:
345
+ whatsapp.contact_chats, important
346
+ """
347
+ if jid is None:
348
+ raise ValueError("Missing required parameter 'jid'.")
349
+
350
+ # Trigger authentication
351
+ self._authenticator()
352
+
353
+ user_id = self.api_key
354
+ chats = whatsapp_get_contact_chats(jid, limit, page, user_id)
355
+ return chats
356
+
357
+ def get_last_interaction(
358
+ self,
359
+ jid: str,
360
+ ) -> str:
361
+ """
362
+ Get most recent WhatsApp message involving the contact.
363
+
364
+ Args:
365
+ jid (string): The JID of the contact to search for
366
+
367
+ Returns:
368
+ string: Retrieved message
369
+
370
+ Raises:
371
+ ValueError: Raised when required parameters are missing.
372
+
373
+ Tags:
374
+ whatsapp.interaction, important
375
+ """
376
+ if jid is None:
377
+ raise ValueError("Missing required parameter 'jid'.")
378
+
379
+ # Trigger authentication
380
+ self._authenticator()
381
+
382
+ user_id = self.api_key
383
+ message = whatsapp_get_last_interaction(jid, user_id)
384
+ return message
385
+
386
+ def get_message_context(
387
+ self,
388
+ message_id: str,
389
+ before: int = 5,
390
+ after: int = 5,
391
+ ) -> dict[str, Any]:
392
+ """
393
+ Get context around a specific WhatsApp message.
394
+
395
+ Args:
396
+ message_id (string): The ID of the message to get context for
397
+ before (integer): Number of messages to include before the target message (default 5)
398
+ after (integer): Number of messages to include after the target message (default 5)
399
+
400
+ Returns:
401
+ Dict[str, Any]: Retrieved message context
402
+
403
+ Raises:
404
+ ValueError: Raised when required parameters are missing.
405
+
406
+ Tags:
407
+ whatsapp.message_context, important
408
+ """
409
+ if message_id is None:
410
+ raise ValueError("Missing required parameter 'message_id'.")
411
+
412
+ # Trigger authentication
413
+ self._authenticator()
414
+
415
+ user_id = self.api_key
416
+ context = whatsapp_get_message_context(message_id, before, after, user_id)
417
+ return context
418
+
419
+ def send_message(
420
+ self,
421
+ recipient: str,
422
+ message: str,
423
+ ) -> dict[str, Any]:
424
+ """
425
+ Send a WhatsApp message to a person or group. For group chats use the JID.
426
+
427
+ Args:
428
+ recipient (string): The recipient - either a phone number with country code but no + or other symbols,
429
+ or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us")
430
+ message (string): The message text to send
431
+
432
+ Returns:
433
+ Dict[str, Any]: A dictionary containing success status and a status message
434
+
435
+ Raises:
436
+ ValueError: Raised when required parameters are missing.
437
+
438
+ Tags:
439
+ whatsapp.send_message, important
440
+ """
441
+ if recipient is None:
442
+ raise ValueError("Missing required parameter 'recipient'.")
443
+ if message is None:
444
+ raise ValueError("Missing required parameter 'message'.")
445
+
446
+ # Trigger authentication
447
+ self._authenticator()
448
+
449
+ user_id = self.api_key
450
+ # Call the whatsapp_send_message function with the unified recipient parameter
451
+ success, status_message = whatsapp_send_message(recipient, message, user_id)
452
+ return {
453
+ "success": success,
454
+ "message": status_message,
455
+ }
456
+
457
+ def send_file(
458
+ self,
459
+ recipient: str,
460
+ media_path: str,
461
+ ) -> dict[str, Any]:
462
+ """
463
+ Send a file such as a picture, raw audio, video or document via WhatsApp to the specified recipient. For group messages use the JID.
464
+
465
+ Args:
466
+ recipient (string): The recipient - either a phone number with country code but no + or other symbols,
467
+ or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us")
468
+ media_path (string): The absolute path to the media file to send (image, video, document)
469
+
470
+ Returns:
471
+ Dict[str, Any]: A dictionary containing success status and a status message
472
+
473
+ Raises:
474
+ ValueError: Raised when required parameters are missing.
475
+
476
+ Tags:
477
+ whatsapp.send_file, important
478
+ """
479
+ if recipient is None:
480
+ raise ValueError("Missing required parameter 'recipient'.")
481
+ if media_path is None:
482
+ raise ValueError("Missing required parameter 'media_path'.")
483
+
484
+ # Trigger authentication
485
+ self._authenticator()
486
+
487
+ user_id = self.api_key
488
+ # Call the whatsapp_send_file function
489
+ success, status_message = whatsapp_send_file(recipient, media_path, user_id)
490
+ return {
491
+ "success": success,
492
+ "message": status_message,
493
+ }
494
+
495
+ def send_audio_message(
496
+ self,
497
+ recipient: str,
498
+ media_path: str,
499
+ ) -> dict[str, Any]:
500
+ """
501
+ Send any audio file as a WhatsApp audio message to the specified recipient. For group messages use the JID. If it errors due to ffmpeg not being installed, use send_file instead.
502
+
503
+ Args:
504
+ recipient (string): The recipient - either a phone number with country code but no + or other symbols,
505
+ or a JID (e.g., "123456789@s.whatsapp.net" or a group JID like "123456789@g.us")
506
+ media_path (string): The absolute path to the audio file to send (will be converted to Opus .ogg if it's not a .ogg file)
507
+
508
+ Returns:
509
+ Dict[str, Any]: A dictionary containing success status and a status message
510
+
511
+ Raises:
512
+ ValueError: Raised when required parameters are missing.
513
+
514
+ Tags:
515
+ whatsapp.send_audio_message, important
516
+ """
517
+ if recipient is None:
518
+ raise ValueError("Missing required parameter 'recipient'.")
519
+ if media_path is None:
520
+ raise ValueError("Missing required parameter 'media_path'.")
521
+
522
+ # Trigger authentication
523
+ self._authenticator()
524
+
525
+ user_id = self.api_key
526
+ success, status_message = whatsapp_audio_voice_message(
527
+ recipient, media_path, user_id
528
+ )
529
+ return {
530
+ "success": success,
531
+ "message": status_message,
532
+ }
533
+
534
+ def download_media(
535
+ self,
536
+ message_id: str,
537
+ chat_jid: str,
538
+ ) -> dict[str, Any]:
539
+ """
540
+ Download media from a WhatsApp message and get the local file path.
541
+
542
+ Args:
543
+ message_id (string): The ID of the message containing the media
544
+ chat_jid (string): The JID of the chat containing the message
545
+
546
+ Returns:
547
+ Dict[str, Any]: A dictionary containing success status, a status message, and the file path if successful
548
+
549
+ Raises:
550
+ ValueError: Raised when required parameters are missing.
551
+
552
+ Tags:
553
+ whatsapp.download_media, important
554
+ """
555
+ if message_id is None:
556
+ raise ValueError("Missing required parameter 'message_id'.")
557
+ if chat_jid is None:
558
+ raise ValueError("Missing required parameter 'chat_jid'.")
559
+
560
+ # Trigger authentication
561
+ self._authenticator()
562
+
563
+ user_id = self.api_key
564
+ file_path = whatsapp_download_media(message_id, chat_jid, user_id)
565
+
566
+ if file_path:
567
+ return {
568
+ "success": True,
569
+ "message": "Media downloaded successfully",
570
+ "file_path": file_path,
571
+ }
572
+ else:
573
+ return {
574
+ "success": False,
575
+ "message": "Failed to download media",
576
+ }
577
+
578
+ def list_tools(self):
579
+ """
580
+ Lists the available tools (methods) for this application.
581
+ """
582
+ return [
583
+ self.search_contacts,
584
+ self.list_messages,
585
+ self.list_chats,
586
+ self.get_chat,
587
+ self.get_direct_chat_by_contact,
588
+ self.get_contact_chats,
589
+ self.get_last_interaction,
590
+ self.get_message_context,
591
+ self.send_message,
592
+ self.send_file,
593
+ self.send_audio_message,
594
+ self.download_media,
595
+ ]
@@ -0,0 +1,34 @@
1
+ # WhatsappBusinessApp MCP Server
2
+
3
+ An MCP Server for the WhatsappBusinessApp API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the WhatsappBusinessApp API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `get_analytics` | Retrieves details of a specified WhatsApp Business Account (WABA) with customizable fields using the GET method. |
13
+ | `get_credit_lines` | Retrieves the extended credit lines available for a specified business account using its ID. |
14
+ | `get_business_account` | Retrieves information about a business account using the specified API version and business account ID, optionally filtering the response fields via a query parameter. |
15
+ | `get_commerce_settings` | Retrieves the commerce settings configured for a specific WhatsApp Business phone number. |
16
+ | `set_or_update_commerce_settings` | Updates WhatsApp Business commerce settings (cart availability and catalog visibility) for a specific business phone number. |
17
+ | `upload_file` | Uploads a file using the specified API version and application ID, with optional query parameters for file length and type, and returns a successful status message upon completion. |
18
+ | `resume_session` | Initiates a session using the provided SESSION_ID and file offset specified in the header, supporting further session-related operations via the POST method at the "/{api-version}/<SESSION_ID>" endpoint. |
19
+ | `get_business_phone_number` | Retrieves details for a specific business phone number ID using query parameters to specify returned fields. |
20
+ | `get_all_business_phone_numbers` | Retrieves a list of phone numbers associated with a specific WhatsApp Business Account (WABA), allowing for filtering and customization of the response fields. |
21
+ | `get_qr_code` | Retrieves a message linked to a specific QR code for a business phone number using the GET method via the API. |
22
+ | `delete_qr_code` | Deletes a specific WhatsApp Business QR code using the provided QR code ID and returns a success message if the operation is completed successfully. |
23
+ | `get_all_qr_codes_default_fields` | Retrieves a list of message QR code deep links associated with a business phone number, filtered by specified fields and QR code identifiers. |
24
+ | `create_qr_code` | Creates a WhatsApp Business QR code with a predefined message and returns the generated code details. |
25
+ | `get_template_by_id_default_fields` | Retrieves a template using the specified template ID from the API version path. |
26
+ | `edit_template` | Creates or processes a resource using the specified template ID based on the API version and returns a successful status upon completion. |
27
+ | `get_template_by_name_default_fields` | Retrieves a list of WhatsApp message templates associated with a specific WhatsApp Business Account using the "GET" method, allowing filtering by template name. |
28
+ | `create_message_template` | Creates a new WhatsApp message template for a business account, allowing businesses to send standardized messages to customers. |
29
+ | `delete_template_by_name` | Deletes WhatsApp message templates by name (all languages) or specific ID using query parameters and returns a success status. |
30
+ | `get_subscribed_apps` | Retrieves a list of apps subscribed to webhooks for a WhatsApp Business Account using the GET method. |
31
+ | `subscribe_app_to_waba_swebhooks` | Subscribes an app to webhooks for a WhatsApp Business Account (WABA) using the POST method at the `/subscribed_apps` endpoint, allowing the app to receive updates and notifications from the WABA. |
32
+ | `unsubscribe_apps_by_waba_id` | Unsubscribes an app from webhook notifications for a WhatsApp Business Account. |
33
+ | `get_all_shared_wabas` | Retrieves information about WhatsApp Business accounts associated with a business client, using the specified business account ID and API version. |
34
+ | `get_all_owned_wabas` | Retrieves a list of WhatsApp Business Accounts owned by or shared with the specified business account using a GET request to the given endpoint. |
@@ -0,0 +1 @@
1
+ from .app import WhatsappBusinessApp