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
@@ -36,55 +36,73 @@ class GoogleDriveApp(APIApplication):
|
|
36
36
|
|
37
37
|
def get_drive_info(self) -> dict[str, Any]:
|
38
38
|
"""
|
39
|
-
|
40
|
-
|
39
|
+
Retrieves detailed information about the user's Google Drive storage and account.
|
40
|
+
|
41
41
|
Returns:
|
42
|
-
A dictionary containing information
|
43
|
-
|
42
|
+
A dictionary containing Drive information including storage quota (usage, limit) and user details (name, email, etc.).
|
43
|
+
|
44
|
+
Raises:
|
45
|
+
HTTPError: If the API request fails or returns an error status code
|
46
|
+
ConnectionError: If there are network connectivity issues
|
47
|
+
AuthenticationError: If the authentication credentials are invalid or expired
|
48
|
+
|
49
|
+
Tags:
|
50
|
+
get, info, storage, drive, quota, user, api, important
|
44
51
|
"""
|
45
52
|
url = f"{self.base_url}/about"
|
46
53
|
params = {"fields": "storageQuota,user"}
|
47
|
-
|
48
54
|
response = self._get(url, params=params)
|
49
55
|
return response.json()
|
50
56
|
|
51
|
-
def list_files(
|
57
|
+
def list_files(
|
58
|
+
self, page_size: int = 10, query: str = None, order_by: str = None
|
59
|
+
) -> dict[str, Any]:
|
52
60
|
"""
|
53
|
-
|
54
|
-
|
61
|
+
Lists and retrieves files from Google Drive with optional filtering, pagination, and sorting.
|
62
|
+
|
55
63
|
Args:
|
56
|
-
page_size: Maximum number of files to return (default: 10)
|
57
|
-
query:
|
58
|
-
order_by:
|
59
|
-
|
64
|
+
page_size: Maximum number of files to return per page (default: 10)
|
65
|
+
query: Optional search query string using Google Drive query syntax (e.g., "mimeType='image/jpeg'")
|
66
|
+
order_by: Optional field name to sort results by, with optional direction (e.g., "modifiedTime desc")
|
67
|
+
|
60
68
|
Returns:
|
61
|
-
|
69
|
+
Dictionary containing a list of files and metadata, including 'files' array and optional 'nextPageToken' for pagination
|
70
|
+
|
71
|
+
Raises:
|
72
|
+
HTTPError: Raised when the API request fails or returns an error status code
|
73
|
+
RequestException: Raised when network connectivity issues occur during the API request
|
74
|
+
|
75
|
+
Tags:
|
76
|
+
list, files, search, google-drive, pagination, important
|
62
77
|
"""
|
63
78
|
url = f"{self.base_url}/files"
|
64
79
|
params = {
|
65
80
|
"pageSize": page_size,
|
66
81
|
}
|
67
|
-
|
68
82
|
if query:
|
69
83
|
params["q"] = query
|
70
|
-
|
71
84
|
if order_by:
|
72
85
|
params["orderBy"] = order_by
|
73
|
-
|
74
86
|
response = self._get(url, params=params)
|
75
87
|
response.raise_for_status()
|
76
88
|
return response.json()
|
77
|
-
|
78
89
|
|
79
90
|
def get_file(self, file_id: str) -> dict[str, Any]:
|
80
91
|
"""
|
81
|
-
|
82
|
-
|
92
|
+
Retrieves detailed metadata for a specific file using its ID.
|
93
|
+
|
83
94
|
Args:
|
84
|
-
file_id:
|
85
|
-
|
95
|
+
file_id: String identifier of the file whose metadata should be retrieved
|
96
|
+
|
86
97
|
Returns:
|
87
|
-
|
98
|
+
Dictionary containing the file's metadata including properties such as name, size, type, and other attributes
|
99
|
+
|
100
|
+
Raises:
|
101
|
+
HTTPError: When the API request fails due to invalid file_id or network issues
|
102
|
+
JSONDecodeError: When the API response cannot be parsed as JSON
|
103
|
+
|
104
|
+
Tags:
|
105
|
+
retrieve, file, metadata, get, api, important
|
88
106
|
"""
|
89
107
|
url = f"{self.base_url}/files/{file_id}"
|
90
108
|
response = self._get(url)
|
@@ -92,13 +110,19 @@ class GoogleDriveApp(APIApplication):
|
|
92
110
|
|
93
111
|
def delete_file(self, file_id: str) -> dict[str, Any]:
|
94
112
|
"""
|
95
|
-
|
96
|
-
|
113
|
+
Deletes a specified file from Google Drive and returns a status message.
|
114
|
+
|
97
115
|
Args:
|
98
|
-
file_id: The
|
99
|
-
|
116
|
+
file_id: The unique identifier string of the file to be deleted from Google Drive
|
117
|
+
|
100
118
|
Returns:
|
101
|
-
A
|
119
|
+
A dictionary containing either a success message {'message': 'File deleted successfully'} or an error message {'error': 'error description'}
|
120
|
+
|
121
|
+
Raises:
|
122
|
+
Exception: When the DELETE request fails due to network issues, invalid file_id, insufficient permissions, or other API errors
|
123
|
+
|
124
|
+
Tags:
|
125
|
+
delete, file-management, google-drive, api, important
|
102
126
|
"""
|
103
127
|
url = f"{self.base_url}/files/{file_id}"
|
104
128
|
try:
|
@@ -106,108 +130,114 @@ class GoogleDriveApp(APIApplication):
|
|
106
130
|
return {"message": "File deleted successfully"}
|
107
131
|
except Exception as e:
|
108
132
|
return {"error": str(e)}
|
109
|
-
|
133
|
+
|
110
134
|
def create_file_from_text(
|
111
135
|
self,
|
112
136
|
file_name: str,
|
113
137
|
text_content: str,
|
114
138
|
parent_id: str = None,
|
115
|
-
mime_type: str = "text/plain"
|
139
|
+
mime_type: str = "text/plain",
|
116
140
|
) -> dict[str, Any]:
|
117
141
|
"""
|
118
|
-
|
119
|
-
|
142
|
+
Creates a new file in Google Drive with specified text content and returns the file's metadata.
|
143
|
+
|
120
144
|
Args:
|
121
145
|
file_name: Name of the file to create on Google Drive
|
122
146
|
text_content: Plain text content to be written to the file
|
123
|
-
parent_id: ID of the parent folder
|
124
|
-
mime_type: MIME type of the file (
|
125
|
-
|
147
|
+
parent_id: Optional ID of the parent folder where the file will be created
|
148
|
+
mime_type: MIME type of the file (defaults to 'text/plain')
|
149
|
+
|
126
150
|
Returns:
|
127
|
-
|
151
|
+
Dictionary containing metadata of the created file including ID, name, and other Google Drive file properties
|
152
|
+
|
153
|
+
Raises:
|
154
|
+
HTTPStatusError: Raised when the API request fails during file creation or content upload
|
155
|
+
UnicodeEncodeError: Raised when the text_content cannot be encoded in UTF-8
|
156
|
+
|
157
|
+
Tags:
|
158
|
+
create, file, upload, drive, text, important, storage, document
|
128
159
|
"""
|
129
|
-
metadata = {
|
130
|
-
"name": file_name,
|
131
|
-
"mimeType": mime_type
|
132
|
-
}
|
133
|
-
|
160
|
+
metadata = {"name": file_name, "mimeType": mime_type}
|
134
161
|
if parent_id:
|
135
162
|
metadata["parents"] = [parent_id]
|
136
|
-
|
137
163
|
create_url = f"{self.base_url}/files"
|
138
164
|
create_response = self._post(create_url, data=metadata)
|
139
165
|
file_data = create_response.json()
|
140
166
|
file_id = file_data.get("id")
|
141
|
-
|
142
|
-
# Step 2: Update the file with text content
|
143
167
|
upload_url = f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media"
|
144
168
|
upload_headers = self._get_headers()
|
145
169
|
upload_headers["Content-Type"] = f"{mime_type}; charset=utf-8"
|
146
|
-
|
147
170
|
upload_response = httpx.patch(
|
148
|
-
upload_url,
|
149
|
-
headers=upload_headers,
|
150
|
-
content=text_content.encode("utf-8")
|
171
|
+
upload_url, headers=upload_headers, content=text_content.encode("utf-8")
|
151
172
|
)
|
152
173
|
upload_response.raise_for_status()
|
153
|
-
|
154
174
|
response_data = upload_response.json()
|
155
175
|
return response_data
|
156
|
-
|
176
|
+
|
157
177
|
def find_folder_id_by_name(self, folder_name: str) -> str | None:
|
158
178
|
"""
|
159
|
-
|
160
|
-
|
179
|
+
Searches for and retrieves a Google Drive folder's ID using its name.
|
180
|
+
|
161
181
|
Args:
|
162
|
-
folder_name: The name of the folder to
|
163
|
-
|
182
|
+
folder_name: The name of the folder to search for in Google Drive
|
183
|
+
|
164
184
|
Returns:
|
165
|
-
The folder ID if found, None
|
185
|
+
str | None: The folder's ID if a matching folder is found, None if no folder is found or if an error occurs
|
186
|
+
|
187
|
+
Raises:
|
188
|
+
Exception: Caught internally and logged when API requests fail or response parsing errors occur
|
189
|
+
|
190
|
+
Tags:
|
191
|
+
search, find, google-drive, folder, query, api, utility
|
166
192
|
"""
|
167
193
|
query = f"mimeType='application/vnd.google-apps.folder' and name='{folder_name}' and trashed=false"
|
168
194
|
try:
|
169
195
|
response = self._get(
|
170
196
|
f"{self.base_url}/files",
|
171
|
-
params={"q": query, "fields": "files(id,name)"}
|
197
|
+
params={"q": query, "fields": "files(id,name)"},
|
172
198
|
)
|
173
199
|
files = response.json().get("files", [])
|
174
200
|
return files[0]["id"] if files else None
|
175
201
|
except Exception as e:
|
176
202
|
logger.error(f"Error finding folder ID by name: {e}")
|
177
203
|
return None
|
178
|
-
|
204
|
+
|
179
205
|
def create_folder(self, folder_name: str, parent_id: str = None) -> dict[str, Any]:
|
180
206
|
"""
|
181
|
-
|
182
|
-
|
207
|
+
Creates a new folder in Google Drive with optional parent folder specification
|
208
|
+
|
183
209
|
Args:
|
184
210
|
folder_name: Name of the folder to create
|
185
|
-
parent_id: ID of the parent folder
|
186
|
-
|
187
|
-
|
211
|
+
parent_id: ID or name of the parent folder. Can be either a folder ID string or a folder name that will be automatically looked up
|
212
|
+
|
188
213
|
Returns:
|
189
|
-
|
214
|
+
Dictionary containing the created folder's metadata including its ID, name, and other Drive-specific information
|
215
|
+
|
216
|
+
Raises:
|
217
|
+
ValueError: Raised when a parent folder name is provided but cannot be found in Google Drive
|
218
|
+
|
219
|
+
Tags:
|
220
|
+
create, folder, drive, storage, important, management
|
190
221
|
"""
|
191
222
|
import re
|
192
|
-
|
223
|
+
|
193
224
|
metadata = {
|
194
225
|
"name": folder_name,
|
195
|
-
"mimeType": "application/vnd.google-apps.folder"
|
226
|
+
"mimeType": "application/vnd.google-apps.folder",
|
196
227
|
}
|
197
|
-
|
198
228
|
if parent_id:
|
199
229
|
if not re.match(r"^[a-zA-Z0-9_-]{28,33}$", parent_id):
|
200
230
|
found_id = self.find_folder_id_by_name(parent_id)
|
201
231
|
if found_id:
|
202
232
|
metadata["parents"] = [found_id]
|
203
233
|
else:
|
204
|
-
raise ValueError(
|
234
|
+
raise ValueError(
|
235
|
+
f"Could not find parent folder with name: {parent_id}"
|
236
|
+
)
|
205
237
|
else:
|
206
238
|
metadata["parents"] = [parent_id]
|
207
|
-
|
208
239
|
url = f"{self.base_url}/files"
|
209
240
|
params = {"supportsAllDrives": "true"}
|
210
|
-
|
211
241
|
response = self._post(url, data=metadata, params=params)
|
212
242
|
return response.json()
|
213
243
|
|
@@ -216,53 +246,46 @@ class GoogleDriveApp(APIApplication):
|
|
216
246
|
file_name: str,
|
217
247
|
file_path: str,
|
218
248
|
parent_id: str = None,
|
219
|
-
mime_type: str = None
|
249
|
+
mime_type: str = None,
|
220
250
|
) -> dict[str, Any]:
|
221
251
|
"""
|
222
|
-
|
223
|
-
|
224
|
-
This method is suitable for files under 5MB in size. It automatically
|
225
|
-
reads the file from the provided path.
|
226
|
-
|
252
|
+
Uploads a file to Google Drive by creating a file metadata entry and uploading the binary content.
|
253
|
+
|
227
254
|
Args:
|
228
255
|
file_name: Name to give the file on Google Drive
|
229
256
|
file_path: Path to the local file to upload
|
230
|
-
parent_id: ID of the parent folder to create the file in
|
231
|
-
mime_type: MIME type of the file
|
232
|
-
|
233
|
-
|
257
|
+
parent_id: Optional ID of the parent folder to create the file in
|
258
|
+
mime_type: MIME type of the file (e.g., 'image/jpeg', 'image/png', 'application/pdf')
|
259
|
+
|
234
260
|
Returns:
|
235
|
-
|
261
|
+
Dictionary containing the uploaded file's metadata from Google Drive
|
262
|
+
|
263
|
+
Raises:
|
264
|
+
FileNotFoundError: When the specified file_path does not exist or is not accessible
|
265
|
+
HTTPError: When the API request fails or returns an error status code
|
266
|
+
IOError: When there are issues reading the file content
|
267
|
+
|
268
|
+
Tags:
|
269
|
+
upload, file-handling, google-drive, api, important, binary, storage
|
236
270
|
"""
|
237
|
-
|
238
|
-
|
239
|
-
metadata = {
|
240
|
-
"name": file_name,
|
241
|
-
"mimeType": mime_type
|
242
|
-
}
|
243
|
-
|
271
|
+
metadata = {"name": file_name, "mimeType": mime_type}
|
244
272
|
if parent_id:
|
245
273
|
metadata["parents"] = [parent_id]
|
246
|
-
|
247
274
|
create_url = f"{self.base_url}/files"
|
248
275
|
create_response = self._post(create_url, data=metadata)
|
249
276
|
file_data = create_response.json()
|
250
277
|
file_id = file_data.get("id")
|
251
|
-
|
252
|
-
with open(file_path, 'rb') as file_content:
|
278
|
+
with open(file_path, "rb") as file_content:
|
253
279
|
binary_content = file_content.read()
|
254
|
-
|
280
|
+
|
255
281
|
upload_url = f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media"
|
256
282
|
upload_headers = self._get_headers()
|
257
283
|
upload_headers["Content-Type"] = mime_type
|
258
|
-
|
284
|
+
|
259
285
|
upload_response = httpx.patch(
|
260
|
-
upload_url,
|
261
|
-
headers=upload_headers,
|
262
|
-
content=binary_content
|
286
|
+
upload_url, headers=upload_headers, content=binary_content
|
263
287
|
)
|
264
288
|
upload_response.raise_for_status()
|
265
|
-
|
266
289
|
response_data = upload_response.json()
|
267
290
|
return response_data
|
268
291
|
|
@@ -277,4 +300,4 @@ class GoogleDriveApp(APIApplication):
|
|
277
300
|
self.create_folder,
|
278
301
|
self.get_file,
|
279
302
|
self.delete_file,
|
280
|
-
]
|
303
|
+
]
|
@@ -30,15 +30,24 @@ class GoogleMailApp(APIApplication):
|
|
30
30
|
}
|
31
31
|
|
32
32
|
def send_email(self, to: str, subject: str, body: str) -> str:
|
33
|
-
"""
|
33
|
+
"""
|
34
|
+
Sends an email using the Gmail API and returns a confirmation or error message.
|
34
35
|
|
35
36
|
Args:
|
36
37
|
to: The email address of the recipient
|
37
|
-
subject: The subject of the email
|
38
|
-
body: The
|
38
|
+
subject: The subject line of the email
|
39
|
+
body: The main content of the email message
|
39
40
|
|
40
41
|
Returns:
|
41
|
-
A confirmation message
|
42
|
+
A string containing either a success confirmation message or an error description
|
43
|
+
|
44
|
+
Raises:
|
45
|
+
NotAuthorizedError: When Gmail API authentication is not valid or has expired
|
46
|
+
KeyError: When required configuration keys are missing
|
47
|
+
Exception: For any other unexpected errors during the email sending process
|
48
|
+
|
49
|
+
Tags:
|
50
|
+
send, email, api, communication, important
|
42
51
|
"""
|
43
52
|
try:
|
44
53
|
url = f"{self.base_api_url}/messages/send"
|
@@ -89,15 +98,24 @@ class GoogleMailApp(APIApplication):
|
|
89
98
|
raise
|
90
99
|
|
91
100
|
def create_draft(self, to: str, subject: str, body: str) -> str:
|
92
|
-
"""
|
101
|
+
"""
|
102
|
+
Creates a draft email message in Gmail using the Gmail API and returns a confirmation status.
|
93
103
|
|
94
104
|
Args:
|
95
105
|
to: The email address of the recipient
|
96
|
-
subject: The subject of the email
|
97
|
-
body: The
|
106
|
+
subject: The subject line of the draft email
|
107
|
+
body: The main content/message of the draft email
|
98
108
|
|
99
109
|
Returns:
|
100
|
-
A
|
110
|
+
A string containing either a success message with the draft ID or an error message describing the failure
|
111
|
+
|
112
|
+
Raises:
|
113
|
+
NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
|
114
|
+
KeyError: When required configuration keys are missing
|
115
|
+
Exception: For general API errors, network issues, or other unexpected problems
|
116
|
+
|
117
|
+
Tags:
|
118
|
+
create, email, draft, gmail, api, important
|
101
119
|
"""
|
102
120
|
try:
|
103
121
|
url = f"{self.base_api_url}/drafts"
|
@@ -129,13 +147,22 @@ class GoogleMailApp(APIApplication):
|
|
129
147
|
return f"Error creating draft: {type(e).__name__} - {str(e)}"
|
130
148
|
|
131
149
|
def send_draft(self, draft_id: str) -> str:
|
132
|
-
"""
|
150
|
+
"""
|
151
|
+
Sends an existing draft email using the Gmail API and returns a confirmation message.
|
133
152
|
|
134
153
|
Args:
|
135
|
-
draft_id: The
|
154
|
+
draft_id: The unique identifier of the Gmail draft to be sent
|
136
155
|
|
137
156
|
Returns:
|
138
|
-
A
|
157
|
+
A string containing either a success message with the sent message ID or an error message detailing the failure reason
|
158
|
+
|
159
|
+
Raises:
|
160
|
+
NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
|
161
|
+
KeyError: When required configuration keys are missing from the API response
|
162
|
+
Exception: For other unexpected errors during the API request or response handling
|
163
|
+
|
164
|
+
Tags:
|
165
|
+
send, email, api, communication, important, draft
|
139
166
|
"""
|
140
167
|
try:
|
141
168
|
url = f"{self.base_api_url}/drafts/send"
|
@@ -165,14 +192,23 @@ class GoogleMailApp(APIApplication):
|
|
165
192
|
return f"Error sending draft: {type(e).__name__} - {str(e)}"
|
166
193
|
|
167
194
|
def get_draft(self, draft_id: str, format: str = "full") -> str:
|
168
|
-
"""
|
195
|
+
"""
|
196
|
+
Retrieves and formats a specific draft email from Gmail by its ID
|
169
197
|
|
170
198
|
Args:
|
171
|
-
draft_id:
|
172
|
-
format:
|
199
|
+
draft_id: String identifier of the draft email to retrieve
|
200
|
+
format: Output format of the draft (options: minimal, full, raw, metadata). Defaults to 'full'
|
173
201
|
|
174
202
|
Returns:
|
175
|
-
|
203
|
+
A formatted string containing the draft email details (ID, recipient, subject) or an error message if retrieval fails
|
204
|
+
|
205
|
+
Raises:
|
206
|
+
NotAuthorizedError: When the user's Gmail authorization is invalid or expired
|
207
|
+
KeyError: When required configuration keys or response data fields are missing
|
208
|
+
Exception: For any other unexpected errors during draft retrieval
|
209
|
+
|
210
|
+
Tags:
|
211
|
+
retrieve, email, gmail, draft, api, format, important
|
176
212
|
"""
|
177
213
|
try:
|
178
214
|
url = f"{self.base_api_url}/drafts/{draft_id}"
|
@@ -223,15 +259,24 @@ class GoogleMailApp(APIApplication):
|
|
223
259
|
def list_drafts(
|
224
260
|
self, max_results: int = 20, q: str = None, include_spam_trash: bool = False
|
225
261
|
) -> str:
|
226
|
-
"""
|
262
|
+
"""
|
263
|
+
Retrieves and formats a list of email drafts from the user's Gmail mailbox with optional filtering and pagination.
|
227
264
|
|
228
265
|
Args:
|
229
266
|
max_results: Maximum number of drafts to return (max 500, default 20)
|
230
|
-
q: Search query to filter drafts
|
231
|
-
include_spam_trash:
|
267
|
+
q: Search query string to filter drafts using Gmail search syntax (default None)
|
268
|
+
include_spam_trash: Boolean flag to include drafts from spam and trash folders (default False)
|
232
269
|
|
233
270
|
Returns:
|
234
|
-
A formatted list of
|
271
|
+
A formatted string containing the list of draft IDs and count information, or an error message if the request fails
|
272
|
+
|
273
|
+
Raises:
|
274
|
+
NotAuthorizedError: When the Gmail API authentication is missing or invalid
|
275
|
+
KeyError: When required configuration keys are missing
|
276
|
+
Exception: For general errors during API communication or data processing
|
277
|
+
|
278
|
+
Tags:
|
279
|
+
list, email, drafts, gmail, api, search, query, pagination, important
|
235
280
|
"""
|
236
281
|
try:
|
237
282
|
url = f"{self.base_api_url}/drafts"
|
@@ -286,13 +331,22 @@ class GoogleMailApp(APIApplication):
|
|
286
331
|
return f"Error listing drafts: {type(e).__name__} - {str(e)}"
|
287
332
|
|
288
333
|
def get_message(self, message_id: str) -> str:
|
289
|
-
"""
|
334
|
+
"""
|
335
|
+
Retrieves and formats a specific email message from Gmail API by its ID, including sender, recipient, date, subject, and message preview.
|
290
336
|
|
291
337
|
Args:
|
292
|
-
message_id: The
|
338
|
+
message_id: The unique identifier of the Gmail message to retrieve
|
293
339
|
|
294
340
|
Returns:
|
295
|
-
|
341
|
+
A formatted string containing the message details (ID, From, To, Date, Subject, Preview) or an error message if the retrieval fails
|
342
|
+
|
343
|
+
Raises:
|
344
|
+
NotAuthorizedError: When the request lacks proper Gmail API authorization
|
345
|
+
KeyError: When required configuration keys or message fields are missing
|
346
|
+
Exception: For general API communication errors or unexpected issues
|
347
|
+
|
348
|
+
Tags:
|
349
|
+
retrieve, email, format, api, gmail, message, important
|
296
350
|
"""
|
297
351
|
try:
|
298
352
|
url = f"{self.base_api_url}/messages/{message_id}"
|
@@ -350,15 +404,24 @@ class GoogleMailApp(APIApplication):
|
|
350
404
|
def list_messages(
|
351
405
|
self, max_results: int = 20, q: str = None, include_spam_trash: bool = False
|
352
406
|
) -> str:
|
353
|
-
"""
|
407
|
+
"""
|
408
|
+
Retrieves and formats a list of messages from the user's Gmail mailbox with optional filtering and pagination support.
|
354
409
|
|
355
410
|
Args:
|
356
411
|
max_results: Maximum number of messages to return (max 500, default 20)
|
357
|
-
q: Search query to filter messages
|
358
|
-
include_spam_trash:
|
412
|
+
q: Search query string to filter messages using Gmail search syntax
|
413
|
+
include_spam_trash: Boolean flag to include messages from spam and trash folders (default False)
|
359
414
|
|
360
415
|
Returns:
|
361
|
-
A formatted list of
|
416
|
+
A formatted string containing the list of message IDs and thread IDs, or an error message if the operation fails
|
417
|
+
|
418
|
+
Raises:
|
419
|
+
NotAuthorizedError: When the Gmail API authentication is invalid or missing
|
420
|
+
KeyError: When required configuration keys are missing
|
421
|
+
Exception: For general API errors, network issues, or other unexpected problems
|
422
|
+
|
423
|
+
Tags:
|
424
|
+
list, messages, gmail, search, query, pagination, important
|
362
425
|
"""
|
363
426
|
try:
|
364
427
|
url = f"{self.base_api_url}/messages"
|
@@ -417,10 +480,21 @@ class GoogleMailApp(APIApplication):
|
|
417
480
|
return f"Error listing messages: {type(e).__name__} - {str(e)}"
|
418
481
|
|
419
482
|
def list_labels(self) -> str:
|
420
|
-
"""
|
483
|
+
"""
|
484
|
+
Retrieves and formats a list of all labels (both system and user-created) from the user's Gmail account, organizing them by type and sorting them alphabetically.
|
485
|
+
|
486
|
+
Args:
|
487
|
+
None: This method takes no arguments
|
421
488
|
|
422
489
|
Returns:
|
423
|
-
A formatted list of labels or an error message
|
490
|
+
A formatted string containing a list of Gmail labels categorized by type (system and user), with their IDs, or an error message if the operation fails.
|
491
|
+
|
492
|
+
Raises:
|
493
|
+
NotAuthorizedError: Raised when the user's Gmail authorization is invalid or missing
|
494
|
+
Exception: Raised when any other unexpected error occurs during the API request or data processing
|
495
|
+
|
496
|
+
Tags:
|
497
|
+
list, gmail, labels, fetch, organize, important, management
|
424
498
|
"""
|
425
499
|
try:
|
426
500
|
url = f"{self.base_api_url}/labels"
|
@@ -486,13 +560,21 @@ class GoogleMailApp(APIApplication):
|
|
486
560
|
return f"Error listing labels: {type(e).__name__} - {str(e)}"
|
487
561
|
|
488
562
|
def create_label(self, name: str) -> str:
|
489
|
-
"""
|
563
|
+
"""
|
564
|
+
Creates a new Gmail label with specified visibility settings and returns creation status details.
|
490
565
|
|
491
566
|
Args:
|
492
567
|
name: The display name of the label to create
|
493
568
|
|
494
569
|
Returns:
|
495
|
-
A
|
570
|
+
A formatted string containing the creation status, including the new label's name and ID if successful, or an error message if the creation fails
|
571
|
+
|
572
|
+
Raises:
|
573
|
+
NotAuthorizedError: Raised when the request lacks proper Gmail API authorization
|
574
|
+
Exception: Raised for any other unexpected errors during label creation
|
575
|
+
|
576
|
+
Tags:
|
577
|
+
create, label, gmail, management, important
|
496
578
|
"""
|
497
579
|
try:
|
498
580
|
url = f"{self.base_api_url}/labels"
|
@@ -531,13 +613,21 @@ class GoogleMailApp(APIApplication):
|
|
531
613
|
return f"Error creating label: {type(e).__name__} - {str(e)}"
|
532
614
|
|
533
615
|
def get_profile(self) -> str:
|
534
|
-
"""
|
616
|
+
"""
|
617
|
+
Retrieves and formats the user's Gmail profile information including email address, message count, thread count, and history ID.
|
535
618
|
|
536
|
-
|
537
|
-
|
619
|
+
Args:
|
620
|
+
None: This method takes no arguments besides self
|
538
621
|
|
539
622
|
Returns:
|
540
|
-
A formatted string containing the user's profile information or an error message
|
623
|
+
A formatted string containing the user's Gmail profile information or an error message if the request fails
|
624
|
+
|
625
|
+
Raises:
|
626
|
+
NotAuthorizedError: Raised when the user's credentials are invalid or authorization is required
|
627
|
+
Exception: Raised for any other unexpected errors during the API request or data processing
|
628
|
+
|
629
|
+
Tags:
|
630
|
+
fetch, profile, gmail, user-info, api-request, important
|
541
631
|
"""
|
542
632
|
try:
|
543
633
|
url = f"{self.base_api_url}/profile"
|