nworks 0.2.2 → 0.3.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.md +41 -3
- package/dist/index.js +332 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +222 -0
- package/dist/mcp.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ nworks login \
|
|
|
25
25
|
--private-key <PATH_TO_KEY> \
|
|
26
26
|
--bot-id <BOT_ID>
|
|
27
27
|
|
|
28
|
-
# User OAuth 로그인 (
|
|
29
|
-
nworks login --user --scope calendar.read
|
|
28
|
+
# User OAuth 로그인 (캘린더, 드라이브 등 사용자 API용)
|
|
29
|
+
nworks login --user --scope calendar.read,file
|
|
30
30
|
|
|
31
31
|
# 인증 확인
|
|
32
32
|
nworks whoami
|
|
@@ -39,6 +39,12 @@ nworks directory members
|
|
|
39
39
|
|
|
40
40
|
# 오늘 일정 조회
|
|
41
41
|
nworks calendar list
|
|
42
|
+
|
|
43
|
+
# 드라이브 파일 목록
|
|
44
|
+
nworks drive list
|
|
45
|
+
|
|
46
|
+
# 파일 업로드
|
|
47
|
+
nworks drive upload --file ./report.pdf
|
|
42
48
|
```
|
|
43
49
|
|
|
44
50
|
## CLI Commands
|
|
@@ -95,6 +101,36 @@ nworks calendar list --user <userId>
|
|
|
95
101
|
|
|
96
102
|
> **Note**: 캘린더 API는 User OAuth가 필요합니다. 먼저 `nworks login --user --scope calendar.read`를 실행하세요.
|
|
97
103
|
|
|
104
|
+
### 드라이브 (User OAuth 필요)
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# 루트 파일/폴더 목록
|
|
108
|
+
nworks drive list
|
|
109
|
+
|
|
110
|
+
# 특정 폴더 내 파일 목록
|
|
111
|
+
nworks drive list --folder <folderId>
|
|
112
|
+
|
|
113
|
+
# 페이지네이션
|
|
114
|
+
nworks drive list --count 50 --cursor <nextCursor>
|
|
115
|
+
|
|
116
|
+
# 파일 업로드 (루트)
|
|
117
|
+
nworks drive upload --file ./report.pdf
|
|
118
|
+
|
|
119
|
+
# 특정 폴더에 업로드
|
|
120
|
+
nworks drive upload --file ./report.pdf --folder <folderId>
|
|
121
|
+
|
|
122
|
+
# 동일 파일명 덮어쓰기
|
|
123
|
+
nworks drive upload --file ./report.pdf --overwrite
|
|
124
|
+
|
|
125
|
+
# 파일 다운로드
|
|
126
|
+
nworks drive download --file-id <fileId>
|
|
127
|
+
|
|
128
|
+
# 다운로드 경로/파일명 지정
|
|
129
|
+
nworks drive download --file-id <fileId> --out ./downloads --name report.pdf
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
> **Note**: 드라이브 API는 User OAuth가 필요합니다. 먼저 `nworks login --user --scope file`을 실행하세요. 읽기만 필요하면 `file.read` scope로 충분합니다.
|
|
133
|
+
|
|
98
134
|
### MCP 서버
|
|
99
135
|
|
|
100
136
|
```bash
|
|
@@ -134,6 +170,8 @@ nworks mcp --list-tools # 등록된 tool 목록
|
|
|
134
170
|
| `bot.read` | Bot 채널/구성원 조회 | Service Account | `message members` |
|
|
135
171
|
| `user.read` | 조직 구성원 조회 | Service Account | `directory members` |
|
|
136
172
|
| `calendar.read` | 캘린더 일정 조회 | User OAuth | `calendar list` |
|
|
173
|
+
| `file` | 드라이브 읽기/쓰기 | User OAuth | `drive list/upload/download` |
|
|
174
|
+
| `file.read` | 드라이브 읽기 전용 | User OAuth | `drive list/download` |
|
|
137
175
|
|
|
138
176
|
> **Tip**: scope를 변경한 후에는 토큰을 재발급해야 합니다.
|
|
139
177
|
> ```bash
|
|
@@ -186,7 +224,7 @@ NWORKS_VERBOSE=1 # optional, 디버그 로깅
|
|
|
186
224
|
|
|
187
225
|
- ~~**v0.1** — 메시지, 조직 구성원, MCP 서버~~
|
|
188
226
|
- ~~**v0.2** — 캘린더 일정 조회 + User OAuth~~
|
|
189
|
-
-
|
|
227
|
+
- ~~**v0.3** — 드라이브 파일 조회/업로드/다운로드 (`nworks drive`)~~
|
|
190
228
|
- **v0.4** — 게시판, 메일 (`nworks board`, `nworks mail`)
|
|
191
229
|
|
|
192
230
|
## License
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
import { createRequire } from "module";
|
|
10
|
-
import { Command as
|
|
10
|
+
import { Command as Command9 } from "commander";
|
|
11
11
|
|
|
12
12
|
// src/commands/login.ts
|
|
13
13
|
import { Command } from "commander";
|
|
@@ -827,9 +827,237 @@ var listCommand = new Command6("list").description("List calendar events (requir
|
|
|
827
827
|
});
|
|
828
828
|
var calendarCommand = new Command6("calendar").description("Calendar operations (requires User OAuth)").addCommand(listCommand);
|
|
829
829
|
|
|
830
|
-
// src/commands/
|
|
830
|
+
// src/commands/drive.ts
|
|
831
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
832
|
+
import { join as join2 } from "path";
|
|
831
833
|
import { Command as Command7 } from "commander";
|
|
832
834
|
|
|
835
|
+
// src/api/drive.ts
|
|
836
|
+
import { readFile as readFile4, stat } from "fs/promises";
|
|
837
|
+
import { basename } from "path";
|
|
838
|
+
var BASE_URL3 = "https://www.worksapis.com/v1.0";
|
|
839
|
+
async function authedFetch(url2, init, profile) {
|
|
840
|
+
const token = await getValidUserToken(profile);
|
|
841
|
+
const headers = new Headers(init.headers);
|
|
842
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
843
|
+
return fetch(url2, { ...init, headers });
|
|
844
|
+
}
|
|
845
|
+
async function handleError(res) {
|
|
846
|
+
if (res.status === 401) {
|
|
847
|
+
throw new AuthError("User token expired. Run `nworks login --user --scope file` again.");
|
|
848
|
+
}
|
|
849
|
+
let code = "UNKNOWN";
|
|
850
|
+
let description = `HTTP ${res.status}`;
|
|
851
|
+
try {
|
|
852
|
+
const body = await res.json();
|
|
853
|
+
code = body.code ?? code;
|
|
854
|
+
description = body.description ?? description;
|
|
855
|
+
} catch {
|
|
856
|
+
}
|
|
857
|
+
throw new ApiError(code, description, res.status);
|
|
858
|
+
}
|
|
859
|
+
async function listFiles(userId = "me", folderId, count = 20, cursor, profile = "default") {
|
|
860
|
+
const base = `${BASE_URL3}/users/${userId}/drive/files`;
|
|
861
|
+
const path = folderId ? `${base}/${folderId}/children` : base;
|
|
862
|
+
const params = new URLSearchParams();
|
|
863
|
+
params.set("count", String(count));
|
|
864
|
+
if (cursor) params.set("cursor", cursor);
|
|
865
|
+
const url2 = `${path}?${params.toString()}`;
|
|
866
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
867
|
+
console.error(`[nworks] GET ${url2}`);
|
|
868
|
+
}
|
|
869
|
+
const res = await authedFetch(url2, { method: "GET" }, profile);
|
|
870
|
+
if (!res.ok) return handleError(res);
|
|
871
|
+
const data = await res.json();
|
|
872
|
+
return { files: data.files ?? [], responseMetaData: data.responseMetaData };
|
|
873
|
+
}
|
|
874
|
+
async function uploadFile(localPath, userId = "me", folderId, overwrite = false, profile = "default") {
|
|
875
|
+
const fileName = basename(localPath);
|
|
876
|
+
const fileStat = await stat(localPath);
|
|
877
|
+
const fileSize = fileStat.size;
|
|
878
|
+
const base = `${BASE_URL3}/users/${userId}/drive/files`;
|
|
879
|
+
const createUrl = folderId ? `${base}/${folderId}` : base;
|
|
880
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
881
|
+
console.error(`[nworks] POST ${createUrl} (create upload URL)`);
|
|
882
|
+
}
|
|
883
|
+
const createRes = await authedFetch(
|
|
884
|
+
createUrl,
|
|
885
|
+
{
|
|
886
|
+
method: "POST",
|
|
887
|
+
headers: { "Content-Type": "application/json" },
|
|
888
|
+
body: JSON.stringify({ fileName, fileSize, overwrite })
|
|
889
|
+
},
|
|
890
|
+
profile
|
|
891
|
+
);
|
|
892
|
+
if (!createRes.ok) return handleError(createRes);
|
|
893
|
+
const { uploadUrl } = await createRes.json();
|
|
894
|
+
const fileBuffer = await readFile4(localPath);
|
|
895
|
+
const boundary = `----nworks${Date.now()}`;
|
|
896
|
+
const header = Buffer.from(
|
|
897
|
+
`--${boundary}\r
|
|
898
|
+
Content-Disposition: form-data; name="Filedata"; filename="${fileName}"\r
|
|
899
|
+
Content-Type: application/octet-stream\r
|
|
900
|
+
\r
|
|
901
|
+
`
|
|
902
|
+
);
|
|
903
|
+
const footer = Buffer.from(`\r
|
|
904
|
+
--${boundary}--\r
|
|
905
|
+
`);
|
|
906
|
+
const body = Buffer.concat([header, fileBuffer, footer]);
|
|
907
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
908
|
+
console.error(`[nworks] POST ${uploadUrl} (upload content, ${fileSize} bytes)`);
|
|
909
|
+
}
|
|
910
|
+
const uploadRes = await authedFetch(
|
|
911
|
+
uploadUrl,
|
|
912
|
+
{
|
|
913
|
+
method: "POST",
|
|
914
|
+
headers: { "Content-Type": `multipart/form-data; boundary=${boundary}` },
|
|
915
|
+
body
|
|
916
|
+
},
|
|
917
|
+
profile
|
|
918
|
+
);
|
|
919
|
+
if (!uploadRes.ok) return handleError(uploadRes);
|
|
920
|
+
return await uploadRes.json();
|
|
921
|
+
}
|
|
922
|
+
async function downloadFile(fileId, userId = "me", profile = "default") {
|
|
923
|
+
const url2 = `${BASE_URL3}/users/${userId}/drive/files/${fileId}/download`;
|
|
924
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
925
|
+
console.error(`[nworks] GET ${url2} (get download URL)`);
|
|
926
|
+
}
|
|
927
|
+
const redirectRes = await authedFetch(
|
|
928
|
+
url2,
|
|
929
|
+
{ method: "GET", redirect: "manual" },
|
|
930
|
+
profile
|
|
931
|
+
);
|
|
932
|
+
if (redirectRes.status === 401) {
|
|
933
|
+
throw new AuthError("User token expired. Run `nworks login --user --scope file` again.");
|
|
934
|
+
}
|
|
935
|
+
const location = redirectRes.headers.get("location");
|
|
936
|
+
if (!location) {
|
|
937
|
+
if (!redirectRes.ok) return handleError(redirectRes);
|
|
938
|
+
throw new ApiError("NO_REDIRECT", "No download URL returned", redirectRes.status);
|
|
939
|
+
}
|
|
940
|
+
if (process.env["NWORKS_VERBOSE"] === "1") {
|
|
941
|
+
console.error(`[nworks] GET ${location} (download content)`);
|
|
942
|
+
}
|
|
943
|
+
const downloadRes = await authedFetch(location, { method: "GET" }, profile);
|
|
944
|
+
if (!downloadRes.ok) return handleError(downloadRes);
|
|
945
|
+
const arrayBuffer = await downloadRes.arrayBuffer();
|
|
946
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
947
|
+
const disposition = downloadRes.headers.get("content-disposition");
|
|
948
|
+
let fileName;
|
|
949
|
+
if (disposition) {
|
|
950
|
+
const match = disposition.match(/filename\*?=(?:UTF-8''|"?)([^";]+)/i);
|
|
951
|
+
if (match?.[1]) {
|
|
952
|
+
fileName = decodeURIComponent(match[1].replace(/"/g, ""));
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return { buffer, fileName };
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// src/commands/drive.ts
|
|
959
|
+
var listCommand2 = new Command7("list").description("List files in Drive (requires User OAuth with file or file.read scope)").option("--user <userId>", "Target user ID (default: me)").option("--folder <folderId>", "Folder ID to list (default: root)").option("--count <n>", "Items per page (default: 20)", "20").option("--cursor <cursor>", "Pagination cursor").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
960
|
+
try {
|
|
961
|
+
const result = await listFiles(
|
|
962
|
+
opts.user ?? "me",
|
|
963
|
+
opts.folder,
|
|
964
|
+
parseInt(opts.count, 10),
|
|
965
|
+
opts.cursor,
|
|
966
|
+
opts.profile
|
|
967
|
+
);
|
|
968
|
+
const files = result.files.map((f) => ({
|
|
969
|
+
name: f.fileName,
|
|
970
|
+
type: f.fileType,
|
|
971
|
+
size: f.fileSize,
|
|
972
|
+
modified: f.modifiedTime,
|
|
973
|
+
fileId: f.fileId
|
|
974
|
+
}));
|
|
975
|
+
output(
|
|
976
|
+
{
|
|
977
|
+
files,
|
|
978
|
+
count: files.length,
|
|
979
|
+
nextCursor: result.responseMetaData?.nextCursor ?? null
|
|
980
|
+
},
|
|
981
|
+
opts
|
|
982
|
+
);
|
|
983
|
+
} catch (err) {
|
|
984
|
+
const error48 = err;
|
|
985
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
986
|
+
process.exitCode = 1;
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
var uploadCommand = new Command7("upload").description("Upload a file to Drive (requires User OAuth with file scope)").requiredOption("--file <path>", "Local file path to upload").option("--user <userId>", "Target user ID (default: me)").option("--folder <folderId>", "Destination folder ID (default: root)").option("--overwrite", "Overwrite if file exists", false).option("--profile <name>", "Profile name", "default").option("--json", "JSON output").option("--dry-run", "Print request without uploading").action(async (opts) => {
|
|
990
|
+
try {
|
|
991
|
+
if (opts.dryRun) {
|
|
992
|
+
output(
|
|
993
|
+
{
|
|
994
|
+
dryRun: true,
|
|
995
|
+
request: {
|
|
996
|
+
file: opts.file,
|
|
997
|
+
user: opts.user ?? "me",
|
|
998
|
+
folder: opts.folder ?? "(root)",
|
|
999
|
+
overwrite: opts.overwrite
|
|
1000
|
+
}
|
|
1001
|
+
},
|
|
1002
|
+
opts
|
|
1003
|
+
);
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
const result = await uploadFile(
|
|
1007
|
+
opts.file,
|
|
1008
|
+
opts.user ?? "me",
|
|
1009
|
+
opts.folder,
|
|
1010
|
+
opts.overwrite,
|
|
1011
|
+
opts.profile
|
|
1012
|
+
);
|
|
1013
|
+
output(
|
|
1014
|
+
{
|
|
1015
|
+
success: true,
|
|
1016
|
+
fileId: result.fileId,
|
|
1017
|
+
fileName: result.fileName,
|
|
1018
|
+
fileSize: result.fileSize,
|
|
1019
|
+
filePath: result.filePath,
|
|
1020
|
+
fileType: result.fileType
|
|
1021
|
+
},
|
|
1022
|
+
opts
|
|
1023
|
+
);
|
|
1024
|
+
} catch (err) {
|
|
1025
|
+
const error48 = err;
|
|
1026
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
1027
|
+
process.exitCode = 1;
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
var downloadCommand = new Command7("download").description("Download a file from Drive (requires User OAuth with file or file.read scope)").requiredOption("--file-id <fileId>", "File ID to download").option("--out <path>", "Output directory (default: current directory)").option("--name <filename>", "Output filename (default: original name)").option("--user <userId>", "Target user ID (default: me)").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
|
|
1031
|
+
try {
|
|
1032
|
+
const result = await downloadFile(
|
|
1033
|
+
opts.fileId,
|
|
1034
|
+
opts.user ?? "me",
|
|
1035
|
+
opts.profile
|
|
1036
|
+
);
|
|
1037
|
+
const fileName = opts.name ?? result.fileName ?? opts.fileId;
|
|
1038
|
+
const outDir = opts.out ?? process.cwd();
|
|
1039
|
+
const outPath = join2(outDir, fileName);
|
|
1040
|
+
await writeFile2(outPath, result.buffer);
|
|
1041
|
+
output(
|
|
1042
|
+
{
|
|
1043
|
+
success: true,
|
|
1044
|
+
fileName,
|
|
1045
|
+
path: outPath,
|
|
1046
|
+
size: result.buffer.length
|
|
1047
|
+
},
|
|
1048
|
+
opts
|
|
1049
|
+
);
|
|
1050
|
+
} catch (err) {
|
|
1051
|
+
const error48 = err;
|
|
1052
|
+
errorOutput({ code: error48.code, message: error48.message }, opts);
|
|
1053
|
+
process.exitCode = 1;
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
var driveCommand = new Command7("drive").description("Drive operations (requires User OAuth with file scope)").addCommand(listCommand2).addCommand(uploadCommand).addCommand(downloadCommand);
|
|
1057
|
+
|
|
1058
|
+
// src/commands/mcp-cmd.ts
|
|
1059
|
+
import { Command as Command8 } from "commander";
|
|
1060
|
+
|
|
833
1061
|
// src/mcp/server.ts
|
|
834
1062
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
835
1063
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -14712,6 +14940,105 @@ function registerTools(server) {
|
|
|
14712
14940
|
}
|
|
14713
14941
|
}
|
|
14714
14942
|
);
|
|
14943
|
+
server.tool(
|
|
14944
|
+
"nworks_drive_list",
|
|
14945
|
+
"\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C/\uD3F4\uB354 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694)",
|
|
14946
|
+
{
|
|
14947
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)"),
|
|
14948
|
+
folderId: external_exports.string().optional().describe("\uD3F4\uB354 ID (\uBBF8\uC9C0\uC815 \uC2DC \uB8E8\uD2B8)"),
|
|
14949
|
+
count: external_exports.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 20, \uCD5C\uB300: 200)"),
|
|
14950
|
+
cursor: external_exports.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C")
|
|
14951
|
+
},
|
|
14952
|
+
async ({ userId, folderId, count, cursor }) => {
|
|
14953
|
+
try {
|
|
14954
|
+
const result = await listFiles(
|
|
14955
|
+
userId ?? "me",
|
|
14956
|
+
folderId,
|
|
14957
|
+
count ?? 20,
|
|
14958
|
+
cursor
|
|
14959
|
+
);
|
|
14960
|
+
const files = result.files.map((f) => ({
|
|
14961
|
+
fileId: f.fileId,
|
|
14962
|
+
name: f.fileName,
|
|
14963
|
+
type: f.fileType,
|
|
14964
|
+
size: f.fileSize,
|
|
14965
|
+
modified: f.modifiedTime,
|
|
14966
|
+
path: f.filePath
|
|
14967
|
+
}));
|
|
14968
|
+
return {
|
|
14969
|
+
content: [{ type: "text", text: JSON.stringify({ files, count: files.length, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
|
|
14970
|
+
};
|
|
14971
|
+
} catch (err) {
|
|
14972
|
+
const error48 = err;
|
|
14973
|
+
return {
|
|
14974
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
14975
|
+
isError: true
|
|
14976
|
+
};
|
|
14977
|
+
}
|
|
14978
|
+
}
|
|
14979
|
+
);
|
|
14980
|
+
server.tool(
|
|
14981
|
+
"nworks_drive_upload",
|
|
14982
|
+
"\uB85C\uCEEC \uD30C\uC77C\uC744 \uB4DC\uB77C\uC774\uBE0C\uC5D0 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file scope \uD544\uC694)",
|
|
14983
|
+
{
|
|
14984
|
+
filePath: external_exports.string().describe("\uC5C5\uB85C\uB4DC\uD560 \uB85C\uCEEC \uD30C\uC77C \uACBD\uB85C"),
|
|
14985
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)"),
|
|
14986
|
+
folderId: external_exports.string().optional().describe("\uC5C5\uB85C\uB4DC\uD560 \uD3F4\uB354 ID (\uBBF8\uC9C0\uC815 \uC2DC \uB8E8\uD2B8)"),
|
|
14987
|
+
overwrite: external_exports.boolean().optional().describe("\uB3D9\uC77C \uD30C\uC77C\uBA85 \uB36E\uC5B4\uC4F0\uAE30 (\uAE30\uBCF8: false)")
|
|
14988
|
+
},
|
|
14989
|
+
async ({ filePath, userId, folderId, overwrite }) => {
|
|
14990
|
+
try {
|
|
14991
|
+
const result = await uploadFile(
|
|
14992
|
+
filePath,
|
|
14993
|
+
userId ?? "me",
|
|
14994
|
+
folderId,
|
|
14995
|
+
overwrite ?? false
|
|
14996
|
+
);
|
|
14997
|
+
return {
|
|
14998
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, ...result }) }]
|
|
14999
|
+
};
|
|
15000
|
+
} catch (err) {
|
|
15001
|
+
const error48 = err;
|
|
15002
|
+
return {
|
|
15003
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
15004
|
+
isError: true
|
|
15005
|
+
};
|
|
15006
|
+
}
|
|
15007
|
+
}
|
|
15008
|
+
);
|
|
15009
|
+
server.tool(
|
|
15010
|
+
"nworks_drive_download",
|
|
15011
|
+
"\uB4DC\uB77C\uC774\uBE0C \uD30C\uC77C\uC744 \uB2E4\uC6B4\uB85C\uB4DC\uD569\uB2C8\uB2E4 (User OAuth file \uB610\uB294 file.read scope \uD544\uC694)",
|
|
15012
|
+
{
|
|
15013
|
+
fileId: external_exports.string().describe("\uB2E4\uC6B4\uB85C\uB4DC\uD560 \uD30C\uC77C ID"),
|
|
15014
|
+
outputDir: external_exports.string().optional().describe("\uC800\uC7A5 \uB514\uB809\uD1A0\uB9AC (\uBBF8\uC9C0\uC815 \uC2DC \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC)"),
|
|
15015
|
+
outputName: external_exports.string().optional().describe("\uC800\uC7A5 \uD30C\uC77C\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uC6D0\uBCF8 \uD30C\uC77C\uBA85)"),
|
|
15016
|
+
userId: external_exports.string().optional().describe("\uB300\uC0C1 \uC0AC\uC6A9\uC790 ID (\uBBF8\uC9C0\uC815 \uC2DC me)")
|
|
15017
|
+
},
|
|
15018
|
+
async ({ fileId, outputDir, outputName, userId }) => {
|
|
15019
|
+
try {
|
|
15020
|
+
const { writeFile: writeFile3 } = await import("fs/promises");
|
|
15021
|
+
const { join: join3 } = await import("path");
|
|
15022
|
+
const result = await downloadFile(
|
|
15023
|
+
fileId,
|
|
15024
|
+
userId ?? "me"
|
|
15025
|
+
);
|
|
15026
|
+
const fileName = outputName ?? result.fileName ?? fileId;
|
|
15027
|
+
const dir = outputDir ?? process.cwd();
|
|
15028
|
+
const outPath = join3(dir, fileName);
|
|
15029
|
+
await writeFile3(outPath, result.buffer);
|
|
15030
|
+
return {
|
|
15031
|
+
content: [{ type: "text", text: JSON.stringify({ success: true, fileName, path: outPath, size: result.buffer.length }) }]
|
|
15032
|
+
};
|
|
15033
|
+
} catch (err) {
|
|
15034
|
+
const error48 = err;
|
|
15035
|
+
return {
|
|
15036
|
+
content: [{ type: "text", text: `Error: ${error48.message}` }],
|
|
15037
|
+
isError: true
|
|
15038
|
+
};
|
|
15039
|
+
}
|
|
15040
|
+
}
|
|
15041
|
+
);
|
|
14715
15042
|
server.tool(
|
|
14716
15043
|
"nworks_whoami",
|
|
14717
15044
|
"\uD604\uC7AC \uC778\uC99D\uB41C NAVER WORKS \uACC4\uC815 \uC815\uBCF4\uB97C \uD655\uC778\uD569\uB2C8\uB2E4",
|
|
@@ -14753,7 +15080,7 @@ async function startMcpServer() {
|
|
|
14753
15080
|
}
|
|
14754
15081
|
|
|
14755
15082
|
// src/commands/mcp-cmd.ts
|
|
14756
|
-
var mcpCommand = new
|
|
15083
|
+
var mcpCommand = new Command8("mcp").description("Start MCP server (stdio transport)").option("--list-tools", "List available MCP tools").action(async (opts) => {
|
|
14757
15084
|
if (opts.listTools) {
|
|
14758
15085
|
console.log("nworks_message_send \u2014 Send message to user or channel");
|
|
14759
15086
|
console.log("nworks_message_members \u2014 List channel members");
|
|
@@ -14768,13 +15095,14 @@ var mcpCommand = new Command7("mcp").description("Start MCP server (stdio transp
|
|
|
14768
15095
|
// src/index.ts
|
|
14769
15096
|
var require2 = createRequire(import.meta.url);
|
|
14770
15097
|
var { version: version2 } = require2("../package.json");
|
|
14771
|
-
var program = new
|
|
15098
|
+
var program = new Command9().name("nworks").description("NAVER WORKS CLI \u2014 built for humans and AI agents").version(version2).option("--json", "Always output JSON").option("-v, --verbose", "Debug logging").option("--dry-run", "Print request without calling API").option("-p, --profile <name>", "Profile name", "default");
|
|
14772
15099
|
program.addCommand(loginCommand);
|
|
14773
15100
|
program.addCommand(logoutCommand);
|
|
14774
15101
|
program.addCommand(whoamiCommand);
|
|
14775
15102
|
program.addCommand(messageCommand);
|
|
14776
15103
|
program.addCommand(directoryCommand);
|
|
14777
15104
|
program.addCommand(calendarCommand);
|
|
15105
|
+
program.addCommand(driveCommand);
|
|
14778
15106
|
program.addCommand(mcpCommand);
|
|
14779
15107
|
program.parse();
|
|
14780
15108
|
//# sourceMappingURL=index.js.map
|