universal-mcp 0.1.7rc1__py3-none-any.whl → 0.1.8__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/ahrefs/README.md +76 -0
 - universal_mcp/applications/ahrefs/app.py +2291 -0
 - universal_mcp/applications/application.py +95 -5
 - universal_mcp/applications/calendly/README.md +78 -0
 - universal_mcp/applications/calendly/__init__.py +0 -0
 - universal_mcp/applications/calendly/app.py +1195 -0
 - universal_mcp/applications/coda/README.md +133 -0
 - universal_mcp/applications/coda/__init__.py +0 -0
 - universal_mcp/applications/coda/app.py +3671 -0
 - universal_mcp/applications/e2b/app.py +14 -28
 - universal_mcp/applications/figma/README.md +74 -0
 - universal_mcp/applications/figma/__init__.py +0 -0
 - universal_mcp/applications/figma/app.py +1261 -0
 - universal_mcp/applications/firecrawl/app.py +38 -35
 - universal_mcp/applications/github/app.py +127 -85
 - universal_mcp/applications/google_calendar/app.py +62 -138
 - universal_mcp/applications/google_docs/app.py +47 -52
 - universal_mcp/applications/google_drive/app.py +119 -113
 - universal_mcp/applications/google_mail/app.py +124 -50
 - universal_mcp/applications/google_sheet/app.py +89 -91
 - universal_mcp/applications/markitdown/app.py +9 -8
 - universal_mcp/applications/notion/app.py +254 -134
 - universal_mcp/applications/perplexity/app.py +13 -41
 - universal_mcp/applications/reddit/app.py +94 -85
 - universal_mcp/applications/resend/app.py +12 -13
 - universal_mcp/applications/{serp → serpapi}/app.py +14 -25
 - universal_mcp/applications/tavily/app.py +11 -18
 - universal_mcp/applications/wrike/README.md +71 -0
 - universal_mcp/applications/wrike/__init__.py +0 -0
 - universal_mcp/applications/wrike/app.py +1372 -0
 - universal_mcp/applications/youtube/README.md +82 -0
 - universal_mcp/applications/youtube/__init__.py +0 -0
 - universal_mcp/applications/youtube/app.py +1428 -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/agentr.py +27 -4
 - universal_mcp/integrations/integration.py +146 -32
 - universal_mcp/logger.py +3 -56
 - universal_mcp/servers/__init__.py +6 -14
 - universal_mcp/servers/server.py +201 -146
 - 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/installation.py +201 -10
 - universal_mcp/utils/openapi.py +229 -46
 - {universal_mcp-0.1.7rc1.dist-info → universal_mcp-0.1.8.dist-info}/METADATA +9 -5
 - universal_mcp-0.1.8.dist-info/RECORD +81 -0
 - universal_mcp-0.1.7rc1.dist-info/RECORD +0 -58
 - /universal_mcp/{utils/bridge.py → applications/ahrefs/__init__.py} +0 -0
 - /universal_mcp/applications/{serp → serpapi}/README.md +0 -0
 - {universal_mcp-0.1.7rc1.dist-info → universal_mcp-0.1.8.dist-info}/WHEEL +0 -0
 - {universal_mcp-0.1.7rc1.dist-info → universal_mcp-0.1.8.dist-info}/entry_points.txt +0 -0
 
| 
         @@ -4,7 +4,6 @@ import httpx 
     | 
|
| 
       4 
4 
     | 
    
         
             
            from loguru import logger
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            from universal_mcp.applications.application import APIApplication
         
     | 
| 
       7 
     | 
    
         
            -
            from universal_mcp.exceptions import NotAuthorizedError
         
     | 
| 
       8 
7 
     | 
    
         
             
            from universal_mcp.integrations import Integration
         
     | 
| 
       9 
8 
     | 
    
         | 
| 
       10 
9 
     | 
    
         | 
| 
         @@ -18,73 +17,75 @@ class GoogleDriveApp(APIApplication): 
     | 
|
| 
       18 
17 
     | 
    
         
             
                    super().__init__(name="google-drive", integration=integration)
         
     | 
| 
       19 
18 
     | 
    
         
             
                    self.base_url = "https://www.googleapis.com/drive/v3"
         
     | 
| 
       20 
19 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                def _get_headers(self):
         
     | 
| 
       22 
     | 
    
         
            -
                    if not self.integration:
         
     | 
| 
       23 
     | 
    
         
            -
                        raise ValueError("Integration not configured for GoogleDriveApp")
         
     | 
| 
       24 
     | 
    
         
            -
                    credentials = self.integration.get_credentials()
         
     | 
| 
       25 
     | 
    
         
            -
                    if not credentials:
         
     | 
| 
       26 
     | 
    
         
            -
                        logger.warning("No Google Drive credentials found via integration.")
         
     | 
| 
       27 
     | 
    
         
            -
                        action = self.integration.authorize()
         
     | 
| 
       28 
     | 
    
         
            -
                        raise NotAuthorizedError(action)
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                    if "headers" in credentials:
         
     | 
| 
       31 
     | 
    
         
            -
                        return credentials["headers"]
         
     | 
| 
       32 
     | 
    
         
            -
                    return {
         
     | 
| 
       33 
     | 
    
         
            -
                        "Authorization": f"Bearer {credentials['access_token']}",
         
     | 
| 
       34 
     | 
    
         
            -
                        "Content-Type": "application/json",
         
     | 
| 
       35 
     | 
    
         
            -
                    }
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
20 
     | 
    
         
             
                def get_drive_info(self) -> dict[str, Any]:
         
     | 
| 
       38 
21 
     | 
    
         
             
                    """
         
     | 
| 
       39 
     | 
    
         
            -
                     
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                    Retrieves detailed information about the user's Google Drive storage and account.
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       41 
24 
     | 
    
         
             
                    Returns:
         
     | 
| 
       42 
     | 
    
         
            -
                        A dictionary containing information  
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
                        A dictionary containing Drive information including storage quota (usage, limit) and user details (name, email, etc.).
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 28 
     | 
    
         
            +
                        HTTPError: If the API request fails or returns an error status code
         
     | 
| 
      
 29 
     | 
    
         
            +
                        ConnectionError: If there are network connectivity issues
         
     | 
| 
      
 30 
     | 
    
         
            +
                        AuthenticationError: If the authentication credentials are invalid or expired
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 33 
     | 
    
         
            +
                        get, info, storage, drive, quota, user, api, important
         
     | 
| 
       44 
34 
     | 
    
         
             
                    """
         
     | 
| 
       45 
35 
     | 
    
         
             
                    url = f"{self.base_url}/about"
         
     | 
| 
       46 
36 
     | 
    
         
             
                    params = {"fields": "storageQuota,user"}
         
     | 
| 
       47 
     | 
    
         
            -
                    
         
     | 
| 
       48 
37 
     | 
    
         
             
                    response = self._get(url, params=params)
         
     | 
| 
       49 
38 
     | 
    
         
             
                    return response.json()
         
     | 
| 
       50 
39 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                def list_files( 
     | 
| 
      
 40 
     | 
    
         
            +
                def list_files(
         
     | 
| 
      
 41 
     | 
    
         
            +
                    self, page_size: int = 10, query: str = None, order_by: str = None
         
     | 
| 
      
 42 
     | 
    
         
            +
                ) -> dict[str, Any]:
         
     | 
| 
       52 
43 
     | 
    
         
             
                    """
         
     | 
| 
       53 
     | 
    
         
            -
                     
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                    Lists and retrieves files from Google Drive with optional filtering, pagination, and sorting.
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       55 
46 
     | 
    
         
             
                    Args:
         
     | 
| 
       56 
     | 
    
         
            -
                        page_size: Maximum number of files to return (default: 10)
         
     | 
| 
       57 
     | 
    
         
            -
                        query:  
     | 
| 
       58 
     | 
    
         
            -
                        order_by:  
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 47 
     | 
    
         
            +
                        page_size: Maximum number of files to return per page (default: 10)
         
     | 
| 
      
 48 
     | 
    
         
            +
                        query: Optional search query string using Google Drive query syntax (e.g., "mimeType='image/jpeg'")
         
     | 
| 
      
 49 
     | 
    
         
            +
                        order_by: Optional field name to sort results by, with optional direction (e.g., "modifiedTime desc")
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
       60 
51 
     | 
    
         
             
                    Returns:
         
     | 
| 
       61 
     | 
    
         
            -
                         
     | 
| 
      
 52 
     | 
    
         
            +
                        Dictionary containing a list of files and metadata, including 'files' array and optional 'nextPageToken' for pagination
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 55 
     | 
    
         
            +
                        HTTPError: Raised when the API request fails or returns an error status code
         
     | 
| 
      
 56 
     | 
    
         
            +
                        RequestException: Raised when network connectivity issues occur during the API request
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 59 
     | 
    
         
            +
                        list, files, search, google-drive, pagination, important
         
     | 
| 
       62 
60 
     | 
    
         
             
                    """
         
     | 
| 
       63 
61 
     | 
    
         
             
                    url = f"{self.base_url}/files"
         
     | 
| 
       64 
62 
     | 
    
         
             
                    params = {
         
     | 
| 
       65 
63 
     | 
    
         
             
                        "pageSize": page_size,
         
     | 
| 
       66 
64 
     | 
    
         
             
                    }
         
     | 
| 
       67 
     | 
    
         
            -
                    
         
     | 
| 
       68 
65 
     | 
    
         
             
                    if query:
         
     | 
| 
       69 
66 
     | 
    
         
             
                        params["q"] = query
         
     | 
| 
       70 
     | 
    
         
            -
                    
         
     | 
| 
       71 
67 
     | 
    
         
             
                    if order_by:
         
     | 
| 
       72 
68 
     | 
    
         
             
                        params["orderBy"] = order_by
         
     | 
| 
       73 
     | 
    
         
            -
                    
         
     | 
| 
       74 
69 
     | 
    
         
             
                    response = self._get(url, params=params)
         
     | 
| 
       75 
70 
     | 
    
         
             
                    response.raise_for_status()
         
     | 
| 
       76 
71 
     | 
    
         
             
                    return response.json()
         
     | 
| 
       77 
     | 
    
         
            -
                
         
     | 
| 
       78 
72 
     | 
    
         | 
| 
       79 
73 
     | 
    
         
             
                def get_file(self, file_id: str) -> dict[str, Any]:
         
     | 
| 
       80 
74 
     | 
    
         
             
                    """
         
     | 
| 
       81 
     | 
    
         
            -
                     
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
      
 75 
     | 
    
         
            +
                    Retrieves detailed metadata for a specific file using its ID.
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       83 
77 
     | 
    
         
             
                    Args:
         
     | 
| 
       84 
     | 
    
         
            -
                        file_id:  
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
      
 78 
     | 
    
         
            +
                        file_id: String identifier of the file whose metadata should be retrieved
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
       86 
80 
     | 
    
         
             
                    Returns:
         
     | 
| 
       87 
     | 
    
         
            -
                         
     | 
| 
      
 81 
     | 
    
         
            +
                        Dictionary containing the file's metadata including properties such as name, size, type, and other attributes
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 84 
     | 
    
         
            +
                        HTTPError: When the API request fails due to invalid file_id or network issues
         
     | 
| 
      
 85 
     | 
    
         
            +
                        JSONDecodeError: When the API response cannot be parsed as JSON
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 88 
     | 
    
         
            +
                        retrieve, file, metadata, get, api, important
         
     | 
| 
       88 
89 
     | 
    
         
             
                    """
         
     | 
| 
       89 
90 
     | 
    
         
             
                    url = f"{self.base_url}/files/{file_id}"
         
     | 
| 
       90 
91 
     | 
    
         
             
                    response = self._get(url)
         
     | 
| 
         @@ -92,13 +93,19 @@ class GoogleDriveApp(APIApplication): 
     | 
|
| 
       92 
93 
     | 
    
         | 
| 
       93 
94 
     | 
    
         
             
                def delete_file(self, file_id: str) -> dict[str, Any]:
         
     | 
| 
       94 
95 
     | 
    
         
             
                    """
         
     | 
| 
       95 
     | 
    
         
            -
                     
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
      
 96 
     | 
    
         
            +
                    Deletes a specified file from Google Drive and returns a status message.
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
       97 
98 
     | 
    
         
             
                    Args:
         
     | 
| 
       98 
     | 
    
         
            -
                        file_id: The  
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
      
 99 
     | 
    
         
            +
                        file_id: The unique identifier string of the file to be deleted from Google Drive
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
       100 
101 
     | 
    
         
             
                    Returns:
         
     | 
| 
       101 
     | 
    
         
            -
                        A  
     | 
| 
      
 102 
     | 
    
         
            +
                        A dictionary containing either a success message {'message': 'File deleted successfully'} or an error message {'error': 'error description'}
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 105 
     | 
    
         
            +
                        Exception: When the DELETE request fails due to network issues, invalid file_id, insufficient permissions, or other API errors
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 108 
     | 
    
         
            +
                        delete, file-management, google-drive, api, important
         
     | 
| 
       102 
109 
     | 
    
         
             
                    """
         
     | 
| 
       103 
110 
     | 
    
         
             
                    url = f"{self.base_url}/files/{file_id}"
         
     | 
| 
       104 
111 
     | 
    
         
             
                    try:
         
     | 
| 
         @@ -106,108 +113,114 @@ class GoogleDriveApp(APIApplication): 
     | 
|
| 
       106 
113 
     | 
    
         
             
                        return {"message": "File deleted successfully"}
         
     | 
| 
       107 
114 
     | 
    
         
             
                    except Exception as e:
         
     | 
| 
       108 
115 
     | 
    
         
             
                        return {"error": str(e)}
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
       110 
117 
     | 
    
         
             
                def create_file_from_text(
         
     | 
| 
       111 
118 
     | 
    
         
             
                    self,
         
     | 
| 
       112 
119 
     | 
    
         
             
                    file_name: str,
         
     | 
| 
       113 
120 
     | 
    
         
             
                    text_content: str,
         
     | 
| 
       114 
121 
     | 
    
         
             
                    parent_id: str = None,
         
     | 
| 
       115 
     | 
    
         
            -
                    mime_type: str = "text/plain"
         
     | 
| 
      
 122 
     | 
    
         
            +
                    mime_type: str = "text/plain",
         
     | 
| 
       116 
123 
     | 
    
         
             
                ) -> dict[str, Any]:
         
     | 
| 
       117 
124 
     | 
    
         
             
                    """
         
     | 
| 
       118 
     | 
    
         
            -
                     
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
      
 125 
     | 
    
         
            +
                    Creates a new file in Google Drive with specified text content and returns the file's metadata.
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
       120 
127 
     | 
    
         
             
                    Args:
         
     | 
| 
       121 
128 
     | 
    
         
             
                        file_name: Name of the file to create on Google Drive
         
     | 
| 
       122 
129 
     | 
    
         
             
                        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 
     | 
    
         
            -
             
     | 
| 
      
 130 
     | 
    
         
            +
                        parent_id: Optional ID of the parent folder where the file will be created
         
     | 
| 
      
 131 
     | 
    
         
            +
                        mime_type: MIME type of the file (defaults to 'text/plain')
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
       126 
133 
     | 
    
         
             
                    Returns:
         
     | 
| 
       127 
     | 
    
         
            -
                         
     | 
| 
      
 134 
     | 
    
         
            +
                        Dictionary containing metadata of the created file including ID, name, and other Google Drive file properties
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 137 
     | 
    
         
            +
                        HTTPStatusError: Raised when the API request fails during file creation or content upload
         
     | 
| 
      
 138 
     | 
    
         
            +
                        UnicodeEncodeError: Raised when the text_content cannot be encoded in UTF-8
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 141 
     | 
    
         
            +
                        create, file, upload, drive, text, important, storage, document
         
     | 
| 
       128 
142 
     | 
    
         
             
                    """
         
     | 
| 
       129 
     | 
    
         
            -
                    metadata = {
         
     | 
| 
       130 
     | 
    
         
            -
                        "name": file_name,
         
     | 
| 
       131 
     | 
    
         
            -
                        "mimeType": mime_type
         
     | 
| 
       132 
     | 
    
         
            -
                    }
         
     | 
| 
       133 
     | 
    
         
            -
                    
         
     | 
| 
      
 143 
     | 
    
         
            +
                    metadata = {"name": file_name, "mimeType": mime_type}
         
     | 
| 
       134 
144 
     | 
    
         
             
                    if parent_id:
         
     | 
| 
       135 
145 
     | 
    
         
             
                        metadata["parents"] = [parent_id]
         
     | 
| 
       136 
     | 
    
         
            -
                        
         
     | 
| 
       137 
146 
     | 
    
         
             
                    create_url = f"{self.base_url}/files"
         
     | 
| 
       138 
147 
     | 
    
         
             
                    create_response = self._post(create_url, data=metadata)
         
     | 
| 
       139 
148 
     | 
    
         
             
                    file_data = create_response.json()
         
     | 
| 
       140 
149 
     | 
    
         
             
                    file_id = file_data.get("id")
         
     | 
| 
       141 
     | 
    
         
            -
                    
         
     | 
| 
       142 
     | 
    
         
            -
                    # Step 2: Update the file with text content
         
     | 
| 
       143 
150 
     | 
    
         
             
                    upload_url = f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media"
         
     | 
| 
       144 
151 
     | 
    
         
             
                    upload_headers = self._get_headers()
         
     | 
| 
       145 
152 
     | 
    
         
             
                    upload_headers["Content-Type"] = f"{mime_type}; charset=utf-8"
         
     | 
| 
       146 
     | 
    
         
            -
                    
         
     | 
| 
       147 
153 
     | 
    
         
             
                    upload_response = httpx.patch(
         
     | 
| 
       148 
     | 
    
         
            -
                        upload_url,
         
     | 
| 
       149 
     | 
    
         
            -
                        headers=upload_headers,
         
     | 
| 
       150 
     | 
    
         
            -
                        content=text_content.encode("utf-8")
         
     | 
| 
      
 154 
     | 
    
         
            +
                        upload_url, headers=upload_headers, content=text_content.encode("utf-8")
         
     | 
| 
       151 
155 
     | 
    
         
             
                    )
         
     | 
| 
       152 
156 
     | 
    
         
             
                    upload_response.raise_for_status()
         
     | 
| 
       153 
     | 
    
         
            -
                    
         
     | 
| 
       154 
157 
     | 
    
         
             
                    response_data = upload_response.json()
         
     | 
| 
       155 
158 
     | 
    
         
             
                    return response_data
         
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
       157 
160 
     | 
    
         
             
                def find_folder_id_by_name(self, folder_name: str) -> str | None:
         
     | 
| 
       158 
161 
     | 
    
         
             
                    """
         
     | 
| 
       159 
     | 
    
         
            -
                     
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
      
 162 
     | 
    
         
            +
                    Searches for and retrieves a Google Drive folder's ID using its name.
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
       161 
164 
     | 
    
         
             
                    Args:
         
     | 
| 
       162 
     | 
    
         
            -
                        folder_name: The name of the folder to  
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
      
 165 
     | 
    
         
            +
                        folder_name: The name of the folder to search for in Google Drive
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
       164 
167 
     | 
    
         
             
                    Returns:
         
     | 
| 
       165 
     | 
    
         
            -
                        The folder ID if found, None  
     | 
| 
      
 168 
     | 
    
         
            +
                        str | None: The folder's ID if a matching folder is found, None if no folder is found or if an error occurs
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 171 
     | 
    
         
            +
                        Exception: Caught internally and logged when API requests fail or response parsing errors occur
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 174 
     | 
    
         
            +
                        search, find, google-drive, folder, query, api, utility
         
     | 
| 
       166 
175 
     | 
    
         
             
                    """
         
     | 
| 
       167 
176 
     | 
    
         
             
                    query = f"mimeType='application/vnd.google-apps.folder' and name='{folder_name}' and trashed=false"
         
     | 
| 
       168 
177 
     | 
    
         
             
                    try:
         
     | 
| 
       169 
178 
     | 
    
         
             
                        response = self._get(
         
     | 
| 
       170 
179 
     | 
    
         
             
                            f"{self.base_url}/files",
         
     | 
| 
       171 
     | 
    
         
            -
                            params={"q": query, "fields": "files(id,name)"}
         
     | 
| 
      
 180 
     | 
    
         
            +
                            params={"q": query, "fields": "files(id,name)"},
         
     | 
| 
       172 
181 
     | 
    
         
             
                        )
         
     | 
| 
       173 
182 
     | 
    
         
             
                        files = response.json().get("files", [])
         
     | 
| 
       174 
183 
     | 
    
         
             
                        return files[0]["id"] if files else None
         
     | 
| 
       175 
184 
     | 
    
         
             
                    except Exception as e:
         
     | 
| 
       176 
185 
     | 
    
         
             
                        logger.error(f"Error finding folder ID by name: {e}")
         
     | 
| 
       177 
186 
     | 
    
         
             
                        return None
         
     | 
| 
       178 
     | 
    
         
            -
             
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
       179 
188 
     | 
    
         
             
                def create_folder(self, folder_name: str, parent_id: str = None) -> dict[str, Any]:
         
     | 
| 
       180 
189 
     | 
    
         
             
                    """
         
     | 
| 
       181 
     | 
    
         
            -
                     
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
      
 190 
     | 
    
         
            +
                    Creates a new folder in Google Drive with optional parent folder specification
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
       183 
192 
     | 
    
         
             
                    Args:
         
     | 
| 
       184 
193 
     | 
    
         
             
                        folder_name: Name of the folder to create
         
     | 
| 
       185 
     | 
    
         
            -
                        parent_id: ID of the parent folder 
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
       187 
     | 
    
         
            -
                                   
         
     | 
| 
      
 194 
     | 
    
         
            +
                        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
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
       188 
196 
     | 
    
         
             
                    Returns:
         
     | 
| 
       189 
     | 
    
         
            -
                         
     | 
| 
      
 197 
     | 
    
         
            +
                        Dictionary containing the created folder's metadata including its ID, name, and other Drive-specific information
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 200 
     | 
    
         
            +
                        ValueError: Raised when a parent folder name is provided but cannot be found in Google Drive
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 203 
     | 
    
         
            +
                        create, folder, drive, storage, important, management
         
     | 
| 
       190 
204 
     | 
    
         
             
                    """
         
     | 
| 
       191 
205 
     | 
    
         
             
                    import re
         
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
       193 
207 
     | 
    
         
             
                    metadata = {
         
     | 
| 
       194 
208 
     | 
    
         
             
                        "name": folder_name,
         
     | 
| 
       195 
     | 
    
         
            -
                        "mimeType": "application/vnd.google-apps.folder"
         
     | 
| 
      
 209 
     | 
    
         
            +
                        "mimeType": "application/vnd.google-apps.folder",
         
     | 
| 
       196 
210 
     | 
    
         
             
                    }
         
     | 
| 
       197 
     | 
    
         
            -
                    
         
     | 
| 
       198 
211 
     | 
    
         
             
                    if parent_id:
         
     | 
| 
       199 
212 
     | 
    
         
             
                        if not re.match(r"^[a-zA-Z0-9_-]{28,33}$", parent_id):
         
     | 
| 
       200 
213 
     | 
    
         
             
                            found_id = self.find_folder_id_by_name(parent_id)
         
     | 
| 
       201 
214 
     | 
    
         
             
                            if found_id:
         
     | 
| 
       202 
215 
     | 
    
         
             
                                metadata["parents"] = [found_id]
         
     | 
| 
       203 
216 
     | 
    
         
             
                            else:
         
     | 
| 
       204 
     | 
    
         
            -
                                raise ValueError( 
     | 
| 
      
 217 
     | 
    
         
            +
                                raise ValueError(
         
     | 
| 
      
 218 
     | 
    
         
            +
                                    f"Could not find parent folder with name: {parent_id}"
         
     | 
| 
      
 219 
     | 
    
         
            +
                                )
         
     | 
| 
       205 
220 
     | 
    
         
             
                        else:
         
     | 
| 
       206 
221 
     | 
    
         
             
                            metadata["parents"] = [parent_id]
         
     | 
| 
       207 
     | 
    
         
            -
                            
         
     | 
| 
       208 
222 
     | 
    
         
             
                    url = f"{self.base_url}/files"
         
     | 
| 
       209 
223 
     | 
    
         
             
                    params = {"supportsAllDrives": "true"}
         
     | 
| 
       210 
     | 
    
         
            -
                    
         
     | 
| 
       211 
224 
     | 
    
         
             
                    response = self._post(url, data=metadata, params=params)
         
     | 
| 
       212 
225 
     | 
    
         
             
                    return response.json()
         
     | 
| 
       213 
226 
     | 
    
         | 
| 
         @@ -216,53 +229,46 @@ class GoogleDriveApp(APIApplication): 
     | 
|
| 
       216 
229 
     | 
    
         
             
                    file_name: str,
         
     | 
| 
       217 
230 
     | 
    
         
             
                    file_path: str,
         
     | 
| 
       218 
231 
     | 
    
         
             
                    parent_id: str = None,
         
     | 
| 
       219 
     | 
    
         
            -
                    mime_type: str = None
         
     | 
| 
      
 232 
     | 
    
         
            +
                    mime_type: str = None,
         
     | 
| 
       220 
233 
     | 
    
         
             
                ) -> dict[str, Any]:
         
     | 
| 
       221 
234 
     | 
    
         
             
                    """
         
     | 
| 
       222 
     | 
    
         
            -
                     
     | 
| 
       223 
     | 
    
         
            -
             
     | 
| 
       224 
     | 
    
         
            -
                    This method is suitable for files under 5MB in size. It automatically
         
     | 
| 
       225 
     | 
    
         
            -
                    reads the file from the provided path.
         
     | 
| 
       226 
     | 
    
         
            -
                    
         
     | 
| 
      
 235 
     | 
    
         
            +
                    Uploads a file to Google Drive by creating a file metadata entry and uploading the binary content.
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
       227 
237 
     | 
    
         
             
                    Args:
         
     | 
| 
       228 
238 
     | 
    
         
             
                        file_name: Name to give the file on Google Drive
         
     | 
| 
       229 
239 
     | 
    
         
             
                        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 
     | 
    
         
            -
                    
         
     | 
| 
      
 240 
     | 
    
         
            +
                        parent_id: Optional ID of the parent folder to create the file in
         
     | 
| 
      
 241 
     | 
    
         
            +
                        mime_type: MIME type of the file (e.g., 'image/jpeg', 'image/png', 'application/pdf')
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
       234 
243 
     | 
    
         
             
                    Returns:
         
     | 
| 
       235 
     | 
    
         
            -
                         
     | 
| 
      
 244 
     | 
    
         
            +
                        Dictionary containing the uploaded file's metadata from Google Drive
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 247 
     | 
    
         
            +
                        FileNotFoundError: When the specified file_path does not exist or is not accessible
         
     | 
| 
      
 248 
     | 
    
         
            +
                        HTTPError: When the API request fails or returns an error status code
         
     | 
| 
      
 249 
     | 
    
         
            +
                        IOError: When there are issues reading the file content
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 252 
     | 
    
         
            +
                        upload, file-handling, google-drive, api, important, binary, storage
         
     | 
| 
       236 
253 
     | 
    
         
             
                    """
         
     | 
| 
       237 
     | 
    
         
            -
                    
         
     | 
| 
       238 
     | 
    
         
            -
                        
         
     | 
| 
       239 
     | 
    
         
            -
                    metadata = {
         
     | 
| 
       240 
     | 
    
         
            -
                        "name": file_name,
         
     | 
| 
       241 
     | 
    
         
            -
                        "mimeType": mime_type
         
     | 
| 
       242 
     | 
    
         
            -
                    }
         
     | 
| 
       243 
     | 
    
         
            -
                    
         
     | 
| 
      
 254 
     | 
    
         
            +
                    metadata = {"name": file_name, "mimeType": mime_type}
         
     | 
| 
       244 
255 
     | 
    
         
             
                    if parent_id:
         
     | 
| 
       245 
256 
     | 
    
         
             
                        metadata["parents"] = [parent_id]
         
     | 
| 
       246 
     | 
    
         
            -
                        
         
     | 
| 
       247 
257 
     | 
    
         
             
                    create_url = f"{self.base_url}/files"
         
     | 
| 
       248 
258 
     | 
    
         
             
                    create_response = self._post(create_url, data=metadata)
         
     | 
| 
       249 
259 
     | 
    
         
             
                    file_data = create_response.json()
         
     | 
| 
       250 
260 
     | 
    
         
             
                    file_id = file_data.get("id")
         
     | 
| 
       251 
     | 
    
         
            -
                    
         
     | 
| 
       252 
     | 
    
         
            -
                    with open(file_path, 'rb') as file_content:
         
     | 
| 
      
 261 
     | 
    
         
            +
                    with open(file_path, "rb") as file_content:
         
     | 
| 
       253 
262 
     | 
    
         
             
                        binary_content = file_content.read()
         
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
       255 
264 
     | 
    
         
             
                        upload_url = f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media"
         
     | 
| 
       256 
265 
     | 
    
         
             
                        upload_headers = self._get_headers()
         
     | 
| 
       257 
266 
     | 
    
         
             
                        upload_headers["Content-Type"] = mime_type
         
     | 
| 
       258 
     | 
    
         
            -
             
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
       259 
268 
     | 
    
         
             
                        upload_response = httpx.patch(
         
     | 
| 
       260 
     | 
    
         
            -
                            upload_url,
         
     | 
| 
       261 
     | 
    
         
            -
                            headers=upload_headers,
         
     | 
| 
       262 
     | 
    
         
            -
                            content=binary_content
         
     | 
| 
      
 269 
     | 
    
         
            +
                            upload_url, headers=upload_headers, content=binary_content
         
     | 
| 
       263 
270 
     | 
    
         
             
                        )
         
     | 
| 
       264 
271 
     | 
    
         
             
                        upload_response.raise_for_status()
         
     | 
| 
       265 
     | 
    
         
            -
                    
         
     | 
| 
       266 
272 
     | 
    
         
             
                    response_data = upload_response.json()
         
     | 
| 
       267 
273 
     | 
    
         
             
                    return response_data
         
     | 
| 
       268 
274 
     | 
    
         | 
| 
         @@ -277,4 +283,4 @@ class GoogleDriveApp(APIApplication): 
     | 
|
| 
       277 
283 
     | 
    
         
             
                        self.create_folder,
         
     | 
| 
       278 
284 
     | 
    
         
             
                        self.get_file,
         
     | 
| 
       279 
285 
     | 
    
         
             
                        self.delete_file,
         
     | 
| 
       280 
     | 
    
         
            -
                    ]
         
     | 
| 
      
 286 
     | 
    
         
            +
                    ]
         
     | 
| 
         @@ -13,32 +13,25 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       13 
13 
     | 
    
         
             
                    super().__init__(name="google-mail", integration=integration)
         
     | 
| 
       14 
14 
     | 
    
         
             
                    self.base_api_url = "https://gmail.googleapis.com/gmail/v1/users/me"
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                def _get_headers(self):
         
     | 
| 
       17 
     | 
    
         
            -
                    if not self.integration:
         
     | 
| 
       18 
     | 
    
         
            -
                        raise ValueError("Integration not configured for GmailApp")
         
     | 
| 
       19 
     | 
    
         
            -
                    credentials = self.integration.get_credentials()
         
     | 
| 
       20 
     | 
    
         
            -
                    if not credentials:
         
     | 
| 
       21 
     | 
    
         
            -
                        logger.warning("No Gmail credentials found via integration.")
         
     | 
| 
       22 
     | 
    
         
            -
                        action = self.integration.authorize()
         
     | 
| 
       23 
     | 
    
         
            -
                        raise NotAuthorizedError(action)
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                    if "headers" in credentials:
         
     | 
| 
       26 
     | 
    
         
            -
                        return credentials["headers"]
         
     | 
| 
       27 
     | 
    
         
            -
                    return {
         
     | 
| 
       28 
     | 
    
         
            -
                        "Authorization": f"Bearer {credentials['access_token']}",
         
     | 
| 
       29 
     | 
    
         
            -
                        "Content-Type": "application/json",
         
     | 
| 
       30 
     | 
    
         
            -
                    }
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
16 
     | 
    
         
             
                def send_email(self, to: str, subject: str, body: str) -> str:
         
     | 
| 
       33 
     | 
    
         
            -
                    """ 
     | 
| 
      
 17 
     | 
    
         
            +
                    """
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Sends an email using the Gmail API and returns a confirmation or error message.
         
     | 
| 
       34 
19 
     | 
    
         | 
| 
       35 
20 
     | 
    
         
             
                    Args:
         
     | 
| 
       36 
21 
     | 
    
         
             
                        to: The email address of the recipient
         
     | 
| 
       37 
     | 
    
         
            -
                        subject: The subject of the email
         
     | 
| 
       38 
     | 
    
         
            -
                        body: The  
     | 
| 
      
 22 
     | 
    
         
            +
                        subject: The subject line of the email
         
     | 
| 
      
 23 
     | 
    
         
            +
                        body: The main content of the email message
         
     | 
| 
       39 
24 
     | 
    
         | 
| 
       40 
25 
     | 
    
         
             
                    Returns:
         
     | 
| 
       41 
     | 
    
         
            -
                        A confirmation message
         
     | 
| 
      
 26 
     | 
    
         
            +
                        A string containing either a success confirmation message or an error description
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 29 
     | 
    
         
            +
                        NotAuthorizedError: When Gmail API authentication is not valid or has expired
         
     | 
| 
      
 30 
     | 
    
         
            +
                        KeyError: When required configuration keys are missing
         
     | 
| 
      
 31 
     | 
    
         
            +
                        Exception: For any other unexpected errors during the email sending process
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 34 
     | 
    
         
            +
                        send, email, api, communication, important
         
     | 
| 
       42 
35 
     | 
    
         
             
                    """
         
     | 
| 
       43 
36 
     | 
    
         
             
                    try:
         
     | 
| 
       44 
37 
     | 
    
         
             
                        url = f"{self.base_api_url}/messages/send"
         
     | 
| 
         @@ -89,15 +82,24 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       89 
82 
     | 
    
         
             
                        raise
         
     | 
| 
       90 
83 
     | 
    
         | 
| 
       91 
84 
     | 
    
         
             
                def create_draft(self, to: str, subject: str, body: str) -> str:
         
     | 
| 
       92 
     | 
    
         
            -
                    """ 
     | 
| 
      
 85 
     | 
    
         
            +
                    """
         
     | 
| 
      
 86 
     | 
    
         
            +
                    Creates a draft email message in Gmail using the Gmail API and returns a confirmation status.
         
     | 
| 
       93 
87 
     | 
    
         | 
| 
       94 
88 
     | 
    
         
             
                    Args:
         
     | 
| 
       95 
89 
     | 
    
         
             
                        to: The email address of the recipient
         
     | 
| 
       96 
     | 
    
         
            -
                        subject: The subject of the email
         
     | 
| 
       97 
     | 
    
         
            -
                        body: The  
     | 
| 
      
 90 
     | 
    
         
            +
                        subject: The subject line of the draft email
         
     | 
| 
      
 91 
     | 
    
         
            +
                        body: The main content/message of the draft email
         
     | 
| 
       98 
92 
     | 
    
         | 
| 
       99 
93 
     | 
    
         
             
                    Returns:
         
     | 
| 
       100 
     | 
    
         
            -
                        A  
     | 
| 
      
 94 
     | 
    
         
            +
                        A string containing either a success message with the draft ID or an error message describing the failure
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 97 
     | 
    
         
            +
                        NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
         
     | 
| 
      
 98 
     | 
    
         
            +
                        KeyError: When required configuration keys are missing
         
     | 
| 
      
 99 
     | 
    
         
            +
                        Exception: For general API errors, network issues, or other unexpected problems
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 102 
     | 
    
         
            +
                        create, email, draft, gmail, api, important
         
     | 
| 
       101 
103 
     | 
    
         
             
                    """
         
     | 
| 
       102 
104 
     | 
    
         
             
                    try:
         
     | 
| 
       103 
105 
     | 
    
         
             
                        url = f"{self.base_api_url}/drafts"
         
     | 
| 
         @@ -129,13 +131,22 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       129 
131 
     | 
    
         
             
                        return f"Error creating draft: {type(e).__name__} - {str(e)}"
         
     | 
| 
       130 
132 
     | 
    
         | 
| 
       131 
133 
     | 
    
         
             
                def send_draft(self, draft_id: str) -> str:
         
     | 
| 
       132 
     | 
    
         
            -
                    """ 
     | 
| 
      
 134 
     | 
    
         
            +
                    """
         
     | 
| 
      
 135 
     | 
    
         
            +
                    Sends an existing draft email using the Gmail API and returns a confirmation message.
         
     | 
| 
       133 
136 
     | 
    
         | 
| 
       134 
137 
     | 
    
         
             
                    Args:
         
     | 
| 
       135 
     | 
    
         
            -
                        draft_id: The  
     | 
| 
      
 138 
     | 
    
         
            +
                        draft_id: The unique identifier of the Gmail draft to be sent
         
     | 
| 
       136 
139 
     | 
    
         | 
| 
       137 
140 
     | 
    
         
             
                    Returns:
         
     | 
| 
       138 
     | 
    
         
            -
                        A  
     | 
| 
      
 141 
     | 
    
         
            +
                        A string containing either a success message with the sent message ID or an error message detailing the failure reason
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 144 
     | 
    
         
            +
                        NotAuthorizedError: When the user's Gmail API authorization is invalid or expired
         
     | 
| 
      
 145 
     | 
    
         
            +
                        KeyError: When required configuration keys are missing from the API response
         
     | 
| 
      
 146 
     | 
    
         
            +
                        Exception: For other unexpected errors during the API request or response handling
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 149 
     | 
    
         
            +
                        send, email, api, communication, important, draft
         
     | 
| 
       139 
150 
     | 
    
         
             
                    """
         
     | 
| 
       140 
151 
     | 
    
         
             
                    try:
         
     | 
| 
       141 
152 
     | 
    
         
             
                        url = f"{self.base_api_url}/drafts/send"
         
     | 
| 
         @@ -165,14 +176,23 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       165 
176 
     | 
    
         
             
                        return f"Error sending draft: {type(e).__name__} - {str(e)}"
         
     | 
| 
       166 
177 
     | 
    
         | 
| 
       167 
178 
     | 
    
         
             
                def get_draft(self, draft_id: str, format: str = "full") -> str:
         
     | 
| 
       168 
     | 
    
         
            -
                    """ 
     | 
| 
      
 179 
     | 
    
         
            +
                    """
         
     | 
| 
      
 180 
     | 
    
         
            +
                    Retrieves and formats a specific draft email from Gmail by its ID
         
     | 
| 
       169 
181 
     | 
    
         | 
| 
       170 
182 
     | 
    
         
             
                    Args:
         
     | 
| 
       171 
     | 
    
         
            -
                        draft_id:  
     | 
| 
       172 
     | 
    
         
            -
                        format:  
     | 
| 
      
 183 
     | 
    
         
            +
                        draft_id: String identifier of the draft email to retrieve
         
     | 
| 
      
 184 
     | 
    
         
            +
                        format: Output format of the draft (options: minimal, full, raw, metadata). Defaults to 'full'
         
     | 
| 
       173 
185 
     | 
    
         | 
| 
       174 
186 
     | 
    
         
             
                    Returns:
         
     | 
| 
       175 
     | 
    
         
            -
                         
     | 
| 
      
 187 
     | 
    
         
            +
                        A formatted string containing the draft email details (ID, recipient, subject) or an error message if retrieval fails
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 190 
     | 
    
         
            +
                        NotAuthorizedError: When the user's Gmail authorization is invalid or expired
         
     | 
| 
      
 191 
     | 
    
         
            +
                        KeyError: When required configuration keys or response data fields are missing
         
     | 
| 
      
 192 
     | 
    
         
            +
                        Exception: For any other unexpected errors during draft retrieval
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 195 
     | 
    
         
            +
                        retrieve, email, gmail, draft, api, format, important
         
     | 
| 
       176 
196 
     | 
    
         
             
                    """
         
     | 
| 
       177 
197 
     | 
    
         
             
                    try:
         
     | 
| 
       178 
198 
     | 
    
         
             
                        url = f"{self.base_api_url}/drafts/{draft_id}"
         
     | 
| 
         @@ -223,15 +243,24 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       223 
243 
     | 
    
         
             
                def list_drafts(
         
     | 
| 
       224 
244 
     | 
    
         
             
                    self, max_results: int = 20, q: str = None, include_spam_trash: bool = False
         
     | 
| 
       225 
245 
     | 
    
         
             
                ) -> str:
         
     | 
| 
       226 
     | 
    
         
            -
                    """ 
     | 
| 
      
 246 
     | 
    
         
            +
                    """
         
     | 
| 
      
 247 
     | 
    
         
            +
                    Retrieves and formats a list of email drafts from the user's Gmail mailbox with optional filtering and pagination.
         
     | 
| 
       227 
248 
     | 
    
         | 
| 
       228 
249 
     | 
    
         
             
                    Args:
         
     | 
| 
       229 
250 
     | 
    
         
             
                        max_results: Maximum number of drafts to return (max 500, default 20)
         
     | 
| 
       230 
     | 
    
         
            -
                        q: Search query to filter drafts  
     | 
| 
       231 
     | 
    
         
            -
                        include_spam_trash:  
     | 
| 
      
 251 
     | 
    
         
            +
                        q: Search query string to filter drafts using Gmail search syntax (default None)
         
     | 
| 
      
 252 
     | 
    
         
            +
                        include_spam_trash: Boolean flag to include drafts from spam and trash folders (default False)
         
     | 
| 
       232 
253 
     | 
    
         | 
| 
       233 
254 
     | 
    
         
             
                    Returns:
         
     | 
| 
       234 
     | 
    
         
            -
                        A formatted list of  
     | 
| 
      
 255 
     | 
    
         
            +
                        A formatted string containing the list of draft IDs and count information, or an error message if the request fails
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 258 
     | 
    
         
            +
                        NotAuthorizedError: When the Gmail API authentication is missing or invalid
         
     | 
| 
      
 259 
     | 
    
         
            +
                        KeyError: When required configuration keys are missing
         
     | 
| 
      
 260 
     | 
    
         
            +
                        Exception: For general errors during API communication or data processing
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 263 
     | 
    
         
            +
                        list, email, drafts, gmail, api, search, query, pagination, important
         
     | 
| 
       235 
264 
     | 
    
         
             
                    """
         
     | 
| 
       236 
265 
     | 
    
         
             
                    try:
         
     | 
| 
       237 
266 
     | 
    
         
             
                        url = f"{self.base_api_url}/drafts"
         
     | 
| 
         @@ -286,13 +315,22 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       286 
315 
     | 
    
         
             
                        return f"Error listing drafts: {type(e).__name__} - {str(e)}"
         
     | 
| 
       287 
316 
     | 
    
         | 
| 
       288 
317 
     | 
    
         
             
                def get_message(self, message_id: str) -> str:
         
     | 
| 
       289 
     | 
    
         
            -
                    """ 
     | 
| 
      
 318 
     | 
    
         
            +
                    """
         
     | 
| 
      
 319 
     | 
    
         
            +
                    Retrieves and formats a specific email message from Gmail API by its ID, including sender, recipient, date, subject, and message preview.
         
     | 
| 
       290 
320 
     | 
    
         | 
| 
       291 
321 
     | 
    
         
             
                    Args:
         
     | 
| 
       292 
     | 
    
         
            -
                        message_id: The  
     | 
| 
      
 322 
     | 
    
         
            +
                        message_id: The unique identifier of the Gmail message to retrieve
         
     | 
| 
       293 
323 
     | 
    
         | 
| 
       294 
324 
     | 
    
         
             
                    Returns:
         
     | 
| 
       295 
     | 
    
         
            -
                         
     | 
| 
      
 325 
     | 
    
         
            +
                        A formatted string containing the message details (ID, From, To, Date, Subject, Preview) or an error message if the retrieval fails
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
      
 327 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 328 
     | 
    
         
            +
                        NotAuthorizedError: When the request lacks proper Gmail API authorization
         
     | 
| 
      
 329 
     | 
    
         
            +
                        KeyError: When required configuration keys or message fields are missing
         
     | 
| 
      
 330 
     | 
    
         
            +
                        Exception: For general API communication errors or unexpected issues
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 333 
     | 
    
         
            +
                        retrieve, email, format, api, gmail, message, important
         
     | 
| 
       296 
334 
     | 
    
         
             
                    """
         
     | 
| 
       297 
335 
     | 
    
         
             
                    try:
         
     | 
| 
       298 
336 
     | 
    
         
             
                        url = f"{self.base_api_url}/messages/{message_id}"
         
     | 
| 
         @@ -350,15 +388,24 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       350 
388 
     | 
    
         
             
                def list_messages(
         
     | 
| 
       351 
389 
     | 
    
         
             
                    self, max_results: int = 20, q: str = None, include_spam_trash: bool = False
         
     | 
| 
       352 
390 
     | 
    
         
             
                ) -> str:
         
     | 
| 
       353 
     | 
    
         
            -
                    """ 
     | 
| 
      
 391 
     | 
    
         
            +
                    """
         
     | 
| 
      
 392 
     | 
    
         
            +
                    Retrieves and formats a list of messages from the user's Gmail mailbox with optional filtering and pagination support.
         
     | 
| 
       354 
393 
     | 
    
         | 
| 
       355 
394 
     | 
    
         
             
                    Args:
         
     | 
| 
       356 
395 
     | 
    
         
             
                        max_results: Maximum number of messages to return (max 500, default 20)
         
     | 
| 
       357 
     | 
    
         
            -
                        q: Search query to filter messages  
     | 
| 
       358 
     | 
    
         
            -
                        include_spam_trash:  
     | 
| 
      
 396 
     | 
    
         
            +
                        q: Search query string to filter messages using Gmail search syntax
         
     | 
| 
      
 397 
     | 
    
         
            +
                        include_spam_trash: Boolean flag to include messages from spam and trash folders (default False)
         
     | 
| 
       359 
398 
     | 
    
         | 
| 
       360 
399 
     | 
    
         
             
                    Returns:
         
     | 
| 
       361 
     | 
    
         
            -
                        A formatted list of  
     | 
| 
      
 400 
     | 
    
         
            +
                        A formatted string containing the list of message IDs and thread IDs, or an error message if the operation fails
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 403 
     | 
    
         
            +
                        NotAuthorizedError: When the Gmail API authentication is invalid or missing
         
     | 
| 
      
 404 
     | 
    
         
            +
                        KeyError: When required configuration keys are missing
         
     | 
| 
      
 405 
     | 
    
         
            +
                        Exception: For general API errors, network issues, or other unexpected problems
         
     | 
| 
      
 406 
     | 
    
         
            +
             
     | 
| 
      
 407 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 408 
     | 
    
         
            +
                        list, messages, gmail, search, query, pagination, important
         
     | 
| 
       362 
409 
     | 
    
         
             
                    """
         
     | 
| 
       363 
410 
     | 
    
         
             
                    try:
         
     | 
| 
       364 
411 
     | 
    
         
             
                        url = f"{self.base_api_url}/messages"
         
     | 
| 
         @@ -417,10 +464,21 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       417 
464 
     | 
    
         
             
                        return f"Error listing messages: {type(e).__name__} - {str(e)}"
         
     | 
| 
       418 
465 
     | 
    
         | 
| 
       419 
466 
     | 
    
         
             
                def list_labels(self) -> str:
         
     | 
| 
       420 
     | 
    
         
            -
                    """ 
     | 
| 
      
 467 
     | 
    
         
            +
                    """
         
     | 
| 
      
 468 
     | 
    
         
            +
                    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.
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
      
 470 
     | 
    
         
            +
                    Args:
         
     | 
| 
      
 471 
     | 
    
         
            +
                        None: This method takes no arguments
         
     | 
| 
       421 
472 
     | 
    
         | 
| 
       422 
473 
     | 
    
         
             
                    Returns:
         
     | 
| 
       423 
     | 
    
         
            -
                        A formatted list of labels or an error message
         
     | 
| 
      
 474 
     | 
    
         
            +
                        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.
         
     | 
| 
      
 475 
     | 
    
         
            +
             
     | 
| 
      
 476 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 477 
     | 
    
         
            +
                        NotAuthorizedError: Raised when the user's Gmail authorization is invalid or missing
         
     | 
| 
      
 478 
     | 
    
         
            +
                        Exception: Raised when any other unexpected error occurs during the API request or data processing
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
      
 480 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 481 
     | 
    
         
            +
                        list, gmail, labels, fetch, organize, important, management
         
     | 
| 
       424 
482 
     | 
    
         
             
                    """
         
     | 
| 
       425 
483 
     | 
    
         
             
                    try:
         
     | 
| 
       426 
484 
     | 
    
         
             
                        url = f"{self.base_api_url}/labels"
         
     | 
| 
         @@ -486,13 +544,21 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       486 
544 
     | 
    
         
             
                        return f"Error listing labels: {type(e).__name__} - {str(e)}"
         
     | 
| 
       487 
545 
     | 
    
         | 
| 
       488 
546 
     | 
    
         
             
                def create_label(self, name: str) -> str:
         
     | 
| 
       489 
     | 
    
         
            -
                    """ 
     | 
| 
      
 547 
     | 
    
         
            +
                    """
         
     | 
| 
      
 548 
     | 
    
         
            +
                    Creates a new Gmail label with specified visibility settings and returns creation status details.
         
     | 
| 
       490 
549 
     | 
    
         | 
| 
       491 
550 
     | 
    
         
             
                    Args:
         
     | 
| 
       492 
551 
     | 
    
         
             
                        name: The display name of the label to create
         
     | 
| 
       493 
552 
     | 
    
         | 
| 
       494 
553 
     | 
    
         
             
                    Returns:
         
     | 
| 
       495 
     | 
    
         
            -
                        A  
     | 
| 
      
 554 
     | 
    
         
            +
                        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
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
      
 556 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 557 
     | 
    
         
            +
                        NotAuthorizedError: Raised when the request lacks proper Gmail API authorization
         
     | 
| 
      
 558 
     | 
    
         
            +
                        Exception: Raised for any other unexpected errors during label creation
         
     | 
| 
      
 559 
     | 
    
         
            +
             
     | 
| 
      
 560 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 561 
     | 
    
         
            +
                        create, label, gmail, management, important
         
     | 
| 
       496 
562 
     | 
    
         
             
                    """
         
     | 
| 
       497 
563 
     | 
    
         
             
                    try:
         
     | 
| 
       498 
564 
     | 
    
         
             
                        url = f"{self.base_api_url}/labels"
         
     | 
| 
         @@ -531,13 +597,21 @@ class GoogleMailApp(APIApplication): 
     | 
|
| 
       531 
597 
     | 
    
         
             
                        return f"Error creating label: {type(e).__name__} - {str(e)}"
         
     | 
| 
       532 
598 
     | 
    
         | 
| 
       533 
599 
     | 
    
         
             
                def get_profile(self) -> str:
         
     | 
| 
       534 
     | 
    
         
            -
                    """ 
     | 
| 
      
 600 
     | 
    
         
            +
                    """
         
     | 
| 
      
 601 
     | 
    
         
            +
                    Retrieves and formats the user's Gmail profile information including email address, message count, thread count, and history ID.
         
     | 
| 
       535 
602 
     | 
    
         | 
| 
       536 
     | 
    
         
            -
                     
     | 
| 
       537 
     | 
    
         
            -
             
     | 
| 
      
 603 
     | 
    
         
            +
                    Args:
         
     | 
| 
      
 604 
     | 
    
         
            +
                        None: This method takes no arguments besides self
         
     | 
| 
       538 
605 
     | 
    
         | 
| 
       539 
606 
     | 
    
         
             
                    Returns:
         
     | 
| 
       540 
     | 
    
         
            -
                        A formatted string containing the user's profile information or an error message
         
     | 
| 
      
 607 
     | 
    
         
            +
                        A formatted string containing the user's Gmail profile information or an error message if the request fails
         
     | 
| 
      
 608 
     | 
    
         
            +
             
     | 
| 
      
 609 
     | 
    
         
            +
                    Raises:
         
     | 
| 
      
 610 
     | 
    
         
            +
                        NotAuthorizedError: Raised when the user's credentials are invalid or authorization is required
         
     | 
| 
      
 611 
     | 
    
         
            +
                        Exception: Raised for any other unexpected errors during the API request or data processing
         
     | 
| 
      
 612 
     | 
    
         
            +
             
     | 
| 
      
 613 
     | 
    
         
            +
                    Tags:
         
     | 
| 
      
 614 
     | 
    
         
            +
                        fetch, profile, gmail, user-info, api-request, important
         
     | 
| 
       541 
615 
     | 
    
         
             
                    """
         
     | 
| 
       542 
616 
     | 
    
         
             
                    try:
         
     | 
| 
       543 
617 
     | 
    
         
             
                        url = f"{self.base_api_url}/profile"
         
     |