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
File without changes
@@ -0,0 +1 @@
1
+ from .app import GoogleAdsApp
@@ -0,0 +1,23 @@
1
+ from universal_mcp.applications.application import APIApplication
2
+ from universal_mcp.integrations import Integration
3
+
4
+
5
+ class GoogleAdsApp(APIApplication):
6
+ """
7
+ Base class for Universal MCP Applications.
8
+ """
9
+
10
+ def __init__(self, integration: Integration = None, **kwargs) -> None:
11
+ super().__init__(name="google-ads", integration=integration, **kwargs)
12
+
13
+ def run(self):
14
+ """
15
+ Example tool implementation.
16
+ """
17
+ return "Task completed successfully."
18
+
19
+ def list_tools(self):
20
+ """
21
+ Lists the available tools (methods) for this application.
22
+ """
23
+ return [self.run]
@@ -0,0 +1,21 @@
1
+ # GoogleCalendarApp MCP Server
2
+
3
+ An MCP Server for the GoogleCalendarApp API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the GoogleCalendarApp API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `get_event` | Retrieves detailed information about a specific Google Calendar event by its ID |
13
+ | `get_today_events` | Retrieves events from Google Calendar for today or a specified number of future days. |
14
+ | `list_events` | Retrieves a list of events from Google Calendar with customizable filtering, sorting, and pagination options |
15
+ | `quick_add_event` | Creates a calendar event. Use it only when user specfies that they want to add a quick event |
16
+ | `add_an_event` | Creates a new calendar event with details like start time, end time, summary, description, location, attendees, and recurrence rules. |
17
+ | `update_event` | Updates an existing calendar event. This method updates the entire event resource. |
18
+ | `get_event_instances` | Retrieves all instances of a recurring calendar event within a specified time range. |
19
+ | `get_user_timezone` | Gets the user's calendar timezone setting to help with timezone-aware event creation. |
20
+ | `delete_event` | Deletes an event from the specified calendar. |
21
+ | `query_free_busy` | Checks if you have free slots or not by querying the free/busy status of your calendars. |
@@ -0,0 +1 @@
1
+ from .app import GoogleCalendarApp
@@ -0,0 +1,574 @@
1
+ from datetime import UTC, datetime, timedelta
2
+ from typing import Any
3
+
4
+ from loguru import logger
5
+ from universal_mcp.applications.application import APIApplication
6
+ from universal_mcp.integrations import Integration
7
+
8
+
9
+ class GoogleCalendarApp(APIApplication):
10
+ def __init__(self, integration: Integration) -> None:
11
+ super().__init__(name="google-calendar", integration=integration)
12
+ self.base_api_url = "https://www.googleapis.com/calendar/v3/calendars/primary"
13
+ self.base_url = "https://www.googleapis.com/calendar/v3"
14
+
15
+ def _format_datetime(self, dt_string: str) -> str:
16
+ """Format a datetime string from ISO format to a human-readable format.
17
+
18
+ Args:
19
+ dt_string: A datetime string in ISO format (e.g., "2023-06-01T10:00:00Z")
20
+
21
+ Returns:
22
+ A formatted datetime string (e.g., "2023-06-01 10:00 AM") or the original string with
23
+ "(All day)" appended if it's just a date
24
+ """
25
+ if not dt_string or dt_string == "Unknown":
26
+ return "Unknown"
27
+
28
+ # Check if it's just a date (all-day event) or a datetime
29
+ if "T" in dt_string:
30
+ # It's a datetime - parse and format it
31
+ try:
32
+ # Handle Z (UTC) suffix by replacing with +00:00 timezone
33
+ if dt_string.endswith("Z"):
34
+ dt_string = dt_string.replace("Z", "+00:00")
35
+
36
+ # Parse the ISO datetime string
37
+ dt = datetime.fromisoformat(dt_string)
38
+
39
+ # Format to a more readable form
40
+ return dt.strftime("%Y-%m-%d %I:%M %p")
41
+ except ValueError:
42
+ # In case of parsing error, return the original
43
+ logger.warning(f"Could not parse datetime string: {dt_string}")
44
+ return dt_string
45
+ else:
46
+ # It's just a date (all-day event)
47
+ return f"{dt_string} (All day)"
48
+
49
+ def get_today_events(
50
+ self,
51
+ days: int = 1,
52
+ max_results: int | None = None,
53
+ time_zone: str | None = None,
54
+ ) -> dict[str, Any]:
55
+ """
56
+ Retrieves events from Google Calendar for today or a specified number of future days.
57
+
58
+ Args:
59
+ days: Number of days to retrieve events for (default: 1, which is just today)
60
+ max_results: Maximum number of events to return (optional)
61
+ time_zone: Time zone used in the response (optional, default is calendar's time zone)
62
+
63
+ Returns:
64
+ Dictionary containing the complete API response with all events and metadata
65
+
66
+ Raises:
67
+ HTTPError: Raised when the API request fails or returns an error status code
68
+
69
+ Tags:
70
+ fetch, list, calendar, events, date-time, important, api
71
+ """
72
+ today = datetime.now(UTC).date()
73
+ end_date = today + timedelta(days=days)
74
+ time_min = f"{today.isoformat()}T00:00:00Z"
75
+ time_max = f"{end_date.isoformat()}T00:00:00Z"
76
+ url = f"{self.base_api_url}/events"
77
+ params = {
78
+ "timeMin": time_min,
79
+ "timeMax": time_max,
80
+ "singleEvents": "true",
81
+ "orderBy": "startTime",
82
+ }
83
+ if max_results is not None:
84
+ params["maxResults"] = str(max_results)
85
+ if time_zone:
86
+ params["timeZone"] = time_zone
87
+ date_range = "today" if days == 1 else f"the next {days} days"
88
+ logger.info(f"Retrieving calendar events for {date_range}")
89
+ response = self._get(url, params=params)
90
+
91
+ return self._handle_response(response)
92
+
93
+ def get_event(
94
+ self,
95
+ event_id: str,
96
+ max_attendees: int | None = None,
97
+ time_zone: str | None = None,
98
+ ) -> dict[str, Any]:
99
+ """
100
+ Retrieves detailed information about a specific Google Calendar event by its ID
101
+
102
+ Args:
103
+ event_id: The unique identifier of the calendar event to retrieve
104
+ max_attendees: Optional. The maximum number of attendees to include in the response. If None, includes all attendees
105
+ time_zone: Optional. The time zone to use for formatting dates in the response. If None, uses the calendar's default time zone
106
+
107
+ Returns:
108
+ Dictionary containing the complete API response with all event details
109
+
110
+ Raises:
111
+ HTTPError: Raised when the API request fails or returns an error status code
112
+ JSONDecodeError: Raised when the API response cannot be parsed as JSON
113
+
114
+ Tags:
115
+ retrieve, calendar, event, api, important
116
+ """
117
+ url = f"{self.base_api_url}/events/{event_id}"
118
+ params = {}
119
+ if max_attendees is not None:
120
+ params["maxAttendees"] = max_attendees
121
+ if time_zone:
122
+ params["timeZone"] = time_zone
123
+ logger.info(f"Retrieving calendar event with ID: {event_id}")
124
+ response = self._get(url, params=params)
125
+ return self._handle_response(response)
126
+
127
+ def list_events(
128
+ self,
129
+ max_results: int = 10,
130
+ time_min: str | None = None,
131
+ time_max: str | None = None,
132
+ q: str | None = None,
133
+ order_by: str = "startTime",
134
+ single_events: bool = True,
135
+ time_zone: str | None = None,
136
+ page_token: str | None = None,
137
+ ) -> dict[str, Any]:
138
+ """
139
+ Retrieves a list of events from Google Calendar with customizable filtering, sorting, and pagination options
140
+
141
+ Args:
142
+ max_results: Maximum number of events to return (default: 10, max: 2500)
143
+ time_min: Start time in ISO format (e.g., '2023-12-01T00:00:00Z'). Defaults to current time if not specified
144
+ time_max: End time in ISO format (e.g., '2023-12-31T23:59:59Z')
145
+ q: Free text search terms to filter events (searches across summary, description, location, attendees)
146
+ order_by: Sort order for results - either 'startTime' (default) or 'updated'
147
+ single_events: Whether to expand recurring events into individual instances (default: True)
148
+ time_zone: Time zone for response formatting (defaults to calendar's time zone)
149
+ page_token: Token for retrieving a specific page of results in paginated responses
150
+
151
+ Returns:
152
+ Dictionary containing the complete API response with all events and metadata
153
+
154
+ Raises:
155
+ HTTPError: Raised when the API request fails or returns an error status code
156
+ JSONDecodeError: Raised when the API response cannot be parsed as JSON
157
+
158
+ Tags:
159
+ list, retrieve, calendar, events, pagination, api, important
160
+ """
161
+ url = f"{self.base_api_url}/events"
162
+ params = {
163
+ "maxResults": str(max_results),
164
+ "orderBy": order_by,
165
+ "singleEvents": str(single_events).lower(),
166
+ }
167
+ if time_min:
168
+ params["timeMin"] = time_min
169
+ else:
170
+ # Default to current time if not specified
171
+ now = datetime.utcnow().isoformat() + "Z" # 'Z' indicates UTC time
172
+ params["timeMin"] = now
173
+ if time_max:
174
+ params["timeMax"] = time_max
175
+ if q:
176
+ params["q"] = q
177
+ if time_zone:
178
+ params["timeZone"] = time_zone
179
+ if page_token:
180
+ params["pageToken"] = page_token
181
+ logger.info(f"Retrieving calendar events with params: {params}")
182
+ response = self._get(url, params=params)
183
+
184
+ return self._handle_response(response)
185
+
186
+ def add_an_event(
187
+ self,
188
+ start: dict[str, Any],
189
+ end: dict[str, Any],
190
+ summary: str,
191
+ description: str | None = None,
192
+ location: str | None = None,
193
+ attendees: list[dict[str, str]] | None = None,
194
+ recurrence: list[str] | None = None,
195
+ calendar_id: str = "primary",
196
+ ) -> dict[str, Any]:
197
+ """
198
+ Creates a new calendar event with details like start time, end time, summary, description, location, attendees, and recurrence rules.
199
+ Always check the timezone using get_user_timezone before creating an event.
200
+
201
+ Args:
202
+ start: Start time of the event (required). Must include timezone offset or timeZone field.
203
+ Examples:
204
+ - {"dateTime": "2025-08-7T16:30:00+05:30"} (with offset)
205
+ - {"dateTime": "2025-08-7T16:30:00", "timeZone": "Asia/Kolkata"} (with timeZone field)
206
+ - {"dateTime": "2025-08-7T16:30:00Z", "timeZone": "UTC"} (UTC time)
207
+ end: End time of the event (required). Must include timezone offset or timeZone field.
208
+ Examples:
209
+ - {"dateTime": "2025-08-7T17:30:00+05:30"} (with offset)
210
+ - {"dateTime": "2025-08-7T17:30:00", "timeZone": "Asia/Kolkata"} (with timeZone field)
211
+ - {"dateTime": "2025-08-7T17:30:00Z", "timeZone": "UTC"} (UTC time)
212
+ summary: Event title/summary (required). Example: "New"
213
+ description: Event description. Example: "hey"
214
+ location: Event location. Example: "Delhi"
215
+ attendees: List of attendee dictionaries. Example: [{"email": "example@gmail.com"}]
216
+ recurrence: List of RRULE, RDATE, or EXDATE strings for recurring events (optional).
217
+ Example: ["RRULE:FREQ=WEEKLY;COUNT=5;BYDAY=TU,FR"],
218
+ # For an all-day event starting on June 1st, 2015 and repeating every 3 days throughout the month,excluding June 10th but including June 9th and 11th:
219
+ Example: [
220
+ "EXDATE;VALUE=DATE:20150610",
221
+ "RDATE;VALUE=DATE:20150609,20150611",
222
+ "RRULE:FREQ=DAILY;UNTIL=20150628;INTERVAL=3"
223
+ ],
224
+ calendar_id: Calendar identifier (default: "primary")
225
+
226
+ Returns:
227
+ Dictionary containing the complete API response with the created event details
228
+
229
+ Raises:
230
+ HTTPError: Raised when the API request fails or returns an error status code
231
+
232
+ Tags:
233
+ create, calendar, event, insert, recurring, important
234
+ """
235
+
236
+ request_body_data = {
237
+ "start": start,
238
+ "end": end,
239
+ "summary": summary,
240
+ "description": description,
241
+ "location": location,
242
+ "attendees": attendees,
243
+ "recurrence": recurrence,
244
+ }
245
+ request_body_data = {
246
+ k: v for k, v in request_body_data.items() if v is not None
247
+ }
248
+
249
+ url = f"{self.base_url}/calendars/{calendar_id}/events"
250
+
251
+ response = self._post(url, data=request_body_data)
252
+
253
+ return self._handle_response(response)
254
+
255
+ def quick_add_event(self, text: str, send_updates: str = "none") -> dict[str, Any]:
256
+ """
257
+ Creates a calendar event. Use it only when user specfies that they want to add a quick event
258
+
259
+ Args:
260
+ text: Natural language text describing the event (e.g., 'Meeting with John at Coffee Shop tomorrow 3pm-4pm')
261
+ send_updates: Specifies who should receive event notifications: 'all', 'externalOnly', or 'none' (default)
262
+
263
+ Returns:
264
+ Dictionary containing the complete API response with the created event details
265
+
266
+ Raises:
267
+ HTTPError: Raised when the API request fails or returns an error status code
268
+
269
+ Tags:
270
+ create, calendar, event, quick-add, natural-language, important
271
+ """
272
+ url = f"{self.base_api_url}/events/quickAdd"
273
+ params = {"text": text, "sendUpdates": send_updates}
274
+ logger.info(f"Creating event via quickAdd: '{text}'")
275
+ response = self._post(url, data=None, params=params)
276
+
277
+ return self._handle_response(response)
278
+
279
+ def get_event_instances(
280
+ self,
281
+ event_id: str,
282
+ max_results: int = 25,
283
+ time_min: str | None = None,
284
+ time_max: str | None = None,
285
+ time_zone: str | None = None,
286
+ show_deleted: bool = False,
287
+ page_token: str | None = None,
288
+ ) -> dict[str, Any]:
289
+ """
290
+ Retrieves all instances of a recurring calendar event within a specified time range.
291
+
292
+ Args:
293
+ event_id: ID of the recurring event
294
+ max_results: Maximum number of event instances to return (default: 25, max: 2500)
295
+ time_min: Lower bound (inclusive) for event's end time in ISO format
296
+ time_max: Upper bound (exclusive) for event's start time in ISO format
297
+ time_zone: Time zone used in the response (defaults to calendar's time zone)
298
+ show_deleted: Whether to include deleted instances (default: False)
299
+ page_token: Token for retrieving a specific page of results
300
+
301
+ Returns:
302
+ Dictionary containing the complete API response with all event instances and metadata
303
+
304
+ Raises:
305
+ HTTPError: Raised when the API request fails or returns an error status code
306
+ JSONDecodeError: Raised when the API response cannot be parsed as JSON
307
+
308
+ Tags:
309
+ list, retrieve, calendar, events, recurring, pagination, api, important
310
+ """
311
+ url = f"{self.base_api_url}/events/{event_id}/instances"
312
+ params = {
313
+ "maxResults": str(max_results),
314
+ "showDeleted": str(show_deleted).lower(),
315
+ }
316
+ if time_min:
317
+ params["timeMin"] = time_min
318
+ if time_max:
319
+ params["timeMax"] = time_max
320
+ if time_zone:
321
+ params["timeZone"] = time_zone
322
+ if page_token:
323
+ params["pageToken"] = page_token
324
+ logger.info(f"Retrieving instances of recurring event with ID: {event_id}")
325
+ response = self._get(url, params=params)
326
+
327
+ return self._handle_response(response)
328
+
329
+ def delete_event(
330
+ self,
331
+ calendarId,
332
+ eventId,
333
+ sendNotifications=None,
334
+ sendUpdates=None,
335
+ alt=None,
336
+ fields=None,
337
+ key=None,
338
+ oauth_token=None,
339
+ prettyPrint=None,
340
+ quotaUser=None,
341
+ userIp=None,
342
+ ) -> Any:
343
+ """
344
+ Deletes an event from the specified calendar.
345
+
346
+ Args:
347
+ calendarId (string): calendarId
348
+ eventId (string): eventId
349
+ sendNotifications (string): No description provided. Example: 'true'.
350
+ sendUpdates (string): No description provided. Example: 'amet in'.
351
+ alt (string): Data format for the response. Example: 'json'.
352
+ fields (string): Selector specifying which fields to include in a partial response. Example: 'amet in'.
353
+ key (string): API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token. Example: 'amet in'.
354
+ oauth_token (string): OAuth 2.0 token for the current user. Example: 'amet in'.
355
+ prettyPrint (string): Returns response with indentations and line breaks. Example: 'true'.
356
+ quotaUser (string): An opaque string that represents a user for quota purposes. Must not exceed 40 characters. Example: 'amet in'.
357
+ userIp (string): Deprecated. Please use quotaUser instead. Example: 'amet in'.
358
+
359
+ Returns:
360
+ Any: No Content
361
+
362
+ Tags:
363
+ calendars, {calendarId}, events, {eventId}
364
+ """
365
+ if calendarId is None:
366
+ raise ValueError("Missing required parameter 'calendarId'")
367
+ if eventId is None:
368
+ raise ValueError("Missing required parameter 'eventId'")
369
+ url = f"{self.base_url}/calendars/{calendarId}/events/{eventId}"
370
+ query_params = {
371
+ k: v
372
+ for k, v in [
373
+ ("sendNotifications", sendNotifications),
374
+ ("sendUpdates", sendUpdates),
375
+ ("alt", alt),
376
+ ("fields", fields),
377
+ ("key", key),
378
+ ("oauth_token", oauth_token),
379
+ ("prettyPrint", prettyPrint),
380
+ ("quotaUser", quotaUser),
381
+ ("userIp", userIp),
382
+ ]
383
+ if v is not None
384
+ }
385
+ response = self._delete(url, params=query_params)
386
+ return self._handle_response(response)
387
+
388
+ def update_event(
389
+ self,
390
+ event_id: str,
391
+ start: dict[str, Any],
392
+ end: dict[str, Any],
393
+ summary: str,
394
+ description: str | None = None,
395
+ location: str | None = None,
396
+ attendees: list[dict[str, str]] | None = None,
397
+ recurrence: list[str] | None = None,
398
+ calendar_id: str = "primary",
399
+ send_updates: str = "none",
400
+ max_attendees: int | None = None,
401
+ ) -> dict[str, Any]:
402
+ """
403
+ Updates an existing calendar event. This method updates the entire event resource.
404
+ To do a partial update, first get the event, then update it using etags to ensure atomicity.
405
+
406
+ Args:
407
+ event_id: The unique identifier of the calendar event to update (required)
408
+ start: Start time of the event (required). Must include timezone offset or timeZone field.
409
+ Examples:
410
+ - {"dateTime": "2025-08-7T16:30:00+05:30"} (with offset)
411
+ - {"dateTime": "2025-08-7T16:30:00", "timeZone": "Asia/Kolkata"} (with timeZone field)
412
+ - {"dateTime": "2025-08-7T16:30:00Z", "timeZone": "UTC"} (UTC time)
413
+ end: End time of the event (required). Must include timezone offset or timeZone field.
414
+ Examples:
415
+ - {"dateTime": "2025-08-7T17:30:00+05:30"} (with offset)
416
+ - {"dateTime": "2025-08-7T17:30:00", "timeZone": "Asia/Kolkata"} (with timeZone field)
417
+ - {"dateTime": "2025-08-7T17:30:00Z", "timeZone": "UTC"} (UTC time)
418
+ summary: Event title/summary (required). Example: "Updated Meeting"
419
+ description: Event description. Example: "Updated description"
420
+ location: Event location. Example: "Updated Location"
421
+ attendees: List of attendee dictionaries. Example: [{"email": "example@gmail.com"}]
422
+ recurrence: List of RRULE, RDATE, or EXDATE strings for recurring events (optional).
423
+ Example: ["RRULE:FREQ=WEEKLY;COUNT=5;BYDAY=TU,FR"]
424
+ calendar_id: Calendar identifier (default: "primary")
425
+ send_updates: Specifies who should receive event notifications: 'all', 'externalOnly', or 'none' (default)
426
+ max_attendees: Maximum number of attendees to include in the response (optional)
427
+
428
+ Returns:
429
+ Dictionary containing the complete API response with the updated event details
430
+
431
+ Raises:
432
+ HTTPError: Raised when the API request fails or returns an error status code
433
+
434
+ Tags:
435
+ update, calendar, event, modify, important
436
+ """
437
+ request_body_data = {
438
+ "start": start,
439
+ "end": end,
440
+ "summary": summary,
441
+ "description": description,
442
+ "location": location,
443
+ "attendees": attendees,
444
+ "recurrence": recurrence,
445
+ }
446
+ request_body_data = {
447
+ k: v for k, v in request_body_data.items() if v is not None
448
+ }
449
+
450
+ url = f"{self.base_url}/calendars/{calendar_id}/events/{event_id}"
451
+ params = {"sendUpdates": send_updates}
452
+ if max_attendees is not None:
453
+ params["maxAttendees"] = str(max_attendees)
454
+
455
+ logger.info(f"Updating calendar event with ID: {event_id}")
456
+ response = self._put(url, data=request_body_data, params=params)
457
+
458
+ return self._handle_response(response)
459
+
460
+ def get_user_timezone(self) -> dict[str, Any]:
461
+ """
462
+ Gets the user's calendar timezone setting to help with timezone-aware event creation.
463
+
464
+ Returns:
465
+ Dictionary containing the user's timezone information
466
+
467
+ Raises:
468
+ HTTPError: Raised when the API request fails or returns an error status code
469
+
470
+ Tags:
471
+ get, calendar, timezone, settings, important
472
+ """
473
+ url = f"{self.base_api_url}"
474
+ logger.info("Retrieving user's calendar timezone settings")
475
+ response = self._get(url)
476
+ return self._handle_response(response)
477
+
478
+ def query_free_busy(
479
+ self,
480
+ alt=None,
481
+ fields=None,
482
+ key=None,
483
+ oauth_token=None,
484
+ prettyPrint=None,
485
+ quotaUser=None,
486
+ userIp=None,
487
+ calendarExpansionMax=None,
488
+ groupExpansionMax=None,
489
+ items=None,
490
+ timeMax=None,
491
+ timeMin=None,
492
+ timeZone=None,
493
+ ) -> dict[str, Any]:
494
+ """
495
+ Checks if you have free slots or not by querying the free/busy status of your calendars.
496
+
497
+
498
+ Args:
499
+ alt (string): Data format for the response. Example: 'json'.
500
+ fields (string): Selector specifying which fields to include in a partial response. Example: 'amet in'.
501
+ key (string): API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token. Example: 'amet in'.
502
+ oauth_token (string): OAuth 2.0 token for the current user. Example: 'amet in'.
503
+ prettyPrint (string): Returns response with indentations and line breaks. Example: 'true'.
504
+ quotaUser (string): An opaque string that represents a user for quota purposes. Must not exceed 40 characters. Example: 'amet in'.
505
+ userIp (string): Deprecated. Please use quotaUser instead. Example: 'amet in'.
506
+ calendarExpansionMax (number): calendarExpansionMax Example: '37977981'.
507
+ groupExpansionMax (number): groupExpansionMax Example: '-92198829'.
508
+ items (array): items Example: "[{'id': 'qui labore velit in anim'}, {'id': 'sed dolore dolor laborum eiusmod'}]".
509
+ timeMax (string): timeMax Example: '2016-10-26T20:45:39.467Z'.
510
+ timeMin (string): timeMin Example: '1971-06-26T00:25:33.327Z'.
511
+ timeZone (string): timeZone
512
+ Example:
513
+ ```json
514
+ {
515
+ "calendarExpansionMax": 37977981,
516
+ "groupExpansionMax": -92198829,
517
+ "items": [
518
+ {
519
+ "id": "qui labore velit in anim"
520
+ },
521
+ {
522
+ "id": "sed dolore dolor laborum eiusmod"
523
+ }
524
+ ],
525
+ "timeMax": "2016-10-26T20:45:39.467Z",
526
+ "timeMin": "1971-06-26T00:25:33.327Z",
527
+ "timeZone": "UTC"
528
+ }
529
+ ```
530
+
531
+ Returns:
532
+ dict[str, Any]: Successful response
533
+ """
534
+ request_body = {
535
+ "calendarExpansionMax": calendarExpansionMax,
536
+ "groupExpansionMax": groupExpansionMax,
537
+ "items": items,
538
+ "timeMax": timeMax,
539
+ "timeMin": timeMin,
540
+ "timeZone": timeZone,
541
+ }
542
+ request_body = {k: v for k, v in request_body.items() if v is not None}
543
+ url = f"{self.base_url}/freeBusy"
544
+ query_params = {
545
+ k: v
546
+ for k, v in [
547
+ ("alt", alt),
548
+ ("fields", fields),
549
+ ("key", key),
550
+ ("oauth_token", oauth_token),
551
+ ("prettyPrint", prettyPrint),
552
+ ("quotaUser", quotaUser),
553
+ ("userIp", userIp),
554
+ ]
555
+ if v is not None
556
+ }
557
+ response = self._post(url, data=request_body, params=query_params)
558
+ response.raise_for_status()
559
+ return response.json()
560
+
561
+ def list_tools(self):
562
+ return [
563
+ self.get_event,
564
+ self.get_today_events,
565
+ self.list_events,
566
+ self.quick_add_event,
567
+ self.add_an_event,
568
+ self.update_event,
569
+ self.get_event_instances,
570
+ self.get_user_timezone,
571
+ # Auto Generated from Openapi spec
572
+ self.delete_event,
573
+ self.query_free_busy,
574
+ ]
@@ -0,0 +1,25 @@
1
+ # GoogleDocsApp MCP Server
2
+
3
+ An MCP Server for the GoogleDocsApp API.
4
+
5
+ ## 🛠️ Tool List
6
+
7
+ This is automatically generated from OpenAPI schema for the GoogleDocsApp API.
8
+
9
+
10
+ | Tool | Description |
11
+ |------|-------------|
12
+ | `create_document` | Creates a new blank Google Document with the specified title and returns the API response. |
13
+ | `get_document` | Retrieves the latest version of a specified document from the Google Docs API. |
14
+ | `add_content` | Adds text content at a specified position in an existing Google Document via the Google Docs API. |
15
+ | `style_text` | Simplified text styling for Google Document - handles most common cases. |
16
+ | `delete_content` | Deletes content from a specified range in a Google Document. |
17
+ | `insert_table` | Inserts a table at the specified location in a Google Document. |
18
+ | `create_footer` | Creates a Footer in a Google Document. |
19
+ | `create_footnote` | Creates a Footnote segment and inserts a new FootnoteReference at the given location. |
20
+ | `delete_footer` | Deletes a Footer from the document. |
21
+ | `create_header` | Creates a Header in a Google Document. |
22
+ | `delete_header` | Deletes a Header from the document. |
23
+ | `create_paragraph_bullets` | Creates bullets for all of the paragraphs that overlap with the given range. |
24
+ | `delete_paragraph_bullets` | Deletes bullets from all of the paragraphs that overlap with the given range. |
25
+ | `update_paragraph_style` | Updates paragraph styling for a specified range in a Google Document. |
@@ -0,0 +1 @@
1
+ from .app import GoogleDocsApp