nworks 0.3.2 → 0.4.0
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.md +34 -2
- package/dist/index.js +316 -12
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +214 -8
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -14311,6 +14311,85 @@ async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
|
14311
14311
|
return { buffer, fileName };
|
|
14312
14312
|
}
|
|
14313
14313
|
|
|
14314
|
+
// src/api/mail.ts
|
|
14315
|
+
var BASE_URL4 = "https://www.worksapis.com/v1.0";
|
|
14316
|
+
async function authedFetch2(url2, init, profile) {
|
|
14317
|
+
const token = await getValidUserToken(profile);
|
|
14318
|
+
const headers = new Headers(init.headers);
|
|
14319
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
14320
|
+
return fetch(url2, { ...init, headers });
|
|
14321
|
+
}
|
|
14322
|
+
async function handleError2(res) {
|
|
14323
|
+
if (res.status === 401) {
|
|
14324
|
+
throw new AuthError("User token expired. Run `nworks login --user --scope mail` again.");
|
|
14325
|
+
}
|
|
14326
|
+
let code = "UNKNOWN";
|
|
14327
|
+
let description = `HTTP ${res.status}`;
|
|
14328
|
+
try {
|
|
14329
|
+
const body = await res.json();
|
|
14330
|
+
code = body.code ?? code;
|
|
14331
|
+
description = body.description ?? description;
|
|
14332
|
+
} catch {
|
|
14333
|
+
}
|
|
14334
|
+
throw new ApiError(code, description, res.status);
|
|
14335
|
+
}
|
|
14336
|
+
async function sendMail(opts) {
|
|
14337
|
+
const userId = opts.userId ?? "me";
|
|
14338
|
+
const profile = opts.profile ?? "default";
|
|
14339
|
+
const url2 = `${BASE_URL4}/users/${userId}/mail`;
|
|
14340
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
14341
|
+
console.error(`[nworks] POST ${url2}`);
|
|
14342
|
+
}
|
|
14343
|
+
const body = {
|
|
14344
|
+
to: opts.to,
|
|
14345
|
+
subject: opts.subject
|
|
14346
|
+
};
|
|
14347
|
+
if (opts.body !== void 0) body.body = opts.body;
|
|
14348
|
+
if (opts.cc) body.cc = opts.cc;
|
|
14349
|
+
if (opts.bcc) body.bcc = opts.bcc;
|
|
14350
|
+
if (opts.contentType) body.contentType = opts.contentType;
|
|
14351
|
+
const res = await authedFetch2(
|
|
14352
|
+
url2,
|
|
14353
|
+
{
|
|
14354
|
+
method: "POST",
|
|
14355
|
+
headers: { "Content-Type": "application/json" },
|
|
14356
|
+
body: JSON.stringify(body)
|
|
14357
|
+
},
|
|
14358
|
+
profile
|
|
14359
|
+
);
|
|
14360
|
+
if (res.status === 202) return;
|
|
14361
|
+
if (!res.ok) return handleError2(res);
|
|
14362
|
+
}
|
|
14363
|
+
async function listMails(folderId = 0, userId = "me", count = 30, cursor, isUnread, profile = "default") {
|
|
14364
|
+
const params = new URLSearchParams();
|
|
14365
|
+
params.set("count", String(count));
|
|
14366
|
+
if (cursor) params.set("cursor", cursor);
|
|
14367
|
+
if (isUnread) params.set("isUnread", "true");
|
|
14368
|
+
const url2 = `${BASE_URL4}/users/${userId}/mail/mailfolders/${folderId}/children?${params.toString()}`;
|
|
14369
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
14370
|
+
console.error(`[nworks] GET ${url2}`);
|
|
14371
|
+
}
|
|
14372
|
+
const res = await authedFetch2(url2, { method: "GET" }, profile);
|
|
14373
|
+
if (!res.ok) return handleError2(res);
|
|
14374
|
+
const data = await res.json();
|
|
14375
|
+
return {
|
|
14376
|
+
mails: data.mails ?? [],
|
|
14377
|
+
unreadCount: data.unreadCount,
|
|
14378
|
+
folderName: data.folderName,
|
|
14379
|
+
totalCount: data.totalCount,
|
|
14380
|
+
responseMetaData: data.responseMetaData
|
|
14381
|
+
};
|
|
14382
|
+
}
|
|
14383
|
+
async function readMail(mailId, userId = "me", profile = "default") {
|
|
14384
|
+
const url2 = `${BASE_URL4}/users/${userId}/mail/${mailId}`;
|
|
14385
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
14386
|
+
console.error(`[nworks] GET ${url2}`);
|
|
14387
|
+
}
|
|
14388
|
+
const res = await authedFetch2(url2, { method: "GET" }, profile);
|
|
14389
|
+
if (!res.ok) return handleError2(res);
|
|
14390
|
+
return await res.json();
|
|
14391
|
+
}
|
|
14392
|
+
|
|
14314
14393
|
// src/mcp/tools.ts
|
|
14315
14394
|
function registerTools(server) {
|
|
14316
14395
|
server.tool(
|
|
@@ -14515,27 +14594,154 @@ function registerTools(server) {
|
|
|
14515
14594
|
);
|
|
14516
14595
|
server.tool(
|
|
14517
14596
|
"nworks_drive_download",
|
|
14518
|
-
"\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694)",
|
|
14597
|
+
"\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694). 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 \uD30C\uC77C\uC740 text, \uBC14\uC774\uB108\uB9AC\uB294 base64).",
|
|
14519
14598
|
{
|
|
14520
14599
|
fileId: external_exports.string().describe("\uB2E4\uC6B4\uB85C\uB4DC\uD560 \uD30C\uC77C ID"),
|
|
14521
|
-
outputDir: external_exports.string().optional().describe("\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uBBF8\uC9C0\uC815 \uC2DC \
|
|
14600
|
+
outputDir: external_exports.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)"),
|
|
14522
14601
|
outputName: external_exports.string().optional().describe("\uC800\uC7A5 \uD30C\uC77C\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uC6D0\uBCF8 \uD30C\uC77C\uBA85)"),
|
|
14523
14602
|
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
14524
14603
|
},
|
|
14525
14604
|
async ({ fileId, outputDir, outputName, userId }) => {
|
|
14526
14605
|
try {
|
|
14527
|
-
const { writeFile: writeFile2 } = await import("fs/promises");
|
|
14528
|
-
const { join: join2 } = await import("path");
|
|
14529
14606
|
const result = await downloadFile(
|
|
14530
14607
|
fileId,
|
|
14531
14608
|
userId ?? "me"
|
|
14532
14609
|
);
|
|
14533
14610
|
const fileName = outputName ?? result.fileName ?? fileId;
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14611
|
+
if (outputDir) {
|
|
14612
|
+
const { writeFile: writeFile2 } = await import("fs/promises");
|
|
14613
|
+
const { join: join2 } = await import("path");
|
|
14614
|
+
const outPath = join2(outputDir, fileName);
|
|
14615
|
+
await writeFile2(outPath, result.buffer);
|
|
14616
|
+
return {
|
|
14617
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, path: outPath, size: result.buffer.length }) }]
|
|
14618
|
+
};
|
|
14619
|
+
}
|
|
14620
|
+
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;
|
|
14621
|
+
const isText = textExtensions.test(fileName);
|
|
14622
|
+
if (isText) {
|
|
14623
|
+
const text = result.buffer.toString("utf-8");
|
|
14624
|
+
return {
|
|
14625
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "text", content: text }) }]
|
|
14626
|
+
};
|
|
14627
|
+
}
|
|
14628
|
+
const base643 = result.buffer.toString("base64");
|
|
14629
|
+
return {
|
|
14630
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, size: result.buffer.length, encoding: "base64", content: base643 }) }]
|
|
14631
|
+
};
|
|
14632
|
+
} catch (err) {
|
|
14633
|
+
const error48 = err;
|
|
14634
|
+
return {
|
|
14635
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
14636
|
+
isError: true
|
|
14637
|
+
};
|
|
14638
|
+
}
|
|
14639
|
+
}
|
|
14640
|
+
);
|
|
14641
|
+
server.tool(
|
|
14642
|
+
"nworks_mail_send",
|
|
14643
|
+
"\uBA54\uC77C\uC744 \uC804\uC1A1\uD569\uB2C8\uB2E4 (User OAuth mail scope \uD544\uC694). \uBE44\uB3D9\uAE30 \uC804\uC1A1\uC73C\uB85C, \uC131\uACF5 \uC2DC 202 \uC751\uB2F5\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4.",
|
|
14644
|
+
{
|
|
14645
|
+
to: external_exports.string().describe("\uC218\uC2E0\uC790 \uC774\uBA54\uC77C (\uC5EC\uB7EC \uBA85\uC740 ; \uB85C \uAD6C\uBD84)"),
|
|
14646
|
+
subject: external_exports.string().describe("\uBA54\uC77C \uC81C\uBAA9"),
|
|
14647
|
+
body: external_exports.string().optional().describe("\uBA54\uC77C \uBCF8\uBB38"),
|
|
14648
|
+
cc: external_exports.string().optional().describe("\uCC38\uC870 \uC774\uBA54\uC77C (\uC5EC\uB7EC \uBA85\uC740 ; \uB85C \uAD6C\uBD84)"),
|
|
14649
|
+
bcc: external_exports.string().optional().describe("\uC228\uC740\uCC38\uC870 \uC774\uBA54\uC77C (\uC5EC\uB7EC \uBA85\uC740 ; \uB85C \uAD6C\uBD84)"),
|
|
14650
|
+
contentType: external_exports.enum(["html", "text"]).optional().describe("\uBCF8\uBB38 \uD615\uC2DD (\uAE30\uBCF8: html)"),
|
|
14651
|
+
userId: external_exports.string().optional().describe("\uBC1C\uC2E0\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
14652
|
+
},
|
|
14653
|
+
async ({ to, subject, body, cc, bcc, contentType, userId }) => {
|
|
14654
|
+
try {
|
|
14655
|
+
await sendMail({
|
|
14656
|
+
to,
|
|
14657
|
+
subject,
|
|
14658
|
+
body,
|
|
14659
|
+
cc,
|
|
14660
|
+
bcc,
|
|
14661
|
+
contentType,
|
|
14662
|
+
userId: userId ?? "me"
|
|
14663
|
+
});
|
|
14664
|
+
return {
|
|
14665
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, message: "Mail sent (async)" }) }]
|
|
14666
|
+
};
|
|
14667
|
+
} catch (err) {
|
|
14668
|
+
const error48 = err;
|
|
14669
|
+
return {
|
|
14670
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
14671
|
+
isError: true
|
|
14672
|
+
};
|
|
14673
|
+
}
|
|
14674
|
+
}
|
|
14675
|
+
);
|
|
14676
|
+
server.tool(
|
|
14677
|
+
"nworks_mail_list",
|
|
14678
|
+
"\uBA54\uC77C\uD568\uC758 \uBA54\uC77C \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth mail \uB610\uB294 mail.read scope \uD544\uC694)",
|
|
14679
|
+
{
|
|
14680
|
+
folderId: external_exports.number().optional().describe("\uBA54\uC77C \uD3F4\uB354 ID (\uAE30\uBCF8: 0 = \uBC1B\uC740\uD3B8\uC9C0\uD568)"),
|
|
14681
|
+
count: external_exports.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 30, \uCD5C\uB300: 200)"),
|
|
14682
|
+
cursor: external_exports.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C"),
|
|
14683
|
+
isUnread: external_exports.boolean().optional().describe("\uC77D\uC9C0 \uC54A\uC740 \uBA54\uC77C\uB9CC \uC870\uD68C"),
|
|
14684
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
14685
|
+
},
|
|
14686
|
+
async ({ folderId, count, cursor, isUnread, userId }) => {
|
|
14687
|
+
try {
|
|
14688
|
+
const result = await listMails(
|
|
14689
|
+
folderId ?? 0,
|
|
14690
|
+
userId ?? "me",
|
|
14691
|
+
count ?? 30,
|
|
14692
|
+
cursor,
|
|
14693
|
+
isUnread
|
|
14694
|
+
);
|
|
14695
|
+
const mails = result.mails.map((m) => ({
|
|
14696
|
+
mailId: m.mailId,
|
|
14697
|
+
from: m.from.email,
|
|
14698
|
+
subject: m.subject,
|
|
14699
|
+
date: m.receivedTime,
|
|
14700
|
+
status: m.status,
|
|
14701
|
+
attachments: m.attachCount ?? 0
|
|
14702
|
+
}));
|
|
14703
|
+
return {
|
|
14704
|
+
content: [{ type: "text", text: JSON.stringify({ mails, count: mails.length, totalCount: result.totalCount, unreadCount: result.unreadCount, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
|
|
14705
|
+
};
|
|
14706
|
+
} catch (err) {
|
|
14707
|
+
const error48 = err;
|
|
14708
|
+
return {
|
|
14709
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
14710
|
+
isError: true
|
|
14711
|
+
};
|
|
14712
|
+
}
|
|
14713
|
+
}
|
|
14714
|
+
);
|
|
14715
|
+
server.tool(
|
|
14716
|
+
"nworks_mail_read",
|
|
14717
|
+
"\uD2B9\uC815 \uBA54\uC77C\uC758 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth mail \uB610\uB294 mail.read scope \uD544\uC694)",
|
|
14718
|
+
{
|
|
14719
|
+
mailId: external_exports.number().describe("\uBA54\uC77C ID"),
|
|
14720
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
14721
|
+
},
|
|
14722
|
+
async ({ mailId, userId }) => {
|
|
14723
|
+
try {
|
|
14724
|
+
const result = await readMail(
|
|
14725
|
+
mailId,
|
|
14726
|
+
userId ?? "me"
|
|
14727
|
+
);
|
|
14728
|
+
const mail = result.mail;
|
|
14537
14729
|
return {
|
|
14538
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
14730
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
14731
|
+
mailId: mail.mailId,
|
|
14732
|
+
from: mail.from,
|
|
14733
|
+
to: mail.to,
|
|
14734
|
+
cc: mail.cc ?? [],
|
|
14735
|
+
subject: mail.subject,
|
|
14736
|
+
body: mail.body,
|
|
14737
|
+
date: mail.receivedTime,
|
|
14738
|
+
attachments: result.attachments?.map((a) => ({
|
|
14739
|
+
id: a.attachmentId,
|
|
14740
|
+
filename: a.filename,
|
|
14741
|
+
contentType: a.contentType,
|
|
14742
|
+
size: a.size
|
|
14743
|
+
})) ?? []
|
|
14744
|
+
}) }]
|
|
14539
14745
|
};
|
|
14540
14746
|
} catch (err) {
|
|
14541
14747
|
const error48 = err;
|