check_function_availability
Check available MCP functions based on your Fastmail account permissions, helping you know which operations you can perform.
Instructions
Check which MCP functions are available based on account permissions
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/index.ts:959-965 (registration)Tool 'check_function_availability' is registered in the ListToolsRequestSchema handler with its description and input schema.
name: 'check_function_availability', description: 'Check which MCP functions are available based on account permissions', inputSchema: { type: 'object', properties: {}, }, }, - src/index.ts:1747-1809 (handler)Handler for the 'check_function_availability' tool in the CallToolRequestSchema switch statement. It calls client.getSession() to examine JMAP session capabilities and returns a JSON report on which function categories (email, identity, contacts, calendar) are available, including guidance for enabling missing features.
case 'check_function_availability': { const client = initializeClient(); const session = await client.getSession(); const availability = { email: { available: true, functions: [ 'list_mailboxes', 'list_emails', 'get_email', 'send_email', 'create_draft', 'edit_draft', 'send_draft', 'search_emails', 'get_recent_emails', 'mark_email_read', 'pin_email', 'delete_email', 'move_email', 'get_email_attachments', 'download_attachment', 'advanced_search', 'get_thread', 'get_mailbox_stats', 'get_account_summary', 'bulk_mark_read', 'bulk_pin', 'bulk_move', 'bulk_delete', 'add_labels', 'remove_labels', 'bulk_add_labels', 'bulk_remove_labels' ] }, identity: { available: true, functions: ['list_identities'] }, contacts: { available: !!session.capabilities['urn:ietf:params:jmap:contacts'], functions: ['list_contacts', 'get_contact', 'search_contacts'], note: session.capabilities['urn:ietf:params:jmap:contacts'] ? 'Contacts are available' : 'Contacts access not available - may require enabling in Fastmail account settings', enablementGuide: session.capabilities['urn:ietf:params:jmap:contacts'] ? null : { steps: [ '1. Log into Fastmail web interface', '2. Go to Settings → Privacy & Security → Connected Apps & API tokens', '3. Check if contacts scope is enabled for your API token', '4. If not available, you may need to upgrade your Fastmail plan or contact support' ], documentation: 'https://www.fastmail.com/help/technical/jmap-api.html' } }, calendar: { available: !!session.capabilities['urn:ietf:params:jmap:calendars'], functions: ['list_calendars', 'list_calendar_events', 'get_calendar_event', 'create_calendar_event'], note: session.capabilities['urn:ietf:params:jmap:calendars'] ? 'Calendar is available' : 'Calendar access not available - may require enabling in Fastmail account settings', enablementGuide: session.capabilities['urn:ietf:params:jmap:calendars'] ? null : { steps: [ '1. Log into Fastmail web interface', '2. Go to Settings → Privacy & Security → Connected Apps & API tokens', '3. Check if calendar scope is enabled for your API token', '4. If not available, you may need to upgrade your Fastmail plan or contact support' ], documentation: 'https://www.fastmail.com/help/technical/jmap-api.html' } }, capabilities: Object.keys(session.capabilities) }; return { content: [ { type: 'text', text: JSON.stringify(availability, null, 2), }, ], }; } - src/jmap-client.ts:72-115 (helper)getSession() method on JmapClient fetches the JMAP session from the server, validates URLs, and returns session data including capabilities used by the handler.
async getSession(): Promise<JmapSession> { if (this.session) { return this.session; } const response = await fetch(this.auth.getSessionUrl(), { method: 'GET', headers: this.auth.getAuthHeaders() }); if (!response.ok) { throw new Error(`Failed to get session: ${response.statusText}`); } const sessionData = await response.json() as any; // Validate every URL the server hands us before we send the bearer token to it. // The downloadUrl/uploadUrl are URL templates with {accountId}/{blobId}/etc. // placeholders, so we strip those for parsing and validate origin only. const allowUnsafe = this.auth.getAllowUnsafe(); const stripTemplate = (url: string) => url.replace(/\{[^}]+\}/g, 'x'); if (typeof sessionData.apiUrl !== 'string') { throw new Error('Invalid session response: apiUrl missing'); } validateFastmailUrl(sessionData.apiUrl, 'session.apiUrl', allowUnsafe); if (typeof sessionData.downloadUrl === 'string') { validateFastmailUrl(stripTemplate(sessionData.downloadUrl), 'session.downloadUrl', allowUnsafe); } if (typeof sessionData.uploadUrl === 'string') { validateFastmailUrl(stripTemplate(sessionData.uploadUrl), 'session.uploadUrl', allowUnsafe); } this.session = { apiUrl: sessionData.apiUrl, accountId: sessionData.primaryAccounts?.['urn:ietf:params:jmap:mail'] || sessionData.primaryAccounts?.['urn:ietf:params:jmap:core'] || Object.keys(sessionData.accounts)[0], capabilities: sessionData.capabilities, downloadUrl: sessionData.downloadUrl, uploadUrl: sessionData.uploadUrl }; return this.session; }