Skip to main content
Glama
matthewbergvinson

Fathom MCP Server

get_action_items

Extract action items from Fathom meeting recordings to track tasks and follow-ups. Specify a recording ID or check recent meetings for pending items.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
recording_idNoGet action items from a specific meeting
include_completedNoInclude completed action items (default: true)
limitNoNumber of recent meetings to check if no recording_id (default: 10)

Implementation Reference

  • Main handler function: Fetches meetings using Fathom client (specific recording or recent), extracts and filters action items (by completion status), formats into markdown sections using formatActionItems and formatDate.
    async ({ recording_id, include_completed, limit }) => {
      const meetingLimit = limit || 10;
      console.error(recording_id ? `Getting action items for ${recording_id}...` : `Getting action items from recent meetings...`);
    
      if (recording_id) {
        const response = await fathom.listMeetings({ include_action_items: true });
        const meeting = response.items.find(m => m.recording_id === recording_id);
    
        if (!meeting) {
          return {
            content: [{ type: 'text', text: `Meeting with recording ID ${recording_id} not found.` }],
            isError: true,
          };
        }
    
        let items = meeting.action_items || [];
        if (include_completed === false) {
          items = items.filter(i => !i.completed);
        }
    
        const title = meeting.title || meeting.meeting_title || `Meeting ${meeting.recording_id}`;
        const markdown = `## Action Items from: ${title}\n\n${formatActionItems(items)}`;
        
        return {
          content: [{ type: 'text', text: markdown }],
        };
      } else {
        const response = await fathom.listMeetings({ include_action_items: true });
        const meetings = response.items.slice(0, meetingLimit);
    
        const sections: string[] = [];
        for (const meeting of meetings) {
          let items = meeting.action_items || [];
          if (items.length === 0) continue;
    
          if (include_completed === false) {
            items = items.filter(i => !i.completed);
          }
          if (items.length === 0) continue;
    
          const title = meeting.title || meeting.meeting_title || `Meeting ${meeting.recording_id}`;
          const date = formatDate(meeting.recording_start_time);
          sections.push(`### ${title}\n_${date}_\n\n${formatActionItems(items)}`);
        }
    
        const markdown = sections.length > 0
          ? `# Action Items from Recent Meetings\n\n${sections.join('\n\n')}`
          : 'No action items found in recent meetings.';
    
        return {
          content: [{ type: 'text', text: markdown }],
        };
      }
    }
  • Zod schema defining input parameters for the tool.
    {
      recording_id: z.number().optional().describe('Get action items from a specific meeting'),
      include_completed: z.boolean().optional().describe('Include completed action items (default: true)'),
      limit: z.number().optional().describe('Number of recent meetings to check if no recording_id (default: 10)'),
    },
  • src/index.ts:267-327 (registration)
    Registers the 'get_action_items' tool on the MCP server with schema and handler function.
      'get_action_items',
      {
        recording_id: z.number().optional().describe('Get action items from a specific meeting'),
        include_completed: z.boolean().optional().describe('Include completed action items (default: true)'),
        limit: z.number().optional().describe('Number of recent meetings to check if no recording_id (default: 10)'),
      },
      async ({ recording_id, include_completed, limit }) => {
        const meetingLimit = limit || 10;
        console.error(recording_id ? `Getting action items for ${recording_id}...` : `Getting action items from recent meetings...`);
    
        if (recording_id) {
          const response = await fathom.listMeetings({ include_action_items: true });
          const meeting = response.items.find(m => m.recording_id === recording_id);
    
          if (!meeting) {
            return {
              content: [{ type: 'text', text: `Meeting with recording ID ${recording_id} not found.` }],
              isError: true,
            };
          }
    
          let items = meeting.action_items || [];
          if (include_completed === false) {
            items = items.filter(i => !i.completed);
          }
    
          const title = meeting.title || meeting.meeting_title || `Meeting ${meeting.recording_id}`;
          const markdown = `## Action Items from: ${title}\n\n${formatActionItems(items)}`;
          
          return {
            content: [{ type: 'text', text: markdown }],
          };
        } else {
          const response = await fathom.listMeetings({ include_action_items: true });
          const meetings = response.items.slice(0, meetingLimit);
    
          const sections: string[] = [];
          for (const meeting of meetings) {
            let items = meeting.action_items || [];
            if (items.length === 0) continue;
    
            if (include_completed === false) {
              items = items.filter(i => !i.completed);
            }
            if (items.length === 0) continue;
    
            const title = meeting.title || meeting.meeting_title || `Meeting ${meeting.recording_id}`;
            const date = formatDate(meeting.recording_start_time);
            sections.push(`### ${title}\n_${date}_\n\n${formatActionItems(items)}`);
          }
    
          const markdown = sections.length > 0
            ? `# Action Items from Recent Meetings\n\n${sections.join('\n\n')}`
            : 'No action items found in recent meetings.';
    
          return {
            content: [{ type: 'text', text: markdown }],
          };
        }
      }
    );
  • Helper function to format action items into markdown list with completion status, assignee, and timestamp.
    export function formatActionItems(actionItems: ActionItem[] | null | undefined): string {
      if (!actionItems || actionItems.length === 0) {
        return '_No action items_';
      }
    
      return actionItems.map(item => {
        const status = item.completed ? '[x]' : '[ ]';
        const assignee = item.assignee ? ` _(assigned to ${item.assignee.name})_` : '';
        const timestamp = item.recording_timestamp ? ` at ${item.recording_timestamp}` : '';
        return `- ${status} ${item.description}${assignee}${timestamp}`;
      }).join('\n');
    }

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/matthewbergvinson/fathom-mcp'

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