writedock-mcp 0.4.4 → 0.4.6

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.
Files changed (35) hide show
  1. package/README.md +22 -20
  2. package/extension/LICENSE-MULTIPOST.txt +201 -0
  3. package/extension/LICENSE.txt +674 -0
  4. package/extension/NOTICE.txt +13 -0
  5. package/extension/assets/editor-DWoK50xk.js +76 -0
  6. package/extension/assets/editor-VBFqqvXW.css +1 -0
  7. package/extension/assets/icon-128.png +0 -0
  8. package/extension/assets/icon-16.png +0 -0
  9. package/extension/assets/icon-48.png +0 -0
  10. package/extension/assets/index.browser-Hs3ZYqOv.js +157 -0
  11. package/extension/assets/index.ts-DbQynGAJ.js +42 -0
  12. package/extension/assets/logo.svg +5 -0
  13. package/extension/assets/offscreen-3BECPbQX.js +63 -0
  14. package/extension/assets/purify.es-1yEQDPgc.js +3 -0
  15. package/extension/assets/react-vendor-BrXlnJmF.js +40 -0
  16. package/extension/assets/task-utils-DwzGcJkm.js +1 -0
  17. package/extension/manifest.json +40 -0
  18. package/extension/service-worker-loader.js +1 -0
  19. package/extension/src/editor/index.html +16 -0
  20. package/extension/src/offscreen/index.html +6 -0
  21. package/extension/zhihu-publication-observer.js +1 -0
  22. package/extension//345/256/211/350/243/205/344/270/216/346/233/264/346/226/260.txt +19 -0
  23. package/index.cjs +287 -69
  24. package/package.json +3 -2
  25. package/source/package.json +1 -1
  26. package/source/src/__tests__/bridge.test.ts +22 -0
  27. package/source/src/__tests__/extension-update.test.ts +54 -0
  28. package/source/src/__tests__/setup.test.ts +50 -0
  29. package/source/src/bridge.ts +40 -11
  30. package/source/src/extension-id.ts +2 -0
  31. package/source/src/extension-update.ts +82 -0
  32. package/source/src/index.ts +3 -0
  33. package/source/src/release-info.ts +3 -0
  34. package/source/src/server.ts +3 -3
  35. package/source/src/setup.ts +88 -0
package/index.cjs CHANGED
@@ -6820,14 +6820,14 @@ var require_utils = __commonJS({
6820
6820
  BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
6821
6821
  }
6822
6822
  }
6823
- function percentEncodeNonAscii(cp) {
6824
- if (cp < 2048) {
6825
- return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
6823
+ function percentEncodeNonAscii(cp2) {
6824
+ if (cp2 < 2048) {
6825
+ return BYTE_HEX[192 | cp2 >> 6] + BYTE_HEX[128 | cp2 & 63];
6826
6826
  }
6827
- if (cp < 65536) {
6828
- return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
6827
+ if (cp2 < 65536) {
6828
+ return BYTE_HEX[224 | cp2 >> 12] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
6829
6829
  }
6830
- return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
6830
+ return BYTE_HEX[240 | cp2 >> 18] + BYTE_HEX[128 | cp2 >> 12 & 63] + BYTE_HEX[128 | cp2 >> 6 & 63] + BYTE_HEX[128 | cp2 & 63];
6831
6831
  }
6832
6832
  function stringArrayToHexStripped(input) {
6833
6833
  let acc = "";
@@ -7222,8 +7222,8 @@ var require_utils = __commonJS({
7222
7222
  function encodeFragment(input) {
7223
7223
  return encodeComponent(input, isQueryFragmentCharacter);
7224
7224
  }
7225
- function isEscapeSafe(cp) {
7226
- return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
7225
+ function isEscapeSafe(cp2) {
7226
+ return cp2 >= 48 && cp2 <= 57 || cp2 >= 65 && cp2 <= 90 || cp2 >= 97 && cp2 <= 122 || cp2 === 42 || cp2 === 43 || cp2 === 45 || cp2 === 46 || cp2 === 47 || cp2 === 64 || cp2 === 95;
7227
7227
  }
7228
7228
  function normalizeQueryFragmentEncoding(input) {
7229
7229
  let output = "";
@@ -29739,7 +29739,7 @@ var MediaStore = class {
29739
29739
  // package.json
29740
29740
  var package_default = {
29741
29741
  name: "@writedock/mcp-server",
29742
- version: "0.4.4",
29742
+ version: "0.4.6",
29743
29743
  private: true,
29744
29744
  type: "module",
29745
29745
  description: "WriteDock local MCP server for the browser extension",
@@ -29772,6 +29772,91 @@ var distribution_default = {
29772
29772
  registry: "https://registry.npmjs.org/"
29773
29773
  };
29774
29774
 
29775
+ // src/extension-update.ts
29776
+ var import_node_fs = require("fs");
29777
+ var import_promises2 = require("fs/promises");
29778
+ var import_node_os = require("os");
29779
+ var import_node_path2 = require("path");
29780
+
29781
+ // src/extension-id.ts
29782
+ var EXTENSION_ORIGIN = "chrome-extension://himncajjeipncfpoajkcmfieonfpjfhb";
29783
+
29784
+ // src/extension-update.ts
29785
+ var EXTENSION_ID = EXTENSION_ORIGIN.replace("chrome-extension://", "");
29786
+ var readManifest = async (directory) => JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(directory, "manifest.json"), "utf8"));
29787
+ var isWriteDock = (manifest) => manifest.name === "\u5199\u4F5C\u53F0 WriteDock";
29788
+ function bundledExtension(base = __dirname) {
29789
+ try {
29790
+ const directory = (0, import_node_path2.join)(base, "extension");
29791
+ const manifest = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path2.join)(directory, "manifest.json"), "utf8"));
29792
+ return typeof manifest.version === "string" ? { directory, version: manifest.version } : void 0;
29793
+ } catch {
29794
+ return void 0;
29795
+ }
29796
+ }
29797
+ var defaultExtensionDirectory = (home = (0, import_node_os.homedir)()) => (0, import_node_path2.join)(home, "WriteDock", "extension");
29798
+ function browserRoots(user = (0, import_node_os.homedir)()) {
29799
+ const names = process.platform === "win32" ? ["Google/Chrome/User Data", "Microsoft/Edge/User Data", "Chromium/User Data", "BraveSoftware/Brave-Browser/User Data"].map((name) => (0, import_node_path2.join)(process.env.LOCALAPPDATA || (0, import_node_path2.join)(user, "AppData/Local"), name)) : process.platform === "darwin" ? ["Google/Chrome", "Microsoft Edge", "Chromium", "BraveSoftware/Brave-Browser"].map((name) => (0, import_node_path2.join)(user, "Library/Application Support", name)) : ["google-chrome", "microsoft-edge", "chromium", "BraveSoftware/Brave-Browser"].map((name) => (0, import_node_path2.join)(process.env.XDG_CONFIG_HOME || (0, import_node_path2.join)(user, ".config"), name));
29800
+ return names;
29801
+ }
29802
+ async function findInstalledExtension(roots = browserRoots(), id = EXTENSION_ID) {
29803
+ for (const root of roots) {
29804
+ let profiles;
29805
+ try {
29806
+ profiles = await (0, import_promises2.readdir)(root, { withFileTypes: true });
29807
+ } catch {
29808
+ continue;
29809
+ }
29810
+ for (const profile of profiles.filter((item) => item.isDirectory() && /^(Default|Profile \d+)$/.test(item.name))) {
29811
+ for (const filename of ["Secure Preferences", "Preferences"]) {
29812
+ try {
29813
+ const preferences = JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(root, profile.name, filename), "utf8"));
29814
+ const path = preferences.extensions?.settings?.[id]?.path;
29815
+ if (typeof path === "string" && (0, import_node_path2.isAbsolute)(path) && isWriteDock(await readManifest(path))) return (0, import_promises2.realpath)(path);
29816
+ } catch {
29817
+ }
29818
+ }
29819
+ }
29820
+ }
29821
+ return void 0;
29822
+ }
29823
+ async function installExtensionFiles(source2, target) {
29824
+ const next = await readManifest(source2);
29825
+ if (!isWriteDock(next)) throw new Error("\u5185\u7F6E\u6269\u5C55\u6587\u4EF6\u4E0D\u6B63\u786E");
29826
+ let previous;
29827
+ try {
29828
+ previous = await readManifest(target);
29829
+ } catch {
29830
+ }
29831
+ if (previous) {
29832
+ if (!isWriteDock(previous)) throw new Error("\u76EE\u6807\u76EE\u5F55\u4E0D\u662F WriteDock \u6269\u5C55\uFF0C\u672A\u8986\u76D6");
29833
+ if (previous.key !== next.key) throw new Error("\u65E7\u7248\u6269\u5C55\u7684\u8EAB\u4EFD\u4E0D\u540C\uFF0C\u65E0\u6CD5\u539F\u4F4D\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u4E00\u6B21\u65B0\u7248");
29834
+ }
29835
+ await (0, import_promises2.mkdir)(target, { recursive: true });
29836
+ const backup = previous ? await (0, import_promises2.mkdtemp)((0, import_node_path2.join)((0, import_node_os.tmpdir)(), "writedock-extension-backup-")) : void 0;
29837
+ if (backup) await (0, import_promises2.cp)(target, backup, { recursive: true, force: true });
29838
+ try {
29839
+ await (0, import_promises2.cp)(source2, target, { recursive: true, force: true, filter: (path) => path !== (0, import_node_path2.join)(source2, "manifest.json") });
29840
+ const staged = (0, import_node_path2.join)(target, ".writedock-manifest-update.tmp");
29841
+ await (0, import_promises2.writeFile)(staged, await (0, import_promises2.readFile)((0, import_node_path2.join)(source2, "manifest.json")));
29842
+ await (0, import_promises2.rename)(staged, (0, import_node_path2.join)(target, "manifest.json"));
29843
+ } catch (error2) {
29844
+ if (backup) await (0, import_promises2.cp)(backup, target, { recursive: true, force: true });
29845
+ throw error2;
29846
+ } finally {
29847
+ if (backup) await (0, import_promises2.rm)(backup, { recursive: true, force: true }).catch(() => {
29848
+ });
29849
+ }
29850
+ return { directory: target, version: next.version };
29851
+ }
29852
+ async function updateInstalledExtension() {
29853
+ const bundle = bundledExtension();
29854
+ if (!bundle) throw new Error("\u5F53\u524D\u670D\u52A1\u6CA1\u6709\u5185\u7F6E\u6269\u5C55\uFF0C\u8BF7\u91CD\u542F agent \u540E\u518D\u8BD5");
29855
+ const target = await findInstalledExtension();
29856
+ if (!target) throw new Error("\u6CA1\u6709\u627E\u5230\u5DF2\u52A0\u8F7D\u7684\u6269\u5C55\u76EE\u5F55\uFF0C\u8BF7\u624B\u52A8\u66F4\u65B0");
29857
+ return installExtensionFiles(bundle.directory, target);
29858
+ }
29859
+
29775
29860
  // src/release-info.ts
29776
29861
  var CHECK_INTERVAL = 6 * 60 * 6e4;
29777
29862
  var RETRY_INTERVAL = 10 * 6e4;
@@ -29827,8 +29912,10 @@ function refresh() {
29827
29912
  }
29828
29913
  function mcpReleaseInfo() {
29829
29914
  refresh();
29915
+ const bundle = bundledExtension();
29830
29916
  return {
29831
29917
  mcp_version: package_default.version,
29918
+ ...bundle ? { extension_bundle_version: bundle.version } : {},
29832
29919
  ...latestVersion ? { latest_version: latestVersion } : {},
29833
29920
  update_available: !!latestVersion && newerVersion(latestVersion, package_default.version),
29834
29921
  ...checkedAt ? { update_checked_at: checkedAt } : {},
@@ -29895,13 +29982,14 @@ var LocalBridge = class {
29895
29982
  server.on("upgrade", (req, socket, head) => {
29896
29983
  const origin = req.headers.origin;
29897
29984
  const extensionOrigin = typeof origin === "string" && /^chrome-extension:\/\/[a-p]{32}$/.test(origin);
29898
- if (!this.validHost(req.headers.host) || !["/extension", "/pair"].includes(req.url || "") || origin && !extensionOrigin || req.url === "/pair" && !extensionOrigin) {
29985
+ if (!this.validHost(req.headers.host) || !["/extension", "/pair", "/connect"].includes(req.url || "") || origin && !extensionOrigin || req.url === "/pair" && !extensionOrigin || req.url === "/connect" && origin !== EXTENSION_ORIGIN) {
29899
29986
  socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
29900
29987
  socket.destroy();
29901
29988
  return;
29902
29989
  }
29903
29990
  sockets.handleUpgrade(req, socket, head, (ws) => {
29904
29991
  if (req.url === "/pair") this.acceptPairing(ws);
29992
+ else if (req.url === "/connect") void this.acceptConnect(ws);
29905
29993
  else this.accept(ws);
29906
29994
  });
29907
29995
  });
@@ -29933,6 +30021,32 @@ var LocalBridge = class {
29933
30021
  this.pairing = { code, expiresAt, attempts: 0 };
29934
30022
  return { pairing_code: code, expires_at: new Date(expiresAt).toISOString(), expires_in_seconds: 180, instructions: "\u5C06\u6B64\u4E00\u6B21\u6027\u914D\u5BF9\u7801\u7C98\u8D34\u5230\u6269\u5C55\u7684\u300CMCP \u8FDE\u63A5 \u2192 \u8F93\u5165\u4E00\u6B21\u6027\u914D\u5BF9\u7801\u300D\u3002\u6709\u6548\u671F 3 \u5206\u949F\uFF0C\u4F7F\u7528\u4E00\u6B21\u540E\u5931\u6548\u3002\u65E0\u9700\u91CD\u65B0\u5B89\u88C5 MCP \u6216\u4FEE\u6539 agent \u914D\u7F6E\u3002\u786E\u8BA4\u7528\u6237\u8981\u8FDE\u63A5\u5F53\u524D\u6269\u5C55\u540E\u518D\u751F\u6210\u3002" };
29935
30023
  }
30024
+ /** Replaces the extension credential and drops whatever was using the old one. */
30025
+ async replaceExtensionToken(reason) {
30026
+ const token = (0, import_node_crypto2.randomBytes)(32).toString("hex");
30027
+ await this.options.credentials?.setExtensionToken(token);
30028
+ this.extensionToken = token;
30029
+ const previousClient = this.client;
30030
+ this.client = void 0;
30031
+ this.extensionId = void 0;
30032
+ for (const value of this.pending.values()) {
30033
+ clearTimeout(value.timer);
30034
+ value.reject(new Error(reason));
30035
+ }
30036
+ this.pending.clear();
30037
+ previousClient?.close(1e3, "Extension pairing replaced");
30038
+ return token;
30039
+ }
30040
+ /** One-click connection: only this extension's fixed origin can reach here, and the user has just clicked 连接. */
30041
+ async acceptConnect(ws) {
30042
+ try {
30043
+ const token = await this.replaceExtensionToken("\u6269\u5C55\u8FDE\u63A5\u5DF2\u66F4\u6362\uFF1B\u8BF7\u67E5\u8BE2\u539F\u540C\u6B65\u4EFB\u52A1\uFF0C\u4E0D\u8981\u81EA\u52A8\u91CD\u65B0\u63D0\u4EA4\u3002");
30044
+ ws.send(JSON.stringify({ type: "connect_result", token, port: this.port, protocol: "writedock/1" }));
30045
+ ws.close(1e3);
30046
+ } catch {
30047
+ ws.close(1011, "Connect failed");
30048
+ }
30049
+ }
29936
30050
  acceptPairing(ws) {
29937
30051
  const pairing = this.pairing;
29938
30052
  if (!pairing || Date.now() > pairing.expiresAt || pairing.attempts >= 8) {
@@ -29953,18 +30067,7 @@ var LocalBridge = class {
29953
30067
  const message = JSON.parse(body);
29954
30068
  if (this.pairing !== pairing || Date.now() > pairing.expiresAt || message.type !== "pairing_hello" || typeof message.proof !== "string" || !equal(message.proof, proof(pairing.code, "pairing-extension", nonce))) throw new Error("Pairing failed");
29955
30069
  this.pairing = void 0;
29956
- const token = (0, import_node_crypto2.randomBytes)(32).toString("hex");
29957
- await this.options.credentials?.setExtensionToken(token);
29958
- this.extensionToken = token;
29959
- const previousClient = this.client;
29960
- this.client = void 0;
29961
- this.extensionId = void 0;
29962
- for (const value of this.pending.values()) {
29963
- clearTimeout(value.timer);
29964
- value.reject(new Error("\u6269\u5C55\u914D\u5BF9\u5DF2\u66F4\u6362\uFF1B\u8BF7\u67E5\u8BE2\u539F\u540C\u6B65\u4EFB\u52A1\uFF0C\u4E0D\u8981\u81EA\u52A8\u91CD\u65B0\u63D0\u4EA4\u3002"));
29965
- }
29966
- this.pending.clear();
29967
- previousClient?.close(1e3, "Extension pairing replaced");
30070
+ const token = await this.replaceExtensionToken("\u6269\u5C55\u914D\u5BF9\u5DF2\u66F4\u6362\uFF1B\u8BF7\u67E5\u8BE2\u539F\u540C\u6B65\u4EFB\u52A1\uFF0C\u4E0D\u8981\u81EA\u52A8\u91CD\u65B0\u63D0\u4EA4\u3002");
29968
30071
  const key2 = (0, import_node_crypto2.createHmac)("sha256", pairing.code).update(`writedock-pairing-key:${nonce}`).digest();
29969
30072
  const iv = (0, import_node_crypto2.randomBytes)(12);
29970
30073
  const cipher = (0, import_node_crypto2.createCipheriv)("aes-256-gcm", key2, iv);
@@ -30007,6 +30110,13 @@ var LocalBridge = class {
30007
30110
  return;
30008
30111
  }
30009
30112
  if (message.type === "pong") return;
30113
+ if (message.type === "update_extension") {
30114
+ void updateInstalledExtension().then(
30115
+ (result) => ws.send(JSON.stringify({ type: "update_extension_result", ok: true, version: result.version })),
30116
+ (error2) => ws.send(JSON.stringify({ type: "update_extension_result", ok: false, error: messageOf(error2) }))
30117
+ );
30118
+ return;
30119
+ }
30010
30120
  const pending2 = this.pending.get(message.id);
30011
30121
  if (!pending2) return;
30012
30122
  this.pending.delete(message.id);
@@ -30041,6 +30151,10 @@ var LocalBridge = class {
30041
30151
  res.writeHead(status);
30042
30152
  res.end(body);
30043
30153
  };
30154
+ if (req.url === "/hello" && req.method === "GET" && this.validHost(req.headers.host) && (!req.headers.origin || req.headers.origin === EXTENSION_ORIGIN)) {
30155
+ send(200, { service: "writedock-mcp", protocol: "writedock/1", version: mcpReleaseInfo().mcp_version });
30156
+ return;
30157
+ }
30044
30158
  const assetPath = /^\/assets\/([a-f0-9-]{36})$/.exec(req.url || "");
30045
30159
  if (assetPath && this.validHost(req.headers.host) && (!req.headers.origin || /^chrome-extension:\/\/[a-p]{32}$/.test(req.headers.origin))) {
30046
30160
  await this.media.serve(req, res, assetPath[1]);
@@ -30144,7 +30258,7 @@ var LocalBridge = class {
30144
30258
  return await this.httpCall("/assets/register", { path, kind });
30145
30259
  }
30146
30260
  async requestConnected(method, params) {
30147
- if (this.client?.readyState !== import_websocket.default.OPEN) throw new Error("\u6269\u5C55\u672A\u8FDE\u63A5\u3002\u8BF7\u8C03\u7528 begin_pairing\uFF0C\u5C06\u4E00\u6B21\u6027\u914D\u5BF9\u7801\u7C98\u8D34\u5230\u6269\u5C55\u7684 MCP \u8FDE\u63A5\u9875\uFF1B\u65E0\u9700\u91CD\u88C5 MCP\u3002");
30261
+ if (this.client?.readyState !== import_websocket.default.OPEN) throw new Error("\u6269\u5C55\u672A\u8FDE\u63A5\u3002\u8BF7\u8BA9\u7528\u6237\u6253\u5F00\u6D4F\u89C8\u5668\u7684 WriteDock \u6269\u5C55\uFF0C\u5728\u300C\u8FDE\u63A5\u300D\u9875\u70B9\u201C\u8FDE\u63A5\u201D\u3002\u65E0\u9700\u91CD\u88C5 MCP\u3002");
30148
30262
  const id = (0, import_node_crypto2.randomUUID)();
30149
30263
  return new Promise((resolve4, reject) => {
30150
30264
  const timer = setTimeout(() => {
@@ -38347,8 +38461,8 @@ var EMPTY_COMPLETION_RESULT = {
38347
38461
  };
38348
38462
 
38349
38463
  // src/article.ts
38350
- var import_promises2 = require("fs/promises");
38351
- var import_node_path2 = require("path");
38464
+ var import_promises3 = require("fs/promises");
38465
+ var import_node_path3 = require("path");
38352
38466
  var import_node_url = require("url");
38353
38467
 
38354
38468
  // ../../node_modules/.pnpm/marked@17.0.6/node_modules/marked/lib/marked.esm.js
@@ -40186,7 +40300,7 @@ var Tokenizer = class {
40186
40300
  this.sequenceIndex = 0;
40187
40301
  this.xmlMode = xmlMode;
40188
40302
  this.decodeEntities = decodeEntities;
40189
- this.entityDecoder = new EntityDecoder(xmlMode ? xmlDecodeTree : htmlDecodeTree, (cp, consumed) => this.emitCodePoint(cp, consumed));
40303
+ this.entityDecoder = new EntityDecoder(xmlMode ? xmlDecodeTree : htmlDecodeTree, (cp2, consumed) => this.emitCodePoint(cp2, consumed));
40190
40304
  }
40191
40305
  reset() {
40192
40306
  this.state = State.Text;
@@ -40751,21 +40865,21 @@ var Tokenizer = class {
40751
40865
  this.cbs.ontext(this.sectionStart, endIndex);
40752
40866
  }
40753
40867
  }
40754
- emitCodePoint(cp, consumed) {
40868
+ emitCodePoint(cp2, consumed) {
40755
40869
  if (this.baseState !== State.Text && this.baseState !== State.InSpecialTag) {
40756
40870
  if (this.sectionStart < this.entityStart) {
40757
40871
  this.cbs.onattribdata(this.sectionStart, this.entityStart);
40758
40872
  }
40759
40873
  this.sectionStart = this.entityStart + consumed;
40760
40874
  this.index = this.sectionStart - 1;
40761
- this.cbs.onattribentity(cp);
40875
+ this.cbs.onattribentity(cp2);
40762
40876
  } else {
40763
40877
  if (this.sectionStart < this.entityStart) {
40764
40878
  this.cbs.ontext(this.sectionStart, this.entityStart);
40765
40879
  }
40766
40880
  this.sectionStart = this.entityStart + consumed;
40767
40881
  this.index = this.sectionStart - 1;
40768
- this.cbs.ontextentity(cp, this.sectionStart);
40882
+ this.cbs.ontextentity(cp2, this.sectionStart);
40769
40883
  }
40770
40884
  }
40771
40885
  };
@@ -40902,10 +41016,10 @@ var Parser = class {
40902
41016
  this.startIndex = endIndex;
40903
41017
  }
40904
41018
  /** @internal */
40905
- ontextentity(cp, endIndex) {
41019
+ ontextentity(cp2, endIndex) {
40906
41020
  var _a3, _b;
40907
41021
  this.endIndex = endIndex - 1;
40908
- (_b = (_a3 = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a3, fromCodePoint(cp));
41022
+ (_b = (_a3 = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a3, fromCodePoint(cp2));
40909
41023
  this.startIndex = endIndex;
40910
41024
  }
40911
41025
  /**
@@ -41026,8 +41140,8 @@ var Parser = class {
41026
41140
  this.attribvalue += this.getSlice(start, endIndex);
41027
41141
  }
41028
41142
  /** @internal */
41029
- onattribentity(cp) {
41030
- this.attribvalue += fromCodePoint(cp);
41143
+ onattribentity(cp2) {
41144
+ this.attribvalue += fromCodePoint(cp2);
41031
41145
  }
41032
41146
  /** @internal */
41033
41147
  onattribend(quote, endIndex) {
@@ -44916,9 +45030,9 @@ function encodeXML2(input) {
44916
45030
  last = index += 1;
44917
45031
  continue;
44918
45032
  }
44919
- const cp = input.codePointAt(index);
44920
- out += `&#x${cp.toString(16)};`;
44921
- if (cp !== char)
45033
+ const cp2 = input.codePointAt(index);
45034
+ out += `&#x${cp2.toString(16)};`;
45035
+ if (cp2 !== char)
44922
45036
  index++;
44923
45037
  last = index += 1;
44924
45038
  }
@@ -50136,17 +50250,17 @@ async function prepareSource(source2, registerVideo) {
50136
50250
  let markdown = source2.markdown;
50137
50251
  let html = source2.html;
50138
50252
  let title = source2.title?.trim() || "";
50139
- let baseDirectory = source2.base_directory ? await (0, import_promises2.realpath)(source2.base_directory) : void 0;
50253
+ let baseDirectory = source2.base_directory ? await (0, import_promises3.realpath)(source2.base_directory) : void 0;
50140
50254
  if (source2.file_path) {
50141
- if (!(0, import_node_path2.isAbsolute)(source2.file_path)) throw new Error("file_path \u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
50142
- const filename = await (0, import_promises2.realpath)(source2.file_path);
50143
- const info = await (0, import_promises2.stat)(filename);
50255
+ if (!(0, import_node_path3.isAbsolute)(source2.file_path)) throw new Error("file_path \u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");
50256
+ const filename = await (0, import_promises3.realpath)(source2.file_path);
50257
+ const info = await (0, import_promises3.stat)(filename);
50144
50258
  if (!info.isFile() || info.size > TEXT_LIMIT) throw new Error("\u7A3F\u4EF6\u5FC5\u987B\u662F 2 MB \u4EE5\u5185\u7684 Markdown \u6216 HTML \u6587\u4EF6");
50145
- const text = (await (0, import_promises2.readFile)(filename, "utf8")).replace(/^\uFEFF/, "");
50259
+ const text = (await (0, import_promises3.readFile)(filename, "utf8")).replace(/^\uFEFF/, "");
50146
50260
  if (/\.(md|markdown|mdown)$/i.test(filename)) markdown = text;
50147
50261
  else if (/\.html?$/i.test(filename)) html = text;
50148
50262
  else throw new Error("\u7A3F\u4EF6\u6587\u4EF6\u4EC5\u652F\u6301 .md\u3001.markdown\u3001.html\u3001.htm");
50149
- baseDirectory ??= (0, import_node_path2.dirname)(filename);
50263
+ baseDirectory ??= (0, import_node_path3.dirname)(filename);
50150
50264
  }
50151
50265
  const embedded = /* @__PURE__ */ new Map();
50152
50266
  let imageBytes = 0;
@@ -50164,13 +50278,13 @@ async function prepareSource(source2, registerVideo) {
50164
50278
  } else {
50165
50279
  if (!baseDirectory) throw new Error("\u7A3F\u4EF6\u5305\u542B\u672C\u5730\u56FE\u7247\uFF0C\u8BF7\u63D0\u4F9B base_directory \u6216\u4F7F\u7528 file_path");
50166
50280
  const path = src.startsWith("file:") ? (0, import_node_url.fileURLToPath)(src) : decodeURIComponent(src);
50167
- if (/^[a-z][a-z0-9+.-]*:/i.test(path) && !(0, import_node_path2.isAbsolute)(path)) throw new Error("\u56FE\u7247\u5730\u5740\u53EA\u652F\u6301 HTTP(S)\u3001\u672C\u5730\u56FE\u7247\u6216 data URI");
50168
- const filename = await (0, import_promises2.realpath)((0, import_node_path2.resolve)(baseDirectory, path));
50169
- const inside = (0, import_node_path2.relative)(baseDirectory, filename);
50170
- if (inside === ".." || inside.startsWith("../") || inside.startsWith("..\\") || (0, import_node_path2.isAbsolute)(inside)) throw new Error("\u672C\u5730\u56FE\u7247\u5FC5\u987B\u4F4D\u4E8E\u7A3F\u4EF6\u76EE\u5F55\u6216\u660E\u786E\u6307\u5B9A\u7684 base_directory \u5185");
50171
- const info = await (0, import_promises2.stat)(filename);
50281
+ if (/^[a-z][a-z0-9+.-]*:/i.test(path) && !(0, import_node_path3.isAbsolute)(path)) throw new Error("\u56FE\u7247\u5730\u5740\u53EA\u652F\u6301 HTTP(S)\u3001\u672C\u5730\u56FE\u7247\u6216 data URI");
50282
+ const filename = await (0, import_promises3.realpath)((0, import_node_path3.resolve)(baseDirectory, path));
50283
+ const inside = (0, import_node_path3.relative)(baseDirectory, filename);
50284
+ if (inside === ".." || inside.startsWith("../") || inside.startsWith("..\\") || (0, import_node_path3.isAbsolute)(inside)) throw new Error("\u672C\u5730\u56FE\u7247\u5FC5\u987B\u4F4D\u4E8E\u7A3F\u4EF6\u76EE\u5F55\u6216\u660E\u786E\u6307\u5B9A\u7684 base_directory \u5185");
50285
+ const info = await (0, import_promises3.stat)(filename);
50172
50286
  if (!info.isFile() || info.size > IMAGE_LIMIT) throw new Error("\u5355\u5F20\u672C\u5730\u56FE\u7247\u4E0D\u80FD\u8D85\u8FC7 8 MB");
50173
- bytes = await (0, import_promises2.readFile)(filename);
50287
+ bytes = await (0, import_promises3.readFile)(filename);
50174
50288
  }
50175
50289
  if (!bytes.length || bytes.length > IMAGE_LIMIT) throw new Error("\u5355\u5F20\u56FE\u7247\u5FC5\u987B\u5728 8 MB \u4EE5\u5185");
50176
50290
  const mime = imageMime(bytes);
@@ -50271,19 +50385,19 @@ var postSource = {
50271
50385
  var agentWorkflow = "Agent \u53EA\u901A\u8FC7 WriteDock MCP \u6295\u7A3F\u548C\u67E5\u8BE2\u56DE\u6267\uFF0C\u4E0D\u4F9D\u8D56\u4E5F\u4E0D\u8981\u8C03\u7528\u6D4F\u89C8\u5668\u3001Playwright \u6216\u5176\u4ED6\u7F51\u9875\u5DE5\u5177\u3002\u6309\u7ED3\u679C\u7684 next_action \u64CD\u4F5C\uFF1Apoll_task \u7528\u539F task_id/request_id \u67E5\u8BE2 get_sync_task\uFF1Breport_result \u76F4\u63A5\u5411\u7528\u6237\u6C47\u62A5\u9010\u5E73\u53F0\u72B6\u6001\u548C\u94FE\u63A5\u3002submitted/published \u5DF2\u6709\u6269\u5C55\u786E\u8BA4\uFF0C\u4E0D\u518D\u6253\u5F00\u7F51\u9875\u9A8C\u8BC1\uFF1B\u9A8C\u8BC1\u7801\u3001\u56FE\u5F62\u9A8C\u8BC1\u3001\u534F\u8BAE\u3001\u53D1\u5E03\u8BBE\u7F6E\u6216 unknown/interrupted \u90FD\u5C06\u539F\u56E0\u548C\u94FE\u63A5\u4EA4\u7ED9\u7528\u6237\u81EA\u884C\u70B9\u51FB\u5904\u7406\uFF0C\u4E0D\u81EA\u52A8\u91CD\u53D1\u3001\u4E0D\u6362 request_id\u3002\u4EBA\u5DE5\u63A5\u7BA1\u4E0D\u4EE3\u8868\u5DF2\u7ECF\u53D1\u5E03\u3002";
50272
50386
  function createMcpServer(bridge) {
50273
50387
  const server = new McpServer({ name: "writedock", version: package_default.version }, {
50274
- instructions: agentWorkflow + 'WriteDock \u901A\u8FC7\u672C\u673A\u6269\u5C55\u6267\u884C\u6295\u7A3F\u3002\u5148\u68C0\u67E5\u8FDE\u63A5\u548C\u5E73\u53F0\u767B\u5F55\u3002\u5B9E\u9645\u5E73\u53F0\u80FD\u529B\u4EE5 list_platforms \u8FD4\u56DE\u7684 action\u3001publishModes\u3001tools\u3001modeOptions\u3001confirmation\u3001capabilities\u3001coverRequired \u4E3A\u51C6\uFF0C\u6269\u5C55\u66F4\u65B0\u540E\u4F18\u5148\u6309\u8BE5\u5143\u4FE1\u606F\u9009\u62E9\u5DE5\u5177\u3002\u77E5\u4E4E\u3001\u767E\u5BB6\u53F7\u3001\u5FAE\u535A\u957F\u6587\u7AE0\u3001B\u7AD9\u4E13\u680F\u3001\u5C0F\u7EA2\u4E66\u957F\u6587\u4F7F\u7528 publish_article\uFF0CAgent \u76F4\u63A5\u63D0\u4F9B Markdown/HTML \u6216\u6587\u4EF6\u8DEF\u5F84\u5373\u53EF\u53D1\u5E03\uFF0C\u65E0\u9700\u7528\u6237\u5728\u6269\u5C55\u7F16\u8F91\u3002\u767E\u5BB6\u53F7\u5FC5\u987B\u63D0\u4F9B cover \u5C01\u9762\uFF1B\u77E5\u4E4E\u53E6\u652F\u6301 <video src="\u672C\u5730MP4\u8DEF\u5F84"></video> \u6587\u7AE0\u5185\u89C6\u9891\uFF0C\u72EC\u7ACB\u5C01\u9762\u6682\u672A\u63A5\u5165\u3002prepare_article \u4EC5\u4F9B\u53EF\u9009\u672C\u673A\u9884\u89C8\uFF0C\u4E0D\u662F\u53D1\u5E03\u7684\u524D\u7F6E\u8981\u6C42\u3002\u5C0F\u7EA2\u4E66 ID \u4E3A xiaohongshu\uFF0C\u4E09\u79CD\u6A21\u5F0F\u5171\u7528\u6B64\u5E73\u53F0\uFF1A\u5199\u957F\u6587\u7528 publish_article\uFF0C\u652F\u6301\u6B63\u6587\u56FE\u7247\u3001\u539F\u751F\u81EA\u52A8\u6392\u7248\u540E\u53D1\u5E03\uFF0C\u6807\u9898\u6700\u591A 64 \u5B57\u3001\u6B63\u6587\u6700\u591A 10000 \u5B57\uFF0C\u4E0D\u63A5\u72EC\u7ACB cover \u6216\u6587\u7AE0\u5185\u89C6\u9891\uFF1B\u666E\u901A\u56FE\u6587\u7528 publish_post(kind=image)\uFF0C\u72EC\u7ACB\u89C6\u9891\u7528 publish_post(kind=video)\uFF0C\u672A\u4F20 cover_path \u65F6\u4FDD\u7559\u5E73\u53F0\u81EA\u52A8\u751F\u6210\u7684\u7B2C\u4E00\u5E27\u5C01\u9762\u3002\u5C0F\u7EA2\u4E66\u6700\u7EC8\u5747\u987B\u5339\u914D POST /web_api/sns/v2/note \u7684 success=true\u3001result=0 \u548C\u7B14\u8BB0 ID \u56DE\u6267\u624D\u786E\u8BA4 submitted\u3002\u6296\u97F3\u5E73\u53F0 ID \u4E3A douyin\uFF0C\u56FE\u6587\u548C\u89C6\u9891\u540C\u6837\u7528 publish_post(kind=image|video)\uFF0C\u53EF\u9009 cover_path\uFF1B\u56FE\u6587\u8BDD\u9898\u6700\u591A 4 \u4E2A\u3001\u89C6\u9891\u6700\u591A 5 \u4E2A\uFF0C\u5F53\u524D\u53EA\u63A5\u5373\u65F6\u53D1\u5E03\u3002\u6296\u97F3 confirmation=native_page_message\uFF0C\u4EE5\u672C\u6B21\u64CD\u4F5C\u65B0\u589E\u7684\u539F\u751F\u6210\u529F\u63D0\u793A\u786E\u8BA4 submitted\uFF0C\u672A\u6838\u5BF9\u6700\u7EC8 HTTP \u4E1A\u52A1\u56DE\u6267\uFF1B\u4EC5\u8DF3\u8F6C\u4F5C\u54C1\u7BA1\u7406\u65F6\u4ECD\u4E3A unknown\uFF0CAgent \u4E0D\u81EA\u52A8\u91CD\u53D1\u3002\u5C0F\u7EA2\u4E66\u3001\u6296\u97F3\u3001\u5FAE\u535A\u666E\u901A\u56FE\u6587\u4E0E\u72EC\u7ACB\u89C6\u9891\u4F7F\u7528 prepare_post / publish_post\uFF0C\u5FAE\u535A\u5E73\u53F0 ID \u4ECD\u4E3A weibo\uFF0C\u4E0D\u53E6\u5EFA\u5E73\u53F0\u3002\u5FAE\u535A\u56FE\u6587\u6807\u9898\u653E\u5165\u6B63\u6587\u9996\u884C\uFF0C\u6700\u591A 18 \u5F20\u56FE\u7247\uFF1B\u72EC\u7ACB\u89C6\u9891\u6807\u9898\u6700\u591A 30 \u4E2A\u6C49\u5B57\uFF0860 \u4E2A\u534A\u89D2\u5B57\u7B26\uFF09\uFF0Cweibo_video_creation \u5FC5\u586B\uFF0C\u987B\u4F9D\u636E\u7528\u6237\u5B9E\u9645\u5185\u5BB9\u4F20 original\u3001secondary \u6216 repost\uFF0C\u4E0D\u80FD\u9ED8\u8BA4\u539F\u521B\u3002\u5FAE\u535A\u540C\u4E00\u6B21\u53EA\u80FD\u9009\u56FE\u6587\u6216\u89C6\u9891\uFF0C\u957F\u6587\u7AE0\u7EE7\u7EED\u7528 publish_article\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u53D1\u5E03\u5E76\u6307\u5B9A\u5E73\u53F0\u65F6\u624D\u8C03\u7528\u53D1\u5E03\u5DE5\u5177\u3002\u5FAE\u4FE1\u516C\u4F17\u53F7\u3001\u641C\u72D0\u53F7\u76EE\u524D\u7528 sync_article \u4FDD\u5B58\u6587\u7AE0\u8349\u7A3F\u3002B\u7AD9\u4E13\u680F ID \u4E3A bilibili\uFF0C\u4F7F\u7528 publish_article \u76F4\u63A5\u53D1\u5E03\u6587\u5B57\u548C\u6B63\u6587\u56FE\u7247\uFF0C\u4E0D\u63A5\u89C6\u9891\u3001\u97F3\u9891\u3001\u9644\u52A0\u5185\u5BB9\u5361\u7247\u6216\u72EC\u7ACB\u5C01\u9762\uFF1B\u901A\u8FC7\u65B0\u7248\u539F\u751F\u7F16\u8F91\u5668\u4E0A\u4F20\u5E76\u53D1\u5E03\uFF0Ccode=-352 \u65F6\u505C\u6B62\u81EA\u52A8\u63D0\u4EA4\u5E76\u8F6C\u4EBA\u5DE5\u9A8C\u8BC1\u3002\u9047\u5230 needs_user_action \u6216 requires_user_action \u65F6\uFF0C\u628A user_actions \u4E2D\u7684\u539F\u56E0\u548C\u7A3F\u4EF6\u94FE\u63A5\u544A\u8BC9\u7528\u6237\uFF0C\u4F18\u5148\u8BA9\u7528\u6237\u5207\u6362\u5230\u6269\u5C55\u5DF2\u6253\u5F00\u7684\u9875\u9762\u5904\u7406\u9A8C\u8BC1\u7801\u3001\u5C01\u9762\u3001\u5185\u5BB9\u58F0\u660E\u3001\u6765\u6E90\u3001\u539F\u521B\u534F\u8BAE\u6216\u53D1\u5E03\u8BBE\u7F6E\uFF0C\u5E76\u624B\u52A8\u53D1\u5E03\uFF1B\u4E0D\u5F97\u81EA\u52A8\u89E3\u51B3\u9A8C\u8BC1\u7801\u3001\u91CD\u65B0\u63D0\u4EA4\u6216\u6362 request_id\u3002\u8BE5\u72B6\u6001\u53EA\u8BB0\u5F55\u4EBA\u5DE5\u63A5\u7BA1\uFF0C\u4E0D\u4EE3\u8868\u7528\u6237\u4E4B\u540E\u7684\u64CD\u4F5C\u7ED3\u679C\u5DF2\u88AB\u786E\u8BA4\u3002\u6269\u5C55\u66F4\u65B0\u590D\u7528\u5DF2\u6709 MCP\uFF1B\u9700\u8981\u6062\u590D\u8FDE\u63A5\u65F6\u8C03\u7528 begin_pairing\uFF0C\u8BA9\u7528\u6237\u5728\u6269\u5C55\u8F93\u5165\u914D\u5BF9\u7801\u3002\u63D0\u4EA4\u8FD4\u56DE\u4EFB\u52A1 ID\uFF0C\u968F\u540E\u7528 get_sync_task \u67E5\u8BE2\u7ED3\u679C\u3002\u4FDD\u6301\u540C\u4E00\u64CD\u4F5C\u7684 request_id \u4E0D\u53D8\u3002publicationState=unknown \u6216\u4EFB\u52A1\u4E2D\u65AD\u65F6\uFF0C\u5411\u7528\u6237\u7ED9\u51FA\u94FE\u63A5\u8BA9\u5176\u81EA\u884C\u6838\u5BF9\u5E73\u53F0\uFF0CAgent \u4E0D\u6253\u5F00\u7F51\u9875\uFF0C\u4E0D\u8981\u81EA\u52A8\u751F\u6210\u65B0 request_id \u91CD\u53D1\u3002\u76F4\u63A5\u53D1\u5E03\u6210\u529F\u8868\u793A\u5E73\u53F0\u5DF2\u63A5\u53D7\u63D0\u4EA4\uFF0C\u662F\u5426\u516C\u5F00\u5C55\u793A\u4EE5\u5E73\u53F0\u4E3A\u51C6\u3002'
50388
+ instructions: agentWorkflow + 'WriteDock \u901A\u8FC7\u672C\u673A\u6269\u5C55\u6267\u884C\u6295\u7A3F\u3002\u5148\u68C0\u67E5\u8FDE\u63A5\u548C\u5E73\u53F0\u767B\u5F55\u3002\u5B9E\u9645\u5E73\u53F0\u80FD\u529B\u4EE5 list_platforms \u8FD4\u56DE\u7684 action\u3001publishModes\u3001tools\u3001modeOptions\u3001confirmation\u3001capabilities\u3001coverRequired \u4E3A\u51C6\uFF0C\u6269\u5C55\u66F4\u65B0\u540E\u4F18\u5148\u6309\u8BE5\u5143\u4FE1\u606F\u9009\u62E9\u5DE5\u5177\u3002\u77E5\u4E4E\u3001\u767E\u5BB6\u53F7\u3001\u5FAE\u535A\u957F\u6587\u7AE0\u3001B\u7AD9\u4E13\u680F\u3001\u5C0F\u7EA2\u4E66\u957F\u6587\u4F7F\u7528 publish_article\uFF0CAgent \u76F4\u63A5\u63D0\u4F9B Markdown/HTML \u6216\u6587\u4EF6\u8DEF\u5F84\u5373\u53EF\u53D1\u5E03\uFF0C\u65E0\u9700\u7528\u6237\u5728\u6269\u5C55\u7F16\u8F91\u3002\u767E\u5BB6\u53F7\u5FC5\u987B\u63D0\u4F9B cover \u5C01\u9762\uFF1B\u77E5\u4E4E\u53E6\u652F\u6301 <video src="\u672C\u5730MP4\u8DEF\u5F84"></video> \u6587\u7AE0\u5185\u89C6\u9891\uFF0C\u72EC\u7ACB\u5C01\u9762\u6682\u672A\u63A5\u5165\u3002prepare_article \u4EC5\u4F9B\u53EF\u9009\u672C\u673A\u9884\u89C8\uFF0C\u4E0D\u662F\u53D1\u5E03\u7684\u524D\u7F6E\u8981\u6C42\u3002\u5C0F\u7EA2\u4E66 ID \u4E3A xiaohongshu\uFF0C\u4E09\u79CD\u6A21\u5F0F\u5171\u7528\u6B64\u5E73\u53F0\uFF1A\u5199\u957F\u6587\u7528 publish_article\uFF0C\u652F\u6301\u6B63\u6587\u56FE\u7247\u3001\u539F\u751F\u81EA\u52A8\u6392\u7248\u540E\u53D1\u5E03\uFF0C\u6807\u9898\u6700\u591A 64 \u5B57\u3001\u6B63\u6587\u6700\u591A 10000 \u5B57\uFF0C\u4E0D\u63A5\u72EC\u7ACB cover \u6216\u6587\u7AE0\u5185\u89C6\u9891\uFF1B\u666E\u901A\u56FE\u6587\u7528 publish_post(kind=image)\uFF0C\u72EC\u7ACB\u89C6\u9891\u7528 publish_post(kind=video)\uFF0C\u672A\u4F20 cover_path \u65F6\u4FDD\u7559\u5E73\u53F0\u81EA\u52A8\u751F\u6210\u7684\u7B2C\u4E00\u5E27\u5C01\u9762\u3002\u5C0F\u7EA2\u4E66\u6700\u7EC8\u5747\u987B\u5339\u914D POST /web_api/sns/v2/note \u7684 success=true\u3001result=0 \u548C\u7B14\u8BB0 ID \u56DE\u6267\u624D\u786E\u8BA4 submitted\u3002\u6296\u97F3\u5E73\u53F0 ID \u4E3A douyin\uFF0C\u56FE\u6587\u548C\u89C6\u9891\u540C\u6837\u7528 publish_post(kind=image|video)\uFF0C\u53EF\u9009 cover_path\uFF1B\u56FE\u6587\u8BDD\u9898\u6700\u591A 4 \u4E2A\u3001\u89C6\u9891\u6700\u591A 5 \u4E2A\uFF0C\u5F53\u524D\u53EA\u63A5\u5373\u65F6\u53D1\u5E03\u3002\u6296\u97F3 confirmation=native_page_message\uFF0C\u4EE5\u672C\u6B21\u64CD\u4F5C\u65B0\u589E\u7684\u539F\u751F\u6210\u529F\u63D0\u793A\u786E\u8BA4 submitted\uFF0C\u672A\u6838\u5BF9\u6700\u7EC8 HTTP \u4E1A\u52A1\u56DE\u6267\uFF1B\u4EC5\u8DF3\u8F6C\u4F5C\u54C1\u7BA1\u7406\u65F6\u4ECD\u4E3A unknown\uFF0CAgent \u4E0D\u81EA\u52A8\u91CD\u53D1\u3002\u5C0F\u7EA2\u4E66\u3001\u6296\u97F3\u3001\u5FAE\u535A\u666E\u901A\u56FE\u6587\u4E0E\u72EC\u7ACB\u89C6\u9891\u4F7F\u7528 prepare_post / publish_post\uFF0C\u5FAE\u535A\u5E73\u53F0 ID \u4ECD\u4E3A weibo\uFF0C\u4E0D\u53E6\u5EFA\u5E73\u53F0\u3002\u5FAE\u535A\u56FE\u6587\u6807\u9898\u653E\u5165\u6B63\u6587\u9996\u884C\uFF0C\u6700\u591A 18 \u5F20\u56FE\u7247\uFF1B\u72EC\u7ACB\u89C6\u9891\u6807\u9898\u6700\u591A 30 \u4E2A\u6C49\u5B57\uFF0860 \u4E2A\u534A\u89D2\u5B57\u7B26\uFF09\uFF0Cweibo_video_creation \u5FC5\u586B\uFF0C\u987B\u4F9D\u636E\u7528\u6237\u5B9E\u9645\u5185\u5BB9\u4F20 original\u3001secondary \u6216 repost\uFF0C\u4E0D\u80FD\u9ED8\u8BA4\u539F\u521B\u3002\u5FAE\u535A\u540C\u4E00\u6B21\u53EA\u80FD\u9009\u56FE\u6587\u6216\u89C6\u9891\uFF0C\u957F\u6587\u7AE0\u7EE7\u7EED\u7528 publish_article\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u53D1\u5E03\u5E76\u6307\u5B9A\u5E73\u53F0\u65F6\u624D\u8C03\u7528\u53D1\u5E03\u5DE5\u5177\u3002\u5FAE\u4FE1\u516C\u4F17\u53F7\u3001\u641C\u72D0\u53F7\u76EE\u524D\u7528 sync_article \u4FDD\u5B58\u6587\u7AE0\u8349\u7A3F\u3002B\u7AD9\u4E13\u680F ID \u4E3A bilibili\uFF0C\u4F7F\u7528 publish_article \u76F4\u63A5\u53D1\u5E03\u6587\u5B57\u548C\u6B63\u6587\u56FE\u7247\uFF0C\u4E0D\u63A5\u89C6\u9891\u3001\u97F3\u9891\u3001\u9644\u52A0\u5185\u5BB9\u5361\u7247\u6216\u72EC\u7ACB\u5C01\u9762\uFF1B\u901A\u8FC7\u65B0\u7248\u539F\u751F\u7F16\u8F91\u5668\u4E0A\u4F20\u5E76\u53D1\u5E03\uFF0Ccode=-352 \u65F6\u505C\u6B62\u81EA\u52A8\u63D0\u4EA4\u5E76\u8F6C\u4EBA\u5DE5\u9A8C\u8BC1\u3002\u9047\u5230 needs_user_action \u6216 requires_user_action \u65F6\uFF0C\u628A user_actions \u4E2D\u7684\u539F\u56E0\u548C\u7A3F\u4EF6\u94FE\u63A5\u544A\u8BC9\u7528\u6237\uFF0C\u4F18\u5148\u8BA9\u7528\u6237\u5207\u6362\u5230\u6269\u5C55\u5DF2\u6253\u5F00\u7684\u9875\u9762\u5904\u7406\u9A8C\u8BC1\u7801\u3001\u5C01\u9762\u3001\u5185\u5BB9\u58F0\u660E\u3001\u6765\u6E90\u3001\u539F\u521B\u534F\u8BAE\u6216\u53D1\u5E03\u8BBE\u7F6E\uFF0C\u5E76\u624B\u52A8\u53D1\u5E03\uFF1B\u4E0D\u5F97\u81EA\u52A8\u89E3\u51B3\u9A8C\u8BC1\u7801\u3001\u91CD\u65B0\u63D0\u4EA4\u6216\u6362 request_id\u3002\u8BE5\u72B6\u6001\u53EA\u8BB0\u5F55\u4EBA\u5DE5\u63A5\u7BA1\uFF0C\u4E0D\u4EE3\u8868\u7528\u6237\u4E4B\u540E\u7684\u64CD\u4F5C\u7ED3\u679C\u5DF2\u88AB\u786E\u8BA4\u3002\u6269\u5C55\u66F4\u65B0\u590D\u7528\u5DF2\u6709 MCP\uFF1B\u672A\u8FDE\u63A5\u65F6\uFF0C\u8BA9\u7528\u6237\u6253\u5F00 WriteDock \u6269\u5C55\u7684\u300C\u8FDE\u63A5\u300D\u9875\u70B9\u201C\u8FDE\u63A5\u201D\u3002\u63D0\u4EA4\u8FD4\u56DE\u4EFB\u52A1 ID\uFF0C\u968F\u540E\u7528 get_sync_task \u67E5\u8BE2\u7ED3\u679C\u3002\u4FDD\u6301\u540C\u4E00\u64CD\u4F5C\u7684 request_id \u4E0D\u53D8\u3002publicationState=unknown \u6216\u4EFB\u52A1\u4E2D\u65AD\u65F6\uFF0C\u5411\u7528\u6237\u7ED9\u51FA\u94FE\u63A5\u8BA9\u5176\u81EA\u884C\u6838\u5BF9\u5E73\u53F0\uFF0CAgent \u4E0D\u6253\u5F00\u7F51\u9875\uFF0C\u4E0D\u8981\u81EA\u52A8\u751F\u6210\u65B0 request_id \u91CD\u53D1\u3002\u76F4\u63A5\u53D1\u5E03\u6210\u529F\u8868\u793A\u5E73\u53F0\u5DF2\u63A5\u53D7\u63D0\u4EA4\uFF0C\u662F\u5426\u516C\u5F00\u5C55\u793A\u4EE5\u5E73\u53F0\u4E3A\u51C6\u3002'
50275
50389
  });
50276
50390
  const wrap = (operation) => operation().then((result) => ({
50277
50391
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
50278
50392
  })).catch((error2) => ({ content: [{ type: "text", text: error2 instanceof Error ? error2.message : String(error2) }], isError: true }));
50279
50393
  const readOnly = { readOnlyHint: true, destructiveHint: false, openWorldHint: false };
50280
50394
  server.registerTool("get_connection_status", {
50281
- description: "\u68C0\u67E5\u672C\u673A MCP \u4E0E\u6269\u5C55\u7684\u8FDE\u63A5\u3001\u8FD0\u884C\u7248\u672C\u548C npm \u66F4\u65B0\u63D0\u793A\u3002update_available=true \u65F6\u544A\u77E5\u7528\u6237\u91CD\u65B0\u542F\u52A8 WriteDock MCP\uFF0C\u4FDD\u7559\u914D\u7F6E\u548C\u914D\u5BF9\uFF1B\u53D1\u5E03\u4EFB\u52A1\u8FDB\u884C\u4E2D\u4E0D\u8981\u81EA\u52A8\u91CD\u542F\u3002\u65E7\u7248\u670D\u52A1\u53EF\u80FD\u4E0D\u8FD4\u56DE\u7248\u672C\u5B57\u6BB5\uFF1Blatest_version \u7F3A\u5931\u6216 update_checking=true \u65F6\uFF0C\u4E0D\u5F97\u58F0\u79F0\u5DF2\u662F\u6700\u65B0\u7248\u3002",
50395
+ description: "\u68C0\u67E5\u672C\u673A MCP \u4E0E\u6269\u5C55\u7684\u8FDE\u63A5\u3001\u8FD0\u884C\u7248\u672C\u548C npm \u66F4\u65B0\u63D0\u793A\u3002update_available=true \u65F6\u544A\u77E5\u7528\u6237\u91CD\u65B0\u542F\u52A8 WriteDock MCP\uFF0C\u4FDD\u7559\u914D\u7F6E\uFF1B\u53D1\u5E03\u4EFB\u52A1\u8FDB\u884C\u4E2D\u4E0D\u8981\u81EA\u52A8\u91CD\u542F\u3002\u65E7\u7248\u670D\u52A1\u53EF\u80FD\u4E0D\u8FD4\u56DE\u7248\u672C\u5B57\u6BB5\uFF1Blatest_version \u7F3A\u5931\u6216 update_checking=true \u65F6\uFF0C\u4E0D\u5F97\u58F0\u79F0\u5DF2\u662F\u6700\u65B0\u7248\u3002",
50282
50396
  inputSchema: {},
50283
50397
  annotations: { ...readOnly, openWorldHint: true }
50284
50398
  }, () => wrap(() => bridge.status()));
50285
50399
  server.registerTool("begin_pairing", {
50286
- description: "\u9996\u6B21\u8FDE\u63A5\u6216\u6269\u5C55\u5378\u8F7D\u91CD\u88C5\u540E\uFF0C\u751F\u6210 3 \u5206\u949F\u6709\u6548\u7684\u4E00\u6B21\u6027\u914D\u5BF9\u7801\u3002\u8BA9\u7528\u6237\u7C98\u8D34\u5230\u6269\u5C55\u7684 MCP \u8FDE\u63A5\u9875\u5373\u53EF\uFF0C\u590D\u7528\u5DF2\u6709 MCP \u548C agent \u914D\u7F6E\u3002\u65B0\u914D\u5BF9\u4F1A\u66FF\u6362\u6B64\u524D\u6D4F\u89C8\u5668\u7684\u8FDE\u63A5\u6388\u6743\uFF0C\u8BF7\u5728\u7528\u6237\u8981\u6C42\u8FDE\u63A5\u6269\u5C55\u65F6\u8C03\u7528\u3002",
50400
+ description: "\u901A\u5E38\u4E0D\u9700\u8981\uFF1A\u672A\u8FDE\u63A5\u65F6\uFF0C\u8BA9\u7528\u6237\u6253\u5F00 WriteDock \u6269\u5C55\u7684\u300C\u8FDE\u63A5\u300D\u9875\u70B9\u201C\u8FDE\u63A5\u201D\u5373\u53EF\u3002\u53EA\u6709\u7528\u6237\u4F7F\u7528\u65E7\u7248\u6269\u5C55\u65F6\u624D\u751F\u6210 3 \u5206\u949F\u6709\u6548\u7684\u4E00\u6B21\u6027\u914D\u5BF9\u7801\u3002",
50287
50401
  inputSchema: {},
50288
50402
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
50289
50403
  }, () => wrap(() => bridge.beginPairing()));
@@ -50397,24 +50511,24 @@ function createMcpServer(bridge) {
50397
50511
  }
50398
50512
 
50399
50513
  // src/identity.ts
50400
- var import_promises3 = require("fs/promises");
50514
+ var import_promises4 = require("fs/promises");
50401
50515
  var import_node_crypto3 = require("crypto");
50402
- var import_node_os = require("os");
50403
- var import_node_path3 = require("path");
50516
+ var import_node_os2 = require("os");
50517
+ var import_node_path4 = require("path");
50404
50518
  var validToken = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{24,128}$/.test(value);
50405
50519
  function dataDirectory() {
50406
- if (process.env.WRITEDOCK_DATA_DIR) return (0, import_node_path3.resolve)(process.env.WRITEDOCK_DATA_DIR);
50407
- if (process.platform === "darwin") return (0, import_node_path3.join)((0, import_node_os.homedir)(), "Library/Application Support/WriteDock/mcp");
50408
- if (process.platform === "win32") return (0, import_node_path3.join)(process.env.LOCALAPPDATA || (0, import_node_path3.join)((0, import_node_os.homedir)(), "AppData/Local"), "WriteDock/mcp");
50409
- return (0, import_node_path3.join)(process.env.XDG_DATA_HOME || (0, import_node_path3.join)((0, import_node_os.homedir)(), ".local/share"), "writedock/mcp");
50520
+ if (process.env.WRITEDOCK_DATA_DIR) return (0, import_node_path4.resolve)(process.env.WRITEDOCK_DATA_DIR);
50521
+ if (process.platform === "darwin") return (0, import_node_path4.join)((0, import_node_os2.homedir)(), "Library/Application Support/WriteDock/mcp");
50522
+ if (process.platform === "win32") return (0, import_node_path4.join)(process.env.LOCALAPPDATA || (0, import_node_path4.join)((0, import_node_os2.homedir)(), "AppData/Local"), "WriteDock/mcp");
50523
+ return (0, import_node_path4.join)(process.env.XDG_DATA_HOME || (0, import_node_path4.join)((0, import_node_os2.homedir)(), ".local/share"), "writedock/mcp");
50410
50524
  }
50411
50525
  async function loadIdentity(port, legacyToken) {
50412
50526
  if (!Number.isInteger(port) || port < 1024 || port > 65535) throw new Error("WRITEDOCK_PORT \u5FC5\u987B\u662F 1024\u201365535 \u7684\u6574\u6570");
50413
50527
  const directory = dataDirectory();
50414
- await (0, import_promises3.mkdir)(directory, { recursive: true, mode: 448 });
50415
- const filename = (0, import_node_path3.join)(directory, `identity-${port}.json`);
50528
+ await (0, import_promises4.mkdir)(directory, { recursive: true, mode: 448 });
50529
+ const filename = (0, import_node_path4.join)(directory, `identity-${port}.json`);
50416
50530
  const read = async () => {
50417
- const value = JSON.parse(await (0, import_promises3.readFile)(filename, "utf8"));
50531
+ const value = JSON.parse(await (0, import_promises4.readFile)(filename, "utf8"));
50418
50532
  if (value.version !== 1 || !validToken(value.token) || !validToken(value.extensionToken)) throw new Error("MCP \u914D\u5BF9\u8D44\u6599\u683C\u5F0F\u4E0D\u6B63\u786E\uFF1B\u8BF7\u4FDD\u7559\u539F\u6587\u4EF6\u5E76\u68C0\u67E5\u5907\u4EFD\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u8986\u76D6");
50419
50533
  return value;
50420
50534
  };
@@ -50426,16 +50540,16 @@ async function loadIdentity(port, legacyToken) {
50426
50540
  if (legacyToken && !validToken(legacyToken)) throw new Error("\u65E7 WRITEDOCK_TOKEN \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5\u539F MCP \u914D\u7F6E");
50427
50541
  const token = legacyToken || (0, import_node_crypto3.randomBytes)(32).toString("hex");
50428
50542
  const initial = { version: 1, token, extensionToken: token };
50429
- const temporary = (0, import_node_path3.join)(directory, `.identity-${(0, import_node_crypto3.randomUUID)()}.tmp`);
50430
- await (0, import_promises3.writeFile)(temporary, JSON.stringify(initial), { flag: "wx", mode: 384 });
50543
+ const temporary = (0, import_node_path4.join)(directory, `.identity-${(0, import_node_crypto3.randomUUID)()}.tmp`);
50544
+ await (0, import_promises4.writeFile)(temporary, JSON.stringify(initial), { flag: "wx", mode: 384 });
50431
50545
  try {
50432
50546
  try {
50433
- await (0, import_promises3.link)(temporary, filename);
50547
+ await (0, import_promises4.link)(temporary, filename);
50434
50548
  } catch (cause) {
50435
50549
  if (cause.code !== "EEXIST") throw cause;
50436
50550
  }
50437
50551
  } finally {
50438
- await (0, import_promises3.unlink)(temporary);
50552
+ await (0, import_promises4.unlink)(temporary);
50439
50553
  }
50440
50554
  identity = await read();
50441
50555
  }
@@ -50446,18 +50560,117 @@ async function loadIdentity(port, legacyToken) {
50446
50560
  if (!validToken(extensionToken)) throw new Error("\u6269\u5C55\u914D\u5BF9\u5BC6\u94A5\u683C\u5F0F\u4E0D\u6B63\u786E");
50447
50561
  const current = await read();
50448
50562
  if (current.token !== identity.token) throw new Error("MCP \u8EAB\u4EFD\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u542F\u52A8\u670D\u52A1");
50449
- const temporary = (0, import_node_path3.join)(directory, `.identity-${(0, import_node_crypto3.randomUUID)()}.tmp`);
50563
+ const temporary = (0, import_node_path4.join)(directory, `.identity-${(0, import_node_crypto3.randomUUID)()}.tmp`);
50450
50564
  try {
50451
- await (0, import_promises3.writeFile)(temporary, JSON.stringify({ ...current, extensionToken }), { flag: "wx", mode: 384 });
50452
- await (0, import_promises3.rename)(temporary, filename);
50565
+ await (0, import_promises4.writeFile)(temporary, JSON.stringify({ ...current, extensionToken }), { flag: "wx", mode: 384 });
50566
+ await (0, import_promises4.rename)(temporary, filename);
50453
50567
  } finally {
50454
- await (0, import_promises3.unlink)(temporary).catch(() => {
50568
+ await (0, import_promises4.unlink)(temporary).catch(() => {
50455
50569
  });
50456
50570
  }
50457
50571
  }
50458
50572
  };
50459
50573
  }
50460
50574
 
50575
+ // src/setup.ts
50576
+ var import_node_child_process = require("child_process");
50577
+ var import_promises5 = require("fs/promises");
50578
+ var import_node_os3 = require("os");
50579
+ var import_node_path5 = require("path");
50580
+ var COMMAND = "npx";
50581
+ var ARGS = ["-y", "--prefer-online", "writedock-mcp@latest"];
50582
+ async function readIfPresent(path) {
50583
+ try {
50584
+ return await (0, import_promises5.readFile)(path, "utf8");
50585
+ } catch (error2) {
50586
+ if (error2.code === "ENOENT") return void 0;
50587
+ throw error2;
50588
+ }
50589
+ }
50590
+ async function save(path, content, previous) {
50591
+ await (0, import_promises5.mkdir)((0, import_node_path5.dirname)(path), { recursive: true });
50592
+ if (previous !== void 0) await (0, import_promises5.copyFile)(path, `${path}.writedock-backup`);
50593
+ await (0, import_promises5.writeFile)(path, content);
50594
+ }
50595
+ async function configureCodex(path) {
50596
+ const previous = await readIfPresent(path);
50597
+ if (previous !== void 0 && /^\s*\[mcp_servers\.writedock\]/m.test(previous)) return "present";
50598
+ const entry = `[mcp_servers.writedock]
50599
+ command = "${COMMAND}"
50600
+ args = ${JSON.stringify(ARGS)}
50601
+ startup_timeout_sec = 120
50602
+ `;
50603
+ await save(path, previous ? `${previous.replace(/\s*$/, "")}
50604
+
50605
+ ${entry}` : entry, previous);
50606
+ return "added";
50607
+ }
50608
+ async function configureJsonClient(path) {
50609
+ const previous = await readIfPresent(path);
50610
+ const config2 = previous?.trim() ? JSON.parse(previous) : {};
50611
+ if (config2.mcpServers?.writedock) return "present";
50612
+ config2.mcpServers = { ...config2.mcpServers, writedock: { command: COMMAND, args: ARGS } };
50613
+ await save(path, `${JSON.stringify(config2, null, 2)}
50614
+ `, previous);
50615
+ return "added";
50616
+ }
50617
+ var exists = async (path) => await readIfPresent(path) !== void 0;
50618
+ function revealFolder(path) {
50619
+ const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
50620
+ try {
50621
+ const child = (0, import_node_child_process.spawn)(command, [path], { detached: true, stdio: "ignore" });
50622
+ child.on("error", () => {
50623
+ });
50624
+ child.unref();
50625
+ } catch {
50626
+ }
50627
+ }
50628
+ async function runSetup(home = (0, import_node_os3.homedir)(), log = console.log) {
50629
+ const clients = [
50630
+ { name: "Codex", path: (0, import_node_path5.join)(home, ".codex/config.toml"), detect: (0, import_node_path5.join)(home, ".codex/config.toml"), configure: configureCodex },
50631
+ { name: "Claude Code", path: (0, import_node_path5.join)(home, ".claude.json"), detect: (0, import_node_path5.join)(home, ".claude.json"), configure: configureJsonClient },
50632
+ { name: "Cursor", path: (0, import_node_path5.join)(home, ".cursor/mcp.json"), detect: (0, import_node_path5.join)(home, ".cursor/mcp.json"), configure: configureJsonClient },
50633
+ { name: "Claude Desktop", path: (0, import_node_path5.join)(home, "Library/Application Support/Claude/claude_desktop_config.json"), detect: (0, import_node_path5.join)(home, "Library/Application Support/Claude/claude_desktop_config.json"), configure: configureJsonClient }
50634
+ ];
50635
+ let found = 0;
50636
+ for (const client of clients) {
50637
+ if (!await exists(client.detect)) continue;
50638
+ found++;
50639
+ try {
50640
+ const state = await client.configure(client.path);
50641
+ log(state === "added" ? `\u2713 ${client.name}\uFF1A\u5DF2\u6DFB\u52A0 WriteDock\uFF08\u539F\u914D\u7F6E\u5907\u4EFD\u4E3A .writedock-backup\uFF09` : `\u2713 ${client.name}\uFF1A\u5DF2\u6709 WriteDock \u914D\u7F6E\uFF0C\u672A\u6539\u52A8`);
50642
+ } catch (error2) {
50643
+ log(`\u2717 ${client.name}\uFF1A\u914D\u7F6E\u5931\u8D25\uFF08${error2 instanceof Error ? error2.message : String(error2)}\uFF09\uFF0C\u539F\u6587\u4EF6\u672A\u6539\u52A8`);
50644
+ }
50645
+ }
50646
+ if (!found) {
50647
+ log("\u6CA1\u6709\u627E\u5230\u5DF2\u77E5\u7684 agent \u5BA2\u6237\u7AEF\u3002\u8BF7\u5728\u4F60\u7684\u5BA2\u6237\u7AEF\u91CC\u6DFB\u52A0\u8FD9\u4E2A MCP \u670D\u52A1\uFF1A");
50648
+ log(JSON.stringify({ mcpServers: { writedock: { command: COMMAND, args: ARGS } } }, null, 2));
50649
+ }
50650
+ const bundle = bundledExtension();
50651
+ const loaded = bundle ? await findInstalledExtension().catch(() => void 0) : void 0;
50652
+ let extensionFolder;
50653
+ if (bundle) {
50654
+ try {
50655
+ extensionFolder = (await installExtensionFiles(bundle.directory, loaded || defaultExtensionDirectory(home))).directory;
50656
+ } catch (error2) {
50657
+ log(`\u2717 \u6269\u5C55\uFF1A\u5B89\u88C5\u5931\u8D25\uFF08${error2 instanceof Error ? error2.message : String(error2)}\uFF09`);
50658
+ }
50659
+ }
50660
+ log("");
50661
+ log("\u63A5\u4E0B\u6765\uFF1A");
50662
+ log("1. \u91CD\u542F\u4F60\u7684 agent \u5BA2\u6237\u7AEF\uFF0C\u8BA9\u5B83\u52A0\u8F7D WriteDock\u3002");
50663
+ if (extensionFolder && !loaded) {
50664
+ log("2. \u5728 Chrome \u6216 Edge \u6253\u5F00 chrome://extensions\uFF0C\u6253\u5F00\u53F3\u4E0A\u89D2\u7684\u201C\u5F00\u53D1\u8005\u6A21\u5F0F\u201D\uFF0C\u70B9\u201C\u52A0\u8F7D\u5DF2\u89E3\u538B\u7684\u6269\u5C55\u7A0B\u5E8F\u201D\uFF0C\u9009\u62E9\u8FD9\u4E2A\u6587\u4EF6\u5939\uFF1A");
50665
+ log(` ${extensionFolder}`);
50666
+ revealFolder(extensionFolder);
50667
+ log("3. \u6253\u5F00 WriteDock \u6269\u5C55\uFF0C\u70B9\u201C\u8FDE\u63A5\u201D\u3002");
50668
+ } else if (extensionFolder) {
50669
+ log(`2. \u6269\u5C55\u5DF2\u66F4\u65B0\u3002\u5728 chrome://extensions \u70B9\u4E00\u6B21 WriteDock \u7684\u5237\u65B0\u56FE\u6807\uFF0C\u7136\u540E\u70B9\u201C\u8FDE\u63A5\u201D\u3002`);
50670
+ } else log("2. \u6253\u5F00\u6D4F\u89C8\u5668\u7684 WriteDock \u6269\u5C55\uFF0C\u70B9\u201C\u8FDE\u63A5\u201D\u3002");
50671
+ return found;
50672
+ }
50673
+
50461
50674
  // src/index.ts
50462
50675
  async function main() {
50463
50676
  const port = Number(process.env.WRITEDOCK_PORT || 9647);
@@ -50488,6 +50701,11 @@ async function main() {
50488
50701
  }
50489
50702
  if (process.argv.slice(2).some((argument) => argument === "--version" || argument === "-v")) {
50490
50703
  console.log(package_default.version);
50704
+ } else if (process.argv[2] === "setup") {
50705
+ runSetup().catch((error2) => {
50706
+ console.error("[WriteDock MCP]", error2 instanceof Error ? error2.message : String(error2));
50707
+ process.exit(1);
50708
+ });
50491
50709
  } else {
50492
50710
  main().catch((error2) => {
50493
50711
  console.error("[WriteDock MCP]", error2 instanceof Error ? error2.message : String(error2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "writedock-mcp",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "WriteDock local MCP server for the browser extension",
5
5
  "type": "commonjs",
6
6
  "license": "GPL-3.0-only",
@@ -17,7 +17,8 @@
17
17
  "LICENSE-MULTIPOST",
18
18
  "NOTICE.md",
19
19
  "THIRD_PARTY_NOTICES.txt",
20
- "source"
20
+ "source",
21
+ "extension"
21
22
  ],
22
23
  "keywords": [
23
24
  "mcp",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@writedock/mcp-server",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "WriteDock local MCP server for the browser extension",