Skip to main content
Glama
Michaelzag

Migadu MCP Server

by Michaelzag

update_mailbox

Idempotent

Modify mailbox configurations like sending/receiving permissions, spam filters, and access protocols to customize email account behavior.

Instructions

Update mailbox settings. List of dicts with: target (required), name (optional), may_send (optional), may_receive (optional), may_access_imap (optional), may_access_pop3 (optional), spam_action (optional), spam_aggressiveness (optional).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
updatesYes

Implementation Reference

  • Primary MCP tool handler for 'update_mailbox'. Dispatches bulk updates to process_update_mailbox helper with logging.
    @mcp.tool(
        annotations={
            "readOnlyHint": False,
            "destructiveHint": False,
            "idempotentHint": True,
            "openWorldHint": True,
        },
    )
    async def update_mailbox(
        updates: List[Dict[str, Any]], ctx: Context
    ) -> Dict[str, Any]:
        """Update mailbox settings. List of dicts with: target (required), name (optional), may_send (optional), may_receive (optional), may_access_imap (optional), may_access_pop3 (optional), spam_action (optional), spam_aggressiveness (optional)."""
        count = len(list(ensure_iterable(updates)))
        await log_bulk_operation_start(ctx, "Updating", count, "mailbox")
    
        result = await process_update_mailbox(updates, ctx)
        await log_bulk_operation_result(ctx, "Mailbox update", result, "mailbox")
        return result
  • Pydantic input schema for mailbox update requests, validated by bulk_processor_with_schema decorator.
    class MailboxUpdateRequest(BaseModel):
        """Request schema for updating a mailbox"""
    
        target: str = Field(..., description="Email address or local part")
        name: Optional[str] = Field(None, description="Update display name")
        may_send: Optional[bool] = Field(None, description="Allow/deny sending emails")
        may_receive: Optional[bool] = Field(None, description="Allow/deny receiving emails")
        may_access_imap: Optional[bool] = Field(None, description="Allow/deny IMAP access")
        may_access_pop3: Optional[bool] = Field(None, description="Allow/deny POP3 access")
        may_access_managesieve: Optional[bool] = Field(
            None, description="Allow/deny ManageSieve access"
        )
        spam_action: Optional[SpamAction] = Field(None, description="Spam handling action")
        spam_aggressiveness: Optional[SpamAggressiveness] = Field(
            None, description="Spam filtering sensitivity"
        )
        sender_denylist: Optional[str] = Field(None, description="Sender denylist rules")
        sender_allowlist: Optional[str] = Field(None, description="Sender allowlist rules")
        recipient_denylist: Optional[str] = Field(
            None, description="Recipient denylist rules"
        )
  • Tool registration call in main.py that registers the update_mailbox handler via register_mailbox_tools.
    register_mailbox_tools(mcp)
  • Core processing logic for individual mailbox updates, including validation, parsing, service call, and logging.
    @bulk_processor_with_schema(MailboxUpdateRequest)
    async def process_update_mailbox(
        validated_item: MailboxUpdateRequest, ctx: Context
    ) -> Dict[str, Any]:
        """Process a single mailbox update with Pydantic validation"""
        # Use validated Pydantic model directly - all validation already done
        target = validated_item.target
        name = validated_item.name
        may_send = validated_item.may_send
        may_receive = validated_item.may_receive
        may_access_imap = validated_item.may_access_imap
        may_access_pop3 = validated_item.may_access_pop3
        spam_action = validated_item.spam_action
        spam_aggressiveness = validated_item.spam_aggressiveness
    
        # Parse target
        parsed = parse_email_target(target)
        domain, local_part = parsed[0]
        email_address = format_email_address(domain, local_part)
    
        await log_operation_start(ctx, "Updating mailbox", email_address)
    
        service = get_service_factory().mailbox_service()
        result = await service.update_mailbox(
            domain,
            local_part,
            name,
            may_send,
            may_receive,
            may_access_imap,
            may_access_pop3,
            spam_action,
            spam_aggressiveness,
        )
    
        await log_operation_success(ctx, "Updated mailbox", email_address)
        return {"mailbox": result, "email_address": email_address, "success": True}
  • Backend service method that performs the actual API call to update mailbox settings on Migadu.
    async def update_mailbox(
        self,
        domain: str,
        local_part: str,
        name: Optional[str] = None,
        may_send: Optional[bool] = None,
        may_receive: Optional[bool] = None,
        may_access_imap: Optional[bool] = None,
        may_access_pop3: Optional[bool] = None,
        spam_action: Optional[str] = None,
        spam_aggressiveness: Optional[str] = None,
    ) -> Dict[str, Any]:
        """Modify configuration settings for an existing mailbox including permissions and spam filtering.
    
        Allows selective updates to display name, send/receive permissions, protocol access controls,
        and spam filtering behavior without affecting other mailbox settings.
        """
        data: Dict[str, Any] = {}
        if name is not None:
            data["name"] = name
        if may_send is not None:
            data["may_send"] = may_send
        if may_receive is not None:
            data["may_receive"] = may_receive
        if may_access_imap is not None:
            data["may_access_imap"] = may_access_imap
        if may_access_pop3 is not None:
            data["may_access_pop3"] = may_access_pop3
        if spam_action is not None:
            data["spam_action"] = spam_action
        if spam_aggressiveness is not None:
            data["spam_aggressiveness"] = spam_aggressiveness
    
        return await self.client.request(
            "PUT", f"/domains/{domain}/mailboxes/{local_part}", json=data
        )
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide hints: readOnlyHint=false (mutation), openWorldHint=true (flexible inputs), idempotentHint=true (safe to retry), destructiveHint=false (non-destructive). The description adds value by listing specific updatable fields (e.g., spam_action, may_send), which clarifies what settings can be modified beyond the generic 'updates' parameter. However, it doesn't disclose behavioral traits like rate limits, authentication needs, or error conditions, leaving some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose ('Update mailbox settings'), followed by a structured list of fields. It avoids unnecessary words, but the list format is slightly verbose and could be more streamlined. Every sentence (or list item) earns its place by clarifying parameters, making it efficient overall.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has annotations covering mutation and idempotency, but no output schema and 0% schema coverage, the description is moderately complete. It explains what can be updated but lacks details on return values, error handling, or side effects. For a mutation tool with rich annotations, it meets minimum viability but has clear gaps in full context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the schema provides no parameter details. The description compensates by listing the fields within each dict (target, name, may_send, etc.), adding meaning beyond the generic 'updates' array. However, it doesn't explain data types, formats (e.g., what 'target' refers to), or constraints, leaving parameters partially documented. With 0% coverage, baseline is lower, but the description adds moderate value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Update') and resource ('mailbox settings'), making the purpose immediately understandable. It distinguishes from siblings like 'create_mailbox' or 'delete_mailbox' by specifying it modifies existing settings rather than creating or deleting. However, it doesn't explicitly differentiate from other update tools like 'update_alias' or 'update_identity' beyond the resource name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing an existing mailbox), exclusions (e.g., what cannot be updated), or comparisons to siblings like 'get_mailbox' for checking current settings. Usage is implied through the action 'update' but lacks explicit context for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/Michaelzag/migadu-mcp'

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