universal-mcp 0.1.13rc1__py3-none-any.whl → 0.1.13rc2__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 (99) hide show
  1. {universal_mcp-0.1.13rc1.dist-info → universal_mcp-0.1.13rc2.dist-info}/METADATA +1 -1
  2. universal_mcp-0.1.13rc2.dist-info/RECORD +38 -0
  3. universal_mcp/applications/ahrefs/README.md +0 -76
  4. universal_mcp/applications/ahrefs/__init__.py +0 -0
  5. universal_mcp/applications/ahrefs/app.py +0 -2291
  6. universal_mcp/applications/cal_com_v2/README.md +0 -175
  7. universal_mcp/applications/cal_com_v2/__init__.py +0 -0
  8. universal_mcp/applications/cal_com_v2/app.py +0 -5390
  9. universal_mcp/applications/calendly/README.md +0 -78
  10. universal_mcp/applications/calendly/__init__.py +0 -0
  11. universal_mcp/applications/calendly/app.py +0 -1195
  12. universal_mcp/applications/clickup/README.md +0 -160
  13. universal_mcp/applications/clickup/__init__.py +0 -0
  14. universal_mcp/applications/clickup/app.py +0 -5009
  15. universal_mcp/applications/coda/README.md +0 -133
  16. universal_mcp/applications/coda/__init__.py +0 -0
  17. universal_mcp/applications/coda/app.py +0 -3671
  18. universal_mcp/applications/curstdata/README.md +0 -50
  19. universal_mcp/applications/curstdata/__init__.py +0 -0
  20. universal_mcp/applications/curstdata/app.py +0 -551
  21. universal_mcp/applications/e2b/README.md +0 -37
  22. universal_mcp/applications/e2b/app.py +0 -65
  23. universal_mcp/applications/elevenlabs/README.md +0 -84
  24. universal_mcp/applications/elevenlabs/__init__.py +0 -0
  25. universal_mcp/applications/elevenlabs/app.py +0 -1402
  26. universal_mcp/applications/falai/README.md +0 -42
  27. universal_mcp/applications/falai/__init__.py +0 -0
  28. universal_mcp/applications/falai/app.py +0 -332
  29. universal_mcp/applications/figma/README.md +0 -74
  30. universal_mcp/applications/figma/__init__.py +0 -0
  31. universal_mcp/applications/figma/app.py +0 -1261
  32. universal_mcp/applications/firecrawl/README.md +0 -45
  33. universal_mcp/applications/firecrawl/app.py +0 -268
  34. universal_mcp/applications/github/README.md +0 -47
  35. universal_mcp/applications/github/app.py +0 -429
  36. universal_mcp/applications/gong/README.md +0 -88
  37. universal_mcp/applications/gong/__init__.py +0 -0
  38. universal_mcp/applications/gong/app.py +0 -2297
  39. universal_mcp/applications/google_calendar/app.py +0 -442
  40. universal_mcp/applications/google_docs/README.md +0 -40
  41. universal_mcp/applications/google_docs/app.py +0 -88
  42. universal_mcp/applications/google_drive/README.md +0 -44
  43. universal_mcp/applications/google_drive/app.py +0 -286
  44. universal_mcp/applications/google_mail/README.md +0 -47
  45. universal_mcp/applications/google_mail/app.py +0 -664
  46. universal_mcp/applications/google_sheet/README.md +0 -42
  47. universal_mcp/applications/google_sheet/app.py +0 -150
  48. universal_mcp/applications/heygen/README.md +0 -69
  49. universal_mcp/applications/heygen/__init__.py +0 -0
  50. universal_mcp/applications/heygen/app.py +0 -956
  51. universal_mcp/applications/mailchimp/README.md +0 -306
  52. universal_mcp/applications/mailchimp/__init__.py +0 -0
  53. universal_mcp/applications/mailchimp/app.py +0 -10937
  54. universal_mcp/applications/markitdown/app.py +0 -44
  55. universal_mcp/applications/neon/README.md +0 -99
  56. universal_mcp/applications/neon/__init__.py +0 -0
  57. universal_mcp/applications/neon/app.py +0 -1924
  58. universal_mcp/applications/notion/README.md +0 -55
  59. universal_mcp/applications/notion/__init__.py +0 -0
  60. universal_mcp/applications/notion/app.py +0 -527
  61. universal_mcp/applications/perplexity/README.md +0 -37
  62. universal_mcp/applications/perplexity/app.py +0 -65
  63. universal_mcp/applications/reddit/README.md +0 -45
  64. universal_mcp/applications/reddit/app.py +0 -379
  65. universal_mcp/applications/replicate/README.md +0 -65
  66. universal_mcp/applications/replicate/__init__.py +0 -0
  67. universal_mcp/applications/replicate/app.py +0 -980
  68. universal_mcp/applications/resend/README.md +0 -38
  69. universal_mcp/applications/resend/app.py +0 -37
  70. universal_mcp/applications/retell_ai/README.md +0 -46
  71. universal_mcp/applications/retell_ai/__init__.py +0 -0
  72. universal_mcp/applications/retell_ai/app.py +0 -333
  73. universal_mcp/applications/rocketlane/README.md +0 -42
  74. universal_mcp/applications/rocketlane/__init__.py +0 -0
  75. universal_mcp/applications/rocketlane/app.py +0 -194
  76. universal_mcp/applications/serpapi/README.md +0 -37
  77. universal_mcp/applications/serpapi/app.py +0 -73
  78. universal_mcp/applications/shortcut/README.md +0 -153
  79. universal_mcp/applications/shortcut/__init__.py +0 -0
  80. universal_mcp/applications/shortcut/app.py +0 -3880
  81. universal_mcp/applications/spotify/README.md +0 -116
  82. universal_mcp/applications/spotify/__init__.py +0 -0
  83. universal_mcp/applications/spotify/app.py +0 -2526
  84. universal_mcp/applications/supabase/README.md +0 -112
  85. universal_mcp/applications/supabase/__init__.py +0 -0
  86. universal_mcp/applications/supabase/app.py +0 -2970
  87. universal_mcp/applications/tavily/README.md +0 -38
  88. universal_mcp/applications/tavily/app.py +0 -51
  89. universal_mcp/applications/wrike/README.md +0 -71
  90. universal_mcp/applications/wrike/__init__.py +0 -0
  91. universal_mcp/applications/wrike/app.py +0 -1372
  92. universal_mcp/applications/youtube/README.md +0 -82
  93. universal_mcp/applications/youtube/__init__.py +0 -0
  94. universal_mcp/applications/youtube/app.py +0 -1428
  95. universal_mcp/applications/zenquotes/README.md +0 -37
  96. universal_mcp/applications/zenquotes/app.py +0 -31
  97. universal_mcp-0.1.13rc1.dist-info/RECORD +0 -132
  98. {universal_mcp-0.1.13rc1.dist-info → universal_mcp-0.1.13rc2.dist-info}/WHEEL +0 -0
  99. {universal_mcp-0.1.13rc1.dist-info → universal_mcp-0.1.13rc2.dist-info}/entry_points.txt +0 -0
@@ -1,442 +0,0 @@
1
- from datetime import datetime, timedelta
2
-
3
- from loguru import logger
4
-
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
-
14
- def _format_datetime(self, dt_string: str) -> str:
15
- """Format a datetime string from ISO format to a human-readable format.
16
-
17
- Args:
18
- dt_string: A datetime string in ISO format (e.g., "2023-06-01T10:00:00Z")
19
-
20
- Returns:
21
- A formatted datetime string (e.g., "2023-06-01 10:00 AM") or the original string with
22
- "(All day)" appended if it's just a date
23
- """
24
- if not dt_string or dt_string == "Unknown":
25
- return "Unknown"
26
-
27
- # Check if it's just a date (all-day event) or a datetime
28
- if "T" in dt_string:
29
- # It's a datetime - parse and format it
30
- try:
31
- # Handle Z (UTC) suffix by replacing with +00:00 timezone
32
- if dt_string.endswith("Z"):
33
- dt_string = dt_string.replace("Z", "+00:00")
34
-
35
- # Parse the ISO datetime string
36
- dt = datetime.fromisoformat(dt_string)
37
-
38
- # Format to a more readable form
39
- return dt.strftime("%Y-%m-%d %I:%M %p")
40
- except ValueError:
41
- # In case of parsing error, return the original
42
- logger.warning(f"Could not parse datetime string: {dt_string}")
43
- return dt_string
44
- else:
45
- # It's just a date (all-day event)
46
- return f"{dt_string} (All day)"
47
-
48
- def get_today_events(
49
- self, days: int = 1, max_results: int = None, time_zone: str = None
50
- ) -> str:
51
- """
52
- Retrieves and formats events from Google Calendar for today or a specified number of future days, with optional result limiting and timezone specification.
53
-
54
- Args:
55
- days: Number of days to retrieve events for (default: 1, which is just today)
56
- max_results: Maximum number of events to return (optional)
57
- time_zone: Time zone used in the response (optional, default is calendar's time zone)
58
-
59
- Returns:
60
- A formatted string containing a list of calendar events with their times and IDs, or a message indicating no events were found
61
-
62
- Raises:
63
- HTTPError: Raised when the API request fails or returns an error status code
64
-
65
- Tags:
66
- fetch, list, calendar, events, date-time, important, api, formatting
67
- """
68
- today = datetime.utcnow().date()
69
- end_date = today + timedelta(days=days)
70
- time_min = f"{today.isoformat()}T00:00:00Z"
71
- time_max = f"{end_date.isoformat()}T00:00:00Z"
72
- url = f"{self.base_api_url}/events"
73
- params = {
74
- "timeMin": time_min,
75
- "timeMax": time_max,
76
- "singleEvents": "true",
77
- "orderBy": "startTime",
78
- }
79
- if max_results is not None:
80
- params["maxResults"] = max_results
81
- if time_zone:
82
- params["timeZone"] = time_zone
83
- date_range = "today" if days == 1 else f"the next {days} days"
84
- logger.info(f"Retrieving calendar events for {date_range}")
85
- response = self._get(url, params=params)
86
- response.raise_for_status()
87
- events = response.json().get("items", [])
88
- if not events:
89
- return f"No events scheduled for {date_range}."
90
- result = f"Events for {date_range}:\n\n"
91
- for event in events:
92
- # Extract event date and time
93
- start = event.get("start", {})
94
- event_date = (
95
- start.get("date", start.get("dateTime", "")).split("T")[0]
96
- if "T" in start.get("dateTime", "")
97
- else start.get("date", "")
98
- )
99
-
100
- # Extract and format time
101
- start_time = start.get("dateTime", start.get("date", "All day"))
102
-
103
- # Format the time display
104
- if "T" in start_time: # It's a datetime
105
- formatted_time = self._format_datetime(start_time)
106
- # For multi-day view, keep the date; for single day, just show time
107
- if days > 1:
108
- time_display = formatted_time
109
- else:
110
- # Extract just the time part
111
- time_display = (
112
- formatted_time.split(" ")[1]
113
- + " "
114
- + formatted_time.split(" ")[2]
115
- )
116
- else: # It's an all-day event
117
- time_display = f"{event_date} (All day)" if days > 1 else "All day"
118
-
119
- # Get event details
120
- summary = event.get("summary", "Untitled event")
121
- event_id = event.get("id", "No ID")
122
-
123
- result += f"- {time_display}: {summary} (ID: {event_id})\n"
124
- return result
125
-
126
- def get_event(
127
- self, event_id: str, max_attendees: int = None, time_zone: str = None
128
- ) -> str:
129
- """
130
- Retrieves and formats detailed information about a specific Google Calendar event by its ID
131
-
132
- Args:
133
- event_id: The unique identifier of the calendar event to retrieve
134
- max_attendees: Optional. The maximum number of attendees to include in the response. If None, includes all attendees
135
- time_zone: Optional. The time zone to use for formatting dates in the response. If None, uses the calendar's default time zone
136
-
137
- Returns:
138
- A formatted string containing comprehensive event details including summary, time, location, description, creator, organizer, recurrence status, and attendee information
139
-
140
- Raises:
141
- HTTPError: Raised when the API request fails or returns an error status code
142
- JSONDecodeError: Raised when the API response cannot be parsed as JSON
143
-
144
- Tags:
145
- retrieve, calendar, event, format, api, important
146
- """
147
- url = f"{self.base_api_url}/events/{event_id}"
148
- params = {}
149
- if max_attendees is not None:
150
- params["maxAttendees"] = max_attendees
151
- if time_zone:
152
- params["timeZone"] = time_zone
153
- logger.info(f"Retrieving calendar event with ID: {event_id}")
154
- response = self._get(url, params=params)
155
- response.raise_for_status()
156
- event = response.json()
157
- summary = event.get("summary", "Untitled event")
158
- description = event.get("description", "No description")
159
- location = event.get("location", "No location specified")
160
- start = event.get("start", {})
161
- end = event.get("end", {})
162
- start_time = start.get("dateTime", start.get("date", "Unknown"))
163
- end_time = end.get("dateTime", end.get("date", "Unknown"))
164
- start_formatted = self._format_datetime(start_time)
165
- end_formatted = self._format_datetime(end_time)
166
- creator = event.get("creator", {}).get("email", "Unknown")
167
- organizer = event.get("organizer", {}).get("email", "Unknown")
168
- recurrence = "Yes" if "recurrence" in event else "No"
169
- attendees = event.get("attendees", [])
170
- attendee_info = ""
171
- if attendees:
172
- attendee_info = "\nAttendees:\n"
173
- for i, attendee in enumerate(attendees, 1):
174
- email = attendee.get("email", "No email")
175
- name = attendee.get("displayName", email)
176
- response_status = attendee.get("responseStatus", "Unknown")
177
-
178
- status_mapping = {
179
- "accepted": "Accepted",
180
- "declined": "Declined",
181
- "tentative": "Maybe",
182
- "needsAction": "Not responded",
183
- }
184
-
185
- formatted_status = status_mapping.get(response_status, response_status)
186
- attendee_info += f" {i}. {name} ({email}) - {formatted_status}\n"
187
- result = f"Event: {summary}\n"
188
- result += f"ID: {event_id}\n"
189
- result += f"When: {start_formatted} to {end_formatted}\n"
190
- result += f"Where: {location}\n"
191
- result += f"Description: {description}\n"
192
- result += f"Creator: {creator}\n"
193
- result += f"Organizer: {organizer}\n"
194
- result += f"Recurring: {recurrence}\n"
195
- result += attendee_info
196
- return result
197
-
198
- def list_events(
199
- self,
200
- max_results: int = 10,
201
- time_min: str = None,
202
- time_max: str = None,
203
- q: str = None,
204
- order_by: str = "startTime",
205
- single_events: bool = True,
206
- time_zone: str = None,
207
- page_token: str = None,
208
- ) -> str:
209
- """
210
- Retrieves and formats a list of events from Google Calendar with customizable filtering, sorting, and pagination options
211
-
212
- Args:
213
- max_results: Maximum number of events to return (default: 10, max: 2500)
214
- time_min: Start time in ISO format (e.g., '2023-12-01T00:00:00Z'). Defaults to current time if not specified
215
- time_max: End time in ISO format (e.g., '2023-12-31T23:59:59Z')
216
- q: Free text search terms to filter events (searches across summary, description, location, attendees)
217
- order_by: Sort order for results - either 'startTime' (default) or 'updated'
218
- single_events: Whether to expand recurring events into individual instances (default: True)
219
- time_zone: Time zone for response formatting (defaults to calendar's time zone)
220
- page_token: Token for retrieving a specific page of results in paginated responses
221
-
222
- Returns:
223
- A formatted string containing the list of events with details including summary, ID, start time, and location, or a message if no events are found
224
-
225
- Raises:
226
- HTTPError: Raised when the API request fails or returns an error status code
227
-
228
- Tags:
229
- list, calendar, events, search, filter, pagination, format, important
230
- """
231
- url = f"{self.base_api_url}/events"
232
- params = {
233
- "maxResults": max_results,
234
- "singleEvents": str(single_events).lower(),
235
- "orderBy": order_by,
236
- }
237
- if time_min:
238
- params["timeMin"] = time_min
239
- else:
240
- # Default to current time if not specified
241
- now = datetime.utcnow().isoformat() + "Z" # 'Z' indicates UTC time
242
- params["timeMin"] = now
243
- if time_max:
244
- params["timeMax"] = time_max
245
- if q:
246
- params["q"] = q
247
- if time_zone:
248
- params["timeZone"] = time_zone
249
- if page_token:
250
- params["pageToken"] = page_token
251
- logger.info(f"Retrieving calendar events with params: {params}")
252
- response = self._get(url, params=params)
253
- response.raise_for_status()
254
- data = response.json()
255
- events = data.get("items", [])
256
- if not events:
257
- return "No events found matching your criteria."
258
- calendar_summary = data.get("summary", "Your Calendar")
259
- time_zone_info = data.get("timeZone", "Unknown")
260
- result = f"Events from {calendar_summary} (Time Zone: {time_zone_info}):\n\n"
261
- for i, event in enumerate(events, 1):
262
- # Get basic event details
263
- event_id = event.get("id", "No ID")
264
- summary = event.get("summary", "Untitled event")
265
-
266
- # Get event times and format them
267
- start = event.get("start", {})
268
- start_time = start.get("dateTime", start.get("date", "Unknown"))
269
-
270
- # Format the start time using the helper function
271
- start_formatted = self._format_datetime(start_time)
272
-
273
- # Get location if available
274
- location = event.get("location", "No location specified")
275
-
276
- # Check if it's a recurring event
277
- is_recurring = "recurrence" in event
278
- recurring_info = " (Recurring)" if is_recurring else ""
279
-
280
- # Format the event information
281
- result += f"{i}. {summary}{recurring_info}\n"
282
- result += f" ID: {event_id}\n"
283
- result += f" When: {start_formatted}\n"
284
- result += f" Where: {location}\n"
285
-
286
- # Add a separator between events
287
- if i < len(events):
288
- result += "\n"
289
- if "nextPageToken" in data:
290
- next_token = data.get("nextPageToken")
291
- result += (
292
- f"\nMore events available. Use page_token='{next_token}' to see more."
293
- )
294
- return result
295
-
296
- def quick_add_event(self, text: str, send_updates: str = "none") -> str:
297
- """
298
- Creates a calendar event using natural language text input and returns a formatted confirmation message with event details.
299
-
300
- Args:
301
- text: Natural language text describing the event (e.g., 'Meeting with John at Coffee Shop tomorrow 3pm-4pm')
302
- send_updates: Specifies who should receive event notifications: 'all', 'externalOnly', or 'none' (default)
303
-
304
- Returns:
305
- A formatted string containing the confirmation message with event details including summary, time, location, and event ID
306
-
307
- Raises:
308
- HTTPError: Raised when the API request fails or returns an error status code
309
-
310
- Tags:
311
- create, calendar, event, quick-add, natural-language, important
312
- """
313
- url = f"{self.base_api_url}/events/quickAdd"
314
- params = {"text": text, "sendUpdates": send_updates}
315
- logger.info(f"Creating event via quickAdd: '{text}'")
316
- response = self._post(url, data=None, params=params)
317
- response.raise_for_status()
318
- event = response.json()
319
- event_id = event.get("id", "Unknown")
320
- summary = event.get("summary", "Untitled event")
321
- start = event.get("start", {})
322
- end = event.get("end", {})
323
- start_time = start.get("dateTime", start.get("date", "Unknown"))
324
- end_time = end.get("dateTime", end.get("date", "Unknown"))
325
- start_formatted = self._format_datetime(start_time)
326
- end_formatted = self._format_datetime(end_time)
327
- location = event.get("location", "No location specified")
328
- result = "Successfully created event!\n\n"
329
- result += f"Summary: {summary}\n"
330
- result += f"When: {start_formatted}"
331
- if start_formatted != end_formatted:
332
- result += f" to {end_formatted}"
333
- result += f"\nWhere: {location}\n"
334
- result += f"Event ID: {event_id}\n"
335
- result += f"\nUse get_event('{event_id}') to see full details."
336
- return result
337
-
338
- def get_event_instances(
339
- self,
340
- event_id: str,
341
- max_results: int = 25,
342
- time_min: str = None,
343
- time_max: str = None,
344
- time_zone: str = None,
345
- show_deleted: bool = False,
346
- page_token: str = None,
347
- ) -> str:
348
- """
349
- Retrieves and formats all instances of a recurring calendar event within a specified time range, showing details like time, status, and modifications for each occurrence.
350
-
351
- Args:
352
- event_id: ID of the recurring event
353
- max_results: Maximum number of event instances to return (default: 25, max: 2500)
354
- time_min: Lower bound (inclusive) for event's end time in ISO format
355
- time_max: Upper bound (exclusive) for event's start time in ISO format
356
- time_zone: Time zone used in the response (defaults to calendar's time zone)
357
- show_deleted: Whether to include deleted instances (default: False)
358
- page_token: Token for retrieving a specific page of results
359
-
360
- Returns:
361
- A formatted string containing a list of event instances with details including time, status, instance ID, and modification information, plus pagination token if applicable.
362
-
363
- Raises:
364
- HTTPError: Raised when the API request fails or returns an error status code
365
- JSONDecodeError: Raised when the API response cannot be parsed as JSON
366
-
367
- Tags:
368
- list, retrieve, calendar, events, recurring, pagination, formatting, important
369
- """
370
- url = f"{self.base_api_url}/events/{event_id}/instances"
371
- params = {"maxResults": max_results, "showDeleted": str(show_deleted).lower()}
372
- if time_min:
373
- params["timeMin"] = time_min
374
- if time_max:
375
- params["timeMax"] = time_max
376
- if time_zone:
377
- params["timeZone"] = time_zone
378
- if page_token:
379
- params["pageToken"] = page_token
380
- logger.info(f"Retrieving instances of recurring event with ID: {event_id}")
381
- response = self._get(url, params=params)
382
- response.raise_for_status()
383
- data = response.json()
384
- instances = data.get("items", [])
385
- if not instances:
386
- return f"No instances found for recurring event with ID: {event_id}"
387
- parent_summary = instances[0].get("summary", "Untitled recurring event")
388
- result = f"Instances of recurring event: {parent_summary}\n\n"
389
- for i, instance in enumerate(instances, 1):
390
- # Get instance ID and status
391
- instance_id = instance.get("id", "No ID")
392
- status = instance.get("status", "confirmed")
393
-
394
- # Format status for display
395
- status_display = ""
396
- if status == "cancelled":
397
- status_display = " [CANCELLED]"
398
- elif status == "tentative":
399
- status_display = " [TENTATIVE]"
400
-
401
- # Get instance time
402
- start = instance.get("start", {})
403
- original_start_time = instance.get("originalStartTime", {})
404
-
405
- # Determine if this is a modified instance
406
- is_modified = original_start_time and "dateTime" in original_start_time
407
- modified_indicator = " [MODIFIED]" if is_modified else ""
408
-
409
- # Get the time information
410
- start_time = start.get("dateTime", start.get("date", "Unknown"))
411
-
412
- # Format the time using the helper function
413
- formatted_time = self._format_datetime(start_time)
414
-
415
- # Format the instance information
416
- result += f"{i}. {formatted_time}{status_display}{modified_indicator}\n"
417
- result += f" Instance ID: {instance_id}\n"
418
-
419
- # Show original start time if modified
420
- if is_modified:
421
- orig_time = original_start_time.get(
422
- "dateTime", original_start_time.get("date", "Unknown")
423
- )
424
- orig_formatted = self._format_datetime(orig_time)
425
- result += f" Original time: {orig_formatted}\n"
426
-
427
- # Add a separator between instances
428
- if i < len(instances):
429
- result += "\n"
430
- if "nextPageToken" in data:
431
- next_token = data.get("nextPageToken")
432
- result += f"\nMore instances available. Use page_token='{next_token}' to see more."
433
- return result
434
-
435
- def list_tools(self):
436
- return [
437
- self.get_event,
438
- self.get_today_events,
439
- self.list_events,
440
- self.quick_add_event,
441
- self.get_event_instances,
442
- ]
@@ -1,40 +0,0 @@
1
-
2
- # Google Docs MCP Server
3
-
4
- An MCP Server for the Google Docs API.
5
-
6
- ## Supported Integrations
7
-
8
- - AgentR
9
- - API Key (Coming Soon)
10
- - OAuth (Coming Soon)
11
-
12
- ## Tools
13
-
14
- This is automatically generated from OpenAPI schema for the Google Docs API.
15
-
16
- ## Supported Integrations
17
-
18
- This tool can be integrated with any service that supports HTTP requests.
19
-
20
- ## Tool List
21
-
22
- | Tool | Description |
23
- |------|-------------|
24
- | add_content | Adds text content to an existing Google Document. |
25
- | create_document | Creates a new blank Google Document with the specified title. |
26
- | get_document | Gets the latest version of the specified document. |
27
- | validate | Function for validate |
28
-
29
-
30
-
31
- ## Usage
32
-
33
- - Login to AgentR
34
- - Follow the quickstart guide to setup MCP Server for your client
35
- - Visit Apps Store and enable the Google Docs app
36
- - Restart the MCP Server
37
-
38
- ### Local Development
39
-
40
- - Follow the README to test with the local MCP Server
@@ -1,88 +0,0 @@
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 GoogleDocsApp(APIApplication):
8
- def __init__(self, integration: Integration) -> None:
9
- super().__init__(name="google-docs", integration=integration)
10
- self.base_api_url = "https://docs.googleapis.com/v1/documents"
11
-
12
- def create_document(self, title: str) -> dict[str, Any]:
13
- """
14
- Creates a new blank Google Document with the specified title and returns the API response.
15
-
16
- Args:
17
- title: The title for the new Google Document to be created
18
-
19
- Returns:
20
- A dictionary containing the Google Docs API response with document details and metadata
21
-
22
- Raises:
23
- HTTPError: If the API request fails due to network issues, authentication errors, or invalid parameters
24
- RequestException: If there are connection errors or timeout issues during the API request
25
-
26
- Tags:
27
- create, document, api, important, google-docs, http
28
- """
29
- url = self.base_api_url
30
- document_data = {"title": title}
31
- response = self._post(url, data=document_data)
32
- response.raise_for_status()
33
- return response.json()
34
-
35
- def get_document(self, document_id: str) -> dict[str, Any]:
36
- """
37
- Retrieves the latest version of a specified document from the Google Docs API.
38
-
39
- Args:
40
- document_id: The unique identifier of the document to retrieve
41
-
42
- Returns:
43
- A dictionary containing the document data from the Google Docs API response
44
-
45
- Raises:
46
- HTTPError: If the API request fails or the document is not found
47
- JSONDecodeError: If the API response cannot be parsed as JSON
48
-
49
- Tags:
50
- retrieve, read, api, document, google-docs, important
51
- """
52
- url = f"{self.base_api_url}/{document_id}"
53
- response = self._get(url)
54
- return response.json()
55
-
56
- def add_content(
57
- self, document_id: str, content: str, index: int = 1
58
- ) -> dict[str, Any]:
59
- """
60
- Adds text content at a specified position in an existing Google Document via the Google Docs API.
61
-
62
- Args:
63
- document_id: The unique identifier of the Google Document to be updated
64
- content: The text content to be inserted into the document
65
- index: The zero-based position in the document where the text should be inserted (default: 1)
66
-
67
- Returns:
68
- A dictionary containing the Google Docs API response after performing the batch update operation
69
-
70
- Raises:
71
- HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
72
- RequestException: When there are network connectivity issues or API endpoint problems
73
-
74
- Tags:
75
- update, insert, document, api, google-docs, batch, content-management, important
76
- """
77
- url = f"{self.base_api_url}/{document_id}:batchUpdate"
78
- batch_update_data = {
79
- "requests": [
80
- {"insertText": {"location": {"index": index}, "text": content}}
81
- ]
82
- }
83
- response = self._post(url, data=batch_update_data)
84
- response.raise_for_status()
85
- return response.json()
86
-
87
- def list_tools(self):
88
- return [self.create_document, self.get_document, self.add_content]
@@ -1,44 +0,0 @@
1
-
2
- # Google Drive MCP Server
3
-
4
- An MCP Server for the Google Drive API.
5
-
6
- ## Supported Integrations
7
-
8
- - AgentR
9
- - API Key (Coming Soon)
10
- - OAuth (Coming Soon)
11
-
12
- ## Tools
13
-
14
- This is automatically generated from OpenAPI schema for the Google Drive API.
15
-
16
- ## Supported Integrations
17
-
18
- This tool can be integrated with any service that supports HTTP requests.
19
-
20
- ## Tool List
21
-
22
- | Tool | Description |
23
- |------|-------------|
24
- | get_drive_info | Get information about the user's Google Drive, including storage quota and user info. |
25
- | list_files | List files in the user's Google Drive. |
26
- | create_file_from_text | Create a new file from text content in Google Drive. |
27
- | upload_a_file | Upload a file to Google Drive from a local binary file. |
28
- | find_folder_id_by_name | Find a folder's ID by its name. |
29
- | create_folder | Create a new folder in Google Drive. |
30
- | get_file | Get metadata for a specific file. |
31
- | delete_file | Delete a file from Google Drive. |
32
-
33
-
34
-
35
- ## Usage
36
-
37
- - Login to AgentR
38
- - Follow the quickstart guide to setup MCP Server for your client
39
- - Visit Apps Store and enable the Google Drive app
40
- - Restart the MCP Server
41
-
42
- ### Local Development
43
-
44
- - Follow the README to test with the local MCP Server