save-streaming-results
Capture and save real-time mortgage rate data to CSV, JSON, or Markdown formats using a session ID from RateSpot MCP Server for efficient analysis and reporting.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | No | Optional custom filename (without extension) | |
| format | No | Output format | csv |
| sessionId | Yes | Session ID from get-mortgage-rates |
Implementation Reference
- ratespot_mcp_server_streaming.ts:517-585 (handler)The handler function for the 'save-streaming-results' tool. It retrieves the streaming session data, generates a filename with timestamp if not provided, formats the data (JSON with metadata and products, Markdown table, or CSV), writes it to a file in the data directory, ensures the file server is running, generates a download URL, and returns a detailed success message with file information.async (params) => { try { const session = activeSessions.get(params.sessionId); if (!session) { return { content: [{ type: "text", text: `Session ${params.sessionId} not found or expired` }], isError: true }; } const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const defaultName = `mortgage_rates_${timestamp}`; const baseName = params.fileName || defaultName; const extension = params.format === 'json' ? 'json' : params.format === 'markdown' ? 'md' : 'csv'; const fileName = `${baseName}.${extension}`; const filePath = path.join(DATA_DIR, fileName); // Format the data let content = ''; if (params.format === 'json') { content = JSON.stringify({ metadata: session.metadata, products: session.data }, null, 2); } else if (params.format === 'markdown') { content = formatResults(session, 'markdown'); } else { content = formatResults(session, 'csv'); } // Save the file await fs.promises.writeFile(filePath, content, 'utf8'); const manager = await getFileServerManager(); await manager.ensureServerRunning(DATA_DIR); const downloadUrl = await manager.getDownloadUrl(fileName); let response = `✅ **Results Saved Successfully**\n\n`; response += `📊 **Summary:**\n`; response += `• Total Products: ${session.data.length}\n`; response += `• Status: ${session.status}\n`; response += `• Format: ${params.format.toUpperCase()}\n\n`; response += `📁 **File Details:**\n`; response += `• Name: ${fileName}\n`; response += `• Size: ${Math.round(content.length / 1024)} KB\n`; response += `• Path: ${filePath}\n`; response += `• Download: ${downloadUrl}\n\n`; response += `💡 Use 'list-saved-results' tool to see all saved files.`; return { content: [{ type: "text", text: response }] }; } catch (error) { return { content: [{ type: "text", text: `Error saving results: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } }
- Input schema for the 'save-streaming-results' tool using Zod validation: requires sessionId, optional format (defaults to csv), optional fileName.{ sessionId: z.string().describe("Session ID from get-mortgage-rates"), format: z.enum(["csv", "json", "markdown"]).default("csv").describe("Output format"), fileName: z.string().optional().describe("Optional custom filename (without extension)") },
- ratespot_mcp_server_streaming.ts:510-586 (registration)Registers the 'save-streaming-results' tool on the MCP server using server.tool(name, inputSchema, handlerFunction).server.tool( "save-streaming-results", { sessionId: z.string().describe("Session ID from get-mortgage-rates"), format: z.enum(["csv", "json", "markdown"]).default("csv").describe("Output format"), fileName: z.string().optional().describe("Optional custom filename (without extension)") }, async (params) => { try { const session = activeSessions.get(params.sessionId); if (!session) { return { content: [{ type: "text", text: `Session ${params.sessionId} not found or expired` }], isError: true }; } const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const defaultName = `mortgage_rates_${timestamp}`; const baseName = params.fileName || defaultName; const extension = params.format === 'json' ? 'json' : params.format === 'markdown' ? 'md' : 'csv'; const fileName = `${baseName}.${extension}`; const filePath = path.join(DATA_DIR, fileName); // Format the data let content = ''; if (params.format === 'json') { content = JSON.stringify({ metadata: session.metadata, products: session.data }, null, 2); } else if (params.format === 'markdown') { content = formatResults(session, 'markdown'); } else { content = formatResults(session, 'csv'); } // Save the file await fs.promises.writeFile(filePath, content, 'utf8'); const manager = await getFileServerManager(); await manager.ensureServerRunning(DATA_DIR); const downloadUrl = await manager.getDownloadUrl(fileName); let response = `✅ **Results Saved Successfully**\n\n`; response += `📊 **Summary:**\n`; response += `• Total Products: ${session.data.length}\n`; response += `• Status: ${session.status}\n`; response += `• Format: ${params.format.toUpperCase()}\n\n`; response += `📁 **File Details:**\n`; response += `• Name: ${fileName}\n`; response += `• Size: ${Math.round(content.length / 1024)} KB\n`; response += `• Path: ${filePath}\n`; response += `• Download: ${downloadUrl}\n\n`; response += `💡 Use 'list-saved-results' tool to see all saved files.`; return { content: [{ type: "text", text: response }] }; } catch (error) { return { content: [{ type: "text", text: `Error saving results: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );
- Helper function formatResults used by the tool to format session data into markdown table, CSV, or JSON string representations.function formatResults(session: StreamSession, format: string = 'markdown'): string { const products = session.data; // Sort by rate products.sort((a, b) => a.rate - b.rate); if (format === 'markdown') { let output = `# Mortgage Rate Results\n\n`; output += `Found ${products.length} mortgage products\n\n`; output += `| Lender | Rate | APR | Payment | Points | Upfront Costs | Type | Quote |\n`; output += `|---------|------|-----|---------|--------|---------------|------|--------|\n`; for (const product of products) { output += `| ${product.lender} | ${product.rate.toFixed(3)}% | ${product.apr.toFixed(3)}% | $${product.payment.toLocaleString()} | ${product.points.toFixed(3)} | $${product.upfrontCosts.toLocaleString()} | ${product.loanType} | ${product.quoteType} |\n`; } return output; } else if (format === 'csv') { let output = 'Lender,Rate,APR,Payment,Points,Upfront_Costs,Loan_Type,Quote_Type\n'; for (const product of products) { output += `${escapeCSV(product.lender)},${product.rate}%,${product.apr}%,$${product.payment},${product.points},$${product.upfrontCosts},${product.loanType},${product.quoteType}\n`; } return output; } else { return JSON.stringify(products, null, 2); } }