mail_create_email
Create new emails in Mail.app by specifying recipient, subject, and body content through AppleScript automation.
Instructions
[Mail operations] Create a new email in Mail.app
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| recipient | Yes | Email recipient | |
| subject | Yes | Email subject | |
| body | Yes | Email body |
Implementation Reference
- src/categories/mail.ts:13-71 (handler)Full tool definition including handler script (AppleScript template), schema, and internal urlEncode helper for mail_create_email (constructed as mail_create_email). The handler generates and executes AppleScript to create email via mailto URL.{ name: "create_email", description: "Create a new email in Mail.app", schema: { type: "object", properties: { recipient: { type: "string", description: "Email recipient", }, subject: { type: "string", description: "Email subject", }, body: { type: "string", description: "Email body", }, }, required: ["recipient", "subject", "body"], }, script: (args) => ` set recipient to "${args.recipient}" set subject to "${args.subject}" set body to "${args.body}" -- URL encode subject and body set encodedSubject to my urlEncode(subject) set encodedBody to my urlEncode(body) -- Construct the mailto URL set mailtoURL to "mailto:" & recipient & "?subject=" & encodedSubject & "&body=" & encodedBody -- Use Apple Mail's 'mailto' command to create the email tell application "Mail" mailto mailtoURL activate end tell -- Handler to URL-encode text on urlEncode(theText) set theEncodedText to "" set theChars to every character of theText repeat with aChar in theChars set charCode to ASCII number aChar if charCode = 32 then set theEncodedText to theEncodedText & "%20" -- Space else if (charCode ≥ 48 and charCode ≤ 57) or (charCode ≥ 65 and charCode ≤ 90) or (charCode ≥ 97 and charCode ≤ 122) or charCode = 45 or charCode = 46 or charCode = 95 or charCode = 126 then -- Allowed characters: A-Z, a-z, 0-9, -, ., _, ~ set theEncodedText to theEncodedText & aChar else -- Convert to %HH format set hexCode to do shell script "printf '%02X' " & charCode set theEncodedText to theEncodedText & "%" & hexCode end if end repeat return theEncodedText end urlEncode `,
- src/categories/mail.ts:16-33 (schema)Input schema defining required recipient, subject, body for create_email tool.schema: { type: "object", properties: { recipient: { type: "string", description: "Email recipient", }, subject: { type: "string", description: "Email subject", }, body: { type: "string", description: "Email body", }, }, required: ["recipient", "subject", "body"], },
- src/framework.ts:221-232 (registration)Dynamic tool registration in listTools handler: constructs 'mail_create_email' from category 'mail' + script 'create_email'.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: this.categories.flatMap((category) => category.scripts.map((script) => ({ name: `${category.name}_${script.name}`, // Changed from dot to underscore description: `[${category.description}] ${script.description}`, inputSchema: script.schema || { type: "object", properties: {}, }, })), ), }));
- src/framework.ts:235-331 (handler)Generic MCP tool call handler: resolves 'mail_create_email' to mail category + create_email script, generates AppleScript from template with args, executes via osascript.this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const toolName = request.params.name; this.log("info", "Tool execution requested", { tool: toolName, hasArguments: !!request.params.arguments }); try { // Split on underscore instead of dot const [categoryName, ...scriptNameParts] = toolName.split("_"); const scriptName = scriptNameParts.join("_"); // Rejoin in case script name has underscores const category = this.categories.find((c) => c.name === categoryName); if (!category) { this.log("warning", "Category not found", { categoryName }); throw new McpError( ErrorCode.MethodNotFound, `Category not found: ${categoryName}`, ); } const script = category.scripts.find((s) => s.name === scriptName); if (!script) { this.log("warning", "Script not found", { categoryName, scriptName }); throw new McpError( ErrorCode.MethodNotFound, `Script not found: ${scriptName}`, ); } this.log("debug", "Generating script content", { categoryName, scriptName, isFunction: typeof script.script === "function" }); const scriptContent = typeof script.script === "function" ? script.script(request.params.arguments) : script.script; const result = await this.executeScript(scriptContent); this.log("info", "Tool execution completed successfully", { tool: toolName, resultLength: result.length }); return { content: [ { type: "text", text: result, }, ], }; } catch (error) { if (error instanceof McpError) { this.log("error", "MCP error during tool execution", { tool: toolName, errorCode: error.code, errorMessage: error.message }); throw error; } let errorMessage = "Unknown error occurred"; if (error && typeof error === "object") { if ("message" in error && typeof error.message === "string") { errorMessage = error.message; } else if (error instanceof Error) { errorMessage = error.message; } } else if (typeof error === "string") { errorMessage = error; } this.log("error", "Error during tool execution", { tool: toolName, errorMessage }); return { content: [ { type: "text", text: `Error: ${errorMessage}`, }, ], isError: true, }; } });
- src/index.ts:31-31 (registration)Registers the mail category (containing create_email) with the framework server.server.addCategory(mailCategory);