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.
- package/README.md +22 -20
- package/extension/LICENSE-MULTIPOST.txt +201 -0
- package/extension/LICENSE.txt +674 -0
- package/extension/NOTICE.txt +13 -0
- package/extension/assets/editor-DWoK50xk.js +76 -0
- package/extension/assets/editor-VBFqqvXW.css +1 -0
- package/extension/assets/icon-128.png +0 -0
- package/extension/assets/icon-16.png +0 -0
- package/extension/assets/icon-48.png +0 -0
- package/extension/assets/index.browser-Hs3ZYqOv.js +157 -0
- package/extension/assets/index.ts-DbQynGAJ.js +42 -0
- package/extension/assets/logo.svg +5 -0
- package/extension/assets/offscreen-3BECPbQX.js +63 -0
- package/extension/assets/purify.es-1yEQDPgc.js +3 -0
- package/extension/assets/react-vendor-BrXlnJmF.js +40 -0
- package/extension/assets/task-utils-DwzGcJkm.js +1 -0
- package/extension/manifest.json +40 -0
- package/extension/service-worker-loader.js +1 -0
- package/extension/src/editor/index.html +16 -0
- package/extension/src/offscreen/index.html +6 -0
- package/extension/zhihu-publication-observer.js +1 -0
- package/extension//345/256/211/350/243/205/344/270/216/346/233/264/346/226/260.txt +19 -0
- package/index.cjs +287 -69
- package/package.json +3 -2
- package/source/package.json +1 -1
- package/source/src/__tests__/bridge.test.ts +22 -0
- package/source/src/__tests__/extension-update.test.ts +54 -0
- package/source/src/__tests__/setup.test.ts +50 -0
- package/source/src/bridge.ts +40 -11
- package/source/src/extension-id.ts +2 -0
- package/source/src/extension-update.ts +82 -0
- package/source/src/index.ts +3 -0
- package/source/src/release-info.ts +3 -0
- package/source/src/server.ts +3 -3
- 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(
|
|
6824
|
-
if (
|
|
6825
|
-
return BYTE_HEX[192 |
|
|
6823
|
+
function percentEncodeNonAscii(cp2) {
|
|
6824
|
+
if (cp2 < 2048) {
|
|
6825
|
+
return BYTE_HEX[192 | cp2 >> 6] + BYTE_HEX[128 | cp2 & 63];
|
|
6826
6826
|
}
|
|
6827
|
-
if (
|
|
6828
|
-
return BYTE_HEX[224 |
|
|
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 |
|
|
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(
|
|
7226
|
-
return
|
|
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.
|
|
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 =
|
|
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\
|
|
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
|
|
38351
|
-
var
|
|
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, (
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
41030
|
-
this.attribvalue += fromCodePoint(
|
|
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
|
|
44920
|
-
out += `&#x${
|
|
44921
|
-
if (
|
|
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,
|
|
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,
|
|
50142
|
-
const filename = await (0,
|
|
50143
|
-
const info = await (0,
|
|
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,
|
|
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,
|
|
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,
|
|
50168
|
-
const filename = await (0,
|
|
50169
|
-
const inside = (0,
|
|
50170
|
-
if (inside === ".." || inside.startsWith("../") || inside.startsWith("..\\") || (0,
|
|
50171
|
-
const info = await (0,
|
|
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,
|
|
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\
|
|
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\
|
|
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: "\
|
|
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
|
|
50514
|
+
var import_promises4 = require("fs/promises");
|
|
50401
50515
|
var import_node_crypto3 = require("crypto");
|
|
50402
|
-
var
|
|
50403
|
-
var
|
|
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,
|
|
50407
|
-
if (process.platform === "darwin") return (0,
|
|
50408
|
-
if (process.platform === "win32") return (0,
|
|
50409
|
-
return (0,
|
|
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,
|
|
50415
|
-
const filename = (0,
|
|
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,
|
|
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,
|
|
50430
|
-
await (0,
|
|
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,
|
|
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,
|
|
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,
|
|
50563
|
+
const temporary = (0, import_node_path4.join)(directory, `.identity-${(0, import_node_crypto3.randomUUID)()}.tmp`);
|
|
50450
50564
|
try {
|
|
50451
|
-
await (0,
|
|
50452
|
-
await (0,
|
|
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,
|
|
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.
|
|
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",
|