nworks-plus 1.3.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +8 -8
- package/README.ko.md +24 -10
- package/README.md +23 -9
- package/dist/index.js +220 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +148 -2
- package/dist/mcp.js.map +1 -1
- package/package.json +3 -2
package/dist/mcp.js
CHANGED
|
@@ -983,8 +983,7 @@ Content-Type: application/octet-stream\r
|
|
|
983
983
|
if (!uploadRes.ok) return handleError2(uploadRes);
|
|
984
984
|
return await uploadRes.json();
|
|
985
985
|
}
|
|
986
|
-
async function
|
|
987
|
-
const url = `${BASE_URL3}/users/${sanitizePathSegment(userId)}/drive/files/${sanitizePathSegment(fileId)}/download`;
|
|
986
|
+
async function downloadViaRedirect(url, profile) {
|
|
988
987
|
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
989
988
|
console.error(`[nworks] GET ${url} (get download URL)`);
|
|
990
989
|
}
|
|
@@ -1019,6 +1018,48 @@ async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
|
1019
1018
|
}
|
|
1020
1019
|
return { buffer, fileName };
|
|
1021
1020
|
}
|
|
1021
|
+
async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
1022
|
+
const url = `${BASE_URL3}/users/${sanitizePathSegment(userId)}/drive/files/${sanitizePathSegment(fileId)}/download`;
|
|
1023
|
+
return downloadViaRedirect(url, profile);
|
|
1024
|
+
}
|
|
1025
|
+
async function listSharedDrives(count = 100, cursor, profile = "default") {
|
|
1026
|
+
const params = new URLSearchParams();
|
|
1027
|
+
params.set("count", String(count));
|
|
1028
|
+
if (cursor) params.set("cursor", cursor);
|
|
1029
|
+
const url = `${BASE_URL3}/sharedrives?${params.toString()}`;
|
|
1030
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1031
|
+
console.error(`[nworks] GET ${url}`);
|
|
1032
|
+
}
|
|
1033
|
+
const res = await authedFetch2(url, { method: "GET" }, profile);
|
|
1034
|
+
if (!res.ok) return handleError2(res);
|
|
1035
|
+
const data = await res.json();
|
|
1036
|
+
const raw = data.sharedDrives ?? data.sharedrives ?? [];
|
|
1037
|
+
const sharedDrives = raw.map((d) => ({
|
|
1038
|
+
sharedriveId: d.sharedriveId,
|
|
1039
|
+
name: d.name ?? d.sharedriveName ?? "",
|
|
1040
|
+
permissionType: d.permissionType
|
|
1041
|
+
}));
|
|
1042
|
+
return { sharedDrives, responseMetaData: data.responseMetaData };
|
|
1043
|
+
}
|
|
1044
|
+
async function listSharedDriveFiles(sharedriveId, folderId, count = 20, cursor, profile = "default") {
|
|
1045
|
+
const base = `${BASE_URL3}/sharedrives/${sanitizePathSegment(sharedriveId)}/files`;
|
|
1046
|
+
const path = folderId ? `${base}/${sanitizePathSegment(folderId)}/children` : base;
|
|
1047
|
+
const params = new URLSearchParams();
|
|
1048
|
+
params.set("count", String(count));
|
|
1049
|
+
if (cursor) params.set("cursor", cursor);
|
|
1050
|
+
const url = `${path}?${params.toString()}`;
|
|
1051
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
1052
|
+
console.error(`[nworks] GET ${url}`);
|
|
1053
|
+
}
|
|
1054
|
+
const res = await authedFetch2(url, { method: "GET" }, profile);
|
|
1055
|
+
if (!res.ok) return handleError2(res);
|
|
1056
|
+
const data = await res.json();
|
|
1057
|
+
return { files: data.files ?? [], responseMetaData: data.responseMetaData };
|
|
1058
|
+
}
|
|
1059
|
+
async function downloadSharedDriveFile(sharedriveId, fileId, profile = "default") {
|
|
1060
|
+
const url = `${BASE_URL3}/sharedrives/${sanitizePathSegment(sharedriveId)}/files/${sanitizePathSegment(fileId)}/download`;
|
|
1061
|
+
return downloadViaRedirect(url, profile);
|
|
1062
|
+
}
|
|
1022
1063
|
|
|
1023
1064
|
// src/api/mail.ts
|
|
1024
1065
|
var BASE_URL4 = "https://www.worksapis.com/v1.0";
|
|
@@ -2289,6 +2330,111 @@ OAuth Redirect URI: http://localhost:9876/callback`,
|
|
|
2289
2330
|
}
|
|
2290
2331
|
}
|
|
2291
2332
|
);
|
|
2333
|
+
server.tool(
|
|
2334
|
+
"nworks_drive_sharedrive_list",
|
|
2335
|
+
"\uD300 \uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C(Shared Drive) \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uAC1C\uC778 '\uB0B4 \uB4DC\uB77C\uC774\uBE0C'\uAC00 \uC544\uB2CC \uD300 \uACF5\uC720 \uC800\uC7A5\uC18C\uB97C \uCC3E\uC744 \uB54C \uC0AC\uC6A9. '\uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C \uBCF4\uC5EC\uC918', '\uD300 \uB4DC\uB77C\uC774\uBE0C \uBAA9\uB85D' \uB4F1\uC758 \uC694\uCCAD\uC5D0 \uC0AC\uC6A9. \uBC18\uD658\uB41C sharedriveId\uB85C nworks_drive_sharedrive_files\uB97C \uD638\uCD9C\uD574 \uB0B4\uBD80 \uD30C\uC77C\uC744 \uC870\uD68C\uD558\uC138\uC694. User OAuth \uC778\uC99D \uD544\uC694 (file.read scope)",
|
|
2336
|
+
{
|
|
2337
|
+
count: z.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 100)"),
|
|
2338
|
+
cursor: z.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C")
|
|
2339
|
+
},
|
|
2340
|
+
async ({ count, cursor }) => {
|
|
2341
|
+
try {
|
|
2342
|
+
const result = await listSharedDrives(count ?? 100, cursor);
|
|
2343
|
+
return {
|
|
2344
|
+
content: [{ type: "text", text: JSON.stringify({ sharedDrives: result.sharedDrives, count: result.sharedDrives.length, hasMore: !!result.responseMetaData?.nextCursor, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
|
|
2345
|
+
};
|
|
2346
|
+
} catch (err) {
|
|
2347
|
+
return {
|
|
2348
|
+
content: [{ type: "text", text: mcpErrorHint(err, "drive.list") }],
|
|
2349
|
+
isError: true
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
);
|
|
2354
|
+
server.tool(
|
|
2355
|
+
"nworks_drive_sharedrive_files",
|
|
2356
|
+
"\uD2B9\uC815 \uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C(Shared Drive) \uC548\uC758 \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. sharedriveId\uB294 nworks_drive_sharedrive_list\uB85C \uC870\uD68C \uAC00\uB2A5. folderId\uB97C \uC9C0\uC815\uD558\uBA74 \uD574\uB2F9 \uD3F4\uB354 \uB0B4\uBD80\uB97C, \uBBF8\uC9C0\uC815 \uC2DC \uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C \uB8E8\uD2B8\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4. User OAuth \uC778\uC99D \uD544\uC694 (file.read scope)",
|
|
2357
|
+
{
|
|
2358
|
+
sharedriveId: z.string().describe("\uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C ID (nworks_drive_sharedrive_list\uB85C \uC870\uD68C \uAC00\uB2A5)"),
|
|
2359
|
+
folderId: z.string().optional().describe("\uD3F4\uB354 ID (\uBBF8\uC9C0\uC815 \uC2DC \uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C \uB8E8\uD2B8)"),
|
|
2360
|
+
count: z.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 20, \uCD5C\uB300: 200)"),
|
|
2361
|
+
cursor: z.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C")
|
|
2362
|
+
},
|
|
2363
|
+
async ({ sharedriveId, folderId, count, cursor }) => {
|
|
2364
|
+
try {
|
|
2365
|
+
const result = await listSharedDriveFiles(sharedriveId, folderId, count ?? 20, cursor);
|
|
2366
|
+
const files = result.files.map((f) => ({
|
|
2367
|
+
fileId: f.fileId,
|
|
2368
|
+
name: f.fileName,
|
|
2369
|
+
type: f.fileType,
|
|
2370
|
+
size: f.fileSize,
|
|
2371
|
+
modified: f.modifiedTime,
|
|
2372
|
+
path: f.filePath
|
|
2373
|
+
}));
|
|
2374
|
+
return {
|
|
2375
|
+
content: [{ type: "text", text: JSON.stringify({ files, count: files.length, hasMore: !!result.responseMetaData?.nextCursor, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
|
|
2376
|
+
};
|
|
2377
|
+
} catch (err) {
|
|
2378
|
+
return {
|
|
2379
|
+
content: [{ type: "text", text: mcpErrorHint(err, "drive.list") }],
|
|
2380
|
+
isError: true
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
);
|
|
2385
|
+
server.tool(
|
|
2386
|
+
"nworks_drive_sharedrive_download",
|
|
2387
|
+
"\uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C(Shared Drive)\uC758 \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4. sharedriveId\xB7fileId\uB294 nworks_drive_sharedrive_files\uB85C \uC870\uD68C \uAC00\uB2A5. outputDir\uC744 \uC9C0\uC815\uD558\uBA74 \uB85C\uCEEC\uC5D0 \uD30C\uC77C\uB85C \uC800\uC7A5\uD558\uACE0, \uBBF8\uC9C0\uC815 \uC2DC \uD30C\uC77C \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uBC18\uD658\uD569\uB2C8\uB2E4 (\uD14D\uC2A4\uD2B8\uB294 text, \uBC14\uC774\uB108\uB9AC\uB294 base64). 5MB \uCD08\uACFC \uD30C\uC77C\uC740 \uBC18\uB4DC\uC2DC outputDir\uB97C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4. User OAuth \uC778\uC99D \uD544\uC694 (file.read scope)",
|
|
2388
|
+
{
|
|
2389
|
+
sharedriveId: z.string().describe("\uACF5\uC720 \uB4DC\uB77C\uC774\uBE0C ID (nworks_drive_sharedrive_list\uB85C \uC870\uD68C \uAC00\uB2A5)"),
|
|
2390
|
+
fileId: z.string().describe("\uB2E4\uC6B4\uB85C\uB4DC\uD560 \uD30C\uC77C ID (nworks_drive_sharedrive_files\uB85C \uC870\uD68C \uAC00\uB2A5)"),
|
|
2391
|
+
outputDir: z.string().optional().describe("\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uC9C0\uC815 \uC2DC \uD30C\uC77C\uB85C \uC800\uC7A5, \uBBF8\uC9C0\uC815 \uC2DC \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uBC18\uD658)"),
|
|
2392
|
+
outputName: z.string().optional().describe("\uC800\uC7A5 \uD30C\uC77C\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uC6D0\uBCF8 \uD30C\uC77C\uBA85)")
|
|
2393
|
+
},
|
|
2394
|
+
async ({ sharedriveId, fileId, outputDir, outputName }) => {
|
|
2395
|
+
try {
|
|
2396
|
+
const result = await downloadSharedDriveFile(sharedriveId, fileId);
|
|
2397
|
+
const fileName = outputName ?? result.fileName ?? fileId;
|
|
2398
|
+
if (outputDir) {
|
|
2399
|
+
const { writeFile: writeFile2 } = await import("fs/promises");
|
|
2400
|
+
const { join: join2 } = await import("path");
|
|
2401
|
+
const safeDir = validateLocalPath(outputDir);
|
|
2402
|
+
const safeName = sanitizeFileName(fileName);
|
|
2403
|
+
const outPath = join2(safeDir, safeName);
|
|
2404
|
+
validateLocalPath(outPath, safeDir);
|
|
2405
|
+
await writeFile2(outPath, result.buffer);
|
|
2406
|
+
return {
|
|
2407
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, path: outPath, size: result.buffer.length }) }]
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
const MAX_INLINE_SIZE = 5 * 1024 * 1024;
|
|
2411
|
+
if (result.buffer.length > MAX_INLINE_SIZE) {
|
|
2412
|
+
const sizeMB = (result.buffer.length / (1024 * 1024)).toFixed(1);
|
|
2413
|
+
return {
|
|
2414
|
+
content: [{ type: "text", text: JSON.stringify({ error: true, message: `\uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${sizeMB}MB). outputDir\uB97C \uC9C0\uC815\uD574\uC11C \uB85C\uCEEC\uC5D0 \uC800\uC7A5\uD558\uC138\uC694.`, fileName, size: result.buffer.length }) }],
|
|
2415
|
+
isError: true
|
|
2416
|
+
};
|
|
2417
|
+
}
|
|
2418
|
+
const textExtensions = /\.(txt|md|csv|json|xml|html|htm|css|js|ts|jsx|tsx|yaml|yml|toml|ini|cfg|conf|log|sh|bash|zsh|py|rb|java|go|rs|c|cpp|h|hpp|sql|graphql|env|gitignore|dockerignore|editorconfig)$/i;
|
|
2419
|
+
const isText = textExtensions.test(fileName);
|
|
2420
|
+
if (isText) {
|
|
2421
|
+
const text = result.buffer.toString("utf-8");
|
|
2422
|
+
return {
|
|
2423
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "text", content: text }) }]
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2426
|
+
const base64 = result.buffer.toString("base64");
|
|
2427
|
+
return {
|
|
2428
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "base64", content: base64 }) }]
|
|
2429
|
+
};
|
|
2430
|
+
} catch (err) {
|
|
2431
|
+
return {
|
|
2432
|
+
content: [{ type: "text", text: mcpErrorHint(err, "drive.download") }],
|
|
2433
|
+
isError: true
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
);
|
|
2292
2438
|
server.tool(
|
|
2293
2439
|
"nworks_mail_send",
|
|
2294
2440
|
"NAVER WORKS \uBA54\uC77C\uC744 \uC804\uC1A1\uD569\uB2C8\uB2E4. '\uBA54\uC77C \uBCF4\uB0B4\uC918', '\uC774\uBA54\uC77C \uC791\uC131\uD574\uC918' \uB4F1\uC758 \uC694\uCCAD\uC5D0 \uC0AC\uC6A9. \uBE44\uB3D9\uAE30 \uC804\uC1A1(\uC131\uACF5 \uC2DC 202). User OAuth \uC778\uC99D \uD544\uC694 (mail scope)",
|