get_thread
Retrieve all emails in a Fastmail conversation thread using the thread ID to view complete email exchanges.
Instructions
Get all emails in a conversation thread
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| threadId | Yes | ID of the thread/conversation |
Implementation Reference
- src/index.ts:1028-1048 (handler)MCP tool handler for 'get_thread': validates threadId parameter, initializes JmapClient, calls getThread, and returns JSON-formatted thread data or error.case 'get_thread': { const { threadId } = args as any; if (!threadId) { throw new McpError(ErrorCode.InvalidParams, 'threadId is required'); } const client = initializeClient(); try { const thread = await client.getThread(threadId); return { content: [ { type: 'text', text: JSON.stringify(thread, null, 2), }, ], }; } catch (error) { // Provide helpful error information throw new McpError(ErrorCode.InternalError, `Thread access failed: ${error instanceof Error ? error.message : String(error)}`); } }
- src/index.ts:535-547 (schema)Tool schema definition including name, description, and inputSchema for validating threadId parameter.name: 'get_thread', description: 'Get all emails in a conversation thread', inputSchema: { type: 'object', properties: { threadId: { type: 'string', description: 'ID of the thread/conversation', }, }, required: ['threadId'], }, },
- src/jmap-client.ts:553-607 (helper)JmapClient.getThread implementation: resolves threadId if it's an email ID, performs Thread/get and Email/get via JMAP to fetch all emails in the thread.async getThread(threadId: string): Promise<any[]> { const session = await this.getSession(); // First, check if threadId is actually an email ID and resolve the thread let actualThreadId = threadId; // Try to get the email first to see if we need to resolve thread ID try { const emailRequest: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:mail'], methodCalls: [ ['Email/get', { accountId: session.accountId, ids: [threadId], properties: ['threadId'] }, 'checkEmail'] ] }; const emailResponse = await this.makeRequest(emailRequest); const email = emailResponse.methodResponses[0][1].list[0]; if (email && email.threadId) { actualThreadId = email.threadId; } } catch (error) { // If email lookup fails, assume threadId is correct } // Use Thread/get with the resolved thread ID const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:mail'], methodCalls: [ ['Thread/get', { accountId: session.accountId, ids: [actualThreadId] }, 'getThread'], ['Email/get', { accountId: session.accountId, '#ids': { resultOf: 'getThread', name: 'Thread/get', path: '/list/*/emailIds' }, properties: ['id', 'subject', 'from', 'to', 'cc', 'receivedAt', 'preview', 'hasAttachment', 'keywords', 'threadId'] }, 'emails'] ] }; const response = await this.makeRequest(request); const threadResult = response.methodResponses[0][1]; // Check if thread was found if (threadResult.notFound && threadResult.notFound.includes(actualThreadId)) { throw new Error(`Thread with ID '${actualThreadId}' not found`); } return response.methodResponses[1][1].list; }