universal-mcp 0.1.8rc1__py3-none-any.whl → 0.1.8rc3__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.
- universal_mcp/__init__.py +0 -2
- universal_mcp/analytics.py +75 -0
- universal_mcp/applications/application.py +28 -5
- universal_mcp/applications/calendly/README.md +78 -0
- universal_mcp/applications/calendly/app.py +1207 -0
- universal_mcp/applications/coda/README.md +133 -0
- universal_mcp/applications/coda/__init__.py +0 -0
- universal_mcp/applications/coda/app.py +3704 -0
- universal_mcp/applications/e2b/app.py +12 -7
- universal_mcp/applications/firecrawl/app.py +27 -0
- universal_mcp/applications/github/app.py +127 -85
- universal_mcp/applications/google_calendar/app.py +62 -127
- universal_mcp/applications/google_docs/app.py +48 -35
- universal_mcp/applications/google_drive/app.py +119 -96
- universal_mcp/applications/google_mail/app.py +124 -34
- universal_mcp/applications/google_sheet/app.py +90 -74
- universal_mcp/applications/markitdown/app.py +9 -8
- universal_mcp/applications/notion/app.py +254 -134
- universal_mcp/applications/perplexity/app.py +16 -14
- universal_mcp/applications/reddit/app.py +94 -85
- universal_mcp/applications/resend/app.py +12 -5
- universal_mcp/applications/serpapi/app.py +11 -4
- universal_mcp/applications/tavily/app.py +11 -8
- universal_mcp/applications/wrike/README.md +71 -0
- universal_mcp/applications/wrike/__init__.py +0 -0
- universal_mcp/applications/wrike/app.py +1384 -0
- universal_mcp/applications/youtube/README.md +82 -0
- universal_mcp/applications/youtube/__init__.py +0 -0
- universal_mcp/applications/youtube/app.py +1446 -0
- universal_mcp/applications/zenquotes/app.py +12 -2
- universal_mcp/exceptions.py +9 -2
- universal_mcp/integrations/__init__.py +24 -1
- universal_mcp/integrations/integration.py +133 -28
- universal_mcp/logger.py +3 -56
- universal_mcp/servers/__init__.py +6 -14
- universal_mcp/servers/server.py +205 -150
- universal_mcp/stores/__init__.py +7 -2
- universal_mcp/stores/store.py +103 -40
- universal_mcp/tools/__init__.py +3 -0
- universal_mcp/tools/adapters.py +43 -0
- universal_mcp/tools/func_metadata.py +213 -0
- universal_mcp/tools/tools.py +342 -0
- universal_mcp/utils/docgen.py +325 -119
- universal_mcp/utils/docstring_parser.py +179 -0
- universal_mcp/utils/dump_app_tools.py +33 -23
- universal_mcp/utils/openapi.py +229 -46
- {universal_mcp-0.1.8rc1.dist-info → universal_mcp-0.1.8rc3.dist-info}/METADATA +8 -4
- universal_mcp-0.1.8rc3.dist-info/RECORD +75 -0
- universal_mcp-0.1.8rc1.dist-info/RECORD +0 -58
- /universal_mcp/{utils/bridge.py → applications/calendly/__init__.py} +0 -0
- {universal_mcp-0.1.8rc1.dist-info → universal_mcp-0.1.8rc3.dist-info}/WHEEL +0 -0
- {universal_mcp-0.1.8rc1.dist-info → universal_mcp-0.1.8rc3.dist-info}/entry_points.txt +0 -0
@@ -59,7 +59,8 @@ class GoogleCalendarApp(APIApplication):
|
|
59
59
|
def get_today_events(
|
60
60
|
self, days: int = 1, max_results: int = None, time_zone: str = None
|
61
61
|
) -> str:
|
62
|
-
"""
|
62
|
+
"""
|
63
|
+
Retrieves and formats events from Google Calendar for today or a specified number of future days, with optional result limiting and timezone specification.
|
63
64
|
|
64
65
|
Args:
|
65
66
|
days: Number of days to retrieve events for (default: 1, which is just today)
|
@@ -67,42 +68,36 @@ class GoogleCalendarApp(APIApplication):
|
|
67
68
|
time_zone: Time zone used in the response (optional, default is calendar's time zone)
|
68
69
|
|
69
70
|
Returns:
|
70
|
-
A formatted list of events or
|
71
|
+
A formatted string containing a list of calendar events with their times and IDs, or a message indicating no events were found
|
72
|
+
|
73
|
+
Raises:
|
74
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
75
|
+
|
76
|
+
Tags:
|
77
|
+
fetch, list, calendar, events, date-time, important, api, formatting
|
71
78
|
"""
|
72
|
-
# Get today's date in ISO format
|
73
79
|
today = datetime.utcnow().date()
|
74
80
|
end_date = today + timedelta(days=days)
|
75
|
-
|
76
|
-
# Format dates for API
|
77
81
|
time_min = f"{today.isoformat()}T00:00:00Z"
|
78
82
|
time_max = f"{end_date.isoformat()}T00:00:00Z"
|
79
|
-
|
80
83
|
url = f"{self.base_api_url}/events"
|
81
|
-
|
82
|
-
# Build query parameters
|
83
84
|
params = {
|
84
85
|
"timeMin": time_min,
|
85
86
|
"timeMax": time_max,
|
86
87
|
"singleEvents": "true",
|
87
88
|
"orderBy": "startTime",
|
88
89
|
}
|
89
|
-
|
90
90
|
if max_results is not None:
|
91
91
|
params["maxResults"] = max_results
|
92
|
-
|
93
92
|
if time_zone:
|
94
93
|
params["timeZone"] = time_zone
|
95
|
-
|
96
94
|
date_range = "today" if days == 1 else f"the next {days} days"
|
97
95
|
logger.info(f"Retrieving calendar events for {date_range}")
|
98
|
-
|
99
96
|
response = self._get(url, params=params)
|
100
97
|
response.raise_for_status()
|
101
|
-
|
102
98
|
events = response.json().get("items", [])
|
103
99
|
if not events:
|
104
100
|
return f"No events scheduled for {date_range}."
|
105
|
-
|
106
101
|
result = f"Events for {date_range}:\n\n"
|
107
102
|
for event in events:
|
108
103
|
# Extract event date and time
|
@@ -137,62 +132,51 @@ class GoogleCalendarApp(APIApplication):
|
|
137
132
|
event_id = event.get("id", "No ID")
|
138
133
|
|
139
134
|
result += f"- {time_display}: {summary} (ID: {event_id})\n"
|
140
|
-
|
141
135
|
return result
|
142
136
|
|
143
137
|
def get_event(
|
144
138
|
self, event_id: str, max_attendees: int = None, time_zone: str = None
|
145
139
|
) -> str:
|
146
|
-
"""
|
140
|
+
"""
|
141
|
+
Retrieves and formats detailed information about a specific Google Calendar event by its ID
|
147
142
|
|
148
143
|
Args:
|
149
|
-
event_id: The
|
150
|
-
max_attendees: Optional. The maximum number of attendees to include in the response
|
151
|
-
time_zone: Optional.
|
144
|
+
event_id: The unique identifier of the calendar event to retrieve
|
145
|
+
max_attendees: Optional. The maximum number of attendees to include in the response. If None, includes all attendees
|
146
|
+
time_zone: Optional. The time zone to use for formatting dates in the response. If None, uses the calendar's default time zone
|
152
147
|
|
153
148
|
Returns:
|
154
|
-
A formatted event details
|
149
|
+
A formatted string containing comprehensive event details including summary, time, location, description, creator, organizer, recurrence status, and attendee information
|
150
|
+
|
151
|
+
Raises:
|
152
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
153
|
+
JSONDecodeError: Raised when the API response cannot be parsed as JSON
|
154
|
+
|
155
|
+
Tags:
|
156
|
+
retrieve, calendar, event, format, api, important
|
155
157
|
"""
|
156
158
|
url = f"{self.base_api_url}/events/{event_id}"
|
157
|
-
|
158
|
-
# Build query parameters
|
159
159
|
params = {}
|
160
160
|
if max_attendees is not None:
|
161
161
|
params["maxAttendees"] = max_attendees
|
162
162
|
if time_zone:
|
163
163
|
params["timeZone"] = time_zone
|
164
|
-
|
165
164
|
logger.info(f"Retrieving calendar event with ID: {event_id}")
|
166
|
-
|
167
165
|
response = self._get(url, params=params)
|
168
166
|
response.raise_for_status()
|
169
|
-
|
170
167
|
event = response.json()
|
171
|
-
|
172
|
-
# Extract event details
|
173
168
|
summary = event.get("summary", "Untitled event")
|
174
169
|
description = event.get("description", "No description")
|
175
170
|
location = event.get("location", "No location specified")
|
176
|
-
|
177
|
-
# Format dates
|
178
171
|
start = event.get("start", {})
|
179
172
|
end = event.get("end", {})
|
180
|
-
|
181
173
|
start_time = start.get("dateTime", start.get("date", "Unknown"))
|
182
174
|
end_time = end.get("dateTime", end.get("date", "Unknown"))
|
183
|
-
|
184
|
-
# Format datetimes using the helper function
|
185
175
|
start_formatted = self._format_datetime(start_time)
|
186
176
|
end_formatted = self._format_datetime(end_time)
|
187
|
-
|
188
|
-
# Get creator and organizer
|
189
177
|
creator = event.get("creator", {}).get("email", "Unknown")
|
190
178
|
organizer = event.get("organizer", {}).get("email", "Unknown")
|
191
|
-
|
192
|
-
# Check if it's a recurring event
|
193
179
|
recurrence = "Yes" if "recurrence" in event else "No"
|
194
|
-
|
195
|
-
# Get attendees if any
|
196
180
|
attendees = event.get("attendees", [])
|
197
181
|
attendee_info = ""
|
198
182
|
if attendees:
|
@@ -211,8 +195,6 @@ class GoogleCalendarApp(APIApplication):
|
|
211
195
|
|
212
196
|
formatted_status = status_mapping.get(response_status, response_status)
|
213
197
|
attendee_info += f" {i}. {name} ({email}) - {formatted_status}\n"
|
214
|
-
|
215
|
-
# Format the response
|
216
198
|
result = f"Event: {summary}\n"
|
217
199
|
result += f"ID: {event_id}\n"
|
218
200
|
result += f"When: {start_formatted} to {end_formatted}\n"
|
@@ -222,7 +204,6 @@ class GoogleCalendarApp(APIApplication):
|
|
222
204
|
result += f"Organizer: {organizer}\n"
|
223
205
|
result += f"Recurring: {recurrence}\n"
|
224
206
|
result += attendee_info
|
225
|
-
|
226
207
|
return result
|
227
208
|
|
228
209
|
def list_events(
|
@@ -236,69 +217,58 @@ class GoogleCalendarApp(APIApplication):
|
|
236
217
|
time_zone: str = None,
|
237
218
|
page_token: str = None,
|
238
219
|
) -> str:
|
239
|
-
"""
|
220
|
+
"""
|
221
|
+
Retrieves and formats a list of events from Google Calendar with customizable filtering, sorting, and pagination options
|
240
222
|
|
241
223
|
Args:
|
242
224
|
max_results: Maximum number of events to return (default: 10, max: 2500)
|
243
|
-
time_min: Start time
|
244
|
-
time_max: End time
|
245
|
-
q: Free text search terms (searches summary, description, location, attendees
|
246
|
-
order_by:
|
247
|
-
single_events: Whether to expand recurring events (default: True)
|
248
|
-
time_zone: Time zone
|
249
|
-
page_token: Token for retrieving a specific page of results
|
225
|
+
time_min: Start time in ISO format (e.g., '2023-12-01T00:00:00Z'). Defaults to current time if not specified
|
226
|
+
time_max: End time in ISO format (e.g., '2023-12-31T23:59:59Z')
|
227
|
+
q: Free text search terms to filter events (searches across summary, description, location, attendees)
|
228
|
+
order_by: Sort order for results - either 'startTime' (default) or 'updated'
|
229
|
+
single_events: Whether to expand recurring events into individual instances (default: True)
|
230
|
+
time_zone: Time zone for response formatting (defaults to calendar's time zone)
|
231
|
+
page_token: Token for retrieving a specific page of results in paginated responses
|
250
232
|
|
251
233
|
Returns:
|
252
|
-
A formatted list of events or
|
234
|
+
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
|
235
|
+
|
236
|
+
Raises:
|
237
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
238
|
+
|
239
|
+
Tags:
|
240
|
+
list, calendar, events, search, filter, pagination, format, important
|
253
241
|
"""
|
254
242
|
url = f"{self.base_api_url}/events"
|
255
|
-
|
256
|
-
# Build query parameters
|
257
243
|
params = {
|
258
244
|
"maxResults": max_results,
|
259
245
|
"singleEvents": str(single_events).lower(),
|
260
246
|
"orderBy": order_by,
|
261
247
|
}
|
262
|
-
|
263
|
-
# Set time boundaries if provided, otherwise default to now for time_min
|
264
248
|
if time_min:
|
265
249
|
params["timeMin"] = time_min
|
266
250
|
else:
|
267
251
|
# Default to current time if not specified
|
268
252
|
now = datetime.utcnow().isoformat() + "Z" # 'Z' indicates UTC time
|
269
253
|
params["timeMin"] = now
|
270
|
-
|
271
254
|
if time_max:
|
272
255
|
params["timeMax"] = time_max
|
273
|
-
|
274
|
-
# Add optional filters if provided
|
275
256
|
if q:
|
276
257
|
params["q"] = q
|
277
|
-
|
278
258
|
if time_zone:
|
279
259
|
params["timeZone"] = time_zone
|
280
|
-
|
281
260
|
if page_token:
|
282
261
|
params["pageToken"] = page_token
|
283
|
-
|
284
262
|
logger.info(f"Retrieving calendar events with params: {params}")
|
285
|
-
|
286
263
|
response = self._get(url, params=params)
|
287
264
|
response.raise_for_status()
|
288
|
-
|
289
265
|
data = response.json()
|
290
266
|
events = data.get("items", [])
|
291
|
-
|
292
267
|
if not events:
|
293
268
|
return "No events found matching your criteria."
|
294
|
-
|
295
|
-
# Extract calendar information
|
296
269
|
calendar_summary = data.get("summary", "Your Calendar")
|
297
270
|
time_zone_info = data.get("timeZone", "Unknown")
|
298
|
-
|
299
271
|
result = f"Events from {calendar_summary} (Time Zone: {time_zone_info}):\n\n"
|
300
|
-
|
301
|
-
# Process and format each event
|
302
272
|
for i, event in enumerate(events, 1):
|
303
273
|
# Get basic event details
|
304
274
|
event_id = event.get("id", "No ID")
|
@@ -327,75 +297,53 @@ class GoogleCalendarApp(APIApplication):
|
|
327
297
|
# Add a separator between events
|
328
298
|
if i < len(events):
|
329
299
|
result += "\n"
|
330
|
-
|
331
|
-
# Add pagination info if available
|
332
300
|
if "nextPageToken" in data:
|
333
301
|
next_token = data.get("nextPageToken")
|
334
302
|
result += (
|
335
303
|
f"\nMore events available. Use page_token='{next_token}' to see more."
|
336
304
|
)
|
337
|
-
|
338
305
|
return result
|
339
306
|
|
340
307
|
def quick_add_event(self, text: str, send_updates: str = "none") -> str:
|
341
|
-
"""
|
342
|
-
|
343
|
-
This method allows you to quickly create an event using a simple text string,
|
344
|
-
similar to how you would add events in the Google Calendar UI.
|
308
|
+
"""
|
309
|
+
Creates a calendar event using natural language text input and returns a formatted confirmation message with event details.
|
345
310
|
|
346
311
|
Args:
|
347
|
-
text:
|
348
|
-
send_updates:
|
312
|
+
text: Natural language text describing the event (e.g., 'Meeting with John at Coffee Shop tomorrow 3pm-4pm')
|
313
|
+
send_updates: Specifies who should receive event notifications: 'all', 'externalOnly', or 'none' (default)
|
349
314
|
|
350
315
|
Returns:
|
351
|
-
A confirmation message with
|
316
|
+
A formatted string containing the confirmation message with event details including summary, time, location, and event ID
|
317
|
+
|
318
|
+
Raises:
|
319
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
320
|
+
|
321
|
+
Tags:
|
322
|
+
create, calendar, event, quick-add, natural-language, important
|
352
323
|
"""
|
353
324
|
url = f"{self.base_api_url}/events/quickAdd"
|
354
|
-
|
355
|
-
# Use params argument instead of manually constructing URL
|
356
325
|
params = {"text": text, "sendUpdates": send_updates}
|
357
|
-
|
358
326
|
logger.info(f"Creating event via quickAdd: '{text}'")
|
359
|
-
|
360
|
-
# Pass params to _post method
|
361
327
|
response = self._post(url, data=None, params=params)
|
362
328
|
response.raise_for_status()
|
363
|
-
|
364
329
|
event = response.json()
|
365
|
-
|
366
|
-
# Extract event details
|
367
330
|
event_id = event.get("id", "Unknown")
|
368
331
|
summary = event.get("summary", "Untitled event")
|
369
|
-
|
370
|
-
# Format dates
|
371
332
|
start = event.get("start", {})
|
372
333
|
end = event.get("end", {})
|
373
|
-
|
374
334
|
start_time = start.get("dateTime", start.get("date", "Unknown"))
|
375
335
|
end_time = end.get("dateTime", end.get("date", "Unknown"))
|
376
|
-
|
377
|
-
# Format datetimes using the helper function
|
378
336
|
start_formatted = self._format_datetime(start_time)
|
379
337
|
end_formatted = self._format_datetime(end_time)
|
380
|
-
|
381
|
-
# Get location if available
|
382
338
|
location = event.get("location", "No location specified")
|
383
|
-
|
384
|
-
# Format the confirmation message
|
385
339
|
result = "Successfully created event!\n\n"
|
386
340
|
result += f"Summary: {summary}\n"
|
387
341
|
result += f"When: {start_formatted}"
|
388
|
-
|
389
|
-
# Only add end time if it's different from start (for all-day events they might be the same)
|
390
342
|
if start_formatted != end_formatted:
|
391
343
|
result += f" to {end_formatted}"
|
392
|
-
|
393
344
|
result += f"\nWhere: {location}\n"
|
394
345
|
result += f"Event ID: {event_id}\n"
|
395
|
-
|
396
|
-
# Add a note about viewing the event
|
397
346
|
result += f"\nUse get_event('{event_id}') to see full details."
|
398
|
-
|
399
347
|
return result
|
400
348
|
|
401
349
|
def get_event_instances(
|
@@ -408,57 +356,47 @@ class GoogleCalendarApp(APIApplication):
|
|
408
356
|
show_deleted: bool = False,
|
409
357
|
page_token: str = None,
|
410
358
|
) -> str:
|
411
|
-
"""
|
412
|
-
|
413
|
-
This method retrieves all occurrences of a recurring event within a specified time range.
|
359
|
+
"""
|
360
|
+
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.
|
414
361
|
|
415
362
|
Args:
|
416
363
|
event_id: ID of the recurring event
|
417
364
|
max_results: Maximum number of event instances to return (default: 25, max: 2500)
|
418
|
-
time_min: Lower bound (inclusive) for event's end time
|
419
|
-
time_max: Upper bound (exclusive) for event's start time
|
420
|
-
time_zone: Time zone used in the response (
|
365
|
+
time_min: Lower bound (inclusive) for event's end time in ISO format
|
366
|
+
time_max: Upper bound (exclusive) for event's start time in ISO format
|
367
|
+
time_zone: Time zone used in the response (defaults to calendar's time zone)
|
421
368
|
show_deleted: Whether to include deleted instances (default: False)
|
422
369
|
page_token: Token for retrieving a specific page of results
|
423
370
|
|
424
371
|
Returns:
|
425
|
-
A formatted list of event instances
|
372
|
+
A formatted string containing a list of event instances with details including time, status, instance ID, and modification information, plus pagination token if applicable.
|
373
|
+
|
374
|
+
Raises:
|
375
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
376
|
+
JSONDecodeError: Raised when the API response cannot be parsed as JSON
|
377
|
+
|
378
|
+
Tags:
|
379
|
+
list, retrieve, calendar, events, recurring, pagination, formatting, important
|
426
380
|
"""
|
427
381
|
url = f"{self.base_api_url}/events/{event_id}/instances"
|
428
|
-
|
429
|
-
# Build query parameters
|
430
382
|
params = {"maxResults": max_results, "showDeleted": str(show_deleted).lower()}
|
431
|
-
|
432
|
-
# Add optional parameters if provided
|
433
383
|
if time_min:
|
434
384
|
params["timeMin"] = time_min
|
435
|
-
|
436
385
|
if time_max:
|
437
386
|
params["timeMax"] = time_max
|
438
|
-
|
439
387
|
if time_zone:
|
440
388
|
params["timeZone"] = time_zone
|
441
|
-
|
442
389
|
if page_token:
|
443
390
|
params["pageToken"] = page_token
|
444
|
-
|
445
391
|
logger.info(f"Retrieving instances of recurring event with ID: {event_id}")
|
446
|
-
|
447
392
|
response = self._get(url, params=params)
|
448
393
|
response.raise_for_status()
|
449
|
-
|
450
394
|
data = response.json()
|
451
395
|
instances = data.get("items", [])
|
452
|
-
|
453
396
|
if not instances:
|
454
397
|
return f"No instances found for recurring event with ID: {event_id}"
|
455
|
-
|
456
|
-
# Extract event summary from the first instance
|
457
398
|
parent_summary = instances[0].get("summary", "Untitled recurring event")
|
458
|
-
|
459
399
|
result = f"Instances of recurring event: {parent_summary}\n\n"
|
460
|
-
|
461
|
-
# Process and format each instance
|
462
400
|
for i, instance in enumerate(instances, 1):
|
463
401
|
# Get instance ID and status
|
464
402
|
instance_id = instance.get("id", "No ID")
|
@@ -500,12 +438,9 @@ class GoogleCalendarApp(APIApplication):
|
|
500
438
|
# Add a separator between instances
|
501
439
|
if i < len(instances):
|
502
440
|
result += "\n"
|
503
|
-
|
504
|
-
# Add pagination info if available
|
505
441
|
if "nextPageToken" in data:
|
506
442
|
next_token = data.get("nextPageToken")
|
507
443
|
result += f"\nMore instances available. Use page_token='{next_token}' to see more."
|
508
|
-
|
509
444
|
return result
|
510
445
|
|
511
446
|
def list_tools(self):
|
@@ -11,7 +11,7 @@ class GoogleDocsApp(APIApplication):
|
|
11
11
|
def __init__(self, integration: Integration) -> None:
|
12
12
|
super().__init__(name="google-docs", integration=integration)
|
13
13
|
self.base_api_url = "https://docs.googleapis.com/v1/documents"
|
14
|
-
|
14
|
+
|
15
15
|
def _get_headers(self):
|
16
16
|
if not self.integration:
|
17
17
|
raise ValueError("Integration not configured for GoogleDocsApp")
|
@@ -26,68 +26,81 @@ class GoogleDocsApp(APIApplication):
|
|
26
26
|
"Authorization": f"Bearer {credentials['access_token']}",
|
27
27
|
"Content-Type": "application/json",
|
28
28
|
}
|
29
|
-
|
29
|
+
|
30
30
|
def create_document(self, title: str) -> dict[str, Any]:
|
31
31
|
"""
|
32
|
-
Creates a new blank Google Document with the specified title.
|
33
|
-
|
32
|
+
Creates a new blank Google Document with the specified title and returns the API response.
|
33
|
+
|
34
34
|
Args:
|
35
|
-
title: The title
|
36
|
-
|
35
|
+
title: The title for the new Google Document to be created
|
36
|
+
|
37
37
|
Returns:
|
38
|
-
|
38
|
+
A dictionary containing the Google Docs API response with document details and metadata
|
39
|
+
|
40
|
+
Raises:
|
41
|
+
HTTPError: If the API request fails due to network issues, authentication errors, or invalid parameters
|
42
|
+
RequestException: If there are connection errors or timeout issues during the API request
|
43
|
+
|
44
|
+
Tags:
|
45
|
+
create, document, api, important, google-docs, http
|
39
46
|
"""
|
40
47
|
url = self.base_api_url
|
41
48
|
document_data = {"title": title}
|
42
49
|
response = self._post(url, data=document_data)
|
43
50
|
response.raise_for_status()
|
44
51
|
return response.json()
|
45
|
-
|
52
|
+
|
46
53
|
def get_document(self, document_id: str) -> dict[str, Any]:
|
47
54
|
"""
|
48
|
-
|
49
|
-
|
55
|
+
Retrieves the latest version of a specified document from the Google Docs API.
|
56
|
+
|
50
57
|
Args:
|
51
|
-
document_id: The
|
52
|
-
|
58
|
+
document_id: The unique identifier of the document to retrieve
|
59
|
+
|
53
60
|
Returns:
|
54
|
-
|
61
|
+
A dictionary containing the document data from the Google Docs API response
|
62
|
+
|
63
|
+
Raises:
|
64
|
+
HTTPError: If the API request fails or the document is not found
|
65
|
+
JSONDecodeError: If the API response cannot be parsed as JSON
|
66
|
+
|
67
|
+
Tags:
|
68
|
+
retrieve, read, api, document, google-docs, important
|
55
69
|
"""
|
56
70
|
url = f"{self.base_api_url}/{document_id}"
|
57
71
|
response = self._get(url)
|
58
72
|
return response.json()
|
59
|
-
|
60
|
-
def add_content(
|
73
|
+
|
74
|
+
def add_content(
|
75
|
+
self, document_id: str, content: str, index: int = 1
|
76
|
+
) -> dict[str, Any]:
|
61
77
|
"""
|
62
|
-
Adds text content
|
63
|
-
|
78
|
+
Adds text content at a specified position in an existing Google Document via the Google Docs API.
|
79
|
+
|
64
80
|
Args:
|
65
|
-
document_id: The
|
66
|
-
content: The text content to
|
67
|
-
index: The position
|
68
|
-
|
81
|
+
document_id: The unique identifier of the Google Document to be updated
|
82
|
+
content: The text content to be inserted into the document
|
83
|
+
index: The zero-based position in the document where the text should be inserted (default: 1)
|
84
|
+
|
69
85
|
Returns:
|
70
|
-
|
86
|
+
A dictionary containing the Google Docs API response after performing the batch update operation
|
87
|
+
|
88
|
+
Raises:
|
89
|
+
HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
|
90
|
+
RequestException: When there are network connectivity issues or API endpoint problems
|
91
|
+
|
92
|
+
Tags:
|
93
|
+
update, insert, document, api, google-docs, batch, content-management, important
|
71
94
|
"""
|
72
95
|
url = f"{self.base_api_url}/{document_id}:batchUpdate"
|
73
96
|
batch_update_data = {
|
74
97
|
"requests": [
|
75
|
-
{
|
76
|
-
"insertText": {
|
77
|
-
"location": {"index": index},
|
78
|
-
"text": content
|
79
|
-
}
|
80
|
-
}
|
98
|
+
{"insertText": {"location": {"index": index}, "text": content}}
|
81
99
|
]
|
82
100
|
}
|
83
|
-
|
84
101
|
response = self._post(url, data=batch_update_data)
|
85
102
|
response.raise_for_status()
|
86
103
|
return response.json()
|
87
|
-
|
104
|
+
|
88
105
|
def list_tools(self):
|
89
|
-
return [
|
90
|
-
self.create_document,
|
91
|
-
self.get_document,
|
92
|
-
self.add_content
|
93
|
-
]
|
106
|
+
return [self.create_document, self.get_document, self.add_content]
|