UNPKG

fireflies-mcp-server

Version:

MCP server for Fireflies.ai API integration

362 lines (333 loc) 9.34 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; // Fireflies API client class FirefliesClient { private apiKey: string; private baseUrl = "https://api.fireflies.ai/graphql"; constructor(apiKey: string) { this.apiKey = apiKey; } private async makeRequest(query: string, variables: any = {}) { const response = await fetch(this.baseUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${this.apiKey}`, }, body: JSON.stringify({ query, variables, }), }); if (!response.ok) { throw new Error(`Fireflies API error: ${response.status} ${response.statusText}`); } const data = await response.json(); if (data.errors) { throw new Error(`GraphQL errors: ${JSON.stringify(data.errors)}`); } return data.data; } async getTranscripts(limit: number = 10, fromDate?: string, toDate?: string) { const query = ` query GetTranscripts($limit: Int, $fromDate: DateTime, $toDate: DateTime, $mine: Boolean) { transcripts(limit: $limit, fromDate: $fromDate, toDate: $toDate, mine: $mine) { id title date duration host_email participants transcript_url summary { overview shorthand_bullet action_items keywords outline bullet_gist short_summary } } } `; return this.makeRequest(query, { limit, fromDate, toDate, mine: true }); } async getTranscriptDetails(transcriptId: string) { const query = ` query GetTranscript($transcriptId: String!) { transcript(id: $transcriptId) { id title date duration host_email participants transcript_url sentences { text speaker_name start_time end_time } summary { overview shorthand_bullet action_items keywords outline bullet_gist short_summary } } } `; return this.makeRequest(query, { transcriptId }); } async searchTranscripts(query: string, limit: number = 10) { const searchQuery = ` query SearchTranscripts($title: String, $limit: Int, $mine: Boolean) { transcripts(title: $title, limit: $limit, mine: $mine) { id title date duration host_email participants summary { overview keywords short_summary } } } `; return this.makeRequest(searchQuery, { title: query, limit, mine: true }); } async generateSummary(transcriptId: string, format: string = "bullet_points") { const query = ` query GetSummary($transcriptId: String!) { transcript(id: $transcriptId) { id title summary { overview shorthand_bullet action_items keywords outline bullet_gist short_summary } } } `; const result = await this.makeRequest(query, { transcriptId }); const summary = result.transcript.summary; if (format === "paragraph") { return { transcript_id: transcriptId, title: result.transcript.title, format: "paragraph", summary: summary.overview, }; } else { return { transcript_id: transcriptId, title: result.transcript.title, format: "bullet_points", summary: { overview: summary.overview, bullet_points: summary.shorthand_bullet, action_items: summary.action_items, keywords: summary.keywords, short_summary: summary.short_summary, }, }; } } } // MCP Server setup const server = new Server( { name: "fireflies-mcp-server", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); // Initialize Fireflies client const apiKey = process.env.FIREFLIES_API_KEY; if (!apiKey) { console.error("FIREFLIES_API_KEY environment variable is required"); process.exit(1); } const firefliesClient = new FirefliesClient(apiKey); // Register tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "fireflies_get_transcripts", description: "Retrieve a list of meeting transcripts with optional filtering", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Maximum number of transcripts to return (default: 10)", default: 10, }, from_date: { type: "string", description: "Start date in ISO format (YYYY-MM-DD)", }, to_date: { type: "string", description: "End date in ISO format (YYYY-MM-DD)", }, }, }, }, { name: "fireflies_get_transcript_details", description: "Get detailed information about a specific transcript", inputSchema: { type: "object", properties: { transcript_id: { type: "string", description: "ID of the transcript to retrieve", }, }, required: ["transcript_id"], }, }, { name: "fireflies_search_transcripts", description: "Search for transcripts containing specific keywords", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query to find relevant transcripts", }, limit: { type: "number", description: "Maximum number of transcripts to return (default: 10)", default: 10, }, }, required: ["query"], }, }, { name: "fireflies_generate_summary", description: "Generate a summary of a meeting transcript", inputSchema: { type: "object", properties: { transcript_id: { type: "string", description: "ID of the transcript to summarize", }, format: { type: "string", description: "Format of the summary ('bullet_points' or 'paragraph')", enum: ["bullet_points", "paragraph"], default: "bullet_points", }, }, required: ["transcript_id"], }, }, ], }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "fireflies_get_transcripts": { const { limit = 10, from_date, to_date } = args as any; const result = await firefliesClient.getTranscripts(limit, from_date, to_date); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "fireflies_get_transcript_details": { const { transcript_id } = args as any; const result = await firefliesClient.getTranscriptDetails(transcript_id); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "fireflies_search_transcripts": { const { query, limit = 10 } = args as any; const result = await firefliesClient.searchTranscripts(query, limit); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "fireflies_generate_summary": { const { transcript_id, format = "bullet_points" } = args as any; const result = await firefliesClient.generateSummary(transcript_id, format); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Fireflies MCP server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });