mira-app-server
Version:
Mira Server - standalone server application using mira-app-core
178 lines • 8.08 kB
JavaScript
"use strict";
/**
* files 模块工具
*
* upload/download 直接走 HttpClient,绕过 Node 下 FileList 未定义的问题(与 CLI 一致)。
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerFileTools = registerFileTools;
const zod_1 = require("zod");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const helpers_1 = require("../helpers");
function registerFileTools(mcp, ctx) {
mcp.registerTool('files_list', {
description: '获取素材库的文件列表(支持过滤)',
inputSchema: {
libraryId: zod_1.z.string().describe('素材库 ID'),
title: zod_1.z.string().optional().describe('按标题模糊搜索'),
extension: zod_1.z.string().optional().describe('按扩展名筛选'),
tags: zod_1.z.array(zod_1.z.string()).optional().describe('按标签筛选'),
folder: zod_1.z.number().optional().describe('按文件夹 ID 筛选'),
limit: zod_1.z.number().optional().describe('数量限制'),
offset: zod_1.z.number().optional().describe('偏移量'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
const filters = {};
if (args.title)
filters.title = args.title;
if (args.extension)
filters.extension = args.extension;
if (args.tags?.length)
filters.tags = args.tags;
if (args.folder !== undefined)
filters.folder = args.folder;
if (args.limit !== undefined)
filters.limit = args.limit;
if (args.offset !== undefined)
filters.offset = args.offset;
const resp = await client.files().getFiles({ libraryId: args.libraryId, filters });
return Array.isArray(resp) ? resp : resp?.result || [];
});
});
mcp.registerTool('files_get', {
description: '获取单个文件的详细信息',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).describe('文件 ID'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().getFile(args.libraryId, String(args.fileId));
});
});
mcp.registerTool('files_upload', {
description: '上传一个或多个本地文件到指定素材库。paths 为本地文件路径数组。',
inputSchema: {
libraryId: zod_1.z.string(),
paths: zod_1.z.array(zod_1.z.string()).describe('本地文件绝对路径数组'),
tags: zod_1.z.array(zod_1.z.string()).optional().describe('为每个文件附加的标签'),
folderId: zod_1.z.string().optional().describe('目标文件夹 ID'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
const formData = new FormData();
for (const p of args.paths) {
const abs = path_1.default.resolve(p);
if (!fs_1.default.existsSync(abs))
throw new Error(`文件不存在: ${abs}`);
const buf = fs_1.default.readFileSync(abs);
const blob = new Blob([new Uint8Array(buf)]);
const name = path_1.default.basename(abs);
const file = new File([blob], name);
formData.append('files', file, name);
}
formData.append('libraryId', args.libraryId);
if (args.tags?.length || args.folderId) {
formData.append('payload', JSON.stringify({ data: { tags: args.tags, folder_id: args.folderId } }));
}
return await client.getHttpClient().upload('/api/files/upload', formData);
});
});
mcp.registerTool('files_download', {
description: '下载文件到本地。output 省略时使用文件原名保存到当前工作目录。',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
output: zod_1.z.string().optional().describe('保存路径'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
const blob = await client.files().download(args.libraryId, String(args.fileId));
const buffer = Buffer.from(await blob.arrayBuffer());
let outPath = args.output;
if (!outPath) {
try {
const info = await client.files().getFile(args.libraryId, String(args.fileId));
outPath = path_1.default.resolve(process.cwd(), info.title || String(args.fileId));
}
catch {
outPath = path_1.default.resolve(process.cwd(), String(args.fileId));
}
}
fs_1.default.writeFileSync(outPath, buffer);
return { savedTo: outPath, bytes: buffer.length };
});
});
mcp.registerTool('files_rename', {
description: '重命名文件(同文件夹下重名会返回 409)',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
name: zod_1.z.string().describe('新文件名'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().renameFile(args.libraryId, String(args.fileId), args.name);
});
});
mcp.registerTool('files_update', {
description: '更新文件元数据(任意键值,如 website 等)',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
data: zod_1.z.record(zod_1.z.any()).describe('要更新的元数据对象'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().updateFile(args.libraryId, String(args.fileId), args.data);
});
});
mcp.registerTool('files_delete', {
description: '删除文件(默认移入回收站,permanent=true 彻底删除)',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
permanent: zod_1.z.boolean().optional().describe('彻底删除而不进回收站'),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().delete(args.libraryId, String(args.fileId), {
moveToRecycleBin: !args.permanent,
});
});
});
mcp.registerTool('files_restore', {
description: '从回收站恢复文件',
inputSchema: {
libraryId: zod_1.z.string(),
fileId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
},
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().restoreFile(args.libraryId, String(args.fileId));
});
});
mcp.registerTool('files_empty_trash', {
description: '清空素材库回收站',
inputSchema: { libraryId: zod_1.z.string() },
}, async (args) => {
return (0, helpers_1.run)(async () => {
const client = ctx.getClient();
return await client.files().emptyTrash(args.libraryId);
});
});
}
//# sourceMappingURL=files.js.map