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,15 @@
1
+ # Exa MCP Server
2
+
3
+ An MCP Server for the Exa API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the Exa API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `search` | Searches for data using the specified criteria and returns a list of results. |
13
+ | `find_similar` | Finds and returns similar items using the API at "/findSimilar" via the POST method. |
14
+ | `get_contents` | Creates new content entries via a POST request to the "/contents" endpoint. |
15
+ | `answer` | Provides an answer to a query using the API endpoint at "/answer" via the POST method. |
@@ -0,0 +1 @@
1
+ from .app import ExaApp
@@ -0,0 +1,221 @@
1
+ from typing import Any
2
+
3
+ from universal_mcp.applications.application import APIApplication
4
+ from universal_mcp.integrations import Integration
5
+
6
+
7
+ class ExaApp(APIApplication):
8
+ def __init__(self, integration: Integration = None, **kwargs) -> None:
9
+ super().__init__(name="exa", integration=integration, **kwargs)
10
+ self.base_url = "https://api.exa.ai"
11
+
12
+ def search(
13
+ self,
14
+ query,
15
+ useAutoprompt=None,
16
+ type=None,
17
+ category=None,
18
+ numResults=None,
19
+ includeDomains=None,
20
+ excludeDomains=None,
21
+ startCrawlDate=None,
22
+ endCrawlDate=None,
23
+ startPublishedDate=None,
24
+ endPublishedDate=None,
25
+ includeText=None,
26
+ excludeText=None,
27
+ contents=None,
28
+ ) -> dict[str, Any]:
29
+ """
30
+ Searches for data using the specified criteria and returns a list of results.
31
+
32
+ Args:
33
+ query (string): The query string for the search. Example: 'Latest developments in LLM capabilities'.
34
+ useAutoprompt (boolean): Autoprompt converts your query to an Exa-style query. Enabled by default for auto search, optional for neural search, and not available for keyword search. Example: 'True'.
35
+ type (string): The type of search. Neural uses an embeddings-based model, keyword is google-like SERP. Default is auto, which automatically decides between keyword and neural. Example: 'auto'.
36
+ category (string): A data category to focus on. Example: 'research paper'.
37
+ numResults (integer): Number of results to return (up to thousands of results available for custom plans) Example: '10'.
38
+ includeDomains (array): List of domains to include in the search. If specified, results will only come from these domains. Example: "['arxiv.org', 'paperswithcode.com']".
39
+ excludeDomains (array): List of domains to exclude from search results. If specified, no results will be returned from these domains.
40
+ startCrawlDate (string): Crawl date refers to the date that Exa discovered a link. Results will include links that were crawled after this date. Must be specified in ISO 8601 format. Example: '2023-01-01'.
41
+ endCrawlDate (string): Crawl date refers to the date that Exa discovered a link. Results will include links that were crawled before this date. Must be specified in ISO 8601 format. Example: '2023-12-31'.
42
+ startPublishedDate (string): Only links with a published date after this will be returned. Must be specified in ISO 8601 format. Example: '2023-01-01'.
43
+ endPublishedDate (string): Only links with a published date before this will be returned. Must be specified in ISO 8601 format. Example: '2023-12-31'.
44
+ includeText (array): List of strings that must be present in webpage text of results. Currently, only 1 string is supported, of up to 5 words. Example: "['large language model']".
45
+ excludeText (array): List of strings that must not be present in webpage text of results. Currently, only 1 string is supported, of up to 5 words. Example: "['course']".
46
+ contents (object): contents
47
+
48
+ Returns:
49
+ dict[str, Any]: OK
50
+
51
+ Tags:
52
+ important
53
+ """
54
+ request_body = {
55
+ "query": query,
56
+ "useAutoprompt": useAutoprompt,
57
+ "type": type,
58
+ "category": category,
59
+ "numResults": numResults,
60
+ "includeDomains": includeDomains,
61
+ "excludeDomains": excludeDomains,
62
+ "startCrawlDate": startCrawlDate,
63
+ "endCrawlDate": endCrawlDate,
64
+ "startPublishedDate": startPublishedDate,
65
+ "endPublishedDate": endPublishedDate,
66
+ "includeText": includeText,
67
+ "excludeText": excludeText,
68
+ "contents": contents,
69
+ }
70
+ request_body = {k: v for k, v in request_body.items() if v is not None}
71
+ url = f"{self.base_url}/search"
72
+ query_params = {}
73
+ response = self._post(url, data=request_body, params=query_params)
74
+ response.raise_for_status()
75
+ return response.json()
76
+
77
+ def find_similar(
78
+ self,
79
+ url,
80
+ numResults=None,
81
+ includeDomains=None,
82
+ excludeDomains=None,
83
+ startCrawlDate=None,
84
+ endCrawlDate=None,
85
+ startPublishedDate=None,
86
+ endPublishedDate=None,
87
+ includeText=None,
88
+ excludeText=None,
89
+ contents=None,
90
+ ) -> dict[str, Any]:
91
+ """
92
+ Finds and returns similar items using the API at "/findSimilar" via the POST method.
93
+
94
+ Args:
95
+ url (string): The url for which you would like to find similar links. Example: 'https://arxiv.org/abs/2307.06435'.
96
+ numResults (integer): Number of results to return (up to thousands of results available for custom plans) Example: '10'.
97
+ includeDomains (array): List of domains to include in the search. If specified, results will only come from these domains. Example: "['arxiv.org', 'paperswithcode.com']".
98
+ excludeDomains (array): List of domains to exclude from search results. If specified, no results will be returned from these domains.
99
+ startCrawlDate (string): Crawl date refers to the date that Exa discovered a link. Results will include links that were crawled after this date. Must be specified in ISO 8601 format. Example: '2023-01-01'.
100
+ endCrawlDate (string): Crawl date refers to the date that Exa discovered a link. Results will include links that were crawled before this date. Must be specified in ISO 8601 format. Example: '2023-12-31'.
101
+ startPublishedDate (string): Only links with a published date after this will be returned. Must be specified in ISO 8601 format. Example: '2023-01-01'.
102
+ endPublishedDate (string): Only links with a published date before this will be returned. Must be specified in ISO 8601 format. Example: '2023-12-31'.
103
+ includeText (array): List of strings that must be present in webpage text of results. Currently, only 1 string is supported, of up to 5 words. Example: "['large language model']".
104
+ excludeText (array): List of strings that must not be present in webpage text of results. Currently, only 1 string is supported, of up to 5 words. Example: "['course']".
105
+ contents (object): contents
106
+
107
+ Returns:
108
+ dict[str, Any]: OK
109
+
110
+ Tags:
111
+ important
112
+ """
113
+ request_body = {
114
+ "url": url,
115
+ "numResults": numResults,
116
+ "includeDomains": includeDomains,
117
+ "excludeDomains": excludeDomains,
118
+ "startCrawlDate": startCrawlDate,
119
+ "endCrawlDate": endCrawlDate,
120
+ "startPublishedDate": startPublishedDate,
121
+ "endPublishedDate": endPublishedDate,
122
+ "includeText": includeText,
123
+ "excludeText": excludeText,
124
+ "contents": contents,
125
+ }
126
+ request_body = {k: v for k, v in request_body.items() if v is not None}
127
+ url = f"{self.base_url}/findSimilar"
128
+ query_params = {}
129
+ response = self._post(url, data=request_body, params=query_params)
130
+ response.raise_for_status()
131
+ return response.json()
132
+
133
+ def get_contents(
134
+ self,
135
+ urls,
136
+ ids=None,
137
+ text=None,
138
+ highlights=None,
139
+ summary=None,
140
+ livecrawl=None,
141
+ livecrawlTimeout=None,
142
+ subpages=None,
143
+ subpageTarget=None,
144
+ extras=None,
145
+ ) -> dict[str, Any]:
146
+ """
147
+ Creates new content entries via a POST request to the "/contents" endpoint.
148
+
149
+ Args:
150
+ urls (array): Array of URLs to crawl (backwards compatible with 'ids' parameter). Example: "['https://arxiv.org/pdf/2307.06435']".
151
+ ids (array): Deprecated - use 'urls' instead. Array of document IDs obtained from searches. Example: "['https://arxiv.org/pdf/2307.06435']".
152
+ text (string): text
153
+ highlights (object): Text snippets the LLM identifies as most relevant from each page.
154
+ summary (object): Summary of the webpage
155
+ livecrawl (string): Options for livecrawling pages.
156
+ 'never': Disable livecrawling (default for neural search).
157
+ 'fallback': Livecrawl when cache is empty (default for keyword search).
158
+ 'always': Always livecrawl.
159
+ 'auto': Use an LLM to detect if query needs real-time content.
160
+ Example: 'always'.
161
+ livecrawlTimeout (integer): The timeout for livecrawling in milliseconds. Example: '1000'.
162
+ subpages (integer): The number of subpages to crawl. The actual number crawled may be limited by system constraints. Example: '1'.
163
+ subpageTarget (string): Keyword to find specific subpages of search results. Can be a single string or an array of strings, comma delimited. Example: 'sources'.
164
+ extras (object): Extra parameters to pass.
165
+
166
+ Returns:
167
+ dict[str, Any]: OK
168
+
169
+ Tags:
170
+ important
171
+ """
172
+ request_body = {
173
+ "urls": urls,
174
+ "ids": ids,
175
+ "text": text,
176
+ "highlights": highlights,
177
+ "summary": summary,
178
+ "livecrawl": livecrawl,
179
+ "livecrawlTimeout": livecrawlTimeout,
180
+ "subpages": subpages,
181
+ "subpageTarget": subpageTarget,
182
+ "extras": extras,
183
+ }
184
+ request_body = {k: v for k, v in request_body.items() if v is not None}
185
+ url = f"{self.base_url}/contents"
186
+ query_params = {}
187
+ response = self._post(url, data=request_body, params=query_params)
188
+ response.raise_for_status()
189
+ return response.json()
190
+
191
+ def answer(self, query, stream=None, text=None, model=None) -> dict[str, Any]:
192
+ """
193
+ Provides an answer to a query using the API endpoint at "/answer" via the POST method.
194
+
195
+ Args:
196
+ query (string): The question or query to answer. Example: 'What is the latest valuation of SpaceX?'.
197
+ stream (boolean): If true, the response is returned as a server-sent events (SSS) stream.
198
+ text (boolean): If true, the response includes full text content in the search results
199
+ model (string): The search model to use for the answer. Exa passes only one query to exa, while exa-pro also passes 2 expanded queries to our search model.
200
+
201
+ Returns:
202
+ dict[str, Any]: OK
203
+
204
+ Tags:
205
+ important
206
+ """
207
+ request_body = {
208
+ "query": query,
209
+ "stream": stream,
210
+ "text": text,
211
+ "model": model,
212
+ }
213
+ request_body = {k: v for k, v in request_body.items() if v is not None}
214
+ url = f"{self.base_url}/answer"
215
+ query_params = {}
216
+ response = self._post(url, data=request_body, params=query_params)
217
+ response.raise_for_status()
218
+ return response.json()
219
+
220
+ def list_tools(self):
221
+ return [self.search, self.find_similar, self.get_contents, self.answer]
@@ -0,0 +1,17 @@
1
+ # Falai MCP Server
2
+
3
+ An MCP Server for the Falai API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the Falai API.
8
+
9
+ | Tool | Description |
10
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
11
+ | `run` | Run a Fal AI application directly and wait for the result. Suitable for short-running applications with synchronous execution from the caller's perspective. |
12
+ | `submit` | Submits a request to the Fal AI queue for asynchronous processing and returns a request ID for tracking the job. |
13
+ | `status` | Checks the status of a previously submitted Fal AI request and retrieves its current execution state |
14
+ | `result` | Retrieves the result of a completed Fal AI request, waiting for completion if the request is still running. |
15
+ | `cancel` | Asynchronously cancels a running or queued Fal AI request. |
16
+ | `upload_file` | Uploads a local file to the Fal CDN and returns its public URL |
17
+ | `generate_image` | Asynchronously generates images using the 'fal-ai/flux/dev' application with customizable parameters and default settings |
@@ -0,0 +1 @@
1
+ from .app import FalaiApp
@@ -0,0 +1,331 @@
1
+ from pathlib import Path
2
+ from typing import Any, Literal
3
+
4
+ from fal_client import AsyncClient, AsyncRequestHandle, Status
5
+ from loguru import logger
6
+ from universal_mcp.applications.application import APIApplication
7
+ from universal_mcp.exceptions import NotAuthorizedError, ToolError
8
+ from universal_mcp.integrations import Integration
9
+
10
+ Priority = Literal["normal", "low"]
11
+
12
+
13
+ class FalaiApp(APIApplication):
14
+ """
15
+ Application for interacting with the Fal AI platform.
16
+
17
+ Provides tools to run, submit, check status, retrieve results, cancel jobs,
18
+ upload files to the Fal CDN, and a specialized tool for generating images.
19
+
20
+ Authentication is handled by the configured Integration provided by the
21
+ Universal MCP server, fetching the necessary API key.
22
+ """
23
+
24
+ def __init__(self, integration: Integration, **kwargs) -> None:
25
+ super().__init__(name="falai", integration=integration, **kwargs)
26
+ self._fal_client = None
27
+
28
+ @property
29
+ def fal_client(self) -> AsyncClient:
30
+ if self._fal_client is None:
31
+ credentials = self.integration.get_credentials()
32
+ logger.info(f"Credentials: {credentials}")
33
+ api_key = (
34
+ credentials.get("api_key")
35
+ or credentials.get("API_KEY")
36
+ or credentials.get("apiKey")
37
+ )
38
+ if not api_key:
39
+ logger.error(
40
+ f"Integration {type(self.integration).__name__} returned credentials in unexpected format."
41
+ )
42
+ raise NotAuthorizedError(
43
+ "Integration returned empty or invalid API key."
44
+ )
45
+ self._fal_client = AsyncClient(key=api_key)
46
+ return self._fal_client
47
+
48
+ async def run(
49
+ self,
50
+ arguments: Any,
51
+ application: str = "fal-ai/flux/dev",
52
+ path: str = "",
53
+ timeout: float | None = None,
54
+ hint: str | None = None,
55
+ ) -> Any:
56
+ """
57
+ Run a Fal AI application directly and wait for the result. Suitable for short-running applications with synchronous execution from the caller's perspective.
58
+
59
+ Args:
60
+ arguments: A dictionary of arguments for the application
61
+ application: The name or ID of the Fal application (defaults to 'fal-ai/flux/dev')
62
+ path: Optional subpath for the application endpoint
63
+ timeout: Optional timeout in seconds for the request
64
+ hint: Optional hint for runner selection
65
+
66
+ Returns:
67
+ The result of the application execution as a Python object (converted from JSON response)
68
+
69
+ Raises:
70
+ ToolError: Raised when the Fal API request fails, wrapping the original exception
71
+
72
+ Tags:
73
+ run, execute, ai, synchronous, fal, important
74
+ """
75
+ try:
76
+ result = await self.fal_client.run(
77
+ application=application,
78
+ arguments=arguments,
79
+ path=path,
80
+ timeout=timeout,
81
+ hint=hint,
82
+ )
83
+ return result
84
+ except Exception as e:
85
+ logger.error(
86
+ f"Error running Fal application {application}: {e}", exc_info=True
87
+ )
88
+ raise ToolError(f"Failed to run Fal application {application}: {e}") from e
89
+
90
+ async def submit(
91
+ self,
92
+ arguments: Any,
93
+ application: str = "fal-ai/flux/dev",
94
+ path: str = "",
95
+ hint: str | None = None,
96
+ webhook_url: str | None = None,
97
+ priority: Priority | None = None,
98
+ ) -> str:
99
+ """
100
+ Submits a request to the Fal AI queue for asynchronous processing and returns a request ID for tracking the job.
101
+
102
+ Args:
103
+ arguments: A dictionary of arguments for the application
104
+ application: The name or ID of the Fal application, defaulting to 'fal-ai/flux/dev'
105
+ path: Optional subpath for the application endpoint
106
+ hint: Optional hint for runner selection
107
+ webhook_url: Optional URL to receive a webhook when the request completes
108
+ priority: Optional queue priority ('normal' or 'low')
109
+
110
+ Returns:
111
+ The request ID (str) of the submitted asynchronous job
112
+
113
+ Raises:
114
+ ToolError: Raised when the Fal API request fails, wrapping the original exception
115
+
116
+ Tags:
117
+ submit, async_job, start, ai, queue
118
+ """
119
+ try:
120
+ handle: AsyncRequestHandle = await self.fal_client.submit(
121
+ application=application,
122
+ arguments=arguments,
123
+ path=path,
124
+ hint=hint,
125
+ webhook_url=webhook_url,
126
+ priority=priority,
127
+ )
128
+ request_id = handle.request_id
129
+ return request_id
130
+ except Exception as e:
131
+ logger.error(
132
+ f"Error submitting Fal application {application}: {e}", exc_info=True
133
+ )
134
+ raise ToolError(
135
+ f"Failed to submit Fal application {application}: {e}"
136
+ ) from e
137
+
138
+ async def status(
139
+ self,
140
+ request_id: str,
141
+ application: str = "fal-ai/flux/dev",
142
+ with_logs: bool = False,
143
+ ) -> Status:
144
+ """
145
+ Checks the status of a previously submitted Fal AI request and retrieves its current execution state
146
+
147
+ Args:
148
+ request_id: The unique identifier of the submitted request, obtained from a previous submit operation
149
+ application: The name or ID of the Fal application (defaults to 'fal-ai/flux/dev')
150
+ with_logs: Boolean flag to include execution logs in the status response (defaults to False)
151
+
152
+ Returns:
153
+ A Status object containing the current state of the request (Queued, InProgress, or Completed)
154
+
155
+ Raises:
156
+ ToolError: Raised when the Fal API request fails or when the provided request ID is invalid
157
+
158
+ Tags:
159
+ status, check, async_job, monitoring, ai
160
+ """
161
+ try:
162
+ handle = self.fal_client.get_handle(
163
+ application=application, request_id=request_id
164
+ )
165
+ status = await handle.status(with_logs=with_logs)
166
+ return status
167
+ except Exception as e:
168
+ logger.error(
169
+ f"Error getting status for Fal request_id {request_id}: {e}",
170
+ exc_info=True,
171
+ )
172
+ raise ToolError(
173
+ f"Failed to get status for Fal request_id {request_id}: {e}"
174
+ ) from e
175
+
176
+ async def result(
177
+ self, request_id: str, application: str = "fal-ai/flux/dev"
178
+ ) -> Any:
179
+ """
180
+ Retrieves the result of a completed Fal AI request, waiting for completion if the request is still running.
181
+
182
+ Args:
183
+ request_id: The unique identifier of the submitted request
184
+ application: The name or ID of the Fal application (defaults to 'fal-ai/flux/dev')
185
+
186
+ Returns:
187
+ The result of the application execution, converted from JSON response to Python data structures (dict/list)
188
+
189
+ Raises:
190
+ ToolError: When the Fal API request fails or the request does not complete successfully
191
+
192
+ Tags:
193
+ result, async-job, status, wait, ai
194
+ """
195
+ try:
196
+ handle = self.fal_client.get_handle(
197
+ application=application, request_id=request_id
198
+ )
199
+ result = await handle.get()
200
+ return result
201
+ except Exception as e:
202
+ logger.error(
203
+ f"Error getting result for Fal request_id {request_id}: {e}",
204
+ exc_info=True,
205
+ )
206
+ raise ToolError(
207
+ f"Failed to get result for Fal request_id {request_id}: {e}"
208
+ ) from e
209
+
210
+ async def cancel(
211
+ self, request_id: str, application: str = "fal-ai/flux/dev"
212
+ ) -> None:
213
+ """
214
+ Asynchronously cancels a running or queued Fal AI request.
215
+
216
+ Args:
217
+ request_id: The unique identifier of the submitted Fal AI request to cancel
218
+ application: The name or ID of the Fal application (defaults to 'fal-ai/flux/dev')
219
+
220
+ Returns:
221
+ None. The function doesn't return any value.
222
+
223
+ Raises:
224
+ ToolError: Raised when the cancellation request fails due to API errors or if the request cannot be cancelled
225
+
226
+ Tags:
227
+ cancel, async_job, ai, fal, management
228
+ """
229
+ try:
230
+ handle = self.fal_client.get_handle(
231
+ application=application, request_id=request_id
232
+ )
233
+ await handle.cancel()
234
+ return None
235
+ except Exception as e:
236
+ logger.error(
237
+ f"Error cancelling Fal request_id {request_id}: {e}", exc_info=True
238
+ )
239
+ raise ToolError(f"Failed to cancel Fal request_id {request_id}: {e}") from e
240
+
241
+ async def upload_file(self, path: str) -> str:
242
+ """
243
+ Uploads a local file to the Fal CDN and returns its public URL
244
+
245
+ Args:
246
+ path: The absolute or relative path to the local file
247
+
248
+ Returns:
249
+ A string containing the public URL of the uploaded file on the CDN
250
+
251
+ Raises:
252
+ ToolError: If the file is not found or if the upload operation fails
253
+
254
+ Tags:
255
+ upload, file, cdn, storage, async, important
256
+ """
257
+ try:
258
+ file_url = await self.fal_client.upload_file(Path(path))
259
+ return file_url
260
+ except FileNotFoundError as e:
261
+ logger.error(f"File not found for upload: {path}", exc_info=True)
262
+ raise ToolError(f"File not found: {path}") from e
263
+ except Exception as e:
264
+ logger.error(f"Error uploading file {path} to Fal CDN: {e}", exc_info=True)
265
+ raise ToolError(f"Failed to upload file {path}: {e}") from e
266
+
267
+ async def generate_image(
268
+ self,
269
+ prompt: str,
270
+ seed: int | None = 6252023,
271
+ image_size: str | None = "landscape_4_3",
272
+ num_images: int | None = 1,
273
+ extra_arguments: dict[str, Any] | None = None,
274
+ path: str = "",
275
+ timeout: float | None = None,
276
+ hint: str | None = None,
277
+ ) -> Any:
278
+ """
279
+ Asynchronously generates images using the 'fal-ai/flux/dev' application with customizable parameters and default settings
280
+
281
+ Args:
282
+ prompt: The text prompt used to guide the image generation
283
+ seed: Random seed for reproducible image generation (default: 6252023)
284
+ image_size: Dimensions of the generated image (default: 'landscape_4_3')
285
+ num_images: Number of images to generate in one request (default: 1)
286
+ extra_arguments: Additional arguments dictionary to pass to the application, can override defaults
287
+ path: Subpath for the application endpoint (rarely used)
288
+ timeout: Maximum time in seconds to wait for the request to complete
289
+ hint: Hint string for runner selection
290
+
291
+ Returns:
292
+ A dictionary containing the generated image URLs and related metadata
293
+
294
+ Raises:
295
+ ToolError: When the image generation request fails or encounters an error
296
+
297
+ Tags:
298
+ generate, image, ai, async, important, flux, customizable, default
299
+ """
300
+ application = "fal-ai/flux/dev"
301
+ arguments = {
302
+ "prompt": prompt,
303
+ "seed": seed,
304
+ "image_size": image_size,
305
+ "num_images": num_images,
306
+ }
307
+ if extra_arguments:
308
+ arguments.update(extra_arguments)
309
+ logger.debug(f"Merged extra_arguments. Final arguments: {arguments}")
310
+ try:
311
+ result = await self.run(
312
+ application=application,
313
+ arguments=arguments,
314
+ path=path,
315
+ timeout=timeout,
316
+ hint=hint,
317
+ )
318
+ return result
319
+ except Exception:
320
+ raise
321
+
322
+ def list_tools(self) -> list[callable]:
323
+ return [
324
+ self.run,
325
+ self.submit,
326
+ self.status,
327
+ self.result,
328
+ self.cancel,
329
+ self.upload_file,
330
+ self.generate_image,
331
+ ]
@@ -0,0 +1,49 @@
1
+ # Figma MCP Server
2
+
3
+ An MCP Server for the Figma API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the Figma API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `get_file` | Retrieves a specified file's data (including versions, geometry, and plugin information) from the API using a unique file identifier. |
13
+ | `get_file_nodes` | Retrieves nodes related to a file identified by the "file_key" using the specified query parameters for filtering by "ids", "version", "depth", "geometry", and "plugin_data". |
14
+ | `get_images` | Retrieves an image specified by the `file_key` using the GET method, allowing optional query parameters for customization such as formatting, scaling, and SVG options. |
15
+ | `get_image_fills` | Retrieves images associated with a file identified by the `{file_key}` using the `/v1/files/{file_key}/images` API endpoint. |
16
+ | `get_team_projects` | Retrieves a list of projects associated with a specific team identified by the team_id parameter. |
17
+ | `get_project_files` | Retrieves files from a specified project, optionally including branch data, using the provided project identifier. |
18
+ | `get_file_versions` | Retrieves a list of file versions using the "GET" method, filtering by file key and optional query parameters for pagination and sorting. |
19
+ | `get_comments` | Retrieves comments associated with a specified file and optionally returns them in Markdown format based on the query parameter. |
20
+ | `post_comment` | Creates a new comment on a file specified by the file_key and returns an appropriate status code. |
21
+ | `delete_comment` | Deletes a specified comment from a file identified by its file key and comment ID. |
22
+ | `get_comment_reactions` | Retrieves reactions for a specific comment in a file using the provided file key and comment ID. |
23
+ | `post_comment_reaction` | Adds a reaction to a specific comment on a file identified by the file key and comment ID using the "POST" method at the "/v1/files/{file_key}/comments/{comment_id}/reactions" endpoint. |
24
+ | `delete_comment_reaction` | Removes a reaction emoji from a comment on a file using the specified emoji parameter. |
25
+ | `get_me` | Retrieves the authenticated user's profile data. |
26
+ | `get_team_components` | Retrieves a list of components for a specified team with pagination support using page_size, after, and before parameters. |
27
+ | `get_file_components` | Retrieves a list of components associated with a file identified by the specified file key using the API endpoint "/v1/files/{file_key}/components". |
28
+ | `get_component` | Retrieves component information for a specific key using the API endpoint at "/v1/components/{key}" with the GET method. |
29
+ | `get_team_component_sets` | Retrieves a paginated list of component sets associated with a specific team ID, supporting pagination via page size, after, and before query parameters. |
30
+ | `get_file_component_sets` | Retrieves the component sets associated with a file identified by a specific file key using the "GET" method at the "/v1/files/{file_key}/component_sets" endpoint. |
31
+ | `get_component_set` | Retrieves a component set by its unique key identifier and returns the associated component data. |
32
+ | `get_team_styles` | Retrieves paginated style resources associated with a specific team using query parameters for pagination control. |
33
+ | `get_file_styles` | Retrieves styles information for a specific file identified by the file key using the API endpoint "/v1/files/{file_key}/styles" with the GET method. |
34
+ | `get_style` | Retrieves a style object associated with the specified key using the "GET" method at the "/v1/styles/{key}" endpoint. |
35
+ | `post_webhook` | Registers a new webhook to receive HTTP callbacks for specified events, returning success or error status codes. |
36
+ | `get_webhook` | Retrieves information about a specific webhook by its ID using the "GET" method at the path "/v2/webhooks/{webhook_id}". |
37
+ | `put_webhook` | Updates an existing webhook's configuration using the provided webhook ID and returns an HTTP status code indicating success or failure. |
38
+ | `delete_webhook` | Deletes a webhook identified by its `webhook_id`, permanently removing it to manage and optimize webhook configurations. |
39
+ | `get_team_webhooks` | Retrieves a list of webhooks for a specified team using the "GET" method, with the team identified by the `team_id` path parameter. |
40
+ | `get_webhook_requests` | Retrieves a list of requests for a specific webhook identified by `{webhook_id}` using the "GET" method. |
41
+ | `get_activity_logs` | Retrieves a list of activity logs filtered by specified events, time range, and other parameters, returning the results in a specified order with a limited number of entries. |
42
+ | `get_payments` | Retrieves payment information based on specified parameters, including plugin payment token, user ID, community file ID, plugin ID, and widget ID, using the "/v1/payments" API endpoint with a GET request. |
43
+ | `get_local_variables` | Retrieves local variables for a file specified by the "file_key" using the "GET" method. |
44
+ | `get_published_variables` | Retrieves the published variables for a file identified by the `{file_key}` using the `GET` method. |
45
+ | `post_variables` | Creates variables for a specific file identified by its file_key and returns an appropriate status code based on the operation's outcome. |
46
+ | `get_dev_resources` | Retrieves development resources associated with a specific file, identified by its file_key, with optional filtering by node IDs. |
47
+ | `post_dev_resources` | Creates developer resources via the API and returns a status response. |
48
+ | `put_dev_resources` | Replaces a specific developer resource at the specified path with updated data, returning a status code for success or error conditions. |
49
+ | `delete_dev_resource` | Deletes a specific development resource associated with a file using the provided file key and development resource ID. |
@@ -0,0 +1 @@
1
+ from .app import FigmaApp