@@ -10,6 +10,7 @@ import {
1010 type Root ,
1111} from "@modelcontextprotocol/sdk/types.js" ;
1212import fs from "fs/promises" ;
13+ import { createReadStream } from "fs" ;
1314import path from "path" ;
1415import os from 'os' ;
1516import { randomBytes } from 'crypto' ;
@@ -475,6 +476,21 @@ async function headFile(filePath: string, numLines: number): Promise<string> {
475476 }
476477}
477478
479+ // Stream a file and return its Base64 representation without loading the
480+ // entire file into memory at once. Chunks are encoded individually and
481+ // concatenated into the final string.
482+ async function readFileAsBase64Stream ( filePath : string ) : Promise < string > {
483+ return new Promise ( ( resolve , reject ) => {
484+ const stream = createReadStream ( filePath , { encoding : 'base64' } ) ;
485+ let data = '' ;
486+ stream . on ( 'data' , ( chunk ) => {
487+ data += chunk ;
488+ } ) ;
489+ stream . on ( 'end' , ( ) => resolve ( data ) ) ;
490+ stream . on ( 'error' , ( err ) => reject ( err ) ) ;
491+ } ) ;
492+ }
493+
478494// Tool handlers
479495server . setRequestHandler ( ListToolsRequestSchema , async ( ) => {
480496 return {
@@ -663,7 +679,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
663679 ".flac" : "audio/flac" ,
664680 } ;
665681 const mimeType = mimeTypes [ extension ] || "application/octet-stream" ;
666- const data = ( await fs . readFile ( validPath ) ) . toString ( "base64" ) ;
682+ const data = await readFileAsBase64Stream ( validPath ) ;
667683 const type = mimeType . startsWith ( "image/" )
668684 ? "image"
669685 : mimeType . startsWith ( "audio/" )
0 commit comments