Stream media file reads
This commit is contained in:
parent
11a064c359
commit
d532a5846d
2 changed files with 18 additions and 2 deletions
|
|
@ -81,7 +81,7 @@ The server's directory access control follows this flow:
|
||||||
- **read_media_file**
|
- **read_media_file**
|
||||||
- Read an image or audio file
|
- Read an image or audio file
|
||||||
- Input: `path` (string)
|
- Input: `path` (string)
|
||||||
- Returns base64 data and MIME type based on the file extension
|
- Streams the file and returns base64 data with the corresponding MIME type
|
||||||
|
|
||||||
- **read_multiple_files**
|
- **read_multiple_files**
|
||||||
- Read multiple files simultaneously
|
- Read multiple files simultaneously
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
type Root,
|
type Root,
|
||||||
} from "@modelcontextprotocol/sdk/types.js";
|
} from "@modelcontextprotocol/sdk/types.js";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
|
import { createReadStream } from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
|
|
@ -475,6 +476,21 @@ async function headFile(filePath: string, numLines: number): Promise<string> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stream a file and return its Base64 representation without loading the
|
||||||
|
// entire file into memory at once. Chunks are encoded individually and
|
||||||
|
// concatenated into the final string.
|
||||||
|
async function readFileAsBase64Stream(filePath: string): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const stream = createReadStream(filePath, { encoding: 'base64' });
|
||||||
|
let data = '';
|
||||||
|
stream.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
stream.on('end', () => resolve(data));
|
||||||
|
stream.on('error', (err) => reject(err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Tool handlers
|
// Tool handlers
|
||||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -663,7 +679,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||||
".flac": "audio/flac",
|
".flac": "audio/flac",
|
||||||
};
|
};
|
||||||
const mimeType = mimeTypes[extension] || "application/octet-stream";
|
const mimeType = mimeTypes[extension] || "application/octet-stream";
|
||||||
const data = (await fs.readFile(validPath)).toString("base64");
|
const data = await readFileAsBase64Stream(validPath);
|
||||||
const type = mimeType.startsWith("image/")
|
const type = mimeType.startsWith("image/")
|
||||||
? "image"
|
? "image"
|
||||||
: mimeType.startsWith("audio/")
|
: mimeType.startsWith("audio/")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue