@opentiny/webmcp-cli 0.0.6 → 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.
@@ -2,44 +2,56 @@
2
2
  "use strict";
3
3
  (() => {
4
4
  // webmcp-tools/my.oschina.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
+ }
13
+ function isOschinaWritePage() {
14
+ return location.href.startsWith("https://my.oschina.net/u") && location.href.endsWith("/blog/ai-write");
15
+ }
16
+ function readArticleFromEditor() {
17
+ const titleInput = document.querySelector(".title-input-container .title-input");
18
+ const title = titleInput?.value?.trim() || "";
19
+ const editor = document.querySelector(".v-md-textarea-editor textarea");
20
+ const content = editor?.value || "";
21
+ return { title, content };
22
+ }
5
23
  var mcp = navigator.modelContext;
6
24
  if (!mcp || typeof mcp.registerTool !== "function") {
7
25
  console.warn("[webmcp-tools] my.oschina.net: document.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
8
26
  } else if (!window.__webmcptools_myoschinanet) {
9
- ;
10
- window.__webmcptools_myoschinanet = true;
11
27
  try {
12
28
  mcp.registerTool({
13
29
  name: "create_article",
14
30
  title: "\u53D1\u5E03\u65B0\u6587\u7AE0",
15
- description: "\u63A5\u6536\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\uFF0C\u5C06\u5B83\u4EEC\u586B\u5199\u5230\u7F51\u9875\u4E2D\u3002",
31
+ description: "\u63A5\u6536\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\uFF0C\u5C06\u5B83\u4EEC\u586B\u5199\u5230\u5F00\u6E90\u4E2D\u56FD\u7F16\u8F91\u5668\u4E2D\u3002",
16
32
  inputSchema: {
17
33
  type: "object",
18
34
  properties: {
19
35
  title: {
20
36
  type: "string",
21
- description: "\u6587\u7AE0\u6807\u9898\uFF0C\u5FC5\u586B\uFF0C \u5EFA\u8BAE\u4E0D\u8D85\u8FC715\u4E2A\u5B57\uFF0C\u4E0D\u5141\u8BB8\u6709\u7279\u6B8A\u7B26\u53F7\u5F71\u54CD\u547D\u4EE4\u884C\u53C2\u6570\u89E3\u6790"
37
+ 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"
22
38
  },
23
39
  content: {
24
40
  type: "string",
25
- description: "\u6587\u7AE0\u5185\u5BB9\u7684base64\u7F16\u7801\u540E\u7684\u5B57\u7B26\u4E32\uFF0C\u5FC5\u586B\u3002"
41
+ description: "\u6587\u7AE0\u5185\u5BB9\u7684 Base64 \u7F16\u7801\u5B57\u7B26\u4E32\uFF0C\u5FC5\u586B\u3002"
26
42
  }
27
43
  },
28
44
  required: ["title", "content"]
29
45
  },
30
- execute: async ({
31
- uid,
32
- title,
33
- content
34
- }) => {
46
+ execute: async ({ title, content }) => {
35
47
  if (!title?.trim()) {
36
48
  throw new Error("\u53C2\u6570 title \u4E0D\u80FD\u4E3A\u7A7A");
37
49
  }
38
50
  if (!content?.trim()) {
39
51
  throw new Error("\u53C2\u6570 content \u4E0D\u80FD\u4E3A\u7A7A");
40
52
  }
41
- if (!(location.href.startsWith(`https://my.oschina.net/u`) && location.href.endsWith(`/blog/ai-write`))) {
42
- throw new Error(`\u5F53\u524D\u9875\u9762\u4E0D\u662F\u53D1\u5E03\u9875\u9762\uFF0C\u8BF7\u5148\u6253\u5F00 https://my.oschina.net/u/<uid>}/blog/ai-write`);
53
+ if (!isOschinaWritePage()) {
54
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F\u53D1\u5E03\u9875\u9762\uFF0C\u8BF7\u5148\u6253\u5F00 https://my.oschina.net/u/<uid>/blog/ai-write");
43
55
  }
44
56
  let decodeContent;
45
57
  try {
@@ -47,11 +59,11 @@
47
59
  } catch {
48
60
  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");
49
61
  }
50
- let switchBtn = document.querySelector(".editor-switch-btn");
62
+ const switchBtn = document.querySelector(".editor-switch-btn");
51
63
  if (switchBtn) {
52
64
  switchBtn.click();
53
65
  }
54
- await new Promise((resolve) => setTimeout(resolve, 300));
66
+ await sleep(300);
55
67
  const titleInput = document.querySelector(".title-input-container .title-input");
56
68
  if (!titleInput) {
57
69
  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");
@@ -59,37 +71,167 @@
59
71
  titleInput.focus();
60
72
  titleInput.value = title;
61
73
  titleInput.dispatchEvent(
62
- new InputEvent("input", {
63
- bubbles: true,
64
- cancelable: true,
65
- data: title
66
- })
74
+ new InputEvent("input", { bubbles: true, cancelable: true, data: title })
67
75
  );
68
76
  titleInput.dispatchEvent(new Event("change", { bubbles: true }));
69
77
  titleInput.blur();
70
78
  if (titleInput.value.trim() !== title.trim()) {
71
79
  throw new Error("\u6807\u9898\u586B\u5199\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5");
72
80
  }
73
- await new Promise((resolve) => setTimeout(resolve, 300));
74
- let editor = document.querySelector(".v-md-textarea-editor textarea");
75
- if (editor) {
76
- editor.value = decodeContent;
77
- editor.dispatchEvent(new Event("change", { bubbles: true }));
78
- editor.blur();
79
- } else {
81
+ await sleep(300);
82
+ const editor = document.querySelector(".v-md-textarea-editor textarea");
83
+ if (!editor) {
80
84
  throw new Error("\u672A\u627E\u5230\u6B63\u6587\u7F16\u8F91\u5668");
81
85
  }
82
- return {
86
+ const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
87
+ editor.focus();
88
+ if (nativeSetter) {
89
+ nativeSetter.call(editor, decodeContent);
90
+ } else {
91
+ editor.value = decodeContent;
92
+ }
93
+ editor.dispatchEvent(new InputEvent("input", { bubbles: true }));
94
+ editor.dispatchEvent(new Event("change", { bubbles: true }));
95
+ editor.blur();
96
+ return toToolResult({
97
+ success: true,
98
+ message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u6210\u529F\u586B\u5199\u5230\u5F00\u6E90\u4E2D\u56FD\u7F16\u8F91\u5668\uFF0C\u8349\u7A3F\u5C06\u81EA\u52A8\u4FDD\u5B58",
99
+ title: title.trim(),
100
+ contentLength: decodeContent.length
101
+ });
102
+ }
103
+ });
104
+ mcp.registerTool({
105
+ name: "get_article_info",
106
+ title: "\u83B7\u53D6\u5F53\u524D\u5F00\u6E90\u4E2D\u56FD\u6587\u7AE0\u4FE1\u606F",
107
+ description: "\u5728\u5F00\u6E90\u4E2D\u56FD\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",
108
+ inputSchema: { type: "object", properties: {} },
109
+ execute: async () => {
110
+ if (!isOschinaWritePage()) {
111
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F\u53D1\u5E03\u9875\u9762\uFF0C\u8BF7\u5148\u6253\u5F00 https://my.oschina.net/u/<uid>/blog/ai-write");
112
+ }
113
+ const { title, content } = readArticleFromEditor();
114
+ return toToolResult({
115
+ success: true,
116
+ title,
117
+ contentLength: content.length,
118
+ content
119
+ });
120
+ }
121
+ });
122
+ mcp.registerTool({
123
+ name: "publish_current_draft",
124
+ title: "\u4E00\u952E\u53D1\u5E03\u5F53\u524D\u5F00\u6E90\u4E2D\u56FD\u8349\u7A3F",
125
+ description: "\u5728\u5F00\u6E90\u4E2D\u56FD\u7F16\u8F91\u5668\u4E2D\u81EA\u52A8\u586B\u5199\u6807\u7B7E\u3001\u5206\u7C7B\u5E76\u70B9\u51FB\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 50~200 \u5B57\u6458\u8981\uFF0C\u5207\u52FF\u76F2\u76EE\u4F7F\u7528\u9ED8\u8BA4\u503C\u3002",
126
+ inputSchema: {
127
+ type: "object",
128
+ properties: {
129
+ category: {
130
+ type: "string",
131
+ description: "\u6587\u7AE0\u5206\u7C7B/\u4E13\u533A\uFF0C\u5982\u300C\u5F00\u6E90\u8D44\u8BAF\u300D\u300C\u8F6F\u4EF6\u67B6\u6784\u300D\u300C\u524D\u7AEF\u300D\u7B49\uFF0C\u9ED8\u8BA4\u300C\u5F00\u6E90\u8D44\u8BAF\u300D"
132
+ },
133
+ tags: {
134
+ type: "array",
135
+ items: { type: "string" },
136
+ description: "\u6587\u7AE0\u6807\u7B7E\u6570\u7EC4\uFF0C\u5FC5\u586B 1~5 \u4E2A\u3002AI \u5E94\u5148\u8BFB\u53D6\u6B63\u6587\u63D0\u70BC\u6838\u5FC3\u6280\u672F\u6808\u6807\u7B7E"
137
+ },
138
+ summary: {
139
+ type: "string",
140
+ description: "\u6587\u7AE0\u6458\u8981\uFF0C\u5FC5\u586B\uFF0C\u5EFA\u8BAE 50~200 \u5B57\u3002\u8C03\u7528\u524D AI \u987B\u57FA\u4E8E get_article_info \u81EA\u4E3B\u603B\u7ED3\u3002"
141
+ }
142
+ },
143
+ required: ["tags", "summary"]
144
+ },
145
+ execute: async ({
146
+ category = "\u5F00\u6E90\u8D44\u8BAF",
147
+ tags,
148
+ summary
149
+ }) => {
150
+ if (!isOschinaWritePage()) {
151
+ throw new Error("\u5F53\u524D\u9875\u9762\u4E0D\u662F\u53D1\u5E03\u9875\u9762\uFF0C\u8BF7\u5148 tabs switch \u5230\u7F16\u8F91\u5668\u6807\u7B7E\u9875\u540E\u518D\u53D1\u5E03");
152
+ }
153
+ if (!tags?.length) {
154
+ throw new Error("\u53C2\u6570 tags \u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u6807\u7B7E");
155
+ }
156
+ const finalSummary = summary?.trim() || "";
157
+ if (!finalSummary) {
158
+ throw new Error("\u53C2\u6570 summary \u4E0D\u80FD\u4E3A\u7A7A");
159
+ }
160
+ if (finalSummary.length < 20) {
161
+ throw new Error(`\u6458\u8981\u8FC7\u77ED\uFF08${finalSummary.length} \u5B57\uFF09\uFF0C\u5EFA\u8BAE\u81F3\u5C11 20 \u5B57`);
162
+ }
163
+ const summaryInput = document.querySelector('textarea[placeholder*="\u6458\u8981"]') || document.querySelector('input[placeholder*="\u6458\u8981"]') || document.querySelector('[class*="summary"] textarea');
164
+ if (summaryInput) {
165
+ const nativeSetter = Object.getOwnPropertyDescriptor(
166
+ summaryInput instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype,
167
+ "value"
168
+ )?.set;
169
+ summaryInput.focus();
170
+ if (nativeSetter) {
171
+ nativeSetter.call(summaryInput, finalSummary);
172
+ } else {
173
+ summaryInput.value = finalSummary;
174
+ }
175
+ summaryInput.dispatchEvent(new InputEvent("input", { bubbles: true }));
176
+ summaryInput.dispatchEvent(new Event("change", { bubbles: true }));
177
+ await sleep(300);
178
+ }
179
+ const catEl = Array.from(
180
+ document.querySelectorAll("select option, li, label, span, div, button")
181
+ ).find((el) => el.textContent?.trim() === category && el.offsetParent !== null);
182
+ if (catEl) {
183
+ catEl.click();
184
+ await sleep(300);
185
+ }
186
+ const tagInput = document.querySelector('input[placeholder*="\u6807\u7B7E"]') || document.querySelector('[class*="tag"] input');
187
+ const addedTags = [];
188
+ if (tagInput) {
189
+ for (const tag of tags.slice(0, 5)) {
190
+ tagInput.focus();
191
+ tagInput.click();
192
+ const nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
193
+ if (nativeSetter) {
194
+ nativeSetter.call(tagInput, tag);
195
+ } else {
196
+ tagInput.value = tag;
197
+ }
198
+ tagInput.dispatchEvent(new InputEvent("input", { bubbles: true, data: tag }));
199
+ await sleep(600);
200
+ const suggestion = Array.from(
201
+ document.querySelectorAll('[class*="suggestion"], [class*="dropdown"] li, .el-select-dropdown__item')
202
+ ).find((el) => el.textContent?.trim().includes(tag));
203
+ if (suggestion) {
204
+ suggestion.click();
205
+ } else {
206
+ tagInput.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true }));
207
+ }
208
+ addedTags.push(tag);
209
+ await sleep(400);
210
+ }
211
+ }
212
+ const publishBtn = Array.from(document.querySelectorAll("button, a")).find((el) => {
213
+ const text = el.textContent?.trim() || "";
214
+ return (text === "\u53D1\u5E03" || text === "\u53D1\u5E03\u535A\u5BA2" || text === "\u7ACB\u5373\u53D1\u5E03" || text.includes("\u53D1\u5E03\u6587\u7AE0")) && el.offsetParent !== null;
215
+ });
216
+ if (!publishBtn) {
217
+ throw new Error("\u672A\u627E\u5230\u300C\u53D1\u5E03\u300D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
218
+ }
219
+ publishBtn.click();
220
+ await sleep(2500);
221
+ return toToolResult({
83
222
  success: true,
84
- message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u6210\u529F\u586B\u5199\u5230\u5F00\u6E90\u4E2D\u56FD\u7684\u7F16\u8F91\u5668\uFF0C\u8349\u7A3F\u5C06\u81EA\u52A8\u4FDD\u5B58",
85
- title: title.trim()
86
- };
223
+ message: `\u5F00\u6E90\u4E2D\u56FD\u53D1\u5E03\u6D41\u7A0B\u5DF2\u89E6\u53D1\uFF0C\u5206\u7C7B: ${category}\uFF0C\u6807\u7B7E: ${addedTags.join(", ") || tags.join(", ")}`,
224
+ category,
225
+ tags: addedTags.length ? addedTags : tags,
226
+ summary: finalSummary,
227
+ url: location.href
228
+ });
87
229
  }
88
230
  });
89
- window.__webmcptools_juejincn = true;
90
- console.log("[webmcp-tools] juejin.cn \u5DE5\u5177\u6CE8\u518C\u6210\u529F");
231
+ window.__webmcptools_myoschinanet = true;
232
+ console.log("[webmcp-tools] my.oschina.net \u5DE5\u5177\u6CE8\u518C\u6210\u529F");
91
233
  } catch (e) {
92
- console.error("[webmcp-tools] juejin.cn \u5DE5\u5177\u6CE8\u518C\u5931\u8D25:", e.message);
234
+ console.error("[webmcp-tools] my.oschina.net \u5DE5\u5177\u6CE8\u518C\u5931\u8D25:", e.message);
93
235
  }
94
236
  }
95
237
  })();
@@ -290,6 +290,22 @@
290
290
  if (cm.state?.doc) return cm.state.doc.length;
291
291
  return 0;
292
292
  }
293
+ function getArticleFullContent() {
294
+ const cm = getCodeMirrorInstance();
295
+ if (cm?.getValue) return cm.getValue();
296
+ if (cm?.state?.doc) return cm.state.doc.toString();
297
+ const ta = findElement(SELECTORS.editor.markdownTextarea);
298
+ if (ta?.value) return ta.value;
299
+ const rich = document.querySelector('[contenteditable="true"]');
300
+ return rich?.textContent || "";
301
+ }
302
+ function decodeBase64Content(content) {
303
+ try {
304
+ return decodeURIComponent(escape(atob(content)));
305
+ } catch {
306
+ return null;
307
+ }
308
+ }
293
309
  function clearCodeMirror() {
294
310
  return setCodeMirrorContent("");
295
311
  }
@@ -550,6 +566,87 @@
550
566
  return { success: true, data: { cleared_items: results.length }, message: `\u8349\u7A3F\u5DF2\u820D\u5F03
551
567
  ${results.join("\n")}` };
552
568
  }
569
+ async function getArticleInfo() {
570
+ const pageType = detectPageType();
571
+ if (pageType !== "editor") {
572
+ return {
573
+ success: false,
574
+ error: "NOT_EDITOR",
575
+ errorCode: "NOT_EDITOR",
576
+ message: `\u5F53\u524D\u4E0D\u5728\u7F16\u8F91\u5668\u9875\u9762\uFF08${pageType}\uFF09\uFF0C\u8BF7\u5148\u5BFC\u822A\u5230\u5199\u6587\u7AE0\u9875\u9762`
577
+ };
578
+ }
579
+ const titleInput = findElement(SELECTORS.editor.titleInput);
580
+ const title = titleInput?.value?.trim() || "";
581
+ const content = getArticleFullContent();
582
+ const tags = findElements(SELECTORS.editor.selectedTags).map((el) => el.textContent?.trim().replace(/\s*[×x]$/, "")).filter(Boolean);
583
+ const catSelect = findElement(SELECTORS.editor.categorySelect);
584
+ const category = catSelect?.options[catSelect.selectedIndex]?.textContent?.trim() || "";
585
+ return {
586
+ success: true,
587
+ data: { title, contentLength: content.length, content, tags, category },
588
+ message: "\u5DF2\u83B7\u53D6\u5F53\u524D\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587"
589
+ };
590
+ }
591
+ async function createArticle(title, contentBase64) {
592
+ if (!title?.trim()) {
593
+ return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A" };
594
+ }
595
+ const content = decodeBase64Content(contentBase64);
596
+ if (!content) {
597
+ return {
598
+ success: false,
599
+ error: "INVALID_BASE64",
600
+ errorCode: "INVALID_BASE64",
601
+ message: "content \u4E0D\u662F\u6709\u6548\u7684 Base64 \u7F16\u7801\uFF0C\u8BF7\u4F7F\u7528 @base64file: \u5F15\u7528\u6587\u4EF6"
602
+ };
603
+ }
604
+ if (detectPageType() !== "editor") {
605
+ return {
606
+ success: false,
607
+ error: "NOT_EDITOR",
608
+ errorCode: "NOT_EDITOR",
609
+ message: "\u5F53\u524D\u4E0D\u5728\u7F16\u8F91\u5668\u9875\u9762\uFF0C\u8BF7\u5148\u6253\u5F00 https://segmentfault.com/write"
610
+ };
611
+ }
612
+ const r1 = await setTitle(title);
613
+ if (!r1.success) return r1;
614
+ const r2 = await setContent(content);
615
+ if (!r2.success) return r2;
616
+ await sleep(CONFIG.autoSaveDelay);
617
+ return {
618
+ success: true,
619
+ data: { title: title.trim(), contentLength: content.length, draft_url: "https://segmentfault.com/user/draft" },
620
+ message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u586B\u5199\uFF0C\u601D\u5426\u5C06\u81EA\u52A8\u4FDD\u5B58\u8349\u7A3F"
621
+ };
622
+ }
623
+ async function publishCurrentDraft(params) {
624
+ if (!params.category?.trim()) {
625
+ return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u53C2\u6570 category \u4E0D\u80FD\u4E3A\u7A7A" };
626
+ }
627
+ if (!params.tags?.length) {
628
+ return { success: false, error: "EMPTY", errorCode: "EMPTY", message: "\u53C2\u6570 tags \u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u6807\u7B7E" };
629
+ }
630
+ if (params.tags.length > 5) {
631
+ return { success: false, error: "TOO_MANY", errorCode: "TOO_MANY", message: "\u6700\u591A 5 \u4E2A\u6807\u7B7E" };
632
+ }
633
+ if (detectPageType() !== "editor") {
634
+ return {
635
+ success: false,
636
+ error: "NOT_EDITOR",
637
+ errorCode: "NOT_EDITOR",
638
+ message: "\u5F53\u524D\u4E0D\u5728\u7F16\u8F91\u5668\u9875\u9762\uFF0C\u8BF7\u5148 tabs switch \u5230\u7F16\u8F91\u5668\u6807\u7B7E\u9875"
639
+ };
640
+ }
641
+ await setArticleType(params.type || "original");
642
+ await setPublishScope("personal");
643
+ await addTags(params.tags, true);
644
+ const catResult = await setCategory(params.category);
645
+ if (!catResult.success) return catResult;
646
+ await setCopyright(params.copyright !== false);
647
+ await sleep(CONFIG.autoSaveDelay);
648
+ return publish(true);
649
+ }
553
650
  async function getState() {
554
651
  const pageType = detectPageType();
555
652
  if (pageType !== "editor") {
@@ -786,6 +883,9 @@ ${results.join("\n")}
786
883
  "set_scheduled_publish",
787
884
  "discard_draft",
788
885
  "get_state",
886
+ "get_article_info",
887
+ "create_article",
888
+ "publish_current_draft",
789
889
  "publish"
790
890
  ],
791
891
  description: "\u64CD\u4F5C\u7C7B\u578B"
@@ -834,6 +934,17 @@ ${results.join("\n")}
834
934
  return await discardDraft();
835
935
  case "get_state":
836
936
  return await getState();
937
+ case "get_article_info":
938
+ return await getArticleInfo();
939
+ case "create_article":
940
+ return await createArticle(args.title, args.content);
941
+ case "publish_current_draft":
942
+ return await publishCurrentDraft({
943
+ category: args.category,
944
+ tags: args.tags,
945
+ type: args.type,
946
+ copyright: args.copyright
947
+ });
837
948
  case "publish":
838
949
  return await publish(args.confirm);
839
950
  default:
@@ -845,7 +956,52 @@ ${results.join("\n")}
845
956
  }
846
957
  }
847
958
  });
848
- console.log("[SF Tool] \u2705 \u5DF2\u6CE8\u518C segmentfault_publish_article v6\uFF08\u7CBE\u7B80\u5FEB\u901F\u7248\uFF09");
959
+ console.log("[SF Tool] \u2705 \u5DF2\u6CE8\u518C segmentfault_publish_article v7\uFF08\u6398\u91D1\u98CE\u683C\u4E09\u4EF6\u5957\uFF09");
960
+ const sfMcp = navigator.modelContext;
961
+ if (sfMcp?.registerTool && !window.__webmcptools_segmentfault_unified) {
962
+ window.__webmcptools_segmentfault_unified = true;
963
+ sfMcp.registerTool({
964
+ name: "create_article",
965
+ title: "\u586B\u5199\u601D\u5426\u6587\u7AE0",
966
+ description: "\u63A5\u6536\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\uFF08Base64\uFF09\uFF0C\u586B\u5199\u5230 SegmentFault \u7F16\u8F91\u5668\u4E2D\u3002\u987B\u5148\u5904\u4E8E /write \u7F16\u8F91\u5668\u9875\u9762\u3002",
967
+ inputSchema: {
968
+ type: "object",
969
+ properties: {
970
+ title: { type: "string", description: "\u6587\u7AE0\u6807\u9898\uFF0C5-100 \u5B57\u7B26" },
971
+ content: { type: "string", description: "\u6B63\u6587 Base64 \u7F16\u7801\uFF0C\u652F\u6301 @base64file:" }
972
+ },
973
+ required: ["title", "content"]
974
+ },
975
+ execute: async (args) => createArticle(args.title, args.content)
976
+ });
977
+ sfMcp.registerTool({
978
+ name: "get_article_info",
979
+ title: "\u83B7\u53D6\u5F53\u524D\u601D\u5426\u6587\u7AE0\u4FE1\u606F",
980
+ description: "\u83B7\u53D6\u7F16\u8F91\u5668\u4E2D\u5F53\u524D\u6587\u7AE0\u7684\u6807\u9898\u548C\u6B63\u6587\uFF0C\u4F9B AI \u63A8\u65AD\u5206\u7C7B\u4E0E\u6807\u7B7E\u3002",
981
+ inputSchema: { type: "object", properties: {} },
982
+ execute: async () => getArticleInfo()
983
+ });
984
+ sfMcp.registerTool({
985
+ name: "publish_current_draft",
986
+ title: "\u4E00\u952E\u53D1\u5E03\u5F53\u524D\u601D\u5426\u8349\u7A3F",
987
+ description: "\u81EA\u52A8\u8BBE\u7F6E\u5206\u7C7B\u3001\u6807\u7B7E\u5E76\u53D1\u5E03\u3002\u8C03\u7528\u524D AI \u5FC5\u987B\u5148 get_article_info\uFF0C\u667A\u80FD\u63A8\u65AD category \u4E0E tags\uFF0C\u5207\u52FF\u76F2\u76EE\u4F7F\u7528\u9ED8\u8BA4\u503C\u3002",
988
+ inputSchema: {
989
+ type: "object",
990
+ properties: {
991
+ category: { type: "string", description: "\u5206\u7C7B\uFF0C\u5982\u300C\u524D\u7AEF\u300D\u300C\u540E\u7AEF\u300D\u300C\u4EBA\u5DE5\u667A\u80FD\u300D" },
992
+ tags: {
993
+ type: "array",
994
+ items: { type: "string" },
995
+ description: "\u6807\u7B7E\u6570\u7EC4\uFF0C1~5 \u4E2A\uFF0C\u987B\u57FA\u4E8E\u6587\u7AE0\u5185\u5BB9\u63A8\u65AD"
996
+ },
997
+ type: { type: "string", enum: ["original", "repost", "translate"], description: "\u6587\u7AE0\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u539F\u521B" },
998
+ copyright: { type: "boolean", description: "\u7248\u6743\u5F00\u5173\uFF0C\u9ED8\u8BA4 true" }
999
+ },
1000
+ required: ["category", "tags"]
1001
+ },
1002
+ execute: async (args) => publishCurrentDraft(args)
1003
+ });
1004
+ }
849
1005
  }
850
1006
  if (document.readyState === "loading") {
851
1007
  document.addEventListener("DOMContentLoaded", registerTool);