mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-18 00:03:23 +02:00
Rename read_file to read_text_file and add read_media_file
This commit is contained in:
@@ -70,10 +70,18 @@ The server's directory access control follows this flow:
|
||||
|
||||
### Tools
|
||||
|
||||
- **read_file**
|
||||
- Read complete contents of a file
|
||||
- **read_text_file**
|
||||
- Read complete contents of a file as text
|
||||
- Inputs:
|
||||
- `path` (string)
|
||||
- `head` (number, optional): First N lines
|
||||
- `tail` (number, optional): Last N lines
|
||||
- Always treats the file as UTF-8 text regardless of extension
|
||||
|
||||
- **read_media_file**
|
||||
- Read an image or audio file
|
||||
- Input: `path` (string)
|
||||
- Reads complete file contents with UTF-8 encoding
|
||||
- Returns base64 data and MIME type based on the file extension
|
||||
|
||||
- **read_multiple_files**
|
||||
- Read multiple files simultaneously
|
||||
|
||||
@@ -116,12 +116,16 @@ async function validatePath(requestedPath: string): Promise<string> {
|
||||
}
|
||||
|
||||
// Schema definitions
|
||||
const ReadFileArgsSchema = z.object({
|
||||
const ReadTextFileArgsSchema = z.object({
|
||||
path: z.string(),
|
||||
tail: z.number().optional().describe('If provided, returns only the last N lines of the file'),
|
||||
head: z.number().optional().describe('If provided, returns only the first N lines of the file')
|
||||
});
|
||||
|
||||
const ReadMediaFileArgsSchema = z.object({
|
||||
path: z.string()
|
||||
});
|
||||
|
||||
const ReadMultipleFilesArgsSchema = z.object({
|
||||
paths: z.array(z.string()),
|
||||
});
|
||||
@@ -476,15 +480,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: [
|
||||
{
|
||||
name: "read_file",
|
||||
name: "read_text_file",
|
||||
description:
|
||||
"Read the complete contents of a file from the file system. " +
|
||||
"Read the complete contents of a file from the file system as text. " +
|
||||
"Handles various text encodings and provides detailed error messages " +
|
||||
"if the file cannot be read. Use this tool when you need to examine " +
|
||||
"the contents of a single file. Use the 'head' parameter to read only " +
|
||||
"the first N lines of a file, or the 'tail' parameter to read only " +
|
||||
"the last N lines of a file. Only works within allowed directories.",
|
||||
inputSchema: zodToJsonSchema(ReadFileArgsSchema) as ToolInput,
|
||||
"the last N lines of a file. Operates on the file as text regardless of extension. " +
|
||||
"Only works within allowed directories.",
|
||||
inputSchema: zodToJsonSchema(ReadTextFileArgsSchema) as ToolInput,
|
||||
},
|
||||
{
|
||||
name: "read_media_file",
|
||||
description:
|
||||
"Read an image or audio file. Returns the base64 encoded data and MIME type. " +
|
||||
"Only works within allowed directories.",
|
||||
inputSchema: zodToJsonSchema(ReadMediaFileArgsSchema) as ToolInput,
|
||||
},
|
||||
{
|
||||
name: "read_multiple_files",
|
||||
@@ -597,10 +609,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
switch (name) {
|
||||
case "read_file": {
|
||||
const parsed = ReadFileArgsSchema.safeParse(args);
|
||||
case "read_text_file": {
|
||||
const parsed = ReadTextFileArgsSchema.safeParse(args);
|
||||
if (!parsed.success) {
|
||||
throw new Error(`Invalid arguments for read_file: ${parsed.error}`);
|
||||
throw new Error(`Invalid arguments for read_text_file: ${parsed.error}`);
|
||||
}
|
||||
const validPath = await validatePath(parsed.data.path);
|
||||
|
||||
@@ -630,6 +642,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
};
|
||||
}
|
||||
|
||||
case "read_media_file": {
|
||||
const parsed = ReadMediaFileArgsSchema.safeParse(args);
|
||||
if (!parsed.success) {
|
||||
throw new Error(`Invalid arguments for read_media_file: ${parsed.error}`);
|
||||
}
|
||||
const validPath = await validatePath(parsed.data.path);
|
||||
const extension = path.extname(validPath).toLowerCase();
|
||||
const mimeTypes: Record<string, string> = {
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
".bmp": "image/bmp",
|
||||
".svg": "image/svg+xml",
|
||||
".mp3": "audio/mpeg",
|
||||
".wav": "audio/wav",
|
||||
".ogg": "audio/ogg",
|
||||
".flac": "audio/flac",
|
||||
};
|
||||
const mimeType = mimeTypes[extension] || "application/octet-stream";
|
||||
const data = (await fs.readFile(validPath)).toString("base64");
|
||||
const type = mimeType.startsWith("image/")
|
||||
? "image"
|
||||
: mimeType.startsWith("audio/")
|
||||
? "audio"
|
||||
: "blob";
|
||||
return {
|
||||
content: [{ type, data, mimeType } as any],
|
||||
};
|
||||
}
|
||||
|
||||
case "read_multiple_files": {
|
||||
const parsed = ReadMultipleFilesArgsSchema.safeParse(args);
|
||||
if (!parsed.success) {
|
||||
|
||||
Reference in New Issue
Block a user