@opentiny/webmcp-cli 0.0.3 → 0.0.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 +1 -1
- package/dist/bin.cjs +364 -69
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +364 -69
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +257 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +257 -40
- package/dist/index.js.map +1 -1
- package/dist/inject-bundle.js +2704 -1420
- package/dist/webmcp-tools/creator.xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/editor.csdn.net.js +1 -1
- package/dist/webmcp-tools/excalidraw.com.js +4 -2
- package/dist/webmcp-tools/juejin.cn.js +132 -63
- package/dist/webmcp-tools/my.oschina.net.js +4 -2
- package/dist/webmcp-tools/segmentfault.com.js +856 -0
- package/dist/webmcp-tools/www.baidu.com.js +4 -2
- package/dist/webmcp-tools/xiaohongshu.com.js +1 -1
- package/dist/webmcp-tools/zhuanlan.zhihu.com.js +238 -0
- package/package.json +5 -4
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
// webmcp-tools/www.baidu.com/index.ts
|
|
5
5
|
var _baiduMcp = navigator.modelContext;
|
|
6
6
|
if (!_baiduMcp || typeof _baiduMcp.registerTool !== "function") {
|
|
7
|
-
console.warn("[webmcp-tools] www.baidu.com:
|
|
8
|
-
} else if (!window.
|
|
7
|
+
console.warn("[webmcp-tools] www.baidu.com: document.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
|
|
8
|
+
} else if (!window.__webmcptools_wwwbaiducom) {
|
|
9
|
+
;
|
|
10
|
+
window.__webmcptools_wwwbaiducom = true;
|
|
9
11
|
try {
|
|
10
12
|
_baiduMcp.registerTool({
|
|
11
13
|
name: "baidu_search",
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
;(function(){
|
|
2
|
+
"use strict";
|
|
3
|
+
(() => {
|
|
4
|
+
// webmcp-tools/zhuanlan.zhihu.com/index.ts
|
|
5
|
+
function isZhihuWritePage() {
|
|
6
|
+
return /^https:\/\/zhuanlan\.zhihu\.com\/(write|p\/\d+\/edit)/.test(location.href);
|
|
7
|
+
}
|
|
8
|
+
function setNativeInputValue(input, value) {
|
|
9
|
+
const setter = Object.getOwnPropertyDescriptor(
|
|
10
|
+
input instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype,
|
|
11
|
+
"value"
|
|
12
|
+
)?.set;
|
|
13
|
+
if (setter) {
|
|
14
|
+
setter.call(input, value);
|
|
15
|
+
} else {
|
|
16
|
+
input.value = value;
|
|
17
|
+
}
|
|
18
|
+
input.dispatchEvent(new InputEvent("input", { bubbles: true, cancelable: true, data: value }));
|
|
19
|
+
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
20
|
+
}
|
|
21
|
+
function findTitleInput() {
|
|
22
|
+
return document.querySelector('textarea[placeholder*="\u6807\u9898"]') || document.querySelector(".WriteIndex-titleInput textarea") || document.querySelector(".WriteIndex-titleInput input");
|
|
23
|
+
}
|
|
24
|
+
function findContentEditor() {
|
|
25
|
+
const draftEditor = document.querySelector(".public-DraftEditor-content");
|
|
26
|
+
if (draftEditor) return draftEditor;
|
|
27
|
+
const candidates = Array.from(
|
|
28
|
+
document.querySelectorAll('[contenteditable="true"], [contenteditable]')
|
|
29
|
+
);
|
|
30
|
+
const visible = candidates.filter((el) => {
|
|
31
|
+
const rect = el.getBoundingClientRect();
|
|
32
|
+
return rect.width > 100 && rect.height > 80 && el.offsetParent !== null;
|
|
33
|
+
});
|
|
34
|
+
return visible[0] || candidates[0] || null;
|
|
35
|
+
}
|
|
36
|
+
function getEditorText(editor) {
|
|
37
|
+
return (editor.innerText || editor.textContent || "").trim();
|
|
38
|
+
}
|
|
39
|
+
function delay(ms) {
|
|
40
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
41
|
+
}
|
|
42
|
+
async function addTopic(topic, scope) {
|
|
43
|
+
const addTopicBtn = Array.from(scope.querySelectorAll("button")).find(
|
|
44
|
+
(btn) => /添加话题|添加专栏话题/.test(btn.textContent?.trim() || "")
|
|
45
|
+
);
|
|
46
|
+
if (addTopicBtn) {
|
|
47
|
+
addTopicBtn.click();
|
|
48
|
+
await delay(500);
|
|
49
|
+
}
|
|
50
|
+
const topicInput = scope.querySelector(
|
|
51
|
+
'input[placeholder*="\u641C\u7D22\u8BDD\u9898"], input[placeholder*="\u8BDD\u9898"], input[placeholder*="\u641C\u7D22"]'
|
|
52
|
+
);
|
|
53
|
+
if (!topicInput) {
|
|
54
|
+
throw new Error("\u672A\u627E\u5230\u8BDD\u9898\u641C\u7D22\u8F93\u5165\u6846\uFF0C\u8BF7\u786E\u8BA4\u53D1\u5E03\u8BBE\u7F6E\u9762\u677F\u5DF2\u6253\u5F00");
|
|
55
|
+
}
|
|
56
|
+
topicInput.focus();
|
|
57
|
+
setNativeInputValue(topicInput, topic);
|
|
58
|
+
await delay(1500);
|
|
59
|
+
const topicItems = Array.from(
|
|
60
|
+
document.querySelectorAll(
|
|
61
|
+
'.TopicSelector-item, .TopicSelector-listItem, [class*="TopicSelector"] [class*="item"], [class*="Topic"] li'
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
let topicItem = topicItems.find((el) => el.textContent?.trim() === topic && el.offsetParent !== null);
|
|
65
|
+
if (!topicItem) {
|
|
66
|
+
topicItem = topicItems.find((el) => el.textContent?.includes(topic) && el.offsetParent !== null);
|
|
67
|
+
}
|
|
68
|
+
if (!topicItem) {
|
|
69
|
+
topicItem = topicItems.find((el) => el.offsetParent !== null);
|
|
70
|
+
}
|
|
71
|
+
if (!topicItem) {
|
|
72
|
+
const foundTexts = topicItems.map((e) => e.textContent?.trim()).filter(Boolean).join(", ");
|
|
73
|
+
throw new Error(`\u8BDD\u9898\u4E0B\u62C9\u9009\u9879\u4E2D\u672A\u627E\u5230\u5339\u914D\u9879: ${topic}\u3002\u5F53\u524D\u9009\u9879: [${foundTexts}]`);
|
|
74
|
+
}
|
|
75
|
+
topicItem.click();
|
|
76
|
+
await delay(400);
|
|
77
|
+
}
|
|
78
|
+
var mcp = navigator.modelContext;
|
|
79
|
+
if (!mcp || typeof mcp.registerTool !== "function") {
|
|
80
|
+
console.warn("[webmcp-tools] zhuanlan.zhihu.com: document.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
|
|
81
|
+
} else if (!window.__webmcptools_zhuanlanzhihucom) {
|
|
82
|
+
try {
|
|
83
|
+
mcp.registerTool({
|
|
84
|
+
name: "create_article",
|
|
85
|
+
title: "\u586B\u5199\u77E5\u4E4E\u4E13\u680F\u6587\u7AE0",
|
|
86
|
+
description: "\u63A5\u6536\u6587\u7AE0\u7684\u6807\u9898\u548C Markdown \u6B63\u6587\uFF0C\u586B\u5199\u5230\u77E5\u4E4E\u4E13\u680F\u7F16\u8F91\u5668\u3002\u6B63\u6587 Markdown \u8F6C HTML \u7C98\u8D34\u7531 webmcp-cli CLI \u5728 Node \u7AEF\u5B8C\u6210\uFF0C\u8BF7\u901A\u8FC7 webmcp-cli run create_article \u8C03\u7528\u3002",
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: "object",
|
|
89
|
+
properties: {
|
|
90
|
+
title: {
|
|
91
|
+
type: "string",
|
|
92
|
+
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"
|
|
93
|
+
},
|
|
94
|
+
content: {
|
|
95
|
+
type: "string",
|
|
96
|
+
description: "\u6587\u7AE0 Markdown \u6B63\u6587\u7684 Base64 \u7F16\u7801\u5B57\u7B26\u4E32\uFF0C\u5FC5\u586B\u3002CLI \u4F1A\u81EA\u52A8\u8F6C\u6362\u4E3A HTML \u540E\u7C98\u8D34\u5230 Draft.js \u7F16\u8F91\u5668\u3002"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
required: ["title", "content"]
|
|
100
|
+
},
|
|
101
|
+
execute: async () => {
|
|
102
|
+
throw new Error(
|
|
103
|
+
"create_article \u6B63\u6587\u586B\u5199\u7531 webmcp-cli CLI \u5728 Node \u7AEF\u6267\u884C\uFF08Markdown \u8F6C HTML + \u7CFB\u7EDF\u526A\u8D34\u677F\u7C98\u8D34\uFF09\uFF0C\u8BF7\u4F7F\u7528 webmcp-cli run create_article \u547D\u4EE4"
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
mcp.registerTool({
|
|
108
|
+
name: "get_article_info",
|
|
109
|
+
title: "\u83B7\u53D6\u5F53\u524D\u77E5\u4E4E\u6587\u7AE0\u4FE1\u606F",
|
|
110
|
+
description: "\u5728\u77E5\u4E4E\u4E13\u680F\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\u8BDD\u9898\u6807\u7B7E\u3002",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {}
|
|
114
|
+
},
|
|
115
|
+
execute: async () => {
|
|
116
|
+
const titleInput = findTitleInput();
|
|
117
|
+
const title = titleInput ? titleInput.value.trim() : "";
|
|
118
|
+
const editor = findContentEditor();
|
|
119
|
+
const content = editor ? getEditorText(editor) : "";
|
|
120
|
+
return {
|
|
121
|
+
content: [{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: JSON.stringify({
|
|
124
|
+
success: true,
|
|
125
|
+
title,
|
|
126
|
+
contentLength: content.length,
|
|
127
|
+
content
|
|
128
|
+
})
|
|
129
|
+
}]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
mcp.registerTool({
|
|
134
|
+
name: "publish_current_draft",
|
|
135
|
+
title: "\u4E00\u952E\u53D1\u5E03\u5F53\u524D\u77E5\u4E4E\u8349\u7A3F",
|
|
136
|
+
description: "\u5728\u77E5\u4E4E\u4E13\u680F\u7F16\u8F91\u5668\u9875\u9762\u4E2D\uFF0C\u81EA\u52A8\u6253\u5F00\u53D1\u5E03\u8BBE\u7F6E\u3001\u6DFB\u52A0\u8BDD\u9898\u5E76\u786E\u8BA4\u53D1\u5E03\u3002\u6CE8\u610F\uFF1A\u8C03\u7528\u6B64\u5DE5\u5177\u524D\uFF0CAI \u5FC5\u987B\u5148\u4F7F\u7528 get_article_info \u4E86\u89E3\u5F53\u524D\u6587\u7AE0\u5185\u5BB9\uFF0C\u5E76\u57FA\u4E8E\u6587\u7AE0\u5185\u5BB9\u667A\u80FD\u63A8\u65AD\u6700\u5408\u9002\u7684\u8BDD\u9898\uFF0C\u5207\u52FF\u76F2\u76EE\u4F7F\u7528\u9ED8\u8BA4\u503C\u3002",
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: "object",
|
|
139
|
+
properties: {
|
|
140
|
+
topic: {
|
|
141
|
+
type: "string",
|
|
142
|
+
description: '\u6587\u7AE0\u8BDD\u9898\u540D\u79F0\u3002AI \u5E94\u5148\u8BFB\u53D6\u5F53\u524D\u6587\u7AE0\u6B63\u6587\u5185\u5BB9\uFF0C\u63D0\u70BC\u51FA\u6700\u76F8\u5173\u7684\u77E5\u4E4E\u8BDD\u9898\uFF0C\u4F8B\u5982 "\u524D\u7AEF"\u3001"Vue.js"\u3001"\u4EBA\u5DE5\u667A\u80FD"\u3001"\u7F16\u7A0B" \u7B49\uFF0C\u9ED8\u8BA4\u503C\u4E3A "\u7F16\u7A0B"'
|
|
143
|
+
},
|
|
144
|
+
topics: {
|
|
145
|
+
type: "array",
|
|
146
|
+
items: { type: "string" },
|
|
147
|
+
description: "\u53EF\u9009\uFF0C\u989D\u5916\u8BDD\u9898\u5217\u8868\uFF08\u6700\u591A\u518D\u6DFB\u52A0 2 \u4E2A\uFF09\uFF0C\u6309\u76F8\u5173\u6027\u4ECE\u9AD8\u5230\u4F4E\u6392\u5217"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
required: ["topic"]
|
|
151
|
+
},
|
|
152
|
+
execute: async ({
|
|
153
|
+
topic = "\u7F16\u7A0B",
|
|
154
|
+
topics = []
|
|
155
|
+
}) => {
|
|
156
|
+
if (!isZhihuWritePage()) {
|
|
157
|
+
throw new Error("\u672A\u5904\u4E8E\u77E5\u4E4E\u4E13\u680F\u7F16\u8F91\u5668\u9875\u9762\uFF0C\u8BF7\u5148 tabs switch \u5230\u7F16\u8F91\u5668\u6807\u7B7E\u9875\u540E\u518D\u53D1\u5E03");
|
|
158
|
+
}
|
|
159
|
+
if (!topic?.trim()) {
|
|
160
|
+
throw new Error("\u53C2\u6570 topic \u4E0D\u80FD\u4E3A\u7A7A");
|
|
161
|
+
}
|
|
162
|
+
const allTopics = [topic.trim(), ...topics.map((t) => t.trim()).filter(Boolean)];
|
|
163
|
+
const uniqueTopics = [...new Set(allTopics)].slice(0, 3);
|
|
164
|
+
const headerButtons = Array.from(document.querySelectorAll("button"));
|
|
165
|
+
let publishEntryBtn = headerButtons.find((btn) => btn.textContent?.trim() === "\u53D1\u5E03" && btn.offsetParent !== null) || headerButtons.find((btn) => btn.textContent?.trim() === "\u53D1\u5E03\u8BBE\u7F6E" && btn.offsetParent !== null);
|
|
166
|
+
if (!publishEntryBtn) {
|
|
167
|
+
publishEntryBtn = document.querySelector(".WriteIndex-submitButton, .PublishPanel-trigger");
|
|
168
|
+
}
|
|
169
|
+
if (!publishEntryBtn) {
|
|
170
|
+
throw new Error("\u672A\u627E\u5230\u300C\u53D1\u5E03\u300D\u6216\u300C\u53D1\u5E03\u8BBE\u7F6E\u300D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u5904\u4E8E\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762\u4E14\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
|
|
171
|
+
}
|
|
172
|
+
publishEntryBtn.click();
|
|
173
|
+
await delay(1200);
|
|
174
|
+
const dialogScope = document.querySelector('.PublishPanel, .Modal, [role="dialog"], .WriteIndex-main') || document;
|
|
175
|
+
for (const t of uniqueTopics) {
|
|
176
|
+
await addTopic(t, dialogScope);
|
|
177
|
+
}
|
|
178
|
+
await delay(500);
|
|
179
|
+
let confirmBtn = dialogScope.querySelector(".PublishPanel-submitButton") || Array.from(dialogScope.querySelectorAll("button")).find(
|
|
180
|
+
(btn) => btn.textContent?.trim() === "\u53D1\u5E03" && btn.offsetParent !== null
|
|
181
|
+
);
|
|
182
|
+
if (!confirmBtn) {
|
|
183
|
+
const allPublishBtns = headerButtons.filter((btn) => btn.textContent?.trim() === "\u53D1\u5E03" && btn.offsetParent !== null);
|
|
184
|
+
confirmBtn = allPublishBtns[allPublishBtns.length - 1];
|
|
185
|
+
}
|
|
186
|
+
if (!confirmBtn) {
|
|
187
|
+
throw new Error("\u672A\u627E\u5230\u786E\u8BA4\u300C\u53D1\u5E03\u300D\u6309\u94AE");
|
|
188
|
+
}
|
|
189
|
+
confirmBtn.click();
|
|
190
|
+
const publishResult = await Promise.race([
|
|
191
|
+
new Promise((resolve) => {
|
|
192
|
+
const startHref = location.href;
|
|
193
|
+
const check = setInterval(() => {
|
|
194
|
+
if (/zhuanlan\.zhihu\.com\/p\/\d+/.test(location.href) && location.href !== startHref) {
|
|
195
|
+
clearInterval(check);
|
|
196
|
+
resolve("url_changed");
|
|
197
|
+
}
|
|
198
|
+
}, 300);
|
|
199
|
+
setTimeout(() => clearInterval(check), 15e3);
|
|
200
|
+
}),
|
|
201
|
+
new Promise((resolve) => {
|
|
202
|
+
const check = setInterval(() => {
|
|
203
|
+
const panel = document.querySelector('.PublishPanel, .Modal[role="dialog"]');
|
|
204
|
+
if (!panel || panel.offsetParent === null) {
|
|
205
|
+
clearInterval(check);
|
|
206
|
+
resolve("panel_closed");
|
|
207
|
+
}
|
|
208
|
+
}, 300);
|
|
209
|
+
setTimeout(() => clearInterval(check), 15e3);
|
|
210
|
+
}),
|
|
211
|
+
new Promise((resolve) => setTimeout(() => resolve("timeout"), 15e3))
|
|
212
|
+
]);
|
|
213
|
+
if (publishResult === "timeout") {
|
|
214
|
+
const panel = document.querySelector('.PublishPanel, .Modal[role="dialog"]');
|
|
215
|
+
if (panel && panel.offsetParent !== null) {
|
|
216
|
+
throw new Error("\u53D1\u5E03\u6587\u7AE0\u5931\u8D25\uFF0C\u53D1\u5E03\u9762\u677F\u672A\u5173\u95ED\uFF0C\u8BF7\u68C0\u67E5\u8BDD\u9898\u6216\u5176\u4ED6\u5FC5\u586B\u9879\u662F\u5426\u6B63\u786E\u586B\u5199");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
content: [{
|
|
221
|
+
type: "text",
|
|
222
|
+
text: JSON.stringify({
|
|
223
|
+
success: true,
|
|
224
|
+
message: `\u81EA\u52A8\u53D1\u5E03\u6D41\u7A0B\u5DF2\u89E6\u53D1\uFF0C\u8BDD\u9898: ${uniqueTopics.join(", ")}\uFF0C\u53D1\u5E03\u4FE1\u53F7: ${publishResult}`,
|
|
225
|
+
url: location.href
|
|
226
|
+
})
|
|
227
|
+
}]
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
window.__webmcptools_zhuanlanzhihucom = true;
|
|
232
|
+
console.log("[webmcp-tools] zhuanlan.zhihu.com \u5DE5\u5177\u6CE8\u518C\u6210\u529F");
|
|
233
|
+
} catch (e) {
|
|
234
|
+
console.error("[webmcp-tools] zhuanlan.zhihu.com \u5DE5\u5177\u6CE8\u518C\u5931\u8D25:", e.message);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
})();
|
|
238
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/webmcp-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "WebMCP CLI for AI Agents to interact with browser via Puppeteer",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,14 +26,15 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@mcp-b/webmcp-polyfill": "^
|
|
30
|
-
"@page-agent/page-controller": "^1.
|
|
29
|
+
"@mcp-b/webmcp-polyfill": "^3.0.0",
|
|
30
|
+
"@page-agent/page-controller": "^1.10.0",
|
|
31
31
|
"clipboardy": "^5.3.1",
|
|
32
32
|
"commander": "^11.1.0",
|
|
33
33
|
"json5": "^2.2.3",
|
|
34
|
+
"marked": "^15.0.7",
|
|
34
35
|
"picocolors": "^1.0.0",
|
|
35
36
|
"puppeteer-core": "^22.0.0",
|
|
36
|
-
"@opentiny/next-sdk": "^0.
|
|
37
|
+
"@opentiny/next-sdk": "^0.4.1"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/node": "^20.0.0",
|