nworks 0.6.2 → 1.0.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/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 Command11 } from "commander";
10
+ import { Command as Command12 } from "commander";
11
11
 
12
12
  // src/commands/login.ts
13
13
  import { Command } from "commander";
@@ -52,20 +52,15 @@ async function ensureConfigDir() {
52
52
  function getCredentialsFromEnv() {
53
53
  const clientId = process.env["NWORKS_CLIENT_ID"];
54
54
  const clientSecret = process.env["NWORKS_CLIENT_SECRET"];
55
- const serviceAccount = process.env["NWORKS_SERVICE_ACCOUNT"];
56
- const privateKeyPath = process.env["NWORKS_PRIVATE_KEY_PATH"];
57
- const botId = process.env["NWORKS_BOT_ID"];
58
- if (clientId && clientSecret && serviceAccount && privateKeyPath && botId) {
59
- return {
60
- clientId,
61
- clientSecret,
62
- serviceAccount,
63
- privateKeyPath,
64
- botId,
65
- domainId: process.env["NWORKS_DOMAIN_ID"]
66
- };
67
- }
68
- return null;
55
+ if (!clientId || !clientSecret) return null;
56
+ return {
57
+ clientId,
58
+ clientSecret,
59
+ serviceAccount: process.env["NWORKS_SERVICE_ACCOUNT"],
60
+ privateKeyPath: process.env["NWORKS_PRIVATE_KEY_PATH"],
61
+ botId: process.env["NWORKS_BOT_ID"],
62
+ domainId: process.env["NWORKS_DOMAIN_ID"]
63
+ };
69
64
  }
70
65
  async function loadCredentials(profile = "default") {
71
66
  const envCreds = getCredentialsFromEnv();
@@ -166,6 +161,11 @@ async function clearCredentials(profile = "default") {
166
161
  import { readFile as readFile2 } from "fs/promises";
167
162
  import jwt from "jsonwebtoken";
168
163
  async function createJWT(creds) {
164
+ if (!creds.serviceAccount || !creds.privateKeyPath) {
165
+ throw new AuthError(
166
+ "Service Account credentials required for bot authentication.\nRun `nworks login` with --service-account and --private-key flags."
167
+ );
168
+ }
169
169
  const privateKey = await readFile2(creds.privateKeyPath, "utf-8");
170
170
  const now = Math.floor(Date.now() / 1e3);
171
171
  const payload = {
@@ -232,7 +232,7 @@ function buildAuthorizeUrl(clientId, scope, state) {
232
232
  });
233
233
  return `${AUTH_URL2}?${params.toString()}`;
234
234
  }
235
- async function startUserOAuthFlow(scope, profile = "default") {
235
+ async function startUserOAuthFlow(_scope, profile = "default") {
236
236
  const creds = await loadCredentials(profile);
237
237
  const code = await waitForAuthCode();
238
238
  return exchangeCodeForToken(code, creds.clientId, creds.clientSecret);
@@ -431,9 +431,31 @@ var loginCommand = new Command("login").description("Authenticate with NAVER WOR
431
431
  }
432
432
  });
433
433
  async function handleUserLogin(scope, profile, opts) {
434
- const creds = await loadCredentials(profile);
434
+ let clientId = opts.clientId;
435
+ let clientSecret = opts.clientSecret;
436
+ try {
437
+ const existing = await loadCredentials(profile);
438
+ if (!clientId) clientId = existing.clientId;
439
+ if (!clientSecret) clientSecret = existing.clientSecret;
440
+ } catch {
441
+ }
442
+ if (process.stdin.isTTY) {
443
+ if (!clientId) clientId = await prompt("Client ID: ");
444
+ if (!clientSecret) clientSecret = await prompt("Client Secret: ");
445
+ }
446
+ if (!clientId || !clientSecret) {
447
+ throw new Error(
448
+ "Client ID and Client Secret are required for User OAuth.\nUse --client-id and --client-secret flags, or set NWORKS_CLIENT_ID / NWORKS_CLIENT_SECRET env vars."
449
+ );
450
+ }
451
+ try {
452
+ const existing = await loadCredentials(profile);
453
+ await saveCredentials({ ...existing, clientId, clientSecret }, profile);
454
+ } catch {
455
+ await saveCredentials({ clientId, clientSecret }, profile);
456
+ }
435
457
  const state = randomBytes(16).toString("hex");
436
- const authorizeUrl = buildAuthorizeUrl(creds.clientId, scope, state);
458
+ const authorizeUrl = buildAuthorizeUrl(clientId, scope, state);
437
459
  console.error(`
438
460
  Opening browser for NAVER WORKS login...`);
439
461
  console.error(`If the browser does not open, visit this URL:
@@ -463,6 +485,11 @@ async function handleServiceAccountLogin(opts) {
463
485
  let botId = opts.botId;
464
486
  const domainId = opts.domainId;
465
487
  const profile = opts.profile;
488
+ if (!clientId) clientId = process.env["NWORKS_CLIENT_ID"];
489
+ if (!clientSecret) clientSecret = process.env["NWORKS_CLIENT_SECRET"];
490
+ if (!serviceAccount) serviceAccount = process.env["NWORKS_SERVICE_ACCOUNT"];
491
+ if (!privateKeyPath) privateKeyPath = process.env["NWORKS_PRIVATE_KEY_PATH"];
492
+ if (!botId) botId = process.env["NWORKS_BOT_ID"];
466
493
  if (process.stdin.isTTY) {
467
494
  if (!clientId) clientId = await prompt("Client ID: ");
468
495
  if (!clientSecret) clientSecret = await prompt("Client Secret: ");
@@ -474,7 +501,7 @@ async function handleServiceAccountLogin(opts) {
474
501
  }
475
502
  if (!clientId || !clientSecret || !serviceAccount || !privateKeyPath || !botId) {
476
503
  throw new Error(
477
- "Missing required fields. Use flags or run interactively."
504
+ "Missing required fields. Use flags, environment variables, or run interactively."
478
505
  );
479
506
  }
480
507
  if (!existsSync2(privateKeyPath)) {
@@ -527,9 +554,9 @@ var whoamiCommand = new Command3("whoami").description("Show current authenticat
527
554
  output(
528
555
  {
529
556
  profile,
530
- serviceAccount: creds.serviceAccount,
557
+ serviceAccount: creds.serviceAccount ?? "(not set)",
531
558
  clientId: creds.clientId,
532
- botId: creds.botId,
559
+ botId: creds.botId ?? "(not set)",
533
560
  domainId: creds.domainId ?? "(not set)",
534
561
  tokenValid: isValid,
535
562
  tokenExpiresAt
@@ -624,6 +651,11 @@ function buildContent(opts) {
624
651
  async function send(opts) {
625
652
  const profile = opts.profile ?? "default";
626
653
  const creds = await loadCredentials(profile);
654
+ if (!creds.botId) {
655
+ throw new Error(
656
+ "Bot ID is required for sending messages.\nRun `nworks login` with --bot-id flag to set up bot credentials."
657
+ );
658
+ }
627
659
  const content = buildContent(opts);
628
660
  const body = { content };
629
661
  if (opts.to) {
@@ -648,6 +680,11 @@ async function send(opts) {
648
680
  }
649
681
  async function listMembers(channelId, profile = "default") {
650
682
  const creds = await loadCredentials(profile);
683
+ if (!creds.botId) {
684
+ throw new Error(
685
+ "Bot ID is required for listing channel members.\nRun `nworks login` with --bot-id flag to set up bot credentials."
686
+ );
687
+ }
651
688
  const result = await request({
652
689
  method: "GET",
653
690
  path: `/bots/${creds.botId}/channels/${channelId}/members`,
@@ -855,7 +892,9 @@ async function getEvent(eventId, userId = "me", profile = "default") {
855
892
  const res = await authedFetch(url2, { method: "GET" }, profile);
856
893
  if (!res.ok) return handleError(res);
857
894
  const data = await res.json();
858
- return data.eventComponents[0];
895
+ const event = data.eventComponents[0];
896
+ if (!event) throw new ApiError("NOT_FOUND", "Event not found", 404);
897
+ return event;
859
898
  }
860
899
  async function updateEvent(opts) {
861
900
  const userId = opts.userId ?? "me";
@@ -1756,9 +1795,223 @@ var deleteCommand2 = new Command9("delete").description("Delete a task (requires
1756
1795
  });
1757
1796
  var taskCommand = new Command9("task").description("Task operations (requires User OAuth with task scope)").addCommand(listCommand4).addCommand(createCommand2).addCommand(updateCommand2).addCommand(deleteCommand2);
1758
1797
 
1759
- // src/commands/mcp-cmd.ts
1798
+ // src/commands/board.ts
1760
1799
  import { Command as Command10 } from "commander";
1761
1800
 
1801
+ // src/api/board.ts
1802
+ var BASE_URL6 = "https://www.worksapis.com/v1.0";
1803
+ async function authedFetch5(url2, init, profile) {
1804
+ const token = await getValidUserToken(profile);
1805
+ const headers = new Headers(init.headers);
1806
+ headers.set("Authorization", `Bearer ${token}`);
1807
+ return fetch(url2, { ...init, headers });
1808
+ }
1809
+ async function handleError5(res) {
1810
+ if (res.status === 401) {
1811
+ throw new AuthError("User token expired. Run `nworks login --user --scope board` again.");
1812
+ }
1813
+ let code = "UNKNOWN";
1814
+ let description = `HTTP ${res.status}`;
1815
+ try {
1816
+ const body = await res.json();
1817
+ code = body.code ?? code;
1818
+ description = body.description ?? description;
1819
+ } catch {
1820
+ }
1821
+ throw new ApiError(code, description, res.status);
1822
+ }
1823
+ function safeParseJson(text) {
1824
+ const safe = text.replace(
1825
+ /"((?:board|post|domain|user)Id)"\s*:\s*(\d{16,})/g,
1826
+ '"$1":"$2"'
1827
+ );
1828
+ return JSON.parse(safe);
1829
+ }
1830
+ async function listBoards(count = 20, cursor, profile = "default") {
1831
+ const params = new URLSearchParams();
1832
+ params.set("count", String(count));
1833
+ if (cursor) params.set("cursor", cursor);
1834
+ const url2 = `${BASE_URL6}/boards?${params.toString()}`;
1835
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1836
+ console.error(`[nworks] GET ${url2}`);
1837
+ }
1838
+ const res = await authedFetch5(url2, { method: "GET" }, profile);
1839
+ if (!res.ok) return handleError5(res);
1840
+ const text = await res.text();
1841
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1842
+ console.error(`[nworks] Response: ${text}`);
1843
+ }
1844
+ const data = safeParseJson(text);
1845
+ return { boards: data.boards ?? [], responseMetaData: data.responseMetaData };
1846
+ }
1847
+ async function listPosts(boardId, count = 20, cursor, profile = "default") {
1848
+ const params = new URLSearchParams();
1849
+ params.set("count", String(count));
1850
+ if (cursor) params.set("cursor", cursor);
1851
+ const url2 = `${BASE_URL6}/boards/${boardId}/posts?${params.toString()}`;
1852
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1853
+ console.error(`[nworks] GET ${url2}`);
1854
+ }
1855
+ const res = await authedFetch5(url2, { method: "GET" }, profile);
1856
+ if (!res.ok) return handleError5(res);
1857
+ const text = await res.text();
1858
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1859
+ console.error(`[nworks] Response: ${text}`);
1860
+ }
1861
+ const data = safeParseJson(text);
1862
+ return { posts: data.posts ?? [], responseMetaData: data.responseMetaData };
1863
+ }
1864
+ async function readPost(boardId, postId, profile = "default") {
1865
+ const url2 = `${BASE_URL6}/boards/${boardId}/posts/${postId}`;
1866
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1867
+ console.error(`[nworks] GET ${url2}`);
1868
+ }
1869
+ const res = await authedFetch5(url2, { method: "GET" }, profile);
1870
+ if (!res.ok) return handleError5(res);
1871
+ const text = await res.text();
1872
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1873
+ console.error(`[nworks] Response: ${text}`);
1874
+ }
1875
+ return safeParseJson(text);
1876
+ }
1877
+ async function createPost(opts) {
1878
+ const profile = opts.profile ?? "default";
1879
+ const body = {
1880
+ title: opts.title,
1881
+ body: opts.body ?? ""
1882
+ };
1883
+ if (opts.enableComment !== void 0) body.enableComment = opts.enableComment;
1884
+ if (opts.sendNotifications !== void 0) body.sendNotifications = opts.sendNotifications;
1885
+ const url2 = `${BASE_URL6}/boards/${opts.boardId}/posts`;
1886
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1887
+ console.error(`[nworks] POST ${url2}`);
1888
+ console.error(`[nworks] Body: ${JSON.stringify(body, null, 2)}`);
1889
+ }
1890
+ const res = await authedFetch5(
1891
+ url2,
1892
+ {
1893
+ method: "POST",
1894
+ headers: { "Content-Type": "application/json" },
1895
+ body: JSON.stringify(body)
1896
+ },
1897
+ profile
1898
+ );
1899
+ if (res.status === 201 || res.ok) {
1900
+ const text = await res.text();
1901
+ if (process.env["NWORKS_VERBOSE"] === "1") {
1902
+ console.error(`[nworks] Response: ${text}`);
1903
+ }
1904
+ return safeParseJson(text);
1905
+ }
1906
+ return handleError5(res);
1907
+ }
1908
+
1909
+ // src/commands/board.ts
1910
+ var listCommand5 = new Command10("list").description("List boards (requires User OAuth with board or board.read scope)").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) => {
1911
+ try {
1912
+ const result = await listBoards(
1913
+ parseInt(opts.count, 10),
1914
+ opts.cursor,
1915
+ opts.profile
1916
+ );
1917
+ const boards = result.boards.map((b) => ({
1918
+ boardId: b.boardId,
1919
+ boardName: b.boardName,
1920
+ description: b.description ?? ""
1921
+ }));
1922
+ output(
1923
+ { boards, count: boards.length, nextCursor: result.responseMetaData?.nextCursor ?? null },
1924
+ opts
1925
+ );
1926
+ } catch (err) {
1927
+ const error48 = err;
1928
+ errorOutput({ code: error48.code, message: error48.message }, opts);
1929
+ process.exitCode = 1;
1930
+ }
1931
+ });
1932
+ var postsCommand = new Command10("posts").description("List posts in a board (requires User OAuth with board or board.read scope)").requiredOption("--board <boardId>", "Board ID").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) => {
1933
+ try {
1934
+ const result = await listPosts(
1935
+ opts.board,
1936
+ parseInt(opts.count, 10),
1937
+ opts.cursor,
1938
+ opts.profile
1939
+ );
1940
+ const posts = result.posts.map((p) => ({
1941
+ postId: p.postId,
1942
+ title: p.title,
1943
+ userName: p.userName ?? "",
1944
+ readCount: p.readCount ?? 0,
1945
+ commentCount: p.commentCount ?? 0,
1946
+ createdTime: p.createdTime ?? ""
1947
+ }));
1948
+ output(
1949
+ { posts, count: posts.length, nextCursor: result.responseMetaData?.nextCursor ?? null },
1950
+ opts
1951
+ );
1952
+ } catch (err) {
1953
+ const error48 = err;
1954
+ errorOutput({ code: error48.code, message: error48.message }, opts);
1955
+ process.exitCode = 1;
1956
+ }
1957
+ });
1958
+ var readCommand2 = new Command10("read").description("Read a post detail (requires User OAuth with board or board.read scope)").requiredOption("--board <boardId>", "Board ID").requiredOption("--post <postId>", "Post ID").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
1959
+ try {
1960
+ const post = await readPost(
1961
+ opts.board,
1962
+ opts.post,
1963
+ opts.profile
1964
+ );
1965
+ output(
1966
+ {
1967
+ postId: post.postId,
1968
+ boardId: post.boardId,
1969
+ title: post.title,
1970
+ body: post.body ?? "",
1971
+ userName: post.userName ?? "",
1972
+ readCount: post.readCount ?? 0,
1973
+ commentCount: post.commentCount ?? 0,
1974
+ createdTime: post.createdTime ?? "",
1975
+ updatedTime: post.updatedTime ?? ""
1976
+ },
1977
+ opts
1978
+ );
1979
+ } catch (err) {
1980
+ const error48 = err;
1981
+ errorOutput({ code: error48.code, message: error48.message }, opts);
1982
+ process.exitCode = 1;
1983
+ }
1984
+ });
1985
+ var createCommand3 = new Command10("create").description("Create a post in a board (requires User OAuth with board scope)").requiredOption("--board <boardId>", "Board ID").requiredOption("--title <title>", "Post title").option("--body <text>", "Post body").option("--no-comment", "Disable comments").option("--notify", "Send notification").option("--profile <name>", "Profile name", "default").option("--json", "JSON output").action(async (opts) => {
1986
+ try {
1987
+ const post = await createPost({
1988
+ boardId: opts.board,
1989
+ title: opts.title,
1990
+ body: opts.body,
1991
+ enableComment: opts.comment,
1992
+ sendNotifications: opts.notify ?? false,
1993
+ profile: opts.profile
1994
+ });
1995
+ output(
1996
+ {
1997
+ success: true,
1998
+ postId: post.postId,
1999
+ boardId: post.boardId,
2000
+ title: post.title
2001
+ },
2002
+ opts
2003
+ );
2004
+ } catch (err) {
2005
+ const error48 = err;
2006
+ errorOutput({ code: error48.code, message: error48.message }, opts);
2007
+ process.exitCode = 1;
2008
+ }
2009
+ });
2010
+ var boardCommand = new Command10("board").description("Board operations (requires User OAuth)").addCommand(listCommand5).addCommand(postsCommand).addCommand(readCommand2).addCommand(createCommand3);
2011
+
2012
+ // src/commands/mcp-cmd.ts
2013
+ import { Command as Command11 } from "commander";
2014
+
1762
2015
  // src/mcp/server.ts
1763
2016
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1764
2017
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -16136,6 +16389,127 @@ function registerTools(server) {
16136
16389
  }
16137
16390
  }
16138
16391
  );
16392
+ server.tool(
16393
+ "nworks_board_list",
16394
+ "\uAC8C\uC2DC\uD310 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth board \uB610\uB294 board.read scope \uD544\uC694)",
16395
+ {
16396
+ count: external_exports.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 20)"),
16397
+ cursor: external_exports.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C")
16398
+ },
16399
+ async ({ count, cursor }) => {
16400
+ try {
16401
+ const result = await listBoards(count ?? 20, cursor);
16402
+ const boards = result.boards.map((b) => ({
16403
+ boardId: b.boardId,
16404
+ boardName: b.boardName,
16405
+ description: b.description ?? ""
16406
+ }));
16407
+ return {
16408
+ content: [{ type: "text", text: JSON.stringify({ boards, count: boards.length, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
16409
+ };
16410
+ } catch (err) {
16411
+ const error48 = err;
16412
+ return {
16413
+ content: [{ type: "text", text: `Error: ${error48.message}` }],
16414
+ isError: true
16415
+ };
16416
+ }
16417
+ }
16418
+ );
16419
+ server.tool(
16420
+ "nworks_board_posts",
16421
+ "\uAC8C\uC2DC\uD310\uC758 \uAE00 \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth board \uB610\uB294 board.read scope \uD544\uC694)",
16422
+ {
16423
+ boardId: external_exports.string().describe("\uAC8C\uC2DC\uD310 ID"),
16424
+ count: external_exports.number().optional().describe("\uD398\uC774\uC9C0\uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: 20, \uCD5C\uB300: 40)"),
16425
+ cursor: external_exports.string().optional().describe("\uD398\uC774\uC9C0\uB124\uC774\uC158 \uCEE4\uC11C")
16426
+ },
16427
+ async ({ boardId, count, cursor }) => {
16428
+ try {
16429
+ const result = await listPosts(boardId, count ?? 20, cursor);
16430
+ const posts = result.posts.map((p) => ({
16431
+ postId: p.postId,
16432
+ title: p.title,
16433
+ userName: p.userName ?? "",
16434
+ readCount: p.readCount ?? 0,
16435
+ commentCount: p.commentCount ?? 0,
16436
+ createdTime: p.createdTime ?? ""
16437
+ }));
16438
+ return {
16439
+ content: [{ type: "text", text: JSON.stringify({ posts, count: posts.length, nextCursor: result.responseMetaData?.nextCursor ?? null }) }]
16440
+ };
16441
+ } catch (err) {
16442
+ const error48 = err;
16443
+ return {
16444
+ content: [{ type: "text", text: `Error: ${error48.message}` }],
16445
+ isError: true
16446
+ };
16447
+ }
16448
+ }
16449
+ );
16450
+ server.tool(
16451
+ "nworks_board_read",
16452
+ "\uAC8C\uC2DC\uD310 \uAE00\uC758 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4 (User OAuth board \uB610\uB294 board.read scope \uD544\uC694)",
16453
+ {
16454
+ boardId: external_exports.string().describe("\uAC8C\uC2DC\uD310 ID"),
16455
+ postId: external_exports.string().describe("\uAE00 ID")
16456
+ },
16457
+ async ({ boardId, postId }) => {
16458
+ try {
16459
+ const post = await readPost(boardId, postId);
16460
+ return {
16461
+ content: [{ type: "text", text: JSON.stringify({
16462
+ postId: post.postId,
16463
+ boardId: post.boardId,
16464
+ title: post.title,
16465
+ body: post.body ?? "",
16466
+ userName: post.userName ?? "",
16467
+ readCount: post.readCount ?? 0,
16468
+ commentCount: post.commentCount ?? 0,
16469
+ createdTime: post.createdTime ?? "",
16470
+ updatedTime: post.updatedTime ?? ""
16471
+ }) }]
16472
+ };
16473
+ } catch (err) {
16474
+ const error48 = err;
16475
+ return {
16476
+ content: [{ type: "text", text: `Error: ${error48.message}` }],
16477
+ isError: true
16478
+ };
16479
+ }
16480
+ }
16481
+ );
16482
+ server.tool(
16483
+ "nworks_board_create",
16484
+ "\uAC8C\uC2DC\uD310\uC5D0 \uAE00\uC744 \uC791\uC131\uD569\uB2C8\uB2E4 (User OAuth board scope \uD544\uC694)",
16485
+ {
16486
+ boardId: external_exports.string().describe("\uAC8C\uC2DC\uD310 ID"),
16487
+ title: external_exports.string().describe("\uAE00 \uC81C\uBAA9"),
16488
+ body: external_exports.string().optional().describe("\uAE00 \uBCF8\uBB38"),
16489
+ enableComment: external_exports.boolean().optional().describe("\uB313\uAE00 \uD5C8\uC6A9 (\uAE30\uBCF8: true)"),
16490
+ sendNotifications: external_exports.boolean().optional().describe("\uC54C\uB9BC \uBC1C\uC1A1 (\uAE30\uBCF8: false)")
16491
+ },
16492
+ async ({ boardId, title, body, enableComment, sendNotifications }) => {
16493
+ try {
16494
+ const post = await createPost({
16495
+ boardId,
16496
+ title,
16497
+ body,
16498
+ enableComment,
16499
+ sendNotifications
16500
+ });
16501
+ return {
16502
+ content: [{ type: "text", text: JSON.stringify({ success: true, postId: post.postId, boardId: post.boardId, title: post.title }) }]
16503
+ };
16504
+ } catch (err) {
16505
+ const error48 = err;
16506
+ return {
16507
+ content: [{ type: "text", text: `Error: ${error48.message}` }],
16508
+ isError: true
16509
+ };
16510
+ }
16511
+ }
16512
+ );
16139
16513
  server.tool(
16140
16514
  "nworks_whoami",
16141
16515
  "\uD604\uC7AC \uC778\uC99D\uB41C NAVER WORKS \uACC4\uC815 \uC815\uBCF4\uB97C \uD655\uC778\uD569\uB2C8\uB2E4",
@@ -16146,9 +16520,9 @@ function registerTools(server) {
16146
16520
  const token = await loadToken();
16147
16521
  const isValid = token ? token.expiresAt > Date.now() / 1e3 : false;
16148
16522
  const info = {
16149
- serviceAccount: creds.serviceAccount,
16523
+ serviceAccount: creds.serviceAccount ?? null,
16150
16524
  clientId: creds.clientId,
16151
- botId: creds.botId,
16525
+ botId: creds.botId ?? null,
16152
16526
  tokenValid: isValid
16153
16527
  };
16154
16528
  return {
@@ -16167,9 +16541,25 @@ function registerTools(server) {
16167
16541
 
16168
16542
  // src/mcp/server.ts
16169
16543
  async function startMcpServer() {
16544
+ try {
16545
+ await loadCredentials();
16546
+ } catch {
16547
+ console.error(
16548
+ "[nworks] Authentication required. Run: nworks login"
16549
+ );
16550
+ }
16551
+ try {
16552
+ const userToken = await loadUserToken();
16553
+ if (!userToken) {
16554
+ console.error(
16555
+ "[nworks] User OAuth not configured. Run: nworks login --user"
16556
+ );
16557
+ }
16558
+ } catch {
16559
+ }
16170
16560
  const server = new McpServer({
16171
16561
  name: "nworks",
16172
- version: "0.2.0"
16562
+ version: "1.0.0"
16173
16563
  });
16174
16564
  registerTools(server);
16175
16565
  const transport = new StdioServerTransport();
@@ -16177,7 +16567,7 @@ async function startMcpServer() {
16177
16567
  }
16178
16568
 
16179
16569
  // src/commands/mcp-cmd.ts
16180
- var mcpCommand = new Command10("mcp").description("Start MCP server (stdio transport)").option("--list-tools", "List available MCP tools").action(async (opts) => {
16570
+ var mcpCommand = new Command11("mcp").description("Start MCP server (stdio transport)").option("--list-tools", "List available MCP tools").action(async (opts) => {
16181
16571
  if (opts.listTools) {
16182
16572
  console.log("nworks_message_send \u2014 Send message to user or channel");
16183
16573
  console.log("nworks_message_members \u2014 List channel members");
@@ -16192,7 +16582,7 @@ var mcpCommand = new Command10("mcp").description("Start MCP server (stdio trans
16192
16582
  // src/index.ts
16193
16583
  var require2 = createRequire(import.meta.url);
16194
16584
  var { version: version2 } = require2("../package.json");
16195
- var program = new Command11().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");
16585
+ var program = new Command12().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");
16196
16586
  program.addCommand(loginCommand);
16197
16587
  program.addCommand(logoutCommand);
16198
16588
  program.addCommand(whoamiCommand);
@@ -16202,6 +16592,7 @@ program.addCommand(calendarCommand);
16202
16592
  program.addCommand(driveCommand);
16203
16593
  program.addCommand(mailCommand);
16204
16594
  program.addCommand(taskCommand);
16595
+ program.addCommand(boardCommand);
16205
16596
  program.addCommand(mcpCommand);
16206
16597
  program.parse();
16207
16598
  //# sourceMappingURL=index.js.map