Skip to main content
Glama
jahfer

JMAP MCP Server

by jahfer

get_email_content

Retrieve the full content of a specific email by providing its ID to access message details through the JMAP protocol.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputSchemaYes

Implementation Reference

  • The handler function that implements the core logic for retrieving full email content by ID. It fetches email metadata and body (text/HTML) using JMAP API, downloads blobs if needed, and formats the output as structured text.
    async ({ emailId }) => {
      const session = await jam.session;
      const accountId = session.primaryAccounts["urn:ietf:params:jmap:mail"];
      const [emails] = await jam.api.Email.get({
        accountId,
        ids: [emailId],
        properties: ["id", "textBody", "htmlBody", "subject", "from", "to", "cc", "bcc", "sentAt", "receivedAt"]
      });
    
      if (!emails || emails.list.length === 0) {
        return {
          content: [{
            type: "text",
            text: `Error: Email with ID ${emailId} not found.`
          }],
          isError: true
        };
      }
    
      const email = emails.list[0];
    
      let bodyContent = 'No body content found.';
    
      const downloadBodyPartContent = async (bodyPart) => {
        if (!bodyPart || !bodyPart.blobId) {
          return null;
        }
        try {
          const response = await jam.downloadBlob({
            accountId,
            blobId: bodyPart.blobId,
            mimeType: bodyPart.type || 'application/octet-stream', // Use part type or a default
            fileName: bodyPart.name || 'body_part' // Use part name or a default
          });
          if (response.ok) {
            return response.text(); // Read the response body as text
          } else {
            console.error(`Failed to download blob ${bodyPart.blobId}: ${response.status} ${response.statusText}`);
            return null;
          }
        } catch (error) {
          console.error(`Error downloading blob ${bodyPart.blobId}:`, error);
          return null;
        }
      };
    
      // Prioritize text body, then HTML body
      if (email.textBody && email.textBody.length > 0) {
        // Assuming we only need the content of the first text part for simplicity
        const firstTextPart = email.textBody[0];
        const downloadedText = await downloadBodyPartContent(firstTextPart);
        if (downloadedText !== null) {
          bodyContent = downloadedText;
        }
      } else if (email.htmlBody && email.htmlBody.length > 0) {
         // Assuming we only need the content of the first html part for simplicity
        const firstHtmlPart = email.htmlBody[0];
        const downloadedHtml = await downloadBodyPartContent(firstHtmlPart);
         // Note: For HTML body, you might want to strip HTML tags for a text representation
        if (downloadedHtml !== null) {
          bodyContent = `[HTML Body - may contain tags]\n${downloadedHtml}`; // Indicate it's HTML
        }
      }
    
      return {
        content: [{
          type: "text",
          text: `Subject: ${email.subject || '(No Subject)'}\nFrom: ${email.from ? email.from.map(f => f.name ? `${f.name} <${f.email}>` : f.email).join(', ') : '(Unknown Sender)'}\nTo: ${email.to ? email.to.map(t => t.name ? `${t.name} <${t.email}>` : t.email).join(', ') : '(Unknown Recipient)'}\nDate: ${email.receivedAt || email.sentAt || '(Unknown Date)'}\n\n---\n\n${bodyContent}`
        }]
      };
    }
  • Input schema and description for the get_email_content tool, using Zod for validation of the emailId parameter.
    {
      description: "Retrieves the full content of an email by its ID, including subject, sender, recipients, date, and body (text or HTML).",
      inputSchema: z.object({
        emailId: z.string().describe("The ID of the email to fetch.")
      })
    },
  • index.js:229-230 (registration)
    Registration of the get_email_content tool on the MCP server via server.tool() call.
    server.tool(
      "get_email_content",
  • Nested helper function used by the handler to download email body part content from JMAP blobs.
    const downloadBodyPartContent = async (bodyPart) => {
      if (!bodyPart || !bodyPart.blobId) {
        return null;
      }
      try {
        const response = await jam.downloadBlob({
          accountId,
          blobId: bodyPart.blobId,
          mimeType: bodyPart.type || 'application/octet-stream', // Use part type or a default
          fileName: bodyPart.name || 'body_part' // Use part name or a default
        });
        if (response.ok) {
          return response.text(); // Read the response body as text
        } else {
          console.error(`Failed to download blob ${bodyPart.blobId}: ${response.status} ${response.statusText}`);
          return null;
        }
      } catch (error) {
        console.error(`Error downloading blob ${bodyPart.blobId}:`, error);
        return null;
      }
    };
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/jahfer/jmap-mcp-server'

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