@opentiny/webmcp-cli 0.0.1-alpha.6 → 0.0.3

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.
@@ -0,0 +1,315 @@
1
+ ;(function(){
2
+ "use strict";
3
+ (() => {
4
+ // webmcp-tools/creator.xiaohongshu.com/index.ts
5
+ var attempts = 0;
6
+ var MAX_ATTEMPTS = 20;
7
+ async function initXhsCreatorTools() {
8
+ const mcp = navigator.modelContext;
9
+ if (!mcp || typeof mcp.registerTool !== "function") {
10
+ attempts++;
11
+ if (attempts < MAX_ATTEMPTS) {
12
+ console.log(`[webmcp-tools] creator.xiaohongshu.com: registerTool \u672A\u5C31\u7EEA\uFF0C500ms \u540E\u8FDB\u884C\u7B2C ${attempts} \u6B21\u91CD\u8BD5...`);
13
+ setTimeout(initXhsCreatorTools, 500);
14
+ } else {
15
+ console.error("[webmcp-tools] creator.xiaohongshu.com: \u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0CregisterTool \u4ECD\u672A\u5C31\u7EEA");
16
+ }
17
+ return;
18
+ }
19
+ const isRegistered = (() => {
20
+ try {
21
+ const list = window.__webmcpcli_tools || [];
22
+ return list.some((t) => t.name === "xhs_publish_note");
23
+ } catch {
24
+ return false;
25
+ }
26
+ })();
27
+ if (!isRegistered) {
28
+ try {
29
+ mcp.registerTool({
30
+ name: "xhs_publish_note",
31
+ title: "\u53D1\u5E03\u5C0F\u7EA2\u4E66\u56FE\u6587\u7B14\u8BB0",
32
+ description: "\u5728\u5C0F\u7EA2\u4E66\u521B\u4F5C\u8005\u4E2D\u5FC3\u53D1\u5E03\u56FE\u6587\u7B14\u8BB0\u6216\u5B58\u4E3A\u8349\u7A3F\u3002\u5FC5\u987B\u5728 https://creator.xiaohongshu.com/publish/publish \u9875\u9762\u6267\u884C\u3002",
33
+ inputSchema: {
34
+ type: "object",
35
+ properties: {
36
+ title: {
37
+ type: "string",
38
+ description: "\u7B14\u8BB0\u6807\u9898\uFF0C\u9650 20 \u5B57\u4EE5\u5185"
39
+ },
40
+ content: {
41
+ type: "string",
42
+ description: "\u7B14\u8BB0\u6B63\u6587\u5185\u5BB9"
43
+ },
44
+ images: {
45
+ type: "array",
46
+ items: {
47
+ type: "object",
48
+ properties: {
49
+ name: { type: "string", description: "\u56FE\u7247\u6587\u4EF6\u540D\uFF0C\u5982 image.jpg" },
50
+ mimeType: { type: "string", description: "\u56FE\u7247 MIME \u7C7B\u578B\uFF0C\u5982 image/jpeg" },
51
+ base64: { type: "string", description: "\u56FE\u7247\u7684 Base64 \u7F16\u7801\u6570\u636E\uFF0C\u4E0D\u542B data:image/... \u524D\u7F00" }
52
+ },
53
+ required: ["name", "mimeType", "base64"]
54
+ },
55
+ description: "\u56FE\u7247\u5217\u8868\uFF0C\u6700\u591A 9 \u5F20"
56
+ },
57
+ topics: {
58
+ type: "array",
59
+ items: { type: "string" },
60
+ description: "\u8BDD\u9898\u5217\u8868\uFF0C\u4E0D\u9700\u8981\u5E26 # \u53F7"
61
+ },
62
+ draft: {
63
+ type: "boolean",
64
+ description: "\u662F\u5426\u4EC5\u4F5C\u4E3A\u8349\u7A3F\u4FDD\u5B58\uFF0C\u9ED8\u8BA4 false\uFF08\u5373\u76F4\u63A5\u53D1\u5E03\uFF09"
65
+ }
66
+ },
67
+ required: ["title", "content", "images"]
68
+ },
69
+ execute: async ({ title, content, images = [], topics = [], draft = false }) => {
70
+ if (!location.href.includes("creator.xiaohongshu.com/publish/publish")) {
71
+ location.href = "https://creator.xiaohongshu.com/publish/publish?from=menu_left&target=image";
72
+ return {
73
+ status: "redirecting",
74
+ message: "\u6B63\u5728\u8DF3\u8F6C\u81F3\u5C0F\u7EA2\u4E66\u521B\u4F5C\u8005\u4E2D\u5FC3\u53D1\u5E03\u9875\u9762\uFF0C\u8DF3\u8F6C\u6210\u529F\u540E\u8BF7\u91CD\u65B0\u8FD0\u884C\u6B64\u5DE5\u5177\u3002"
75
+ };
76
+ }
77
+ if (title.length > 20) {
78
+ throw new Error(`\u6807\u9898\u957F\u5EA6 (${title.length}) \u8D85\u8FC7\u9650\u5236\uFF0C\u6700\u5927 20 \u5B57\u3002`);
79
+ }
80
+ if (images.length === 0) {
81
+ throw new Error("\u53D1\u5E03\u56FE\u6587\u7B14\u8BB0\u81F3\u5C11\u9700\u8981\u63D0\u4F9B\u4E00\u5F20\u56FE\u7247");
82
+ }
83
+ if (images.length > 9) {
84
+ throw new Error("\u6700\u591A\u53EA\u652F\u6301\u4E0A\u4F20 9 \u5F20\u56FE\u7247");
85
+ }
86
+ const TITLE_SELECTORS = [
87
+ '[contenteditable="true"][placeholder*="\u6807\u9898"]',
88
+ '[contenteditable="true"][placeholder*="\u8D5E"]',
89
+ 'input[placeholder*="\u6807\u9898"]',
90
+ 'input[placeholder*="title" i]',
91
+ '[contenteditable="true"][class*="title"]',
92
+ 'input[maxlength="20"]',
93
+ 'input[class*="title"]',
94
+ ".title-input input",
95
+ ".note-title input"
96
+ ];
97
+ const BODY_SELECTORS = [
98
+ '[contenteditable="true"][class*="content"]',
99
+ '[contenteditable="true"][class*="editor"]',
100
+ '[contenteditable="true"][placeholder*="\u63CF\u8FF0"]',
101
+ '[contenteditable="true"][placeholder*="\u6B63\u6587"]',
102
+ '[contenteditable="true"][placeholder*="\u5185\u5BB9"]',
103
+ '.note-content [contenteditable="true"]',
104
+ '.editor-content [contenteditable="true"]'
105
+ ];
106
+ const selectTab = () => {
107
+ const isVisible = (el) => {
108
+ if (!el || el.offsetParent === null) return false;
109
+ const rect = el.getBoundingClientRect();
110
+ return rect.width > 0 && rect.height > 0;
111
+ };
112
+ const nodes = Array.from(document.querySelectorAll('button, [role="tab"], [role="button"], a, label, div, span, li'));
113
+ const targets = ["\u4E0A\u4F20\u56FE\u6587", "\u56FE\u6587", "\u56FE\u7247"];
114
+ for (const target of targets) {
115
+ for (const node of nodes) {
116
+ if (!isVisible(node)) continue;
117
+ const text = (node.innerText || node.textContent || "").replace(/\s+/g, " ").trim();
118
+ if (!text || text.includes("\u89C6\u9891")) continue;
119
+ if (text === target || text.includes(target)) {
120
+ const clickable = node.closest('button, [role="tab"], [role="button"], a, label') || node;
121
+ clickable.click();
122
+ return true;
123
+ }
124
+ }
125
+ }
126
+ return false;
127
+ };
128
+ selectTab();
129
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
130
+ const inputs = Array.from(document.querySelectorAll('input[type="file"]'));
131
+ const fileInput = inputs.find((el) => {
132
+ const accept = el.getAttribute("accept") || "";
133
+ return accept.includes("image") || accept.includes(".jpg") || accept.includes(".png") || accept.includes(".webp");
134
+ });
135
+ if (!fileInput) {
136
+ throw new Error("\u9875\u9762\u4E0A\u672A\u627E\u5230\u56FE\u7247\u4E0A\u4F20\u8F93\u5165\u6846\uFF0C\u8BF7\u786E\u8BA4\u521B\u4F5C\u8005\u4E2D\u5FC3\u9875\u9762\u5B8C\u5168\u52A0\u8F7D");
137
+ }
138
+ const dt = new DataTransfer();
139
+ for (const img of images) {
140
+ try {
141
+ const binary = atob(img.base64);
142
+ const bytes = new Uint8Array(binary.length);
143
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
144
+ const blob = new Blob([bytes], { type: img.mimeType });
145
+ dt.items.add(new File([blob], img.name, { type: img.mimeType }));
146
+ } catch (e) {
147
+ throw new Error(`\u5904\u7406\u56FE\u7247 ${img.name} \u7684 Base64 \u6570\u636E\u5931\u8D25: ` + e.message);
148
+ }
149
+ }
150
+ Object.defineProperty(fileInput, "files", { value: dt.files, writable: false });
151
+ fileInput.dispatchEvent(new Event("change", { bubbles: true }));
152
+ fileInput.dispatchEvent(new Event("input", { bubbles: true }));
153
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
154
+ for (let i = 0; i < 15; i++) {
155
+ const uploading = !!document.querySelector(
156
+ '[class*="upload"][class*="progress"], [class*="uploading"], [class*="loading"][class*="image"]'
157
+ );
158
+ if (!uploading) break;
159
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
160
+ }
161
+ const fillField = (selectors, text) => {
162
+ let foundEl = null;
163
+ for (const sel of selectors) {
164
+ const candidates = Array.from(document.querySelectorAll(sel));
165
+ for (const el of candidates) {
166
+ if (el && el.offsetParent !== null) {
167
+ foundEl = el;
168
+ break;
169
+ }
170
+ }
171
+ if (foundEl) break;
172
+ }
173
+ if (!foundEl) return false;
174
+ foundEl.focus();
175
+ const fireBeforeInput = (el, val) => {
176
+ el.dispatchEvent(new InputEvent("beforeinput", { bubbles: true, data: val, inputType: "insertText" }));
177
+ };
178
+ const fireInput = (el, val) => {
179
+ el.dispatchEvent(new InputEvent("input", { bubbles: true, data: val, inputType: "insertText" }));
180
+ };
181
+ fireBeforeInput(foundEl, text);
182
+ if (foundEl.tagName === "INPUT" || foundEl.tagName === "TEXTAREA") {
183
+ const el = foundEl;
184
+ const proto = el.tagName === "TEXTAREA" ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
185
+ const nativeSetter = Object.getOwnPropertyDescriptor(proto, "value")?.set;
186
+ if (nativeSetter) nativeSetter.call(el, text);
187
+ else el.value = text;
188
+ fireInput(el, text);
189
+ el.dispatchEvent(new Event("change", { bubbles: true }));
190
+ el.blur();
191
+ return true;
192
+ }
193
+ foundEl.textContent = "";
194
+ const selection = window.getSelection();
195
+ const range = document.createRange();
196
+ range.selectNodeContents(foundEl);
197
+ range.collapse(false);
198
+ selection?.removeAllRanges();
199
+ selection?.addRange(range);
200
+ const inserted = document.execCommand("insertText", false, text);
201
+ if (!inserted) foundEl.textContent = text;
202
+ fireInput(foundEl, text);
203
+ foundEl.dispatchEvent(new Event("change", { bubbles: true }));
204
+ foundEl.blur();
205
+ return true;
206
+ };
207
+ const titleFilled = fillField(TITLE_SELECTORS, title);
208
+ if (!titleFilled) throw new Error("\u65E0\u6CD5\u627E\u5230\u6807\u9898\u8F93\u5165\u6846\u6216\u586B\u5145\u6807\u9898\u5931\u8D25");
209
+ await new Promise((resolve) => setTimeout(resolve, 500));
210
+ const contentFilled = fillField(BODY_SELECTORS, content);
211
+ if (!contentFilled) throw new Error("\u65E0\u6CD5\u627E\u5230\u6B63\u6587\u8F93\u5165\u6846\u6216\u586B\u5145\u6B63\u6587\u5931\u8D25");
212
+ await new Promise((resolve) => setTimeout(resolve, 500));
213
+ if (topics && topics.length > 0) {
214
+ const bodyEl = BODY_SELECTORS.map((sel) => Array.from(document.querySelectorAll(sel))).flat().find((node) => node && node.offsetParent !== null && node.isContentEditable);
215
+ if (bodyEl) {
216
+ for (const topic of topics) {
217
+ bodyEl.focus();
218
+ const selection = window.getSelection();
219
+ const range = document.createRange();
220
+ range.selectNodeContents(bodyEl);
221
+ range.collapse(false);
222
+ selection?.removeAllRanges();
223
+ selection?.addRange(range);
224
+ document.execCommand("insertText", false, ` #${topic}`);
225
+ await new Promise((resolve) => setTimeout(resolve, 1200));
226
+ const SUGGESTION_SELECTORS = [
227
+ '[class*="topic-item"]',
228
+ '[class*="hashtag-item"]',
229
+ '[class*="suggest-item"]',
230
+ '[class*="suggestion"] li'
231
+ ];
232
+ let clicked = false;
233
+ for (const sel of SUGGESTION_SELECTORS) {
234
+ const item = document.querySelector(sel);
235
+ if (item && item.offsetParent !== null) {
236
+ item.click();
237
+ clicked = true;
238
+ break;
239
+ }
240
+ }
241
+ if (!clicked) {
242
+ const enterEvent = new KeyboardEvent("keydown", { bubbles: true, cancelable: true, key: "Enter", code: "Enter" });
243
+ bodyEl.dispatchEvent(enterEvent);
244
+ }
245
+ await new Promise((resolve) => setTimeout(resolve, 500));
246
+ }
247
+ }
248
+ }
249
+ const actionLabels = draft ? ["\u6682\u5B58\u79BB\u5F00", "\u5B58\u8349\u7A3F"] : ["\u53D1\u5E03", "\u53D1\u5E03\u7B14\u8BB0"];
250
+ const publishNames = draft ? ["_onSave", "_onSaveDraft"] : ["_onPublish", "onPublish", "_onSubmit"];
251
+ const hosts = Array.from(document.querySelectorAll("xhs-publish-btn"));
252
+ let actionTriggered = false;
253
+ for (const host of hosts) {
254
+ if (host.offsetParent === null) continue;
255
+ for (const name of publishNames) {
256
+ if (typeof host[name] === "function") {
257
+ try {
258
+ host[name]();
259
+ actionTriggered = true;
260
+ break;
261
+ } catch (e) {
262
+ }
263
+ }
264
+ }
265
+ if (actionTriggered) break;
266
+ }
267
+ if (!actionTriggered) {
268
+ const buttons = Array.from(document.querySelectorAll('button, [role="button"]'));
269
+ for (const btn of buttons) {
270
+ const text = (btn.innerText || btn.textContent || "").trim();
271
+ if (actionLabels.some((l) => text === l || text.includes(l)) && btn.offsetParent !== null && !btn.disabled) {
272
+ btn.click();
273
+ actionTriggered = true;
274
+ break;
275
+ }
276
+ }
277
+ }
278
+ if (!actionTriggered) {
279
+ throw new Error("\u672A\u627E\u5230\u53D1\u5E03\u6216\u5B58\u8349\u7A3F\u6309\u94AE\uFF0C\u53D1\u5E03\u52A8\u4F5C\u672A\u89E6\u53D1");
280
+ }
281
+ await new Promise((resolve) => setTimeout(resolve, 4e3));
282
+ const successMarkers = draft ? ["\u8349\u7A3F\u5DF2\u4FDD\u5B58", "\u6682\u5B58\u6210\u529F", "\u4FDD\u5B58\u6210\u529F"] : ["\u53D1\u5E03\u6210\u529F", "\u4E0A\u4F20\u6210\u529F"];
283
+ let successMsg = "";
284
+ for (const el of Array.from(document.querySelectorAll("*"))) {
285
+ if (el.tagName === "STYLE" || el.tagName === "SCRIPT") continue;
286
+ const text = (el.textContent || "").trim();
287
+ if (text.length > 200) continue;
288
+ if (el.children.length === 0 && successMarkers.some((marker) => text.includes(marker))) {
289
+ successMsg = text;
290
+ break;
291
+ }
292
+ }
293
+ return {
294
+ success: true,
295
+ action: draft ? "draft" : "publish",
296
+ message: successMsg || "\u7B14\u8BB0\u5904\u7406\u5B8C\u6210\uFF0C\u8BF7\u5728\u6D4F\u89C8\u5668\u4E2D\u786E\u8BA4\u7ED3\u679C",
297
+ title
298
+ };
299
+ }
300
+ });
301
+ if (typeof mcp.listTools === "function") {
302
+ mcp.listTools().then((list) => {
303
+ window.__webmcpcli_tools = list;
304
+ }).catch(() => {
305
+ });
306
+ }
307
+ console.log("[webmcp-tools] creator.xiaohongshu.com \u4E13\u5C5E\u5DE5\u5177\u6CE8\u518C\u6210\u529F");
308
+ } catch (e) {
309
+ console.error("[webmcp-tools] creator.xiaohongshu.com \u6CE8\u518C\u5931\u8D25:", e.message);
310
+ }
311
+ }
312
+ }
313
+ initXhsCreatorTools();
314
+ })();
315
+ })();
@@ -0,0 +1,155 @@
1
+ ;(function(){
2
+ "use strict";
3
+ (() => {
4
+ // webmcp-tools/editor.csdn.net/index.ts
5
+ function closeTemplateDialog() {
6
+ const modal = Array.from(document.querySelectorAll(".modal")).find(
7
+ (el) => el.textContent?.includes("\u6A21\u7248\u5E93") || el.textContent?.includes("\u6A21\u677F\u5E93")
8
+ );
9
+ if (!modal) return false;
10
+ const closeBtn = modal.querySelector(
11
+ 'button.modal__close-button, [aria-label="\u5173\u95ED"], [title="\u5173\u95ED"]'
12
+ );
13
+ if (closeBtn) {
14
+ closeBtn.click();
15
+ return true;
16
+ }
17
+ const cancelBtn = Array.from(modal.querySelectorAll("button, div")).find(
18
+ (el) => el.textContent?.trim() === "\u53D6\u6D88"
19
+ );
20
+ if (cancelBtn) {
21
+ cancelBtn.click();
22
+ return true;
23
+ }
24
+ return false;
25
+ }
26
+ function scheduleCloseTemplateDialog() {
27
+ const tryClose = () => closeTemplateDialog();
28
+ tryClose();
29
+ setTimeout(tryClose, 500);
30
+ setTimeout(tryClose, 1500);
31
+ }
32
+ var mcp = navigator.modelContext;
33
+ if (!mcp || typeof mcp.registerTool !== "function") {
34
+ console.warn("[webmcp-tools] editor.csdn.net: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
35
+ } else if (!window.__webmcptools_editorcsdnnet) {
36
+ try {
37
+ mcp.registerTool({
38
+ name: "create_article",
39
+ title: "\u586B\u5199 CSDN \u6587\u7AE0",
40
+ description: "\u63A5\u6536\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\uFF08Markdown\uFF09\uFF0C\u586B\u5199\u5230 CSDN Markdown \u7F16\u8F91\u5668\u4E2D\u3002",
41
+ inputSchema: {
42
+ type: "object",
43
+ properties: {
44
+ title: {
45
+ type: "string",
46
+ description: "\u6587\u7AE0\u6807\u9898\uFF0C\u5FC5\u586B\uFF0C\u5EFA\u8BAE\u4E0D\u8D85\u8FC7 100 \u5B57\uFF0C\u4E0D\u5141\u8BB8\u6709\u7279\u6B8A\u7B26\u53F7\u5F71\u54CD\u547D\u4EE4\u884C\u53C2\u6570\u89E3\u6790"
47
+ },
48
+ content: {
49
+ type: "string",
50
+ description: "\u6587\u7AE0 Markdown \u6B63\u6587\u7684 Base64 \u7F16\u7801\u5B57\u7B26\u4E32\uFF0C\u5FC5\u586B\u3002"
51
+ }
52
+ },
53
+ required: ["title", "content"]
54
+ },
55
+ execute: async ({ title, content }) => {
56
+ if (!title?.trim()) {
57
+ throw new Error("\u53C2\u6570 title \u4E0D\u80FD\u4E3A\u7A7A");
58
+ }
59
+ if (!content?.trim()) {
60
+ throw new Error("\u53C2\u6570 content \u4E0D\u80FD\u4E3A\u7A7A");
61
+ }
62
+ if (!location.hostname.endsWith("editor.csdn.net")) {
63
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F CSDN \u7F16\u8F91\u5668\uFF0C\u8BF7\u5148\u6253\u5F00 https://editor.csdn.net/md/");
64
+ }
65
+ closeTemplateDialog();
66
+ await new Promise((r) => setTimeout(r, 300));
67
+ let decodeContent;
68
+ try {
69
+ decodeContent = decodeURIComponent(escape(atob(content)));
70
+ } catch {
71
+ throw new Error("content \u4E0D\u662F\u6709\u6548\u7684 Base64 \u7F16\u7801\uFF0C\u8BF7\u68C0\u67E5\u53C2\u6570\u6216\u4F7F\u7528 @base64file: \u5F15\u7528\u6587\u4EF6");
72
+ }
73
+ const mdTab = Array.from(document.querySelectorAll("button.nav-tab-btn")).find(
74
+ (btn) => btn.textContent?.trim().includes("Markdown")
75
+ );
76
+ if (mdTab) {
77
+ mdTab.click();
78
+ await new Promise((r) => setTimeout(r, 500));
79
+ }
80
+ const titleDisplay = document.querySelector(".article-bar__title-display");
81
+ titleDisplay?.click();
82
+ await new Promise((r) => setTimeout(r, 300));
83
+ const titleInput = document.querySelector("input.article-bar__title--input");
84
+ if (!titleInput) {
85
+ throw new Error("\u672A\u627E\u5230\u6807\u9898\u8F93\u5165\u6846\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D\u5E76\u5DF2\u767B\u5F55");
86
+ }
87
+ titleInput.focus();
88
+ titleInput.value = title;
89
+ titleInput.dispatchEvent(
90
+ new InputEvent("input", { bubbles: true, cancelable: true, data: title })
91
+ );
92
+ titleInput.dispatchEvent(new Event("change", { bubbles: true }));
93
+ titleInput.blur();
94
+ if (titleInput.value.trim() !== title.trim()) {
95
+ throw new Error("\u6807\u9898\u586B\u5199\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
96
+ }
97
+ let editor = null;
98
+ const cmEl = document.querySelector(".CodeMirror");
99
+ if (cmEl?.CodeMirror) {
100
+ cmEl.CodeMirror.setValue(decodeContent);
101
+ if (cmEl.CodeMirror.getValue() !== decodeContent) {
102
+ throw new Error("\u6B63\u6587\u586B\u5199\u5931\u8D25\uFF08CodeMirror\uFF09\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
103
+ }
104
+ editor = "codemirror";
105
+ } else {
106
+ const preEditor = document.querySelector("pre.editor__inner");
107
+ if (preEditor) {
108
+ preEditor.focus();
109
+ document.execCommand("selectAll");
110
+ document.execCommand("delete");
111
+ await new Promise((r) => setTimeout(r, 200));
112
+ const dt = new DataTransfer();
113
+ dt.setData("text/plain", decodeContent);
114
+ preEditor.dispatchEvent(
115
+ new ClipboardEvent("paste", {
116
+ clipboardData: dt,
117
+ bubbles: true,
118
+ cancelable: true
119
+ })
120
+ );
121
+ await new Promise((r) => setTimeout(r, 800));
122
+ let actual = preEditor.textContent || "";
123
+ const probe = decodeContent.trim().slice(0, 40);
124
+ if (!actual.includes(probe)) {
125
+ preEditor.textContent = decodeContent;
126
+ preEditor.dispatchEvent(new InputEvent("input", { bubbles: true }));
127
+ actual = preEditor.textContent || "";
128
+ }
129
+ if (!actual.includes(probe)) {
130
+ throw new Error("\u6B63\u6587\u586B\u5199\u5931\u8D25\uFF08contenteditable\uFF09\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
131
+ }
132
+ editor = "clipboard-paste";
133
+ }
134
+ }
135
+ if (!editor) {
136
+ throw new Error("\u672A\u627E\u5230\u6B63\u6587\u7F16\u8F91\u5668\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
137
+ }
138
+ return {
139
+ success: true,
140
+ message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u6210\u529F\u586B\u5199\u5230 CSDN \u7F16\u8F91\u5668\uFF0C\u8BF7\u4EBA\u5DE5\u5BA1\u6838\u540E\u53D1\u5E03",
141
+ title: title.trim(),
142
+ contentLength: decodeContent.length,
143
+ editor
144
+ };
145
+ }
146
+ });
147
+ window.__webmcptools_editorcsdnnet = true;
148
+ scheduleCloseTemplateDialog();
149
+ console.log("[webmcp-tools] editor.csdn.net \u5DE5\u5177\u6CE8\u518C\u6210\u529F");
150
+ } catch (e) {
151
+ console.error("[webmcp-tools] editor.csdn.net \u5DE5\u5177\u6CE8\u518C\u5931\u8D25:", e.message);
152
+ }
153
+ }
154
+ })();
155
+ })();
@@ -7,6 +7,11 @@
7
7
  console.warn("[webmcp-tools] juejin.cn: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
8
8
  } else if (!window.__webmcptools_juejincn) {
9
9
  try {
10
+ window.__webmcpcli_beforeGetBrowserState = () => {
11
+ window.__webmcpcli_interactiveWhitelist.length = 0;
12
+ const whites = document.querySelectorAll(".link[target]");
13
+ window.__webmcpcli_interactiveWhitelist.push(...whites);
14
+ };
10
15
  mcp.registerTool({
11
16
  name: "create_article",
12
17
  title: "\u53D1\u5E03\u65B0\u6587\u7AE0",
@@ -33,9 +38,7 @@
33
38
  throw new Error("\u53C2\u6570 content \u4E0D\u80FD\u4E3A\u7A7A");
34
39
  }
35
40
  if (!location.href.startsWith("https://juejin.cn/editor/drafts/new")) {
36
- throw new Error(
37
- "\u5F53\u524D\u9875\u9762\u4E0D\u662F\u6398\u91D1\u65B0\u5EFA\u6587\u7AE0\u7F16\u8F91\u5668\uFF0C\u8BF7\u5148\u6253\u5F00 https://juejin.cn/editor/drafts/new?v=2"
38
- );
41
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F\u6398\u91D1\u65B0\u5EFA\u6587\u7AE0\u7F16\u8F91\u5668\uFF0C\u8BF7\u5148\u6253\u5F00 https://juejin.cn/editor/drafts/new?v=2");
39
42
  }
40
43
  let decodeContent;
41
44
  try {
@@ -43,9 +46,7 @@
43
46
  } catch {
44
47
  throw new Error("content \u4E0D\u662F\u6709\u6548\u7684 Base64 \u7F16\u7801\uFF0C\u8BF7\u68C0\u67E5\u53C2\u6570\u6216\u4F7F\u7528 @base64file: \u5F15\u7528\u6587\u4EF6");
45
48
  }
46
- const titleInput = document.querySelector(
47
- ".edit-draft .header .title-input"
48
- );
49
+ const titleInput = document.querySelector(".edit-draft .header .title-input");
49
50
  if (!titleInput) {
50
51
  throw new Error("\u672A\u627E\u5230\u6807\u9898\u8F93\u5165\u6846\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
51
52
  }
@@ -95,6 +96,150 @@
95
96
  };
96
97
  }
97
98
  });
99
+ mcp.registerTool({
100
+ name: "get_article_info",
101
+ title: "\u83B7\u53D6\u5F53\u524D\u6587\u7AE0\u4FE1\u606F",
102
+ description: "\u5728\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762\u4E2D\uFF0C\u83B7\u53D6\u5F53\u524D\u8349\u7A3F\u7684\u6807\u9898\u548C\u6B63\u6587\u5185\u5BB9\uFF0C\u4EE5\u4FBF AI \u5206\u6790\u5176\u4E3B\u9898\u4EE5\u9009\u62E9\u5408\u9002\u7684\u5206\u7C7B\u6807\u7B7E\uFF0C\u6216\u603B\u7ED3\u51FA 50~100 \u5B57\u7684\u6458\u8981\u3002",
103
+ inputSchema: {
104
+ type: "object",
105
+ properties: {}
106
+ },
107
+ execute: async () => {
108
+ const titleInput = document.querySelector(".edit-draft .header .title-input");
109
+ const title = titleInput ? titleInput.value : "";
110
+ const cm5El = document.querySelector(".edit-draft .CodeMirror");
111
+ let content = "";
112
+ if (cm5El?.CodeMirror) {
113
+ content = cm5El.CodeMirror.getValue();
114
+ } else {
115
+ const cm6View = document.querySelector(".cm-editor")?.cmView?.view;
116
+ if (cm6View) {
117
+ content = cm6View.state.doc.toString();
118
+ }
119
+ }
120
+ return {
121
+ success: true,
122
+ title,
123
+ content
124
+ };
125
+ }
126
+ });
127
+ mcp.registerTool({
128
+ name: "publish_current_draft",
129
+ title: "\u4E00\u952E\u53D1\u5E03\u5F53\u524D\u8349\u7A3F",
130
+ description: "\u5728\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762\u4E2D\uFF0C\u81EA\u52A8\u70B9\u51FB\u53D1\u5E03\u3001\u9009\u62E9\u5206\u7C7B\u3001\u6DFB\u52A0\u6807\u7B7E\u5E76\u786E\u8BA4\u53D1\u5E03\u3002\u6CE8\u610F\uFF1A\u8C03\u7528\u6B64\u5DE5\u5177\u524D\uFF0CAI \u5FC5\u987B\u5148\u8BFB\u53D6\u6216\u4E86\u89E3\u5F53\u524D\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\u5185\u5BB9\uFF0C\u5E76\u57FA\u4E8E\u6587\u7AE0\u5185\u5BB9\u667A\u80FD\u63A8\u65AD\u5E76\u9009\u62E9\u6700\u5408\u9002\u7684\u5206\u7C7B\u4E0E\u6807\u7B7E\uFF0C\u5207\u52FF\u76F2\u76EE\u4F7F\u7528\u9ED8\u8BA4\u503C\u3002",
131
+ inputSchema: {
132
+ type: "object",
133
+ properties: {
134
+ category: {
135
+ type: "string",
136
+ description: '\u5206\u7C7B\u540D\u79F0\u3002AI \u5E94\u5148\u8BFB\u53D6\u5F53\u524D\u6587\u7AE0\u6B63\u6587\u5185\u5BB9\u5224\u65AD\u51FA\u5176\u5F52\u5C5E\u7684\u6280\u672F\u9886\u57DF\uFF0C\u4F8B\u5982 "\u524D\u7AEF"\u3001"\u540E\u7AEF"\u3001"Android"\u3001"iOS"\u3001"\u4EBA\u5DE5\u667A\u80FD"\u3001"\u5F00\u53D1\u5DE5\u5177"\u3001"\u4EE3\u7801\u4EBA\u751F" \u7B49\uFF0C\u9ED8\u8BA4\u503C\u4E3A "\u524D\u7AEF"'
137
+ },
138
+ tag: {
139
+ type: "string",
140
+ description: '\u6807\u7B7E\u540D\u79F0\u3002AI \u5E94\u5148\u8BFB\u53D6\u5F53\u524D\u6587\u7AE0\u6B63\u6587\u5185\u5BB9\uFF0C\u63D0\u70BC\u51FA\u5176\u5177\u4F53\u6D89\u53CA\u7684\u6838\u5FC3\u6280\u672F\u6808\u6807\u7B7E\uFF0C\u4F8B\u5982 "Vue.js"\u3001"React"\u3001"JavaScript"\u3001"Python"\u3001"Go" \u7B49\uFF0C\u9ED8\u8BA4\u503C\u4E3A "Vue.js"'
141
+ },
142
+ summary: {
143
+ type: "string",
144
+ description: "\u6587\u7AE0\u6458\u8981\uFF0C\u5FC5\u586B\uFF0C\u5B57\u6570\u5FC5\u987B\u5728 50 \u5230 100 \u5B57\u4E4B\u95F4\u3002\u8C03\u7528\u6B64\u5DE5\u5177\u524D\uFF0CAI \u5FC5\u987B\u5148\u4F7F\u7528 get_article_info \u83B7\u53D6\u6587\u7AE0\u6B63\u6587\uFF0C\u5E76\u81EA\u4E3B\u603B\u7ED3\u51FA\u6458\u8981\u540E\u4F20\u5165\u6B64\u53C2\u6570\u3002"
145
+ }
146
+ },
147
+ required: ["summary"]
148
+ },
149
+ execute: async ({ category = "\u524D\u7AEF", tag = "Vue.js", summary }) => {
150
+ const publishBtn = Array.from(document.querySelectorAll("button")).find(
151
+ (e) => e.textContent?.trim() === "\u53D1\u5E03"
152
+ );
153
+ if (!publishBtn) {
154
+ throw new Error("\u672A\u627E\u5230\u201C\u53D1\u5E03\u201D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u5904\u4E8E\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762");
155
+ }
156
+ publishBtn.click();
157
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
158
+ const categoryButtons = Array.from(
159
+ document.querySelectorAll(".category-list .item, .category-list .category-item, .category-item, .item")
160
+ );
161
+ let catBtn = categoryButtons.find((e) => e.textContent?.includes(category));
162
+ if (!catBtn) {
163
+ catBtn = Array.from(document.querySelectorAll("*")).find(
164
+ (e) => e.textContent === category && e.tagName !== "SCRIPT"
165
+ );
166
+ }
167
+ if (!catBtn) {
168
+ throw new Error(`\u672A\u627E\u5230\u5206\u7C7B\u6309\u94AE: ${category}`);
169
+ }
170
+ ;
171
+ catBtn.click();
172
+ const tagLabel = Array.from(document.querySelectorAll("span, label, .label")).find(
173
+ (e) => e.textContent?.includes("\u6DFB\u52A0\u6807\u7B7E")
174
+ );
175
+ if (!tagLabel) {
176
+ throw new Error("\u672A\u627E\u5230\u201C\u6DFB\u52A0\u6807\u7B7E\u201D\u7684\u8868\u5355\u9879");
177
+ }
178
+ const parent = tagLabel.closest(".form-item, .margin-bottom, .entry-form-item");
179
+ const input = parent ? parent.querySelector("input") : null;
180
+ if (!input) {
181
+ throw new Error("\u672A\u627E\u5230\u6807\u7B7E\u8F93\u5165\u6846");
182
+ }
183
+ input.focus();
184
+ input.value = tag;
185
+ input.dispatchEvent(new Event("input", { bubbles: true }));
186
+ input.dispatchEvent(new Event("change", { bubbles: true }));
187
+ await new Promise((resolve) => setTimeout(resolve, 1500));
188
+ const items = Array.from(
189
+ document.querySelectorAll(
190
+ ".byte-select-option, .select-option, .option, .item, .dropdown-item, .byte-select__option, .byte-select-option-wrapper"
191
+ )
192
+ );
193
+ const tagItem = items.find((e) => e.textContent?.trim() === tag);
194
+ if (!tagItem) {
195
+ throw new Error(`\u6807\u7B7E\u4E0B\u62C9\u9009\u9879\u4E2D\u672A\u627E\u5230\u5339\u914D\u7684: ${tag}`);
196
+ }
197
+ tagItem.click();
198
+ let finalSummary = summary || "";
199
+ if (finalSummary.length < 50) {
200
+ while (finalSummary.length < 50) {
201
+ finalSummary += "\u3002\u8FD9\u662F\u5173\u4E8E\u672C\u6587\u5185\u5BB9\u7684\u8BE6\u7EC6\u4ECB\u7ECD\uFF0C\u6B22\u8FCE\u9605\u8BFB\u5168\u6587\u4E86\u89E3\u66F4\u591A\u7CBE\u5F69\u7684\u6280\u672F\u7EC6\u8282\u4E0E\u5B9E\u8DF5\u7ECF\u9A8C\u5206\u4EAB\u3002";
202
+ }
203
+ }
204
+ if (finalSummary.length > 100) {
205
+ finalSummary = finalSummary.slice(0, 97) + "...";
206
+ }
207
+ const summaryTextarea = document.querySelector('.summary-textarea, textarea[placeholder*="\u6458\u8981"], textarea[placeholder*="\u6587\u7AE0\u7684\u6458\u8981"]');
208
+ if (summaryTextarea) {
209
+ summaryTextarea.focus();
210
+ summaryTextarea.value = finalSummary;
211
+ summaryTextarea.dispatchEvent(new Event("input", { bubbles: true }));
212
+ summaryTextarea.dispatchEvent(new Event("change", { bubbles: true }));
213
+ summaryTextarea.blur();
214
+ await new Promise((resolve) => setTimeout(resolve, 500));
215
+ }
216
+ const titleClose = Array.from(document.querySelectorAll("*")).find(
217
+ (e) => e.textContent?.trim() === "\u53D1\u5E03\u6587\u7AE0"
218
+ );
219
+ if (titleClose) {
220
+ titleClose.click();
221
+ }
222
+ await new Promise((resolve) => setTimeout(resolve, 500));
223
+ const confirmBtn = Array.from(document.querySelectorAll("button")).find(
224
+ (e) => e.textContent?.trim() === "\u786E\u5B9A\u5E76\u53D1\u5E03"
225
+ );
226
+ if (!confirmBtn) {
227
+ throw new Error("\u672A\u627E\u5230\u201C\u786E\u5B9A\u5E76\u53D1\u5E03\u201D\u6309\u94AE");
228
+ }
229
+ confirmBtn.click();
230
+ await new Promise((resolve) => setTimeout(resolve, 500));
231
+ const popupTitle = Array.from(document.querySelectorAll("*")).find(
232
+ (e) => e.textContent?.trim() === "\u53D1\u5E03\u6587\u7AE0" && e.offsetParent !== null
233
+ );
234
+ if (popupTitle) {
235
+ throw new Error("\u53D1\u5E03\u6587\u7AE0\u5931\u8D25\uFF0C\u5F39\u51FA\u6846\u672A\u5173\u95ED\uFF0C\u8BF7\u68C0\u67E5\u5206\u7C7B\u3001\u6807\u7B7E\u6216\u5176\u4ED6\u5FC5\u586B\u9879\u662F\u5426\u6B63\u786E\u586B\u5199");
236
+ }
237
+ return {
238
+ success: true,
239
+ message: `\u81EA\u52A8\u53D1\u5E03\u6D41\u7A0B\u5DF2\u89E6\u53D1\uFF0C\u5206\u7C7B: ${category}, \u6807\u7B7E: ${tag}`
240
+ };
241
+ }
242
+ });
98
243
  window.__webmcptools_juejincn = true;
99
244
  console.log("[webmcp-tools] juejin.cn \u5DE5\u5177\u6CE8\u518C\u6210\u529F");
100
245
  } catch (e) {