Skip to main content
Glama

gmail_add_label_to_messages

Organize Gmail messages by adding labels to specific emails using message IDs or search queries. This tool helps categorize and manage your inbox efficiently.

Instructions

Add a label to one or more messages. Can specify messages by IDs or by search query.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
label_nameNoName of the label to add. Provide either label_name or label_id.
label_idNoID of the label to add. Provide either label_name or label_id.
message_idsNoComma-separated list of message IDs to add the label to.
queryNoGmail search query to find messages. Alternative to message_ids.
max_messagesNoMaximum messages to modify when using query. Default 100, max 500.
confirmYesMust be true to actually modify. Set false to preview.

Implementation Reference

  • MCP tool registration and input schema definition for 'gmail_add_label_to_messages'.
        name="gmail_add_label_to_messages",
        description="Add a label to one or more messages. Can specify messages by IDs or by search query.",
        inputSchema={
            "type": "object",
            "properties": {
                "label_name": {
                    "type": "string",
                    "description": "Name of the label to add. Provide either label_name or label_id."
                },
                "label_id": {
                    "type": "string",
                    "description": "ID of the label to add. Provide either label_name or label_id."
                },
                "message_ids": {
                    "type": "string",
                    "description": "Comma-separated list of message IDs to add the label to."
                },
                "query": {
                    "type": "string",
                    "description": "Gmail search query to find messages. Alternative to message_ids."
                },
                "max_messages": {
                    "type": "integer",
                    "description": "Maximum messages to modify when using query. Default 100, max 500."
                },
                "confirm": {
                    "type": "boolean",
                    "description": "Must be true to actually modify. Set false to preview."
                }
            },
            "required": ["confirm"]
        },
    ),
  • Primary handler function for the gmail_add_label_to_messages tool (handles args, preview/confirm, calls Gmail API). Dispatched from main handle_call_tool when name matches.
    async def _handle_label_modify(client: GmailClient, arguments: dict[str, Any], add: bool) -> list[TextContent]:
        """Handle add/remove label from messages.
        
        Args:
            client: The Gmail client instance.
            arguments: Tool arguments dictionary.
            add: True to add label, False to remove label.
            
        Returns:
            list[TextContent]: Response text.
        """
        label_id = arguments.get("label_id")
        label_name = arguments.get("label_name")
        message_ids_str = arguments.get("message_ids", "")
        query = arguments.get("query")
        max_messages = min(arguments.get("max_messages", 100), 500)
        confirm = arguments.get("confirm", False)
        
        action_verb = "add" if add else "remove"
        action_prep = "to" if add else "from"
        
        if not label_id and not label_name:
            return [TextContent(type="text", text="Error: Provide either label_id or label_name.")]
        if not message_ids_str and not query:
            return [TextContent(type="text", text="Error: Provide either message_ids or query.")]
        
        # Find label by name if ID not provided
        if not label_id:
            label = await client.find_label_by_name(label_name)
            if not label:
                return [TextContent(type="text", text=f"Error: Label not found: {label_name}")]
            label_id = label["id"]
            label_display = label["name"]
        else:
            label_display = label_name or label_id
        
        # Get message IDs from string or query
        if message_ids_str:
            message_ids = [mid.strip() for mid in message_ids_str.split(",") if mid.strip()]
        else:
            search_results = await client.search_emails(query, max_messages)
            if not search_results:
                return [TextContent(type="text", text=f"No emails found matching query: {query}")]
            message_ids = [email.id for email in search_results]
        
        if not confirm:
            return [TextContent(
                type="text",
                text=f"Preview: Would {action_verb} label '{label_display}' {action_prep} {len(message_ids)} message(s). Set confirm=true to proceed."
            )]
        
        if add:
            result = await client.modify_message_labels(message_ids, add_label_ids=[label_id])
        else:
            result = await client.modify_message_labels(message_ids, remove_label_ids=[label_id])
        
        if result["success"] > 0:
            return [TextContent(
                type="text",
                text=f"Success: {'Added' if add else 'Removed'} label '{label_display}' {action_prep} {result['success']} message(s)."
                + (f" Errors: {result['errors']}" if result['errors'] else "")
            )]
        else:
            return [TextContent(type="text", text=f"Error: Failed to modify labels. {result['errors']}")]
  • GmailClient helper method that performs the actual Gmail API batchModify call to add labels to messages.
    async def modify_message_labels(
        self,
        message_ids: list[str],
        add_label_ids: list[str] | None = None,
        remove_label_ids: list[str] | None = None
    ) -> dict:
        """Add or remove labels from messages.
        
        Args:
            message_ids: List of message IDs to modify
            add_label_ids: Label IDs to add to the messages
            remove_label_ids: Label IDs to remove from the messages
            
        Returns:
            Dict with success count and errors
        """
        if not message_ids:
            return {"success": 0, "errors": [], "message": "No message IDs provided"}
        
        if not add_label_ids and not remove_label_ids:
            return {"success": 0, "errors": [], "message": "No labels to add or remove"}
        
        results = {"success": 0, "errors": []}
        
        try:
            body = {"ids": message_ids}
            if add_label_ids:
                body["addLabelIds"] = add_label_ids
            if remove_label_ids:
                body["removeLabelIds"] = remove_label_ids
            
            # Use batchModify for efficiency
            if len(message_ids) <= 1000:
                self.service.users().messages().batchModify(
                    userId="me",
                    body=body
                ).execute()
                results["success"] = len(message_ids)
            else:
                # Process in batches of 1000
                for i in range(0, len(message_ids), 1000):
                    batch = message_ids[i:i+1000]
                    batch_body = body.copy()
                    batch_body["ids"] = batch
                    self.service.users().messages().batchModify(
                        userId="me",
                        body=batch_body
                    ).execute()
                    results["success"] += len(batch)
                    
        except HttpError as e:
            logger.error(f"Failed to modify message labels: {e}")
            results["errors"].append(str(e))
            
        return results
  • Helper method to resolve label name to label ID, used when only name is provided.
    async def find_label_by_name(self, name: str) -> dict | None:
        """Find a label by name (case-insensitive).
        
        Args:
            name: Label name to search for
            
        Returns:
            Label dict or None if not found
        """
        labels = await self.get_labels()
        name_lower = name.lower()
        for label in labels:
            if label.get("name", "").lower() == name_lower:
                return label
        return None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/murphy360/mcp_gmail'

If you have feedback or need assistance with the MCP directory API, please join our Discord server