Skip to main content
Glama

ToolBox MCP Server

fileSystem_tool.ts6.54 kB
import fs from 'fs-extra'; import path from 'path'; // Define parameter schema export const schema = { name: "fileSystem_tool", description: "一个强大的文件系统工具,用于执行读、写、复制、移动、删除、列表等操作。", type: "object", properties: { operation: { type: "string", enum: ["read", "write", "copy", "move", "delete", "list", "listDetails", "chmod", "chown", "getSize"], description: "要执行的文件系统操作 (例如: read, write, copy)" }, sourcePath: { type: "string", description: "源文件的绝对路径" }, targetPath: { type: "string", description: "目标文件的绝对路径 (用于 copy/move 操作)" }, content: { type: "string", description: "要写入文件的内容 (用于 'write' 操作)" }, recursive: { type: "boolean", default: false, description: "递归地对目录应用操作" }, overwrite: { type: "boolean", default: false, description: "在 copy/move 操作中覆盖已存在的文件" }, showHidden: { type: "boolean", default: false, description: "在 list/listDetails 中包含隐藏文件/目录" }, fileMode: { type: "string", pattern: "^[0-7]{3,4}$", description: "文件模式(权限),使用八进制格式 (例如, 755)" }, uid: { type: "number", description: "用于 chown 操作的用户 ID" }, gid: { type: "number", description: "用于 chown 操作的组 ID" } }, required: ["operation", "sourcePath"] }; // Implement tool logic export default async function(request: any) { try { const { operation, sourcePath, targetPath, content, recursive, overwrite, showHidden, fileMode, uid, gid } = request.params.arguments; const basePath = process.cwd(); const isSafePath = (userPath: string | undefined) => { if (!userPath) return true; // Allow targetPath to be optional const resolvedPath = path.resolve(basePath, userPath); return resolvedPath.startsWith(basePath); }; if (!isSafePath(sourcePath)) { throw new Error(`源路径 "${sourcePath}" 超出了允许的操作目录。`); } if (!isSafePath(targetPath)) { throw new Error(`目标路径 "${targetPath}" 超出了允许的操作目录。`); } switch (operation) { case "read": { const data = await fs.readFile(sourcePath, 'utf-8'); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; } case "write": { if (content === undefined) { throw new Error('执行 "write" 操作必须提供 "content" 参数。'); } await fs.writeFile(sourcePath, content, 'utf-8'); return { content: [{ type: "text", text: `文件已成功写入到 ${sourcePath}` }] }; } case "copy": { if (!targetPath) { throw new Error("执行 'copy' 操作必须提供 'targetPath' 参数。"); } await fs.copy(sourcePath, targetPath, { overwrite }); return { content: [{ type: "text", text: `文件已成功从 ${sourcePath} 复制到 ${targetPath}` }] }; } case "move": { if (!targetPath) { throw new Error("执行 'move' 操作必须提供 'targetPath' 参数。"); } await fs.move(sourcePath, targetPath, { overwrite }); return { content: [{ type: "text", text: `文件已成功从 ${sourcePath} 移动到 ${targetPath}` }] }; } case "delete": { await fs.remove(sourcePath); return { content: [{ type: "text", text: `文件 ${sourcePath} 已被成功删除。` }] }; } case "list": { const files = await fs.readdir(sourcePath); // TODO: Implement showHidden filter return { content: [{ type: "text", text: JSON.stringify(files, null, 2) }] }; } case "listDetails": { const files = await fs.readdir(sourcePath); const fileDetails = await Promise.all( files.map(async (file) => { const filePath = path.join(sourcePath, file); const stat = await fs.stat(filePath); return { name: file, type: stat.isFile() ? "file" : stat.isDirectory() ? "directory" : "unknown", size: stat.size, modified: stat.mtime, permissions: stat.mode.toString(8), }; }) ); // TODO: Implement showHidden filter return { content: [{ type: "text", text: JSON.stringify(fileDetails, null, 2) }] }; } case "chmod": { if (!fileMode) { throw new Error("执行 'chmod' 操作必须提供 'fileMode' 参数。"); } await fs.chmod(sourcePath, fileMode); return { content: [{ type: "text", text: `文件权限已成功修改为 ${fileMode}` }] }; } case "chown": { if (uid === undefined || gid === undefined) { throw new Error("执行 'chown' 操作必须同时提供 'uid' 和 'gid' 参数。"); } await fs.chown(sourcePath, uid, gid); return { content: [{ type: "text", text: `文件所有者已成功变更为 UID: ${uid}, GID: ${gid}` }] }; } case "getSize": { const stat = await fs.stat(sourcePath); let totalSize = stat.size; if (stat.isDirectory() && recursive) { // Note: This is a simplified size calculation for the top-level directory. const files = await fs.readdir(sourcePath); totalSize = (await Promise.all(files.map(async file => { const childPath = path.join(sourcePath, file); const childStat = await fs.stat(childPath); return childStat.size; // Simplified: doesn't recurse into subdirectories }))).reduce((a, b) => a + b, stat.size); } return { content: [{ type: "text", text: `路径 ${sourcePath} 的总大小为: ${totalSize} 字节` }] }; } default: throw new Error(`不支持的操作: ${operation}`); } } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } } // Destroy function export async function destroy() { console.log("Destroy fileSystem_tool"); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/xiaoguomeiyitian/ToolBox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server