summarizeWhiteboard
Extract and condense content from Heptabase whiteboards into text or structured formats, optionally including statistics for efficient analysis and review.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | text | |
| includeStatistics | No | ||
| whiteboardId | Yes |
Implementation Reference
- src/tools/export.ts:60-82 (handler)Core handler function that fetches whiteboard data via dataService.getWhiteboard and generates the summary by calling appropriate helper functions based on format.export async function summarizeWhiteboard( dataService: HeptabaseDataService, params: z.infer<typeof summarizeWhiteboardSchema> ) { const data = await dataService.getWhiteboard(params.whiteboardId, { includeCards: true, includeConnections: true }); let summary = ''; if (params.format === 'text') { summary = await generateTextSummary(data, params); } else { summary = await generateStructuredSummary(data, params); } return { content: [{ type: 'text', text: summary }] };
- src/tools/export.ts:15-19 (schema)Zod input schema defining parameters: whiteboardId (string, required), format (enum text/structured, optional default 'text'), includeStatistics (boolean, optional default false).export const summarizeWhiteboardSchema = z.object({ whiteboardId: z.string(), format: z.enum(['text', 'structured']).optional().default('text'), includeStatistics: z.boolean().optional().default(false) });
- src/server.ts:683-694 (registration)Registers the tool internally (this.tools) and with the MCP server (this.server.tool), providing schema and a wrapper handler that ensures data service initialization before calling the core handler.// summarizeWhiteboard tool this.tools.summarizeWhiteboard = { inputSchema: summarizeWhiteboardSchema, handler: async (params) => { await this.ensureDataServiceInitialized(); return summarizeWhiteboard(this.dataService, params); } }; this.server.tool('summarizeWhiteboard', summarizeWhiteboardSchema.shape, async (params: z.infer<typeof summarizeWhiteboardSchema>) => { return this.tools.summarizeWhiteboard.handler(params); });
- src/tools/export.ts:82-255 (helper)Utility helper to recursively extract text content from nested Heptabase card content structures, used in summary generation.}; } async function generateMarkdownExport(data: any, params: any): Promise<string> { const lines: string[] = []; lines.push(`# ${data.whiteboard.name}`); lines.push(''); if (params.includeMetadata) { lines.push('## Metadata'); lines.push(`- Created: ${data.whiteboard.createdTime}`); lines.push(`- Last Modified: ${data.whiteboard.lastEditedTime}`); lines.push(`- Created By: ${data.whiteboard.createdBy}`); lines.push(''); } if (data.cards?.length > 0) { lines.push('## Cards'); lines.push(''); for (const card of data.cards) { lines.push(`### ${card.title}`); const content = JSON.parse(card.content); const text = extractTextFromContent(content); lines.push(text); lines.push(''); } } if (data.connections?.length > 0) { lines.push('## Connections'); lines.push(''); for (const connection of data.connections) { lines.push(`- ${connection.beginId} → ${connection.endId}`); } lines.push(''); } return lines.join('\n'); } async function generateHtmlExport(data: any, params: any): Promise<string> { const lines: string[] = []; lines.push('<!DOCTYPE html>'); lines.push('<html>'); lines.push('<head>'); lines.push(`<title>${data.whiteboard.name}</title>`); lines.push('</head>'); lines.push('<body>'); lines.push(`<h1>${data.whiteboard.name}</h1>`); if (params.includeMetadata) { lines.push('<div class="metadata">'); lines.push(`<p>Created: ${data.whiteboard.createdTime}</p>`); lines.push(`<p>Last Modified: ${data.whiteboard.lastEditedTime}</p>`); lines.push(`<p>Created By: ${data.whiteboard.createdBy}</p>`); lines.push('</div>'); } if (data.cards?.length > 0) { lines.push('<h2>Cards</h2>'); for (const card of data.cards) { lines.push(`<div class="card">`); lines.push(`<h3>${card.title}</h3>`); const content = JSON.parse(card.content); const text = extractTextFromContent(content); lines.push(`<p>${text}</p>`); lines.push('</div>'); } } lines.push('</body>'); lines.push('</html>'); return lines.join('\n'); } async function generateTextSummary(data: any, params: any): Promise<string> { const lines: string[] = []; lines.push(`${data.whiteboard.name}`); lines.push(''); const cardCount = data.cards?.length || 0; const connectionCount = data.connections?.length || 0; lines.push(`Summary: ${cardCount} cards, ${connectionCount} connections`); lines.push(''); if (params.includeStatistics) { let totalWords = 0; let totalChars = 0; if (data.cards) { for (const card of data.cards) { const content = JSON.parse(card.content); const text = extractTextFromContent(content); totalWords += text.split(/\s+/).length; totalChars += text.length; } } lines.push('Statistics:'); lines.push(`- Word count: ${totalWords}`); lines.push(`- Character count: ${totalChars}`); lines.push(''); } if (data.cards?.length > 0) { lines.push('Cards:'); for (const card of data.cards) { lines.push(`- ${card.title}`); } } return lines.join('\n'); } async function generateStructuredSummary(data: any, params: any): Promise<string> { const lines: string[] = []; lines.push('# Summary: ' + data.whiteboard.name); lines.push(''); lines.push('## Overview'); lines.push(`- Total Cards: ${data.cards?.length || 0}`); lines.push(`- Total Connections: ${data.connections?.length || 0}`); lines.push(''); lines.push('## Key Topics'); if (data.cards?.length > 0) { for (const card of data.cards.slice(0, 5)) { lines.push(`- ${card.title}`); } if (data.cards.length > 5) { lines.push(`- ... and ${data.cards.length - 5} more`); } } lines.push(''); lines.push('## Statistics'); const cardCount = data.cards?.length || 0; const connectionCount = data.connections?.length || 0; lines.push(`- ${cardCount} cards`); lines.push(`- ${connectionCount} connections`); if (params.includeStatistics) { // Calculate additional statistics let totalWords = 0; let totalChars = 0; if (data.cards) { for (const card of data.cards) { const content = JSON.parse(card.content); const text = extractTextFromContent(content); totalWords += text.split(/\s+/).length; totalChars += text.length; } } lines.push(`- Word count: ${totalWords}`); lines.push(`- Character count: ${totalChars}`); } return lines.join('\n'); } function extractTextFromContent(content: any): string {
- src/tools/export.ts:165-204 (helper)Helper function for generating simple text summary, listing whiteboard name, counts, optional stats (word/char count), and card titles.async function generateTextSummary(data: any, params: any): Promise<string> { const lines: string[] = []; lines.push(`${data.whiteboard.name}`); lines.push(''); const cardCount = data.cards?.length || 0; const connectionCount = data.connections?.length || 0; lines.push(`Summary: ${cardCount} cards, ${connectionCount} connections`); lines.push(''); if (params.includeStatistics) { let totalWords = 0; let totalChars = 0; if (data.cards) { for (const card of data.cards) { const content = JSON.parse(card.content); const text = extractTextFromContent(content); totalWords += text.split(/\s+/).length; totalChars += text.length; } } lines.push('Statistics:'); lines.push(`- Word count: ${totalWords}`); lines.push(`- Character count: ${totalChars}`); lines.push(''); } if (data.cards?.length > 0) { lines.push('Cards:'); for (const card of data.cards) { lines.push(`- ${card.title}`); } } return lines.join('\n'); }