import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
initStderrTee("email");
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { emailSetup } from "./tools/email-setup.js";
import { emailRead } from "./tools/email-read.js";
import { emailSend } from "./tools/email-send.js";
import { emailSearch } from "./tools/email-search.js";
import { emailOtpExtract } from "./tools/email-otp-extract.js";
import { emailStatus } from "./tools/email-status.js";
import { emailAutoRespondConfig } from "./tools/email-auto-respond-config.js";
import { emailReply } from "./tools/email-reply.js";
import { emailGraphQuery } from "./tools/email-graph-query.js";
import { closeDriver } from "./lib/neo4j.js";
const server = new McpServer({
    name: "maxy-email",
    version: "0.1.0",
});
const accountId = process.env.ACCOUNT_ID;
if (!accountId) {
    throw new Error("ACCOUNT_ID environment variable is required");
}
// ===================================================================
// email-setup — collect and validate email credentials
// ===================================================================
server.tool("email-setup", "Set up the agent's dedicated email account. Validates IMAP and SMTP connectivity before storing credentials. Infers host settings from known providers (Gmail, Outlook, iCloud, Yahoo, Protonmail).", {
    email: z.string().email().describe("The email address for the agent's account (used for IMAP/SMTP authentication)"),
    password: z.string().min(1).describe("The password or app-specific password"),
    agentAddress: z.string().email().optional().describe("The address the agent operates as (for catchall domains where auth email differs from the agent's alias). Defaults to email if not set."),
    imapHost: z.string().optional().describe("IMAP server hostname (auto-inferred for known providers)"),
    imapPort: z.number().int().optional().describe("IMAP port (default: 993 for TLS)"),
    imapSecurity: z.enum(["tls", "starttls"]).optional().describe("IMAP security mode (default: tls)"),
    smtpHost: z.string().optional().describe("SMTP server hostname (auto-inferred for known providers)"),
    smtpPort: z.number().int().optional().describe("SMTP port (default: 587 for STARTTLS)"),
    smtpSecurity: z.enum(["tls", "starttls"]).optional().describe("SMTP security mode (default: starttls)"),
}, async (params) => {
    try {
        const result = await emailSetup({ ...params, accountId });
        const parts = [result.message];
        if (result.providerNotes) {
            parts.push(`\nProvider note: ${result.providerNotes}`);
        }
        return {
            content: [{ type: "text", text: parts.join("") }],
            isError: !result.success,
        };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Email setup failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-read — fetch recent inbox messages
// ===================================================================
server.tool("email-read", "List recent messages (from, subject, date — no body content). Supports filtering by sender, subject, date range, and recipient. Supports pagination via before_uid cursor and folder selection (inbox or sent). Max 50 messages per request.", {
    sender: z.string().optional().describe("Filter by sender address or domain"),
    subjectPattern: z.string().optional().describe("Regex pattern to match subject lines"),
    since: z.string().optional().describe("ISO date — only messages after this date"),
    before: z.string().optional().describe("ISO date — only messages before this date"),
    to: z.string().optional().describe("Filter by recipient address"),
    folder: z.enum(["inbox", "sent"]).optional().describe("Mailbox folder (default: inbox)"),
    before_uid: z.coerce.number().int().optional().describe("Pagination cursor — return messages older than this UID (from previous response's next_before_uid)"),
    limit: z.coerce.number().int().optional().describe("Max messages to return (default: 20, max: 50)"),
}, async (params) => {
    try {
        const text = await emailRead({ ...params, accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Failed to read email: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-send — send an email via SMTP
// ===================================================================
server.tool("email-send", "Send an email from the agent's email account via SMTP.", {
    to: z.string().email().describe("Recipient email address"),
    subject: z.string().describe("Email subject line"),
    body: z.string().describe("Plain text email body"),
    html: z.string().optional().describe("Optional HTML email body"),
}, async (params) => {
    try {
        const text = await emailSend({ ...params, accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Failed to send email: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-search — search inbox by criteria
// ===================================================================
server.tool("email-search", "Search messages by sender, subject, body, or date range. Returns message list (from, subject, date — no body content). Supports pagination via before_uid cursor and folder selection (inbox or sent). Max 50 messages per request.", {
    sender: z.string().optional().describe("Search by sender address or domain"),
    subject: z.string().optional().describe("Search by subject text"),
    body: z.string().optional().describe("Search by keyword in body"),
    since: z.string().optional().describe("ISO date — only messages after this date"),
    before: z.string().optional().describe("ISO date — only messages before this date"),
    to: z.string().optional().describe("Filter by recipient address"),
    folder: z.enum(["inbox", "sent"]).optional().describe("Mailbox folder (default: inbox)"),
    before_uid: z.coerce.number().int().optional().describe("Pagination cursor — return messages older than this UID (from previous response's next_before_uid)"),
    limit: z.coerce.number().int().optional().describe("Max results (default: 20, max: 50)"),
}, async (params) => {
    try {
        const text = await emailSearch({ ...params, accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Email search failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-otp-extract — poll for and extract OTP verification codes
// ===================================================================
server.tool("email-otp-extract", "Poll the agent's email inbox for a verification code (OTP) from a specific sender. Searches recent messages first, then polls at intervals until a matching email arrives or the timeout is reached. Used by other skills during service authentication.", {
    sender: z.string().describe("Expected sender domain (e.g. anthropic.com, cloudflare.com)"),
    subjectPattern: z.string().optional().describe("Optional regex pattern for subject line"),
    timeout: z.number().int().optional().describe("Seconds to poll before giving up (default: 60)"),
}, async (params) => {
    try {
        const result = await emailOtpExtract({ ...params, accountId });
        return {
            content: [{ type: "text", text: result.message }],
            isError: !result.success,
        };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `OTP extraction failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-status — check email connection health
// ===================================================================
server.tool("email-status", "Check the health of the agent's email configuration — IMAP and SMTP connectivity, authentication validity, and inbox status.", {}, async () => {
    try {
        const text = await emailStatus({ accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Email status check failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-reply — reply to an existing email in-thread
// ===================================================================
server.tool("email-reply", "Reply to an email in-thread. Looks up the original message by Message-ID from the email graph, sets In-Reply-To and References headers for correct threading, and sends via SMTP. Use this instead of email-send when responding to a received email.", {
    messageId: z.string().min(1).describe("The Message-ID of the email being replied to (from email-read output)"),
    body: z.string().min(1).describe("Plain text reply body"),
    html: z.string().optional().describe("Optional HTML reply body"),
    replyAll: z.boolean().optional().describe("If true, reply to all original recipients (To + CC). Default: false (reply to sender only)."),
}, async (params) => {
    try {
        const text = await emailReply({ ...params, accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Failed to send reply: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-auto-respond-config — enable/disable auto-respond mode
// ===================================================================
server.tool("email-auto-respond-config", "Configure auto-respond mode. When enabled, a public agent automatically replies to incoming emails. Requires selecting an active public agent to handle responses.", {
    enabled: z.boolean().describe("Enable or disable auto-respond mode"),
    agentSlug: z.string().optional().describe("Slug of the public agent that will handle email responses (required when enabling)"),
    pollIntervalMinutes: z.coerce.number().int().optional().describe("How often to check for new emails, in minutes (default: 5, range: 1–60)"),
    hourlyLimit: z.coerce.number().int().optional().describe("Maximum auto-replies per hour (default: 20, range: 1–1000)"),
    dailyLimit: z.coerce.number().int().optional().describe("Maximum auto-replies per day (default: 100, range: 1–10000)"),
}, async (params) => {
    try {
        const result = await emailAutoRespondConfig({ ...params, accountId });
        const parts = [result.message];
        if (result.agents && result.agents.length > 0) {
            parts.push("\n\nAvailable agents:\n" +
                result.agents
                    .map((a) => `- ${a.displayName} (${a.slug}) — ${a.status}`)
                    .join("\n"));
        }
        return {
            content: [{ type: "text", text: parts.join("") }],
            isError: !result.success,
        };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Auto-respond config failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// email-graph-query — query stored Email nodes in the graph
// ===================================================================
server.tool("email-graph-query", "Query emails stored in the graph. Without a query, lists emails sorted by date (filterable by sender, date range, direction). With a query, runs semantic search over email content. Use this for email history and recall — not for checking the live inbox (use email-read/email-search for that).", {
    query: z.string().optional().describe("Natural-language search query (e.g. 'emails about cabbages'). When omitted, lists all stored emails."),
    sender: z.string().optional().describe("Filter by sender address (case-insensitive substring match)"),
    dateFrom: z.string().optional().describe("ISO date — only emails received on or after this date"),
    dateTo: z.string().optional().describe("ISO date — only emails received on or before this date"),
    direction: z.enum(["inbound", "outbound"]).optional().describe("Filter by direction: inbound (received) or outbound (auto-responded)"),
    offset: z.coerce.number().int().optional().describe("Pagination offset for list mode (default: 0)"),
    limit: z.coerce.number().int().optional().describe("Max results to return (default: 20, max: 50)"),
}, async (params) => {
    try {
        const text = await emailGraphQuery({ ...params, accountId });
        return { content: [{ type: "text", text }] };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Email graph query failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
// ===================================================================
// Lifecycle
// ===================================================================
process.on("SIGINT", async () => {
    await closeDriver();
    process.exit(0);
});
const transport = new StdioServerTransport();
await server.connect(transport);
//# sourceMappingURL=index.js.map