Skip to main content
Glama
contacts-calendar.ts10.2 kB
import { JmapClient, JmapRequest } from './jmap-client.js'; export class ContactsCalendarClient extends JmapClient { private async checkContactsPermission(): Promise<boolean> { const session = await this.getSession(); return !!session.capabilities['urn:ietf:params:jmap:contacts']; } private async checkCalendarsPermission(): Promise<boolean> { const session = await this.getSession(); return !!session.capabilities['urn:ietf:params:jmap:calendars']; } async getContacts(limit: number = 50): Promise<any[]> { // Check permissions first const hasPermission = await this.checkContactsPermission(); if (!hasPermission) { throw new Error('Contacts access not available. This account may not have JMAP contacts permissions enabled. Please check your Fastmail account settings or contact support to enable contacts API access.'); } const session = await this.getSession(); // Try CardDAV namespace first, then Fastmail specific const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:contacts'], methodCalls: [ ['Contact/query', { accountId: session.accountId, limit }, 'query'], ['Contact/get', { accountId: session.accountId, '#ids': { resultOf: 'query', name: 'Contact/query', path: '/ids' }, properties: ['id', 'name', 'emails', 'phones', 'addresses', 'notes'] }, 'contacts'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[1][1].list; } catch (error) { // Fallback: try to get contacts using AddressBook methods const fallbackRequest: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:contacts'], methodCalls: [ ['AddressBook/get', { accountId: session.accountId }, 'addressbooks'] ] }; try { const fallbackResponse = await this.makeRequest(fallbackRequest); return fallbackResponse.methodResponses[0][1].list || []; } catch (fallbackError) { throw new Error(`Contacts not supported or accessible: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling contacts API access in Fastmail settings.`); } } } async getContactById(id: string): Promise<any> { // Check permissions first const hasPermission = await this.checkContactsPermission(); if (!hasPermission) { throw new Error('Contacts access not available. This account may not have JMAP contacts permissions enabled. Please check your Fastmail account settings or contact support to enable contacts API access.'); } const session = await this.getSession(); const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:contacts'], methodCalls: [ ['Contact/get', { accountId: session.accountId, ids: [id] }, 'contact'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[0][1].list[0]; } catch (error) { throw new Error(`Contact access not supported: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling contacts API access in Fastmail settings.`); } } async searchContacts(query: string, limit: number = 20): Promise<any[]> { // Check permissions first const hasPermission = await this.checkContactsPermission(); if (!hasPermission) { throw new Error('Contacts access not available. This account may not have JMAP contacts permissions enabled. Please check your Fastmail account settings or contact support to enable contacts API access.'); } const session = await this.getSession(); const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:contacts'], methodCalls: [ ['Contact/query', { accountId: session.accountId, filter: { text: query }, limit }, 'query'], ['Contact/get', { accountId: session.accountId, '#ids': { resultOf: 'query', name: 'Contact/query', path: '/ids' }, properties: ['id', 'name', 'emails', 'phones', 'addresses', 'notes'] }, 'contacts'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[1][1].list; } catch (error) { throw new Error(`Contact search not supported: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling contacts API access in Fastmail settings.`); } } async getCalendars(): Promise<any[]> { // Check permissions first const hasPermission = await this.checkCalendarsPermission(); if (!hasPermission) { throw new Error('Calendar access not available. This account may not have JMAP calendar permissions enabled. Please check your Fastmail account settings or contact support to enable calendar API access.'); } const session = await this.getSession(); const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:calendars'], methodCalls: [ ['Calendar/get', { accountId: session.accountId }, 'calendars'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[0][1].list; } catch (error) { // Calendar access might require special permissions throw new Error(`Calendar access not supported or requires additional permissions. This may be due to account settings or JMAP scope limitations: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling calendar API access in Fastmail settings.`); } } async getCalendarEvents(calendarId?: string, limit: number = 50): Promise<any[]> { // Check permissions first const hasPermission = await this.checkCalendarsPermission(); if (!hasPermission) { throw new Error('Calendar access not available. This account may not have JMAP calendar permissions enabled. Please check your Fastmail account settings or contact support to enable calendar API access.'); } const session = await this.getSession(); const filter = calendarId ? { inCalendar: calendarId } : {}; const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:calendars'], methodCalls: [ ['CalendarEvent/query', { accountId: session.accountId, filter, sort: [{ property: 'start', isAscending: true }], limit }, 'query'], ['CalendarEvent/get', { accountId: session.accountId, '#ids': { resultOf: 'query', name: 'CalendarEvent/query', path: '/ids' }, properties: ['id', 'title', 'description', 'start', 'end', 'location', 'participants'] }, 'events'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[1][1].list; } catch (error) { throw new Error(`Calendar events access not supported: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling calendar API access in Fastmail settings.`); } } async getCalendarEventById(id: string): Promise<any> { // Check permissions first const hasPermission = await this.checkCalendarsPermission(); if (!hasPermission) { throw new Error('Calendar access not available. This account may not have JMAP calendar permissions enabled. Please check your Fastmail account settings or contact support to enable calendar API access.'); } const session = await this.getSession(); const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:calendars'], methodCalls: [ ['CalendarEvent/get', { accountId: session.accountId, ids: [id] }, 'event'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[0][1].list[0]; } catch (error) { throw new Error(`Calendar event access not supported: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling calendar API access in Fastmail settings.`); } } async createCalendarEvent(event: { calendarId: string; title: string; description?: string; start: string; // ISO 8601 format end: string; // ISO 8601 format location?: string; participants?: Array<{ email: string; name?: string }>; }): Promise<string> { // Check permissions first const hasPermission = await this.checkCalendarsPermission(); if (!hasPermission) { throw new Error('Calendar access not available. This account may not have JMAP calendar permissions enabled. Please check your Fastmail account settings or contact support to enable calendar API access.'); } const session = await this.getSession(); const eventObject = { calendarId: event.calendarId, title: event.title, description: event.description || '', start: event.start, end: event.end, location: event.location || '', participants: event.participants || [] }; const request: JmapRequest = { using: ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:calendars'], methodCalls: [ ['CalendarEvent/set', { accountId: session.accountId, create: { newEvent: eventObject } }, 'createEvent'] ] }; try { const response = await this.makeRequest(request); return response.methodResponses[0][1].created.newEvent.id; } catch (error) { throw new Error(`Calendar event creation not supported: ${error instanceof Error ? error.message : String(error)}. Try checking account permissions or enabling calendar API access in Fastmail settings.`); } } }

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/MadLlama25/fastmail-mcp'

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