Skip to main content
Glama

send_reply

Reply to emails by composing and sending responses to specific messages, supporting text and HTML formats with optional quoting of original content.

Instructions

Reply to an email

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
toYesRecipient email addresses
subjectYesReply subject (usually with Re:)
body_textNoReply body text
body_htmlNoReply body HTML
reply_to_message_idYesOriginal message ID to reply to
quote_originalNoQuote original message (default: true)

Implementation Reference

  • Implementation of the send_reply tool logic, which handles replying to emails, including optional original message quotation and header management.
    def send_reply(
        client,
        to: list[str],
        subject: str,
        body_text: str | None = None,
        body_html: str | None = None,
        original_message: Message | None = None,
        reply_to_message_id: str | None = None,
        references: list[str] | None = None,
        quote_original: bool = True,
        from_addr: str | None = None,
    ) -> SendResult:
        """
        回复邮件
    
        Args:
            client: SMTP 客户端对象
            to: 收件人列表
            subject: 主题 (通常会自动添加 Re:)
            body_text: 回复正文 (纯文本)
            body_html: 回复正文 (HTML)
            original_message: 原邮件消息对象
            reply_to_message_id: 原邮件的 Message-ID
            references: 引用链
            quote_original: 是否引用原文
            from_addr: 发件人地址
    
        Returns:
            SendResult: 发送结果
        """
        # 验证参数
        if not to:
            return SendResult(success=False, error="收件人列表不能为空")
    
        try:
            # 获取发件人地址
            if not from_addr:
                if hasattr(client, "config") and hasattr(client.config, "user"):
                    from_addr = client.config.user
                else:
                    return SendResult(success=False, error="缺少发件人地址")
    
            # 构建回复邮件
            if original_message:
                # 从原邮件提取信息构建回复
                orig_subject = original_message.get("Subject", "")
                if not subject.startswith("Re:"):
                    if orig_subject and not orig_subject.startswith("Re:"):
                        subject = f"Re: {orig_subject}"
                    elif orig_subject:
                        subject = orig_subject
    
                # 构建回复正文
                reply_text = body_text or ""
                if quote_original:
                    orig_from = original_message.get("From", "")
                    orig_date = original_message.get("Date", "")
                    orig_body = ""
                    if original_message.is_multipart():
                        for part in original_message.walk():
                            if part.get_content_type() == "text/plain":
                                try:
                                    orig_body = part.get_payload(decode=True).decode(
                                        "utf-8", errors="replace"
                                    )
                                except Exception:
                                    pass
                                break
                    else:
                        try:
                            orig_body = original_message.get_payload(decode=True).decode(
                                "utf-8", errors="replace"
                            )
                        except Exception:
                            pass
    
                    if orig_body:
                        reply_text += (
                            f"\n\n--- 原始邮件 ---\nFrom: {orig_from}\nDate: {orig_date}\n\n{orig_body}"
                        )
    
                message = build_email_message(
                    sender=from_addr,
                    to=to,
                    subject=subject,
                    body_text=reply_text,
                    body_html=body_html,
                )
    
                # 设置回复相关头
                orig_msg_id = original_message.get("Message-ID", "")
                if orig_msg_id:
                    message["In-Reply-To"] = orig_msg_id
                    message["References"] = orig_msg_id
            else:
                # 没有原邮件,直接构建
                if not subject.startswith("Re:"):
                    subject = f"Re: {subject}"
    
                message = build_email_message(
                    sender=from_addr,
                    to=to,
                    subject=subject,
                    body_text=body_text,
                    body_html=body_html,
                )
    
                if reply_to_message_id:
                    message["In-Reply-To"] = reply_to_message_id
                if references:
                    message["References"] = " ".join(references)
    
            # 生成 Message-ID
            message_id = make_msgid()
            message["Message-ID"] = message_id
    
            # 发送邮件
            smtp = _get_smtp_client(client)
            smtp.send_message(message, from_addr=from_addr, to_addrs=to)
    
            return SendResult(
                success=True,
                message_id=message_id,
            )
    
        except smtplib.SMTPException as e:
            return SendResult(success=False, error=f"SMTP 错误: {str(e)}")
        except Exception as e:
            return SendResult(success=False, error=f"回复失败: {str(e)}")
  • Tool definition for 'send_reply' in the MCP tool registry.
        name="send_reply",
        description="Reply to an email",
        inputSchema={
            "type": "object",
            "properties": {
                "to": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Recipient email addresses",
                },
                "subject": {
                    "type": "string",
                    "description": "Reply subject (usually with Re:)",
                },
                "body_text": {
                    "type": "string",
                    "description": "Reply body text",
                },
                "body_html": {
                    "type": "string",
                    "description": "Reply body HTML",
                },
                "reply_to_message_id": {
                    "type": "string",
                    "description": "Original message ID to reply to",
                },
                "quote_original": {
                    "type": "boolean",
                    "description": "Quote original message (default: true)",
                    "default": True,
                },
            },
            "required": ["to", "subject", "reply_to_message_id"],
        },
    ),
  • MCP tool handler integration for 'send_reply'.
    elif name == "send_reply":
        result = send_reply(
            client=smtp_client,
            to=arguments["to"],
            subject=arguments["subject"],
            body_text=arguments.get("body_text"),
            body_html=arguments.get("body_html"),
            reply_to_message_id=arguments.get("reply_to_message_id"),
            quote_original=arguments.get("quote_original", True),
        )
        return [TextContent(type="text", text=str(result))]
Behavior1/5

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

No annotations are provided, yet the description discloses nothing about behavioral traits: whether the email sends immediately or saves as draft, whether the original message gets marked as 'replied', threading behavior, or handling of HTML vs. text bodies. For a 6-parameter mutation operation, this is a significant disclosure gap.

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

Conciseness3/5

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

The description is extremely brief at four words, which prevents verbosity, but this brevity results in under-specification rather than efficient information density. The single sentence fails to 'earn its place' by not delivering value beyond restating the tool name.

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

Completeness2/5

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

For a mutation tool with 6 parameters (including dual body formats and threading controls) and no output schema, the description is inadequate. It omits critical context about email threading, the relationship to the original message, and what constitutes a valid reply versus other message types.

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?

The input schema has 100% description coverage, documenting all parameters including the distinction between body_text and body_html. Since the schema fully documents parameters, the description's silence on parameter semantics meets the baseline expectation, though it adds no additional context about the relationship between parameters (e.g., that reply_to_message_id links to the parent thread).

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

Purpose3/5

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

The description states the basic action (reply) and resource (email), but fails to distinguish from siblings 'send_email' and 'send_forward'. Given these alternatives, the description should clarify that this creates a threaded response to an existing message versus creating a new conversation or forwarding.

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?

No guidance provided on when to use this tool versus 'send_email' or 'send_forward', nor any mention of prerequisites like requiring a valid message ID from an existing email. The description offers no selection criteria for an agent choosing between the three send-related tools.

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/AdJIa/mail-mcp-server'

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