@opentiny/webmcp-cli 0.0.4 → 0.0.8

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.
@@ -299,7 +299,7 @@
299
299
  }
300
300
  });
301
301
  if (typeof mcp.listTools === "function") {
302
- mcp.listTools().then((list) => {
302
+ mcp.getTools().then((list) => {
303
303
  window.__webmcpcli_tools = list;
304
304
  }).catch(() => {
305
305
  });
@@ -2,6 +2,14 @@
2
2
  "use strict";
3
3
  (() => {
4
4
  // webmcp-tools/editor.csdn.net/index.ts
5
+ function sleep(ms) {
6
+ return new Promise((r) => setTimeout(r, ms));
7
+ }
8
+ function toToolResult(data) {
9
+ return {
10
+ content: [{ type: "text", text: JSON.stringify(data) }]
11
+ };
12
+ }
5
13
  function closeTemplateDialog() {
6
14
  const modal = Array.from(document.querySelectorAll(".modal")).find(
7
15
  (el) => el.textContent?.includes("\u6A21\u7248\u5E93") || el.textContent?.includes("\u6A21\u677F\u5E93")
@@ -23,6 +31,31 @@
23
31
  }
24
32
  return false;
25
33
  }
34
+ function removePublishMask() {
35
+ document.querySelectorAll(".mark-mask-box-div").forEach((m) => m.remove());
36
+ }
37
+ function isCsdnEditorPage() {
38
+ return location.hostname.endsWith("editor.csdn.net");
39
+ }
40
+ function readArticleFromEditor() {
41
+ const titleInput = document.querySelector("input.article-bar__title--input");
42
+ const title = titleInput?.value?.trim() || "";
43
+ const cmEl = document.querySelector(".CodeMirror");
44
+ if (cmEl?.CodeMirror) {
45
+ return { title, content: cmEl.CodeMirror.getValue(), editor: "codemirror" };
46
+ }
47
+ const preEditor = document.querySelector("pre.editor__inner");
48
+ if (preEditor) {
49
+ return { title, content: preEditor.textContent || "", editor: "clipboard-paste" };
50
+ }
51
+ return { title, content: "", editor: null };
52
+ }
53
+ function findPublishButtons() {
54
+ return Array.from(document.querySelectorAll("button")).filter((b) => {
55
+ const el = b;
56
+ return el.textContent?.trim() === "\u53D1\u5E03\u6587\u7AE0" && el.offsetParent !== null;
57
+ });
58
+ }
26
59
  function scheduleCloseTemplateDialog() {
27
60
  const tryClose = () => closeTemplateDialog();
28
61
  tryClose();
@@ -31,7 +64,7 @@
31
64
  }
32
65
  var mcp = navigator.modelContext;
33
66
  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");
67
+ console.warn("[webmcp-tools] editor.csdn.net: document.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
35
68
  } else if (!window.__webmcptools_editorcsdnnet) {
36
69
  try {
37
70
  mcp.registerTool({
@@ -59,11 +92,11 @@
59
92
  if (!content?.trim()) {
60
93
  throw new Error("\u53C2\u6570 content \u4E0D\u80FD\u4E3A\u7A7A");
61
94
  }
62
- if (!location.hostname.endsWith("editor.csdn.net")) {
95
+ if (!isCsdnEditorPage()) {
63
96
  throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F CSDN \u7F16\u8F91\u5668\uFF0C\u8BF7\u5148\u6253\u5F00 https://editor.csdn.net/md/");
64
97
  }
65
98
  closeTemplateDialog();
66
- await new Promise((r) => setTimeout(r, 300));
99
+ await sleep(300);
67
100
  let decodeContent;
68
101
  try {
69
102
  decodeContent = decodeURIComponent(escape(atob(content)));
@@ -75,11 +108,11 @@
75
108
  );
76
109
  if (mdTab) {
77
110
  mdTab.click();
78
- await new Promise((r) => setTimeout(r, 500));
111
+ await sleep(500);
79
112
  }
80
113
  const titleDisplay = document.querySelector(".article-bar__title-display");
81
114
  titleDisplay?.click();
82
- await new Promise((r) => setTimeout(r, 300));
115
+ await sleep(300);
83
116
  const titleInput = document.querySelector("input.article-bar__title--input");
84
117
  if (!titleInput) {
85
118
  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");
@@ -108,7 +141,7 @@
108
141
  preEditor.focus();
109
142
  document.execCommand("selectAll");
110
143
  document.execCommand("delete");
111
- await new Promise((r) => setTimeout(r, 200));
144
+ await sleep(200);
112
145
  const dt = new DataTransfer();
113
146
  dt.setData("text/plain", decodeContent);
114
147
  preEditor.dispatchEvent(
@@ -118,7 +151,7 @@
118
151
  cancelable: true
119
152
  })
120
153
  );
121
- await new Promise((r) => setTimeout(r, 800));
154
+ await sleep(800);
122
155
  let actual = preEditor.textContent || "";
123
156
  const probe = decodeContent.trim().slice(0, 40);
124
157
  if (!actual.includes(probe)) {
@@ -135,13 +168,170 @@
135
168
  if (!editor) {
136
169
  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
170
  }
138
- return {
171
+ return toToolResult({
139
172
  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",
173
+ message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u6210\u529F\u586B\u5199\u5230 CSDN \u7F16\u8F91\u5668",
141
174
  title: title.trim(),
142
175
  contentLength: decodeContent.length,
143
176
  editor
144
- };
177
+ });
178
+ }
179
+ });
180
+ mcp.registerTool({
181
+ name: "get_article_info",
182
+ title: "\u83B7\u53D6\u5F53\u524D CSDN \u6587\u7AE0\u4FE1\u606F",
183
+ description: "\u5728 CSDN \u7F16\u8F91\u5668\u9875\u9762\u4E2D\u83B7\u53D6\u5F53\u524D\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\uFF0C\u4EE5\u4FBF AI \u5206\u6790\u4E3B\u9898\u3001\u9009\u62E9\u5408\u9002\u7684\u5206\u7C7B\u4E0E\u6807\u7B7E\uFF0C\u6216\u751F\u6210\u6458\u8981\u3002",
184
+ inputSchema: { type: "object", properties: {} },
185
+ execute: async () => {
186
+ if (!isCsdnEditorPage()) {
187
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F CSDN \u7F16\u8F91\u5668\uFF0C\u8BF7\u5148\u6253\u5F00 https://editor.csdn.net/md/");
188
+ }
189
+ const { title, content, editor } = readArticleFromEditor();
190
+ return toToolResult({
191
+ success: true,
192
+ title,
193
+ contentLength: content.length,
194
+ content,
195
+ editor
196
+ });
197
+ }
198
+ });
199
+ mcp.registerTool({
200
+ name: "publish_current_draft",
201
+ title: "\u4E00\u952E\u53D1\u5E03\u5F53\u524D CSDN \u8349\u7A3F",
202
+ description: "\u5728 CSDN \u7F16\u8F91\u5668\u4E2D\u81EA\u52A8\u6253\u5F00\u53D1\u5E03\u5F39\u7A97\u3001\u586B\u5199\u6807\u7B7E/\u5206\u7C7B/\u6458\u8981\u5E76\u786E\u8BA4\u53D1\u5E03\u3002\u8C03\u7528\u524D AI \u5FC5\u987B\u5148\u4F7F\u7528 get_article_info \u83B7\u53D6\u6B63\u6587\uFF0C\u667A\u80FD\u63A8\u65AD category \u4E0E tags\uFF0C\u5E76\u751F\u6210 100 \u5B57\u4EE5\u5185\u7684\u6458\u8981\uFF0C\u5207\u52FF\u76F2\u76EE\u4F7F\u7528\u9ED8\u8BA4\u503C\u3002",
203
+ inputSchema: {
204
+ type: "object",
205
+ properties: {
206
+ category: {
207
+ type: "string",
208
+ description: "\u6587\u7AE0\u5206\u7C7B\u3002AI \u5E94\u5148\u8BFB\u53D6\u6B63\u6587\u5224\u65AD\u6280\u672F\u9886\u57DF\uFF0C\u5982\u300C\u524D\u7AEF\u300D\u300C\u540E\u7AEF\u300D\u300C\u4EBA\u5DE5\u667A\u80FD\u300D\u300C\u8FD0\u7EF4\u300D\u7B49\uFF0C\u9ED8\u8BA4\u300C\u524D\u7AEF\u300D"
209
+ },
210
+ tags: {
211
+ type: "array",
212
+ items: { type: "string" },
213
+ description: '\u6587\u7AE0\u6807\u7B7E\u6570\u7EC4\uFF0C\u5FC5\u586B 1~3 \u4E2A\u3002AI \u5E94\u5148\u8BFB\u53D6\u6B63\u6587\u63D0\u70BC\u6838\u5FC3\u6280\u672F\u6808\u6807\u7B7E\uFF0C\u5982 ["Vue.js","JavaScript","\u524D\u7AEF"]'
214
+ },
215
+ summary: {
216
+ type: "string",
217
+ description: "\u6587\u7AE0\u6458\u8981\uFF0C\u5FC5\u586B\uFF0C\u5B57\u6570\u5FC5\u987B\u5728 100 \u5B57\u4EE5\u5185\u3002\u8C03\u7528\u524D AI \u987B\u57FA\u4E8E get_article_info \u81EA\u4E3B\u603B\u7ED3\u3002"
218
+ }
219
+ },
220
+ required: ["tags", "summary"]
221
+ },
222
+ execute: async ({
223
+ category = "\u524D\u7AEF",
224
+ tags,
225
+ summary
226
+ }) => {
227
+ if (!isCsdnEditorPage()) {
228
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F CSDN \u7F16\u8F91\u5668\uFF0C\u8BF7\u5148 tabs switch \u5230\u7F16\u8F91\u5668\u6807\u7B7E\u9875\u540E\u518D\u53D1\u5E03");
229
+ }
230
+ if (!tags?.length) {
231
+ throw new Error("\u53C2\u6570 tags \u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u6807\u7B7E");
232
+ }
233
+ if (tags.length > 7) {
234
+ throw new Error("CSDN \u6700\u591A\u652F\u6301 7 \u4E2A\u6807\u7B7E");
235
+ }
236
+ const finalSummary = summary?.trim() || "";
237
+ if (!finalSummary) {
238
+ throw new Error("\u53C2\u6570 summary \u4E0D\u80FD\u4E3A\u7A7A");
239
+ }
240
+ if (finalSummary.length > 100) {
241
+ throw new Error(`\u6458\u8981\u5B57\u6570\u5FC5\u987B\u5728 100 \u5B57\u4EE5\u5185\uFF0C\u5F53\u524D\u5B57\u6570\u4E3A\uFF1A${finalSummary.length}`);
242
+ }
243
+ closeTemplateDialog();
244
+ removePublishMask();
245
+ await sleep(300);
246
+ const toolbarBtn = findPublishButtons()[0];
247
+ if (!toolbarBtn) {
248
+ throw new Error("\u672A\u627E\u5230\u5DE5\u5177\u680F\u300C\u53D1\u5E03\u6587\u7AE0\u300D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
249
+ }
250
+ toolbarBtn.click();
251
+ await sleep(1e3);
252
+ const dialogScope = document.querySelector(".publish-setting, .publish-dialog, .modal:not(:has(.modal__title))") || Array.from(document.querySelectorAll('.modal, [role="dialog"]')).find(
253
+ (el) => el.textContent?.includes("\u6587\u7AE0\u6807\u7B7E") || el.textContent?.includes("\u6458\u8981")
254
+ ) || document;
255
+ const addTagBtn = Array.from(dialogScope.querySelectorAll("button, div, span, a")).find(
256
+ (el) => el.textContent?.trim().includes("\u6DFB\u52A0\u6587\u7AE0\u6807\u7B7E")
257
+ );
258
+ if (addTagBtn) {
259
+ addTagBtn.click();
260
+ await sleep(800);
261
+ }
262
+ const tagDialog = Array.from(document.querySelectorAll('.modal, [role="dialog"]')).find(
263
+ (el) => el.textContent?.includes("\u6587\u7AE0\u6807\u7B7E") && el !== dialogScope
264
+ ) || document;
265
+ const clickedTags = [];
266
+ for (const tag of tags) {
267
+ const tagEls = Array.from(
268
+ tagDialog.querySelectorAll('.el-tag, span.tag, button.tag, li, [class*="tag"]')
269
+ );
270
+ const match = tagEls.find((el) => el.textContent?.trim() === tag && el.offsetParent !== null);
271
+ if (match) {
272
+ match.click();
273
+ clickedTags.push(tag);
274
+ }
275
+ }
276
+ if (clickedTags.length < tags.length) {
277
+ const remaining = tags.filter((t) => !clickedTags.includes(t));
278
+ for (const tag of remaining) {
279
+ const found = Array.from(
280
+ document.querySelectorAll('.el-tag, span.tag, button.tag, [class*="tag"]')
281
+ ).find((el) => el.textContent?.trim() === tag);
282
+ if (found) {
283
+ found.click();
284
+ clickedTags.push(tag);
285
+ }
286
+ }
287
+ }
288
+ const tagCloseBtn = Array.from(tagDialog.querySelectorAll("button, div")).find(
289
+ (el) => el.textContent?.trim() === "\u5173\u95ED" || el.textContent?.trim() === "\u53D6\u6D88"
290
+ );
291
+ tagCloseBtn?.click();
292
+ await sleep(500);
293
+ const catEl = Array.from(dialogScope.querySelectorAll("li, label, span, div, button")).find(
294
+ (el) => el.textContent?.trim() === category && el.offsetParent !== null
295
+ );
296
+ if (catEl) {
297
+ catEl.click();
298
+ await sleep(300);
299
+ }
300
+ const summaryTextarea = dialogScope.querySelector('textarea[placeholder*="\u6458\u8981"]') || Array.from(dialogScope.querySelectorAll("textarea")).find(
301
+ (ta) => ta.placeholder?.includes("\u6458\u8981") || ta.closest('[class*="summary"]')
302
+ ) || dialogScope.querySelector("textarea");
303
+ if (!summaryTextarea) {
304
+ throw new Error("\u672A\u627E\u5230\u6458\u8981\u8F93\u5165\u6846\uFF0C\u8BF7\u68C0\u67E5\u53D1\u5E03\u5F39\u7A97\u662F\u5426\u6B63\u5E38\u6253\u5F00");
305
+ }
306
+ const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
307
+ summaryTextarea.focus();
308
+ if (nativeSetter) {
309
+ nativeSetter.call(summaryTextarea, finalSummary);
310
+ } else {
311
+ summaryTextarea.value = finalSummary;
312
+ }
313
+ summaryTextarea.dispatchEvent(new InputEvent("input", { bubbles: true }));
314
+ summaryTextarea.dispatchEvent(new Event("change", { bubbles: true }));
315
+ summaryTextarea.blur();
316
+ await sleep(300);
317
+ removePublishMask();
318
+ const publishBtns = findPublishButtons();
319
+ const confirmBtn = publishBtns[publishBtns.length - 1] || publishBtns[0];
320
+ if (!confirmBtn) {
321
+ throw new Error("\u672A\u627E\u5230\u5F39\u7A97\u5185\u300C\u53D1\u5E03\u6587\u7AE0\u300D\u786E\u8BA4\u6309\u94AE");
322
+ }
323
+ confirmBtn.click();
324
+ await sleep(3e3);
325
+ const url = location.href;
326
+ const published = url.includes("mp.csdn.net") && url.includes("/success/");
327
+ return toToolResult({
328
+ success: true,
329
+ message: published ? `CSDN \u6587\u7AE0\u53D1\u5E03\u6210\u529F\uFF0C\u5206\u7C7B: ${category}\uFF0C\u6807\u7B7E: ${clickedTags.join(", ")}` : `\u53D1\u5E03\u6D41\u7A0B\u5DF2\u89E6\u53D1\uFF0C\u5206\u7C7B: ${category}\uFF0C\u6807\u7B7E: ${clickedTags.join(", ")}\uFF0C\u8BF7\u68C0\u67E5\u9875\u9762\u662F\u5426\u8DF3\u8F6C\u5230\u53D1\u5E03\u6210\u529F\u9875`,
330
+ category,
331
+ tags: clickedTags,
332
+ summary: finalSummary,
333
+ url
334
+ });
145
335
  }
146
336
  });
147
337
  window.__webmcptools_editorcsdnnet = true;
@@ -4,7 +4,7 @@
4
4
  // webmcp-tools/excalidraw.com/index.ts
5
5
  var _excalidrawMcp = navigator.modelContext;
6
6
  if (!_excalidrawMcp || typeof _excalidrawMcp.registerTool !== "function") {
7
- console.warn("[webmcp-tools] excalidraw.com: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
7
+ console.warn("[webmcp-tools] excalidraw.com: document.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
8
8
  } else if (!window.__webmcptools_excalidrawcom) {
9
9
  ;
10
10
  window.__webmcptools_excalidrawcom = true;