Skip to main content
Glama

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
NameRequiredDescriptionDefault
recipientYesEmail recipient
subjectYesEmail subject
bodyYesEmail body

Implementation Reference

  • 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
      `,
  • 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"],
    },
  • 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: {},
          },
        })),
      ),
    }));
  • 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);

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/joshrutkowski/applescript-mcp'

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