@aiquants/html-to-markdown 0.6.0 → 1.0.0
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/dist/core-ChRwTJHy.js +3 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -18
- package/dist/main.js +1 -105
- package/dist/mcp-server-CvLGX0Fe.js +1 -0
- package/dist/{mcp-server-jjdOcY1v.cjs → mcp-server-eznfa4gh.cjs} +1 -1
- package/dist/mcp-server-streamable-CjY9xfH0.js +1 -0
- package/dist/{mcp-server-streamable-DU6yq8ZG.cjs → mcp-server-streamable-DJ-R_Z_E.cjs} +1 -1
- package/dist/mcp-streamable.cjs +1 -1
- package/dist/mcp-streamable.js +1 -5
- package/dist/mcp.cjs +1 -1
- package/dist/mcp.js +1 -12
- package/dist/version-D8gIcbbb.cjs +7 -0
- package/dist/version-DEqf1gI6.js +7 -0
- package/package.json +7 -7
- package/dist/core-txi0EJ9v.js +0 -21162
- package/dist/mcp-server-B8T7ljWL.js +0 -267
- package/dist/mcp-server-streamable-Bv5fFO_D.js +0 -7882
- package/dist/version-DrEUqsN7.js +0 -11568
- package/dist/version-Jbxn3hLf.cjs +0 -1
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { Window } from "happy-dom";
|
|
2
|
-
const window = new Window();
|
|
3
|
-
Object.assign(global, {
|
|
4
|
-
document: window.document,
|
|
5
|
-
window,
|
|
6
|
-
self: window
|
|
7
|
-
});
|
|
8
|
-
import { J as JSONRPCMessageSchema, g as getPackageVersion, S as Server, L as ListToolsRequestSchema, M as MCP_TOOL_SCHEMAS, C as CallToolRequestSchema, p as parseHtmlToMarkdownArgs, c as createSuccessResult, a as createErrorResult, b as parseSaveContentArgs, s as saveContentToFile, d as parseUrlToMarkdownFileArgs } from "./version-DrEUqsN7.js";
|
|
9
|
-
import process from "node:process";
|
|
10
|
-
import { h as htmlToMarkdown } from "./core-txi0EJ9v.js";
|
|
11
|
-
class ReadBuffer {
|
|
12
|
-
append(chunk) {
|
|
13
|
-
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
14
|
-
}
|
|
15
|
-
readMessage() {
|
|
16
|
-
if (!this._buffer) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
const index = this._buffer.indexOf("\n");
|
|
20
|
-
if (index === -1) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
24
|
-
this._buffer = this._buffer.subarray(index + 1);
|
|
25
|
-
return deserializeMessage(line);
|
|
26
|
-
}
|
|
27
|
-
clear() {
|
|
28
|
-
this._buffer = void 0;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function deserializeMessage(line) {
|
|
32
|
-
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
33
|
-
}
|
|
34
|
-
function serializeMessage(message) {
|
|
35
|
-
return JSON.stringify(message) + "\n";
|
|
36
|
-
}
|
|
37
|
-
class StdioServerTransport {
|
|
38
|
-
constructor(_stdin = process.stdin, _stdout = process.stdout) {
|
|
39
|
-
this._stdin = _stdin;
|
|
40
|
-
this._stdout = _stdout;
|
|
41
|
-
this._readBuffer = new ReadBuffer();
|
|
42
|
-
this._started = false;
|
|
43
|
-
this._ondata = (chunk) => {
|
|
44
|
-
this._readBuffer.append(chunk);
|
|
45
|
-
this.processReadBuffer();
|
|
46
|
-
};
|
|
47
|
-
this._onerror = (error) => {
|
|
48
|
-
var _a;
|
|
49
|
-
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Starts listening for messages on stdin.
|
|
54
|
-
*/
|
|
55
|
-
async start() {
|
|
56
|
-
if (this._started) {
|
|
57
|
-
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
|
|
58
|
-
}
|
|
59
|
-
this._started = true;
|
|
60
|
-
this._stdin.on("data", this._ondata);
|
|
61
|
-
this._stdin.on("error", this._onerror);
|
|
62
|
-
}
|
|
63
|
-
processReadBuffer() {
|
|
64
|
-
var _a, _b;
|
|
65
|
-
while (true) {
|
|
66
|
-
try {
|
|
67
|
-
const message = this._readBuffer.readMessage();
|
|
68
|
-
if (message === null) {
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async close() {
|
|
78
|
-
var _a;
|
|
79
|
-
this._stdin.off("data", this._ondata);
|
|
80
|
-
this._stdin.off("error", this._onerror);
|
|
81
|
-
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
82
|
-
if (remainingDataListeners === 0) {
|
|
83
|
-
this._stdin.pause();
|
|
84
|
-
}
|
|
85
|
-
this._readBuffer.clear();
|
|
86
|
-
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
87
|
-
}
|
|
88
|
-
send(message) {
|
|
89
|
-
return new Promise((resolve) => {
|
|
90
|
-
const json = serializeMessage(message);
|
|
91
|
-
if (this._stdout.write(json)) {
|
|
92
|
-
resolve();
|
|
93
|
-
} else {
|
|
94
|
-
this._stdout.once("drain", resolve);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
class HtmlToMarkdownMcpServer {
|
|
100
|
-
constructor() {
|
|
101
|
-
this.version = getPackageVersion();
|
|
102
|
-
this.server = new Server(
|
|
103
|
-
{
|
|
104
|
-
name: "@aiquants/html-to-markdown",
|
|
105
|
-
version: this.version,
|
|
106
|
-
description: "Convert web pages and HTML to Markdown with JavaScript dynamic content support and table structure preservation. Includes separate file saving tool."
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
capabilities: {
|
|
110
|
-
tools: {}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
);
|
|
114
|
-
this.setupToolHandlers();
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Setup tool handlers for the MCP server.
|
|
118
|
-
* MCP サーバーのツールハンドラーを設定
|
|
119
|
-
*/
|
|
120
|
-
setupToolHandlers() {
|
|
121
|
-
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
122
|
-
return {
|
|
123
|
-
tools: [
|
|
124
|
-
{
|
|
125
|
-
name: "html_to_markdown",
|
|
126
|
-
description: "Convert web pages or HTML strings to Markdown format. Handles JavaScript-rendered dynamic content and preserves table structures.",
|
|
127
|
-
inputSchema: MCP_TOOL_SCHEMAS.htmlToMarkdown
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
name: "save_content_to_file",
|
|
131
|
-
description: "Save text content to a file with specified path or directory. Supports automatic filename generation and format detection.",
|
|
132
|
-
inputSchema: MCP_TOOL_SCHEMAS.saveContentToFile
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
name: "url_to_markdown_file",
|
|
136
|
-
description: "Convert web pages or HTML strings directly to Markdown files. Combines HTML-to-Markdown conversion and file saving in one step. Handles JavaScript-rendered dynamic content.",
|
|
137
|
-
inputSchema: MCP_TOOL_SCHEMAS.urlToMarkdownFile
|
|
138
|
-
}
|
|
139
|
-
]
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
143
|
-
switch (request.params.name) {
|
|
144
|
-
case "html_to_markdown": {
|
|
145
|
-
return await this.handleHtmlToMarkdown(request.params.arguments);
|
|
146
|
-
}
|
|
147
|
-
case "save_content_to_file": {
|
|
148
|
-
return await this.handleSaveContentToFile(request.params.arguments);
|
|
149
|
-
}
|
|
150
|
-
case "url_to_markdown_file": {
|
|
151
|
-
return await this.handleUrlToMarkdownFile(request.params.arguments);
|
|
152
|
-
}
|
|
153
|
-
default:
|
|
154
|
-
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Handle HTML to Markdown conversion tool call.
|
|
160
|
-
* HTML から Markdown への変換ツール呼び出しを処理
|
|
161
|
-
*/
|
|
162
|
-
async handleHtmlToMarkdown(args) {
|
|
163
|
-
try {
|
|
164
|
-
const validatedArgs = parseHtmlToMarkdownArgs(args);
|
|
165
|
-
const { url, html_content, locale = "en-US" } = validatedArgs;
|
|
166
|
-
if (url) {
|
|
167
|
-
try {
|
|
168
|
-
new URL(url);
|
|
169
|
-
} catch {
|
|
170
|
-
throw new Error(`Invalid URL: ${url}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
const result = await htmlToMarkdown(url || "direct-html-input", {
|
|
174
|
-
locale,
|
|
175
|
-
htmlContent: html_content
|
|
176
|
-
});
|
|
177
|
-
const responseText = result.markdown;
|
|
178
|
-
return createSuccessResult(responseText);
|
|
179
|
-
} catch (error) {
|
|
180
|
-
return createErrorResult(error);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Handle save content to file tool call.
|
|
185
|
-
* ファイル保存ツール呼び出しを処理
|
|
186
|
-
*/
|
|
187
|
-
async handleSaveContentToFile(args) {
|
|
188
|
-
try {
|
|
189
|
-
const validatedArgs = parseSaveContentArgs(args);
|
|
190
|
-
const { content, save_path, save_directory, filename } = validatedArgs;
|
|
191
|
-
const savedPath = await saveContentToFile(content, save_path, save_directory, filename);
|
|
192
|
-
const responseText = `File saved successfully to: ${savedPath}`;
|
|
193
|
-
return createSuccessResult(responseText);
|
|
194
|
-
} catch (error) {
|
|
195
|
-
return createErrorResult(error);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Handle URL to Markdown file conversion tool call.
|
|
200
|
-
* URL から Markdown ファイルへの変換ツール呼び出しを処理
|
|
201
|
-
*/
|
|
202
|
-
async handleUrlToMarkdownFile(args) {
|
|
203
|
-
try {
|
|
204
|
-
const validatedArgs = parseUrlToMarkdownFileArgs(args);
|
|
205
|
-
const { url, html_content, locale = "en-US", save_path, save_directory, filename } = validatedArgs;
|
|
206
|
-
if (url) {
|
|
207
|
-
try {
|
|
208
|
-
new URL(url);
|
|
209
|
-
} catch {
|
|
210
|
-
throw new Error(`Invalid URL: ${url}`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const result = await htmlToMarkdown(url || "direct-html-input", {
|
|
214
|
-
locale,
|
|
215
|
-
htmlContent: html_content
|
|
216
|
-
});
|
|
217
|
-
const markdownContent = result.markdown;
|
|
218
|
-
let finalFilename = filename;
|
|
219
|
-
if (!finalFilename && url) {
|
|
220
|
-
finalFilename = this.generateFilenameFromUrl(url);
|
|
221
|
-
}
|
|
222
|
-
const savedPath = await saveContentToFile(markdownContent, save_path, save_directory, finalFilename);
|
|
223
|
-
const responseText = `URL successfully converted to Markdown and saved to: ${savedPath}`;
|
|
224
|
-
return createSuccessResult(responseText);
|
|
225
|
-
} catch (error) {
|
|
226
|
-
return createErrorResult(error);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Generate filename from URL.
|
|
231
|
-
* URL からファイル名を生成
|
|
232
|
-
*/
|
|
233
|
-
generateFilenameFromUrl(url) {
|
|
234
|
-
try {
|
|
235
|
-
const urlObj = new URL(url);
|
|
236
|
-
let filename = urlObj.pathname.split("/").pop() || "page";
|
|
237
|
-
filename = filename.replace(/\.[^.]*$/, "");
|
|
238
|
-
filename = filename.replace(/[<>:"/\\|?*]/g, "_");
|
|
239
|
-
if (!filename || filename.match(/^\.+$/)) {
|
|
240
|
-
filename = "page";
|
|
241
|
-
}
|
|
242
|
-
return filename;
|
|
243
|
-
} catch {
|
|
244
|
-
return "page";
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Start the MCP server.
|
|
249
|
-
* MCP サーバーを開始
|
|
250
|
-
*/
|
|
251
|
-
async start() {
|
|
252
|
-
const transport = new StdioServerTransport();
|
|
253
|
-
await this.server.connect(transport);
|
|
254
|
-
console.info("HTML to Markdown MCP server started");
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
const createMcpServer = () => {
|
|
258
|
-
return new HtmlToMarkdownMcpServer();
|
|
259
|
-
};
|
|
260
|
-
const runMcpServer = async () => {
|
|
261
|
-
const server = createMcpServer();
|
|
262
|
-
await server.start();
|
|
263
|
-
};
|
|
264
|
-
export {
|
|
265
|
-
createMcpServer as c,
|
|
266
|
-
runMcpServer as r
|
|
267
|
-
};
|