@xjtlumedia/markdown-mcp-server 1.0.4 → 2.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/README.md +1 -0
- package/dist/document-analysis.js +223 -0
- package/dist/email-html.js +94 -0
- package/dist/html-import.js +158 -0
- package/dist/index.js +1067 -98
- package/dist/markdown-repair.js +263 -0
- package/dist/platform-converters.js +419 -0
- package/icon.svg +15 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
import { z } from "zod";
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
5
|
import { unified } from 'unified';
|
|
7
6
|
import remarkParse from 'remark-parse';
|
|
8
7
|
import remarkGfm from 'remark-gfm';
|
|
@@ -11,17 +10,60 @@ import remarkStringify from 'remark-stringify';
|
|
|
11
10
|
import remarkRehype from 'remark-rehype';
|
|
12
11
|
import rehypeKatex from 'rehype-katex';
|
|
13
12
|
import rehypeStringify from 'rehype-stringify';
|
|
14
|
-
import puppeteer from 'puppeteer';
|
|
13
|
+
import puppeteer from 'puppeteer-core';
|
|
15
14
|
import * as fs from 'fs/promises';
|
|
16
15
|
import * as path from 'path';
|
|
16
|
+
import * as os from 'os';
|
|
17
17
|
import { parseMarkdownToRTF, parseMarkdownToDocx, parseMarkdownToLaTeX, generateCSV, generateJSON, generateXML, generateXLSXIndex, cleanMarkdownText } from "./core-exports.js";
|
|
18
18
|
import { Packer } from "docx";
|
|
19
|
+
import { markdownToSlack, markdownToDiscord, markdownToJira, markdownToConfluence, markdownToAsciiDoc, markdownToRST, markdownToMediaWiki, markdownToBBCode, markdownToTextile, markdownToOrgMode, } from "./platform-converters.js";
|
|
20
|
+
import { repairMarkdown, lintMarkdown, } from "./markdown-repair.js";
|
|
21
|
+
import { extractCodeBlocks, extractLinks, generateTOC, analyzeDocument, extractStructure, } from "./document-analysis.js";
|
|
22
|
+
import { htmlToMarkdown } from "./html-import.js";
|
|
23
|
+
import { markdownToEmailHtml } from "./email-html.js";
|
|
24
|
+
// Find Chrome/Chromium executable on the system
|
|
25
|
+
async function findChrome() {
|
|
26
|
+
// Docker / CI: honour explicit env var
|
|
27
|
+
const envPath = process.env['PUPPETEER_EXECUTABLE_PATH'];
|
|
28
|
+
if (envPath) {
|
|
29
|
+
try {
|
|
30
|
+
await fs.access(envPath);
|
|
31
|
+
return envPath;
|
|
32
|
+
}
|
|
33
|
+
catch { /* fall through */ }
|
|
34
|
+
}
|
|
35
|
+
const platform = os.platform();
|
|
36
|
+
const candidates = [];
|
|
37
|
+
if (platform === 'win32') {
|
|
38
|
+
const programFiles = process.env['PROGRAMFILES'] || 'C:\\Program Files';
|
|
39
|
+
const programFilesX86 = process.env['PROGRAMFILES(X86)'] || 'C:\\Program Files (x86)';
|
|
40
|
+
const localAppData = process.env['LOCALAPPDATA'] || '';
|
|
41
|
+
candidates.push(path.join(programFiles, 'Google', 'Chrome', 'Application', 'chrome.exe'), path.join(programFilesX86, 'Google', 'Chrome', 'Application', 'chrome.exe'), path.join(localAppData, 'Google', 'Chrome', 'Application', 'chrome.exe'), path.join(programFiles, 'Microsoft', 'Edge', 'Application', 'msedge.exe'), path.join(programFilesX86, 'Microsoft', 'Edge', 'Application', 'msedge.exe'));
|
|
42
|
+
}
|
|
43
|
+
else if (platform === 'darwin') {
|
|
44
|
+
candidates.push('/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge', '/Applications/Chromium.app/Contents/MacOS/Chromium');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
candidates.push('/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser', '/snap/bin/chromium');
|
|
48
|
+
}
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
try {
|
|
51
|
+
await fs.access(candidate);
|
|
52
|
+
return candidate;
|
|
53
|
+
}
|
|
54
|
+
catch { /* not found, try next */ }
|
|
55
|
+
}
|
|
56
|
+
throw new Error('No Chrome/Chromium/Edge browser found. PDF and PNG export require a Chromium-based browser. ' +
|
|
57
|
+
'Please install Google Chrome, Microsoft Edge, or Chromium.');
|
|
58
|
+
}
|
|
19
59
|
const server = new Server({
|
|
20
60
|
name: "markdown-formatter-mcp",
|
|
21
61
|
version: "1.0.0",
|
|
22
62
|
}, {
|
|
23
63
|
capabilities: {
|
|
24
64
|
tools: {},
|
|
65
|
+
prompts: {},
|
|
66
|
+
resources: {},
|
|
25
67
|
},
|
|
26
68
|
});
|
|
27
69
|
// Binary format types that need special handling
|
|
@@ -74,134 +116,994 @@ async function handleOutput(content, outputPath, options) {
|
|
|
74
116
|
return { content: [{ type: "text", text: content }] };
|
|
75
117
|
}
|
|
76
118
|
}
|
|
119
|
+
// --- Shared parameter description constants ---
|
|
120
|
+
const PARAM_MARKDOWN = "The raw Markdown source text to convert. Supports GitHub-Flavored Markdown (tables, task lists, strikethrough) and KaTeX math expressions. Pass the full document content as a string, not a file path.";
|
|
121
|
+
const PARAM_OUTPUT_PATH_TEXT = "Optional. Absolute or relative file path (e.g. './output.txt') where the result will be saved. Parent directories are created automatically. If omitted, the converted text content is returned directly in the response as a string. If provided, the file is written to disk and a JSON summary with { success, file_path, file_size_bytes, format } is returned instead.";
|
|
122
|
+
const PARAM_OUTPUT_PATH_BINARY = (fmt) => `Optional. Absolute or relative file path (e.g. './output.${fmt}') where the binary file will be saved. Parent directories are created automatically. If provided, the file is written to disk and a JSON summary with { success, file_path, file_size_bytes, format } is returned. If omitted, a JSON object with { format, file_size_bytes, hint, base64_preview } is returned — the hint will instruct you to call the tool again with output_path to save the file. Binary formats (${fmt.toUpperCase()}) should almost always specify output_path.`;
|
|
123
|
+
const PARAM_TITLE = "Optional. A document title string. Used as the root element name or document metadata title in the output. Defaults to 'document' if omitted.";
|
|
124
|
+
// Text-output tool annotations: no file write when output_path is omitted → read-only; with output_path → side effect
|
|
125
|
+
const TEXT_TOOL_ANNOTATIONS = {
|
|
126
|
+
title: undefined,
|
|
127
|
+
readOnlyHint: false, // can write files when output_path is provided
|
|
128
|
+
destructiveHint: false, // overwrites files at output_path without warning
|
|
129
|
+
idempotentHint: true, // same input always produces the same output
|
|
130
|
+
openWorldHint: false, // does not interact with external services
|
|
131
|
+
};
|
|
132
|
+
// Binary-output tool annotations (PDF/PNG use Puppeteer which launches a browser)
|
|
133
|
+
const BROWSER_TOOL_ANNOTATIONS = {
|
|
134
|
+
title: undefined,
|
|
135
|
+
readOnlyHint: false,
|
|
136
|
+
destructiveHint: false,
|
|
137
|
+
idempotentHint: true,
|
|
138
|
+
openWorldHint: false, // Puppeteer runs a local headless browser, no network needed for rendering
|
|
139
|
+
};
|
|
77
140
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
78
141
|
return {
|
|
79
142
|
tools: [
|
|
80
143
|
{
|
|
81
144
|
name: "harmonize_markdown",
|
|
82
|
-
description: "Standardize
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
145
|
+
description: "Standardize and normalize Markdown syntax without changing the document's meaning. " +
|
|
146
|
+
"Re-formats headers (ATX-style), normalizes list markers to '-', enforces fenced code blocks with backticks, " +
|
|
147
|
+
"and applies consistent indentation. " +
|
|
148
|
+
"Side effects: when output_path is provided, writes the harmonized Markdown to disk (creates parent directories as needed, overwrites existing files). " +
|
|
149
|
+
"When output_path is omitted, returns the harmonized text as a string with no file I/O. " +
|
|
150
|
+
"Returns: harmonized Markdown string (if no output_path), or JSON with { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
151
|
+
"Use this tool when you need to clean up inconsistent Markdown formatting before further processing. " +
|
|
152
|
+
"Prefer convert_to_md with harmonize=true if you also need to save the result, as it combines both steps. " +
|
|
153
|
+
"Not suitable for converting Markdown to other formats — use the convert_to_* tools instead.",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
158
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
159
|
+
},
|
|
160
|
+
required: ["markdown"],
|
|
161
|
+
},
|
|
162
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Harmonize Markdown" },
|
|
87
163
|
},
|
|
88
164
|
{
|
|
89
165
|
name: "convert_to_txt",
|
|
90
|
-
description: "Convert Markdown to
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
output_path
|
|
94
|
-
|
|
166
|
+
description: "Convert Markdown to plain text by stripping all formatting — removes headers, bold/italic markers, links, images, code fences, and HTML tags. " +
|
|
167
|
+
"The result is a human-readable plain-text string with no markup. This is a destructive conversion: formatting information is permanently lost. " +
|
|
168
|
+
"Side effects: when output_path is provided, writes the plain text to disk (creates parent directories, overwrites existing files). " +
|
|
169
|
+
"When output_path is omitted, returns the plain text string directly. " +
|
|
170
|
+
"Returns: plain text string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
171
|
+
"Use this instead of convert_to_md when you need formatting-free content (e.g. for indexing, search, or clipboard). " +
|
|
172
|
+
"Use convert_to_html or convert_to_pdf if you need to preserve the document's visual structure.",
|
|
173
|
+
inputSchema: {
|
|
174
|
+
type: "object",
|
|
175
|
+
properties: {
|
|
176
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
177
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
178
|
+
},
|
|
179
|
+
required: ["markdown"],
|
|
180
|
+
},
|
|
181
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Plain Text" },
|
|
95
182
|
},
|
|
96
183
|
{
|
|
97
184
|
name: "convert_to_rtf",
|
|
98
|
-
description: "Convert Markdown to
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
output_path
|
|
102
|
-
|
|
185
|
+
description: "Convert Markdown to Rich Text Format (RTF). Produces an RTF document string preserving basic formatting: " +
|
|
186
|
+
"bold, italic, headers (as styled paragraphs), lists, and code blocks. " +
|
|
187
|
+
"Side effects: when output_path is provided, writes the RTF file to disk (creates parent directories, overwrites existing files). " +
|
|
188
|
+
"When output_path is omitted, returns the raw RTF markup as a string. " +
|
|
189
|
+
"Returns: RTF markup string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
190
|
+
"Use this when the target application requires RTF (e.g. legacy word processors, email clients). " +
|
|
191
|
+
"Prefer convert_to_docx for modern Word documents, or convert_to_html for web display.",
|
|
192
|
+
inputSchema: {
|
|
193
|
+
type: "object",
|
|
194
|
+
properties: {
|
|
195
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
196
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
197
|
+
},
|
|
198
|
+
required: ["markdown"],
|
|
199
|
+
},
|
|
200
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to RTF" },
|
|
103
201
|
},
|
|
104
202
|
{
|
|
105
203
|
name: "convert_to_latex",
|
|
106
|
-
description: "Convert Markdown to LaTeX"
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
204
|
+
description: "Convert Markdown to LaTeX source code. Produces a LaTeX document fragment with \\section, \\textbf, \\textit, " +
|
|
205
|
+
"\\begin{itemize}/\\begin{enumerate} list environments, verbatim code blocks, and table environments. " +
|
|
206
|
+
"KaTeX math expressions in the Markdown are passed through as native LaTeX math. " +
|
|
207
|
+
"Side effects: when output_path is provided, writes the .tex file to disk (creates parent directories, overwrites existing files). " +
|
|
208
|
+
"When output_path is omitted, returns the LaTeX source as a string. " +
|
|
209
|
+
"Returns: LaTeX source string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
210
|
+
"Use this when you need to embed content in a LaTeX workflow or compile to PDF via pdflatex/xelatex externally. " +
|
|
211
|
+
"For direct PDF output without a LaTeX toolchain, use convert_to_pdf instead.",
|
|
212
|
+
inputSchema: {
|
|
213
|
+
type: "object",
|
|
214
|
+
properties: {
|
|
215
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
216
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
217
|
+
},
|
|
218
|
+
required: ["markdown"],
|
|
219
|
+
},
|
|
220
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to LaTeX" },
|
|
111
221
|
},
|
|
112
222
|
{
|
|
113
223
|
name: "convert_to_docx",
|
|
114
|
-
description: "Convert Markdown to DOCX
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
224
|
+
description: "Convert Markdown to a Microsoft Word DOCX file. Produces a binary .docx document with styled headings, " +
|
|
225
|
+
"bold/italic text, numbered and bulleted lists, and code formatting. " +
|
|
226
|
+
"This is a binary format — output_path should almost always be provided. " +
|
|
227
|
+
"Side effects: when output_path is provided, writes the DOCX binary to disk (creates parent directories, overwrites existing files). " +
|
|
228
|
+
"When output_path is omitted, returns a JSON object with { format: 'docx', file_size_bytes, hint, base64_preview } — " +
|
|
229
|
+
"the hint will tell you to re-call with output_path to save the file. " +
|
|
230
|
+
"Returns: JSON write-confirmation (if output_path set), or JSON binary-guidance object (if omitted). " +
|
|
231
|
+
"Use this for Word-compatible documents. " +
|
|
232
|
+
"Prefer convert_to_rtf for legacy word processors, convert_to_pdf for read-only distribution, or convert_to_html for web.",
|
|
233
|
+
inputSchema: {
|
|
234
|
+
type: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
237
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_BINARY("docx") },
|
|
238
|
+
},
|
|
239
|
+
required: ["markdown"],
|
|
240
|
+
},
|
|
241
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to DOCX" },
|
|
119
242
|
},
|
|
120
243
|
{
|
|
121
244
|
name: "convert_to_pdf",
|
|
122
|
-
description: "Convert Markdown to PDF (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
output_path
|
|
126
|
-
|
|
245
|
+
description: "Convert Markdown to a PDF document. Renders the Markdown as styled HTML (GFM tables, KaTeX math) and then " +
|
|
246
|
+
"prints it to PDF via a headless Chromium browser (Puppeteer). Requires a locally installed Chrome, Edge, or Chromium — " +
|
|
247
|
+
"set PUPPETEER_EXECUTABLE_PATH env var to override auto-detection. " +
|
|
248
|
+
"This is a binary format — output_path should almost always be provided. " +
|
|
249
|
+
"Side effects: launches a transient headless browser process for rendering (no network requests are made for the conversion itself, " +
|
|
250
|
+
"though the HTML references a CDN KaTeX stylesheet which may be fetched). " +
|
|
251
|
+
"When output_path is provided, writes the PDF to disk (creates parent directories, overwrites existing files). " +
|
|
252
|
+
"When output_path is omitted, returns JSON { format: 'pdf', file_size_bytes, hint, base64_preview }. " +
|
|
253
|
+
"Returns: JSON write-confirmation (if output_path set), or JSON binary-guidance object (if omitted). " +
|
|
254
|
+
"Use this for high-fidelity, print-ready document output. " +
|
|
255
|
+
"Prefer convert_to_html for web-viewable output, convert_to_docx for editable documents, or convert_to_latex for LaTeX toolchains.",
|
|
256
|
+
inputSchema: {
|
|
257
|
+
type: "object",
|
|
258
|
+
properties: {
|
|
259
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
260
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_BINARY("pdf") },
|
|
261
|
+
},
|
|
262
|
+
required: ["markdown"],
|
|
263
|
+
},
|
|
264
|
+
annotations: { ...BROWSER_TOOL_ANNOTATIONS, title: "Convert to PDF" },
|
|
127
265
|
},
|
|
128
266
|
{
|
|
129
267
|
name: "convert_to_image",
|
|
130
|
-
description: "Convert Markdown to PNG
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
output_path
|
|
134
|
-
|
|
268
|
+
description: "Convert Markdown to a PNG image. Renders the Markdown as styled HTML (GFM tables, KaTeX math) and takes a " +
|
|
269
|
+
"full-page screenshot via a headless Chromium browser (Puppeteer). Requires a locally installed Chrome, Edge, or Chromium — " +
|
|
270
|
+
"set PUPPETEER_EXECUTABLE_PATH env var to override auto-detection. " +
|
|
271
|
+
"This is a binary format — output_path should almost always be provided. " +
|
|
272
|
+
"Side effects: launches a transient headless browser process (no persistent state; may fetch KaTeX CDN stylesheet). " +
|
|
273
|
+
"When output_path is provided, writes the PNG to disk (creates parent directories, overwrites existing files). " +
|
|
274
|
+
"When output_path is omitted, returns JSON { format: 'png', file_size_bytes, hint, base64_preview }. " +
|
|
275
|
+
"Returns: JSON write-confirmation (if output_path set), or JSON binary-guidance object (if omitted). " +
|
|
276
|
+
"Use this when you need a visual snapshot of the rendered Markdown (e.g. for embedding in chat, previews, social cards). " +
|
|
277
|
+
"Prefer convert_to_pdf for paginated print output, or convert_to_html for interactive web content.",
|
|
278
|
+
inputSchema: {
|
|
279
|
+
type: "object",
|
|
280
|
+
properties: {
|
|
281
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
282
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_BINARY("png") },
|
|
283
|
+
},
|
|
284
|
+
required: ["markdown"],
|
|
285
|
+
},
|
|
286
|
+
annotations: { ...BROWSER_TOOL_ANNOTATIONS, title: "Convert to PNG Image" },
|
|
135
287
|
},
|
|
136
288
|
{
|
|
137
289
|
name: "convert_to_csv",
|
|
138
|
-
description: "Extract tables from Markdown to CSV"
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
290
|
+
description: "Extract tables from Markdown and convert them to CSV format. Parses GFM pipe-tables from the input and outputs " +
|
|
291
|
+
"comma-separated values. If the Markdown contains multiple tables, they are concatenated with a blank line separator. " +
|
|
292
|
+
"Non-table content is ignored. If the Markdown contains no tables, returns an empty string. " +
|
|
293
|
+
"Side effects: when output_path is provided, writes the CSV to disk (creates parent directories, overwrites existing files). " +
|
|
294
|
+
"When output_path is omitted, returns the CSV text directly as a string. " +
|
|
295
|
+
"Returns: CSV text string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
296
|
+
"Use this for lightweight tabular export or when downstream tools expect CSV. " +
|
|
297
|
+
"Prefer convert_to_xlsx for Excel-compatible spreadsheets with multiple sheets, or convert_to_json for structured data.",
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
302
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
303
|
+
},
|
|
304
|
+
required: ["markdown"],
|
|
305
|
+
},
|
|
306
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to CSV" },
|
|
143
307
|
},
|
|
144
308
|
{
|
|
145
309
|
name: "convert_to_json",
|
|
146
|
-
description: "Convert Markdown to JSON
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
output_path
|
|
151
|
-
|
|
310
|
+
description: "Convert Markdown to a structured JSON representation. Parses the document into a JSON object with the document title " +
|
|
311
|
+
"as the root key, containing arrays of section objects with headings, paragraphs, lists, code blocks, and tables. " +
|
|
312
|
+
"Useful for programmatic analysis or feeding structured content into other systems. " +
|
|
313
|
+
"Side effects: when output_path is provided, writes the JSON to disk (creates parent directories, overwrites existing files). " +
|
|
314
|
+
"When output_path is omitted, returns the JSON string directly. " +
|
|
315
|
+
"Returns: JSON string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
316
|
+
"Use this when you need a machine-readable AST-like representation of the Markdown content. " +
|
|
317
|
+
"Prefer convert_to_xml for XML-based interchange, or convert_to_csv/convert_to_xlsx for tabular data extraction.",
|
|
318
|
+
inputSchema: {
|
|
319
|
+
type: "object",
|
|
320
|
+
properties: {
|
|
321
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
322
|
+
title: { type: "string", description: PARAM_TITLE },
|
|
323
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
324
|
+
},
|
|
325
|
+
required: ["markdown"],
|
|
326
|
+
},
|
|
327
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to JSON" },
|
|
152
328
|
},
|
|
153
329
|
{
|
|
154
330
|
name: "convert_to_xml",
|
|
155
|
-
description: "Convert Markdown to XML"
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
output_path
|
|
160
|
-
|
|
331
|
+
description: "Convert Markdown to an XML document. Parses the Markdown into a structured XML tree with a root element named after " +
|
|
332
|
+
"the title parameter, containing <section>, <heading>, <paragraph>, <list>, <code>, and <table> elements. " +
|
|
333
|
+
"Produces well-formed XML with an <?xml?> declaration. " +
|
|
334
|
+
"Side effects: when output_path is provided, writes the XML to disk (creates parent directories, overwrites existing files). " +
|
|
335
|
+
"When output_path is omitted, returns the XML string directly. " +
|
|
336
|
+
"Returns: XML string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
337
|
+
"Use this for XML-based data interchange or when downstream systems require XML input. " +
|
|
338
|
+
"Prefer convert_to_json for JSON APIs, convert_to_html for XHTML/web content, or convert_to_csv for flat tabular data.",
|
|
339
|
+
inputSchema: {
|
|
340
|
+
type: "object",
|
|
341
|
+
properties: {
|
|
342
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
343
|
+
title: { type: "string", description: "Optional. The root XML element name and document title. Must be a valid XML element name (no spaces or special characters). Defaults to 'document' if omitted." },
|
|
344
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
345
|
+
},
|
|
346
|
+
required: ["markdown"],
|
|
347
|
+
},
|
|
348
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to XML" },
|
|
161
349
|
},
|
|
162
350
|
{
|
|
163
351
|
name: "convert_to_xlsx",
|
|
164
|
-
description: "Convert Markdown tables to Excel
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
output_path
|
|
168
|
-
|
|
352
|
+
description: "Convert Markdown tables to a Microsoft Excel XLSX spreadsheet. Parses GFM pipe-tables from the input " +
|
|
353
|
+
"and creates an Excel workbook. Each table becomes a sheet in the workbook. Non-table content is ignored. " +
|
|
354
|
+
"If the Markdown contains no tables, produces an empty workbook. " +
|
|
355
|
+
"This is a binary format — output_path should almost always be provided. " +
|
|
356
|
+
"Side effects: when output_path is provided, writes the XLSX binary to disk (creates parent directories, overwrites existing files). " +
|
|
357
|
+
"When output_path is omitted, returns JSON { format: 'xlsx', file_size_bytes, hint, base64_preview }. " +
|
|
358
|
+
"Returns: JSON write-confirmation (if output_path set), or JSON binary-guidance object (if omitted). " +
|
|
359
|
+
"Use this when you need a full Excel file with formatting. " +
|
|
360
|
+
"Prefer convert_to_csv for lightweight plain-text tabular export, or convert_to_json for structured programmatic access.",
|
|
361
|
+
inputSchema: {
|
|
362
|
+
type: "object",
|
|
363
|
+
properties: {
|
|
364
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
365
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_BINARY("xlsx") },
|
|
366
|
+
},
|
|
367
|
+
required: ["markdown"],
|
|
368
|
+
},
|
|
369
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to XLSX" },
|
|
169
370
|
},
|
|
170
371
|
{
|
|
171
372
|
name: "convert_to_html",
|
|
172
|
-
description: "Convert Markdown to HTML"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
373
|
+
description: "Convert Markdown to a complete, styled HTML document. Renders GFM (tables, task lists, strikethrough) and " +
|
|
374
|
+
"KaTeX math into semantic HTML with an embedded stylesheet for clean presentation. " +
|
|
375
|
+
"The output is a full <!DOCTYPE html> document with <head> (charset, KaTeX CSS CDN link, inline styles) and <body>. " +
|
|
376
|
+
"Side effects: when output_path is provided, writes the HTML file to disk (creates parent directories, overwrites existing files). " +
|
|
377
|
+
"When output_path is omitted, returns the full HTML string directly. " +
|
|
378
|
+
"Returns: HTML document string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
379
|
+
"Use this when you need a file saved to disk or when you need the full document. " +
|
|
380
|
+
"Prefer generate_html if you only need the HTML string returned directly (no file I/O) and want inline styles without a CDN link. " +
|
|
381
|
+
"Prefer convert_to_pdf for print-ready output, or convert_to_image for a visual snapshot.",
|
|
382
|
+
inputSchema: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
386
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
387
|
+
},
|
|
388
|
+
required: ["markdown"],
|
|
389
|
+
},
|
|
390
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to HTML" },
|
|
177
391
|
},
|
|
178
392
|
{
|
|
179
393
|
name: "convert_to_md",
|
|
180
|
-
description: "Export
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
output_path
|
|
185
|
-
|
|
394
|
+
description: "Export Markdown content, optionally harmonizing its formatting first. When harmonize=false (default), " +
|
|
395
|
+
"returns the input Markdown unchanged. When harmonize=true, applies the same normalization as harmonize_markdown " +
|
|
396
|
+
"(ATX-style headers, '-' list markers, fenced code blocks, consistent indentation) before returning. " +
|
|
397
|
+
"Side effects: when output_path is provided, writes the Markdown to disk (creates parent directories, overwrites existing files). " +
|
|
398
|
+
"When output_path is omitted, returns the Markdown string directly. " +
|
|
399
|
+
"Returns: Markdown string (if no output_path), or JSON { success, file_path, file_size_bytes, format } (if output_path set). " +
|
|
400
|
+
"Use this when you want to save Markdown to a file (with or without cleanup). " +
|
|
401
|
+
"Prefer harmonize_markdown if you only want to normalize formatting without saving to disk. " +
|
|
402
|
+
"Use the convert_to_* family for other output formats.",
|
|
403
|
+
inputSchema: {
|
|
404
|
+
type: "object",
|
|
405
|
+
properties: {
|
|
406
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
407
|
+
harmonize: { type: "boolean", description: "Optional. When true, normalizes Markdown syntax (ATX headers, '-' list markers, fenced code blocks, consistent indentation) before returning or saving. When false or omitted, the Markdown is passed through unchanged. Defaults to false." },
|
|
408
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
409
|
+
},
|
|
410
|
+
required: ["markdown"],
|
|
411
|
+
},
|
|
412
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Export Markdown" },
|
|
186
413
|
},
|
|
187
414
|
{
|
|
188
415
|
name: "generate_html",
|
|
189
|
-
description: "Generate a complete HTML document from Markdown with
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
416
|
+
description: "Generate a complete, self-contained HTML document from Markdown with all styles inlined. " +
|
|
417
|
+
"Renders GFM (tables, task lists, strikethrough) and KaTeX math into a full HTML page with an embedded <style> block " +
|
|
418
|
+
"and a KaTeX CSS CDN link. Returns the HTML string directly — no file is written to disk. " +
|
|
419
|
+
"Side effects: none. This tool is read-only and performs no file I/O. " +
|
|
420
|
+
"Returns: a complete HTML document string (<!DOCTYPE html>…</html>) with inline styles, ready for rendering in a browser. " +
|
|
421
|
+
"The optional title parameter sets the <title> tag in the HTML <head> section. " +
|
|
422
|
+
"Use this when you need styled HTML output returned as a string (e.g., for embedding in responses or previewing). " +
|
|
423
|
+
"Prefer convert_to_html when you need to write the HTML to a file on disk. " +
|
|
424
|
+
"Prefer convert_to_pdf or convert_to_image for non-HTML visual output formats.",
|
|
425
|
+
inputSchema: {
|
|
426
|
+
type: "object",
|
|
427
|
+
properties: {
|
|
428
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
429
|
+
title: { type: "string", description: "Optional. Sets the <title> tag in the HTML document's <head> section. Displayed in browser tabs and bookmarks. Defaults to 'Document' if omitted." },
|
|
430
|
+
},
|
|
431
|
+
required: ["markdown"],
|
|
432
|
+
},
|
|
433
|
+
annotations: {
|
|
434
|
+
title: "Generate HTML Document",
|
|
435
|
+
readOnlyHint: true, // never writes to disk
|
|
436
|
+
destructiveHint: false,
|
|
437
|
+
idempotentHint: true,
|
|
438
|
+
openWorldHint: false,
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
// ── Platform-specific format tools ──
|
|
442
|
+
{
|
|
443
|
+
name: "convert_to_slack",
|
|
444
|
+
description: "Convert Markdown to Slack mrkdwn format. Transforms bold (**) to single asterisks, italic to underscores, " +
|
|
445
|
+
"links to Slack <url|text> syntax, and headers to bold text. " +
|
|
446
|
+
"Use this when pasting formatted content into Slack messages.",
|
|
447
|
+
inputSchema: {
|
|
448
|
+
type: "object",
|
|
449
|
+
properties: {
|
|
450
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
451
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
452
|
+
},
|
|
453
|
+
required: ["markdown"],
|
|
454
|
+
},
|
|
455
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Slack mrkdwn" },
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: "convert_to_discord",
|
|
459
|
+
description: "Convert Markdown to Discord-compatible format. Transforms headers to styled bold/underline text that renders " +
|
|
460
|
+
"correctly in Discord messages. Code blocks and basic formatting are preserved.",
|
|
461
|
+
inputSchema: {
|
|
462
|
+
type: "object",
|
|
463
|
+
properties: {
|
|
464
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
465
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
466
|
+
},
|
|
467
|
+
required: ["markdown"],
|
|
468
|
+
},
|
|
469
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Discord Markdown" },
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
name: "convert_to_jira",
|
|
473
|
+
description: "Convert Markdown to JIRA wiki markup. Transforms headers to h1./h2., bold to single asterisks, " +
|
|
474
|
+
"code blocks to {code} blocks, links to [text|url], and lists to JIRA * and # syntax.",
|
|
475
|
+
inputSchema: {
|
|
476
|
+
type: "object",
|
|
477
|
+
properties: {
|
|
478
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
479
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
480
|
+
},
|
|
481
|
+
required: ["markdown"],
|
|
482
|
+
},
|
|
483
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to JIRA Markup" },
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: "convert_to_confluence",
|
|
487
|
+
description: "Convert Markdown to Confluence wiki markup. Similar to JIRA but includes Confluence-specific {info}, {note} panels " +
|
|
488
|
+
"and {code:language=x} syntax.",
|
|
489
|
+
inputSchema: {
|
|
490
|
+
type: "object",
|
|
491
|
+
properties: {
|
|
492
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
493
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
494
|
+
},
|
|
495
|
+
required: ["markdown"],
|
|
496
|
+
},
|
|
497
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Confluence Markup" },
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
name: "convert_to_asciidoc",
|
|
501
|
+
description: "Convert Markdown to AsciiDoc format. Transforms headers to = syntax, code blocks to ---- delimited blocks, " +
|
|
502
|
+
"links to url[text] syntax, and images to image::url[alt] directives.",
|
|
503
|
+
inputSchema: {
|
|
504
|
+
type: "object",
|
|
505
|
+
properties: {
|
|
506
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
507
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
508
|
+
},
|
|
509
|
+
required: ["markdown"],
|
|
510
|
+
},
|
|
511
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to AsciiDoc" },
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: "convert_to_rst",
|
|
515
|
+
description: "Convert Markdown to reStructuredText (RST) format. Transforms headers to underlined text, " +
|
|
516
|
+
"code blocks to .. code-block:: directives, and links to RST reference syntax.",
|
|
517
|
+
inputSchema: {
|
|
518
|
+
type: "object",
|
|
519
|
+
properties: {
|
|
520
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
521
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
522
|
+
},
|
|
523
|
+
required: ["markdown"],
|
|
524
|
+
},
|
|
525
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to reStructuredText" },
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: "convert_to_mediawiki",
|
|
529
|
+
description: "Convert Markdown to MediaWiki markup. Transforms headers to == syntax, bold to triple quotes, " +
|
|
530
|
+
"code to <syntaxhighlight> tags, and tables to {| wikitable format.",
|
|
531
|
+
inputSchema: {
|
|
532
|
+
type: "object",
|
|
533
|
+
properties: {
|
|
534
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
535
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
536
|
+
},
|
|
537
|
+
required: ["markdown"],
|
|
538
|
+
},
|
|
539
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to MediaWiki" },
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: "convert_to_bbcode",
|
|
543
|
+
description: "Convert Markdown to BBCode format. Transforms formatting to [b], [i], [s], [code], [url], [img] tags. " +
|
|
544
|
+
"Used for forum posts on phpBB, vBulletin, and similar platforms.",
|
|
545
|
+
inputSchema: {
|
|
546
|
+
type: "object",
|
|
547
|
+
properties: {
|
|
548
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
549
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
550
|
+
},
|
|
551
|
+
required: ["markdown"],
|
|
552
|
+
},
|
|
553
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to BBCode" },
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
name: "convert_to_textile",
|
|
557
|
+
description: "Convert Markdown to Textile markup format. Used by Redmine, older versions of Basecamp, and some CMS platforms.",
|
|
558
|
+
inputSchema: {
|
|
559
|
+
type: "object",
|
|
560
|
+
properties: {
|
|
561
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
562
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
563
|
+
},
|
|
564
|
+
required: ["markdown"],
|
|
565
|
+
},
|
|
566
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Textile" },
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
name: "convert_to_orgmode",
|
|
570
|
+
description: "Convert Markdown to Emacs Org Mode format. Transforms headers to * syntax, bold to *text*, " +
|
|
571
|
+
"code blocks to #+BEGIN_SRC/#+END_SRC, and links to [[url][text]] syntax.",
|
|
572
|
+
inputSchema: {
|
|
573
|
+
type: "object",
|
|
574
|
+
properties: {
|
|
575
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
576
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
577
|
+
},
|
|
578
|
+
required: ["markdown"],
|
|
579
|
+
},
|
|
580
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Org Mode" },
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
name: "convert_to_email_html",
|
|
584
|
+
description: "Convert Markdown to email-optimized HTML with all styles inlined. Produces HTML compatible with " +
|
|
585
|
+
"Outlook, Gmail, Apple Mail, and other email clients. No external CSS dependencies. " +
|
|
586
|
+
"Wraps content in a responsive email table layout.",
|
|
587
|
+
inputSchema: {
|
|
588
|
+
type: "object",
|
|
589
|
+
properties: {
|
|
590
|
+
markdown: { type: "string", description: PARAM_MARKDOWN },
|
|
591
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
592
|
+
},
|
|
593
|
+
required: ["markdown"],
|
|
594
|
+
},
|
|
595
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Convert to Email HTML" },
|
|
596
|
+
},
|
|
597
|
+
// ── Import tools ──
|
|
598
|
+
{
|
|
599
|
+
name: "html_to_markdown",
|
|
600
|
+
description: "Convert HTML to Markdown. Performs round-trip import of HTML content back to Markdown format. " +
|
|
601
|
+
"Handles headings, tables, lists, code blocks, links, images, and inline formatting. " +
|
|
602
|
+
"Useful for importing web content or converting HTML emails to Markdown.",
|
|
603
|
+
inputSchema: {
|
|
604
|
+
type: "object",
|
|
605
|
+
properties: {
|
|
606
|
+
html: { type: "string", description: "The HTML content to convert to Markdown. Can be a full HTML document or a fragment." },
|
|
607
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
608
|
+
},
|
|
609
|
+
required: ["html"],
|
|
610
|
+
},
|
|
611
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Import HTML to Markdown" },
|
|
612
|
+
},
|
|
613
|
+
// ── Repair / Lint tools ──
|
|
614
|
+
{
|
|
615
|
+
name: "repair_markdown",
|
|
616
|
+
description: "Repair broken Markdown from LLM output or copy-paste. Fixes unclosed code fences, broken tables " +
|
|
617
|
+
"(mismatched columns, missing separators), stray emphasis markers, missing heading spaces, " +
|
|
618
|
+
"inconsistent list indentation, broken links, and excessive whitespace.",
|
|
619
|
+
inputSchema: {
|
|
620
|
+
type: "object",
|
|
621
|
+
properties: {
|
|
622
|
+
markdown: { type: "string", description: "The potentially broken Markdown text to repair." },
|
|
623
|
+
output_path: { type: "string", description: PARAM_OUTPUT_PATH_TEXT },
|
|
624
|
+
},
|
|
625
|
+
required: ["markdown"],
|
|
626
|
+
},
|
|
627
|
+
annotations: { ...TEXT_TOOL_ANNOTATIONS, title: "Repair Broken Markdown" },
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
name: "lint_markdown",
|
|
631
|
+
description: "Lint Markdown and report issues. Returns a JSON array of lint issues found in the document, " +
|
|
632
|
+
"each with line number, column, severity (error/warning/info), rule name, message, and fixable flag. " +
|
|
633
|
+
"Checks for: missing heading spaces, trailing whitespace, inconsistent list markers, hard tabs, " +
|
|
634
|
+
"multiple blank lines, bare URLs, unclosed emphasis, and unclosed code fences.",
|
|
635
|
+
inputSchema: {
|
|
636
|
+
type: "object",
|
|
637
|
+
properties: {
|
|
638
|
+
markdown: { type: "string", description: "The Markdown text to lint." },
|
|
639
|
+
},
|
|
640
|
+
required: ["markdown"],
|
|
641
|
+
},
|
|
642
|
+
annotations: {
|
|
643
|
+
title: "Lint Markdown",
|
|
644
|
+
readOnlyHint: true,
|
|
645
|
+
destructiveHint: false,
|
|
646
|
+
idempotentHint: true,
|
|
647
|
+
openWorldHint: false,
|
|
648
|
+
},
|
|
649
|
+
},
|
|
650
|
+
// ── Analysis tools ──
|
|
651
|
+
{
|
|
652
|
+
name: "extract_code_blocks",
|
|
653
|
+
description: "Extract all code blocks from a Markdown document. Returns a JSON array of code blocks, " +
|
|
654
|
+
"each with language, code content, and start/end line numbers. " +
|
|
655
|
+
"Useful for extracting code snippets from LLM responses or documentation.",
|
|
656
|
+
inputSchema: {
|
|
657
|
+
type: "object",
|
|
658
|
+
properties: {
|
|
659
|
+
markdown: { type: "string", description: "The Markdown text to extract code blocks from." },
|
|
660
|
+
},
|
|
661
|
+
required: ["markdown"],
|
|
662
|
+
},
|
|
663
|
+
annotations: {
|
|
664
|
+
title: "Extract Code Blocks",
|
|
665
|
+
readOnlyHint: true,
|
|
666
|
+
destructiveHint: false,
|
|
667
|
+
idempotentHint: true,
|
|
668
|
+
openWorldHint: false,
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
name: "extract_links",
|
|
673
|
+
description: "Extract all links and images from a Markdown document. Returns a JSON array with link text, URL, " +
|
|
674
|
+
"line number, and type (inline, reference, image, autolink). " +
|
|
675
|
+
"Useful for link checking, SEO analysis, or extracting references.",
|
|
676
|
+
inputSchema: {
|
|
677
|
+
type: "object",
|
|
678
|
+
properties: {
|
|
679
|
+
markdown: { type: "string", description: "The Markdown text to extract links from." },
|
|
680
|
+
},
|
|
681
|
+
required: ["markdown"],
|
|
682
|
+
},
|
|
683
|
+
annotations: {
|
|
684
|
+
title: "Extract Links",
|
|
685
|
+
readOnlyHint: true,
|
|
686
|
+
destructiveHint: false,
|
|
687
|
+
idempotentHint: true,
|
|
688
|
+
openWorldHint: false,
|
|
689
|
+
},
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
name: "generate_toc",
|
|
693
|
+
description: "Generate a Table of Contents from Markdown headings. Returns a Markdown-formatted TOC with " +
|
|
694
|
+
"indented links to each heading. Handles duplicate heading slugs. " +
|
|
695
|
+
"The max_depth parameter controls the deepest heading level to include.",
|
|
696
|
+
inputSchema: {
|
|
697
|
+
type: "object",
|
|
698
|
+
properties: {
|
|
699
|
+
markdown: { type: "string", description: "The Markdown text to generate a TOC from." },
|
|
700
|
+
max_depth: { type: "number", description: "Maximum heading depth to include (1-6, default: 6)." },
|
|
701
|
+
},
|
|
702
|
+
required: ["markdown"],
|
|
703
|
+
},
|
|
704
|
+
annotations: {
|
|
705
|
+
title: "Generate Table of Contents",
|
|
706
|
+
readOnlyHint: true,
|
|
707
|
+
destructiveHint: false,
|
|
708
|
+
idempotentHint: true,
|
|
709
|
+
openWorldHint: false,
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
name: "analyze_document",
|
|
714
|
+
description: "Analyze a Markdown document and return comprehensive statistics. Returns JSON with: " +
|
|
715
|
+
"line/word/character/paragraph/sentence counts, heading/code block/table/link/image/list/blockquote counts, " +
|
|
716
|
+
"and estimated reading time in minutes.",
|
|
717
|
+
inputSchema: {
|
|
718
|
+
type: "object",
|
|
719
|
+
properties: {
|
|
720
|
+
markdown: { type: "string", description: "The Markdown text to analyze." },
|
|
721
|
+
},
|
|
722
|
+
required: ["markdown"],
|
|
723
|
+
},
|
|
724
|
+
annotations: {
|
|
725
|
+
title: "Analyze Document Statistics",
|
|
726
|
+
readOnlyHint: true,
|
|
727
|
+
destructiveHint: false,
|
|
728
|
+
idempotentHint: true,
|
|
729
|
+
openWorldHint: false,
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
name: "extract_structure",
|
|
734
|
+
description: "Extract the full structure of a Markdown document. Returns JSON with document statistics, " +
|
|
735
|
+
"heading outline, code block summary (language, line count, positions), and link summary " +
|
|
736
|
+
"(totals by type, unique URL count). Provides a bird's-eye view of document architecture.",
|
|
737
|
+
inputSchema: {
|
|
738
|
+
type: "object",
|
|
739
|
+
properties: {
|
|
740
|
+
markdown: { type: "string", description: "The Markdown text to extract structure from." },
|
|
741
|
+
},
|
|
742
|
+
required: ["markdown"],
|
|
743
|
+
},
|
|
744
|
+
annotations: {
|
|
745
|
+
title: "Extract Document Structure",
|
|
746
|
+
readOnlyHint: true,
|
|
747
|
+
destructiveHint: false,
|
|
748
|
+
idempotentHint: true,
|
|
749
|
+
openWorldHint: false,
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
};
|
|
754
|
+
});
|
|
755
|
+
// ── Prompts ──────────────────────────────────────────────────────────
|
|
756
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
757
|
+
return {
|
|
758
|
+
prompts: [
|
|
759
|
+
{
|
|
760
|
+
name: "convert-document",
|
|
761
|
+
description: "Convert a Markdown document to a specified output format. " +
|
|
762
|
+
"Supports: PDF, DOCX, HTML, LaTeX, CSV, JSON, XML, XLSX, RTF, PNG, TXT, MD.",
|
|
763
|
+
arguments: [
|
|
764
|
+
{
|
|
765
|
+
name: "format",
|
|
766
|
+
description: "Target output format: pdf, docx, html, latex, csv, json, xml, xlsx, rtf, png, txt, or md",
|
|
767
|
+
required: true,
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
name: "markdown",
|
|
771
|
+
description: "The Markdown content to convert",
|
|
772
|
+
required: true,
|
|
773
|
+
},
|
|
774
|
+
],
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
name: "extract-tables",
|
|
778
|
+
description: "Extract all tables from a Markdown document and export them as CSV or XLSX spreadsheet format.",
|
|
779
|
+
arguments: [
|
|
780
|
+
{
|
|
781
|
+
name: "format",
|
|
782
|
+
description: "Output format for tables: 'csv' for plain text or 'xlsx' for Excel spreadsheet",
|
|
783
|
+
required: true,
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
name: "markdown",
|
|
787
|
+
description: "The Markdown content containing tables to extract",
|
|
788
|
+
required: true,
|
|
789
|
+
},
|
|
790
|
+
],
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
name: "format-for-sharing",
|
|
794
|
+
description: "Prepare a Markdown document for sharing by harmonizing formatting and converting to " +
|
|
795
|
+
"portable formats (PDF and HTML) with professional styling.",
|
|
796
|
+
arguments: [
|
|
797
|
+
{
|
|
798
|
+
name: "markdown",
|
|
799
|
+
description: "The Markdown content to format for sharing",
|
|
800
|
+
required: true,
|
|
801
|
+
},
|
|
802
|
+
],
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
name: "analyze-and-repair",
|
|
806
|
+
description: "Analyze a Markdown document for issues, repair any problems found, and return " +
|
|
807
|
+
"both the lint report and the repaired document.",
|
|
808
|
+
arguments: [
|
|
809
|
+
{
|
|
810
|
+
name: "markdown",
|
|
811
|
+
description: "The Markdown content to analyze and repair",
|
|
812
|
+
required: true,
|
|
813
|
+
},
|
|
814
|
+
],
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
name: "convert-for-platform",
|
|
818
|
+
description: "Convert Markdown to a platform-specific format. " +
|
|
819
|
+
"Supports: slack, discord, jira, confluence, asciidoc, rst, mediawiki, bbcode, textile, orgmode.",
|
|
820
|
+
arguments: [
|
|
821
|
+
{
|
|
822
|
+
name: "platform",
|
|
823
|
+
description: "Target platform: slack, discord, jira, confluence, asciidoc, rst, mediawiki, bbcode, textile, or orgmode",
|
|
824
|
+
required: true,
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "markdown",
|
|
828
|
+
description: "The Markdown content to convert",
|
|
829
|
+
required: true,
|
|
830
|
+
},
|
|
831
|
+
],
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
name: "document-overview",
|
|
835
|
+
description: "Get a comprehensive overview of a Markdown document: statistics, structure, " +
|
|
836
|
+
"table of contents, code blocks, and links.",
|
|
837
|
+
arguments: [
|
|
838
|
+
{
|
|
839
|
+
name: "markdown",
|
|
840
|
+
description: "The Markdown content to analyze",
|
|
841
|
+
required: true,
|
|
842
|
+
},
|
|
843
|
+
],
|
|
844
|
+
},
|
|
845
|
+
],
|
|
846
|
+
};
|
|
847
|
+
});
|
|
848
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
849
|
+
const { name, arguments: args } = request.params;
|
|
850
|
+
if (name === "convert-document") {
|
|
851
|
+
const format = args?.format || "pdf";
|
|
852
|
+
const markdown = args?.markdown || "";
|
|
853
|
+
return {
|
|
854
|
+
description: `Convert Markdown to ${format.toUpperCase()}`,
|
|
855
|
+
messages: [
|
|
856
|
+
{
|
|
857
|
+
role: "user",
|
|
858
|
+
content: {
|
|
859
|
+
type: "text",
|
|
860
|
+
text: `Please convert the following Markdown document to ${format.toUpperCase()} format using the convert_to_${format} tool.\n\n${markdown}`,
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
],
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
if (name === "extract-tables") {
|
|
867
|
+
const format = args?.format || "csv";
|
|
868
|
+
const markdown = args?.markdown || "";
|
|
869
|
+
return {
|
|
870
|
+
description: `Extract tables from Markdown as ${format.toUpperCase()}`,
|
|
871
|
+
messages: [
|
|
872
|
+
{
|
|
873
|
+
role: "user",
|
|
874
|
+
content: {
|
|
875
|
+
type: "text",
|
|
876
|
+
text: `Please extract all tables from the following Markdown and convert them to ${format.toUpperCase()} format using the convert_to_${format} tool.\n\n${markdown}`,
|
|
877
|
+
},
|
|
878
|
+
},
|
|
879
|
+
],
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
if (name === "format-for-sharing") {
|
|
883
|
+
const markdown = args?.markdown || "";
|
|
884
|
+
return {
|
|
885
|
+
description: "Format Markdown for professional sharing",
|
|
886
|
+
messages: [
|
|
887
|
+
{
|
|
888
|
+
role: "user",
|
|
889
|
+
content: {
|
|
890
|
+
type: "text",
|
|
891
|
+
text: `Please format the following Markdown for sharing. First, use harmonize_markdown to clean up the formatting, then convert it to both PDF (using convert_to_pdf) and HTML (using convert_to_html) for distribution.\n\n${markdown}`,
|
|
892
|
+
},
|
|
893
|
+
},
|
|
894
|
+
],
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
if (name === "analyze-and-repair") {
|
|
898
|
+
const markdown = args?.markdown || "";
|
|
899
|
+
return {
|
|
900
|
+
description: "Analyze and repair Markdown document",
|
|
901
|
+
messages: [
|
|
902
|
+
{
|
|
903
|
+
role: "user",
|
|
904
|
+
content: {
|
|
905
|
+
type: "text",
|
|
906
|
+
text: `Please analyze and repair the following Markdown document:\n\n1. First, use lint_markdown to identify issues in the document.\n2. Then, use repair_markdown to fix the problems.\n3. Finally, use lint_markdown again on the repaired version to confirm issues are resolved.\n\nReturn both the lint report and the repaired Markdown.\n\n${markdown}`,
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
],
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
if (name === "convert-for-platform") {
|
|
913
|
+
const platform = args?.platform || "slack";
|
|
914
|
+
const markdown = args?.markdown || "";
|
|
915
|
+
return {
|
|
916
|
+
description: `Convert Markdown for ${platform}`,
|
|
917
|
+
messages: [
|
|
918
|
+
{
|
|
919
|
+
role: "user",
|
|
920
|
+
content: {
|
|
921
|
+
type: "text",
|
|
922
|
+
text: `Please convert the following Markdown to ${platform} format using the convert_to_${platform} tool.\n\n${markdown}`,
|
|
923
|
+
},
|
|
924
|
+
},
|
|
925
|
+
],
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
if (name === "document-overview") {
|
|
929
|
+
const markdown = args?.markdown || "";
|
|
930
|
+
return {
|
|
931
|
+
description: "Comprehensive document overview",
|
|
932
|
+
messages: [
|
|
933
|
+
{
|
|
934
|
+
role: "user",
|
|
935
|
+
content: {
|
|
936
|
+
type: "text",
|
|
937
|
+
text: `Please provide a comprehensive overview of the following Markdown document:\n\n1. Use analyze_document to get statistics (word count, reading time, etc.)\n2. Use generate_toc to create a table of contents\n3. Use extract_code_blocks to list all code snippets\n4. Use extract_links to catalog all links\n\nSummarize the findings in a clear report.\n\n${markdown}`,
|
|
938
|
+
},
|
|
939
|
+
},
|
|
940
|
+
],
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
944
|
+
});
|
|
945
|
+
// ── Resources ────────────────────────────────────────────────────────
|
|
946
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
947
|
+
return {
|
|
948
|
+
resources: [
|
|
949
|
+
{
|
|
950
|
+
uri: "markdown-formatter://supported-formats",
|
|
951
|
+
name: "Supported Output Formats",
|
|
952
|
+
description: "Complete list of all 22+ supported output formats with tool names, types, and descriptions",
|
|
953
|
+
mimeType: "application/json",
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
uri: "markdown-formatter://conversion-guide",
|
|
957
|
+
name: "Conversion Guide",
|
|
958
|
+
description: "Guide for choosing the right output format based on your use case",
|
|
959
|
+
mimeType: "text/plain",
|
|
960
|
+
},
|
|
195
961
|
],
|
|
196
962
|
};
|
|
197
963
|
});
|
|
964
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
965
|
+
const { uri } = request.params;
|
|
966
|
+
if (uri === "markdown-formatter://supported-formats") {
|
|
967
|
+
return {
|
|
968
|
+
contents: [
|
|
969
|
+
{
|
|
970
|
+
uri,
|
|
971
|
+
mimeType: "application/json",
|
|
972
|
+
text: JSON.stringify({
|
|
973
|
+
formats: [
|
|
974
|
+
{ id: "md", name: "Markdown", tool: "convert_to_md", type: "text", description: "Export or harmonize Markdown" },
|
|
975
|
+
{ id: "txt", name: "Plain Text", tool: "convert_to_txt", type: "text", description: "Strip all formatting" },
|
|
976
|
+
{ id: "html", name: "HTML", tool: "convert_to_html", type: "text", description: "Styled HTML document" },
|
|
977
|
+
{ id: "email_html", name: "Email HTML", tool: "convert_to_email_html", type: "text", description: "Email-optimized HTML with inlined styles" },
|
|
978
|
+
{ id: "pdf", name: "PDF", tool: "convert_to_pdf", type: "binary", description: "Print-ready PDF (requires Chromium)" },
|
|
979
|
+
{ id: "docx", name: "Word DOCX", tool: "convert_to_docx", type: "binary", description: "Microsoft Word document" },
|
|
980
|
+
{ id: "rtf", name: "Rich Text", tool: "convert_to_rtf", type: "text", description: "RTF for legacy word processors" },
|
|
981
|
+
{ id: "latex", name: "LaTeX", tool: "convert_to_latex", type: "text", description: "LaTeX source code" },
|
|
982
|
+
{ id: "csv", name: "CSV", tool: "convert_to_csv", type: "text", description: "Tables to comma-separated values" },
|
|
983
|
+
{ id: "json", name: "JSON", tool: "convert_to_json", type: "text", description: "Structured JSON representation" },
|
|
984
|
+
{ id: "xml", name: "XML", tool: "convert_to_xml", type: "text", description: "XML document" },
|
|
985
|
+
{ id: "xlsx", name: "Excel XLSX", tool: "convert_to_xlsx", type: "binary", description: "Excel spreadsheet from tables" },
|
|
986
|
+
{ id: "png", name: "PNG Image", tool: "convert_to_image", type: "binary", description: "Screenshot image (requires Chromium)" },
|
|
987
|
+
{ id: "slack", name: "Slack mrkdwn", tool: "convert_to_slack", type: "text", description: "Slack messaging format" },
|
|
988
|
+
{ id: "discord", name: "Discord Markdown", tool: "convert_to_discord", type: "text", description: "Discord-compatible formatting" },
|
|
989
|
+
{ id: "jira", name: "JIRA Markup", tool: "convert_to_jira", type: "text", description: "Atlassian JIRA wiki markup" },
|
|
990
|
+
{ id: "confluence", name: "Confluence Markup", tool: "convert_to_confluence", type: "text", description: "Atlassian Confluence wiki markup" },
|
|
991
|
+
{ id: "asciidoc", name: "AsciiDoc", tool: "convert_to_asciidoc", type: "text", description: "AsciiDoc lightweight markup" },
|
|
992
|
+
{ id: "rst", name: "reStructuredText", tool: "convert_to_rst", type: "text", description: "Python/Sphinx documentation format" },
|
|
993
|
+
{ id: "mediawiki", name: "MediaWiki", tool: "convert_to_mediawiki", type: "text", description: "Wikipedia/MediaWiki markup" },
|
|
994
|
+
{ id: "bbcode", name: "BBCode", tool: "convert_to_bbcode", type: "text", description: "Forum posting format" },
|
|
995
|
+
{ id: "textile", name: "Textile", tool: "convert_to_textile", type: "text", description: "Textile markup (Redmine)" },
|
|
996
|
+
{ id: "orgmode", name: "Org Mode", tool: "convert_to_orgmode", type: "text", description: "Emacs Org Mode format" },
|
|
997
|
+
],
|
|
998
|
+
total: 23,
|
|
999
|
+
special_tools: [
|
|
1000
|
+
{ name: "harmonize_markdown", description: "Normalize Markdown formatting without changing content" },
|
|
1001
|
+
{ name: "generate_html", description: "Generate HTML string without file I/O (read-only)" },
|
|
1002
|
+
],
|
|
1003
|
+
analysis_tools: [
|
|
1004
|
+
{ name: "extract_code_blocks", description: "Extract all code blocks with language and line info" },
|
|
1005
|
+
{ name: "extract_links", description: "Extract all links and images with type classification" },
|
|
1006
|
+
{ name: "generate_toc", description: "Generate a Markdown Table of Contents from headings" },
|
|
1007
|
+
{ name: "analyze_document", description: "Comprehensive document statistics (words, lines, reading time)" },
|
|
1008
|
+
{ name: "extract_structure", description: "Full document structure overview (stats, outline, summaries)" },
|
|
1009
|
+
],
|
|
1010
|
+
repair_tools: [
|
|
1011
|
+
{ name: "repair_markdown", description: "Fix broken Markdown from LLM output or copy-paste" },
|
|
1012
|
+
{ name: "lint_markdown", description: "Lint Markdown and report issues as JSON" },
|
|
1013
|
+
],
|
|
1014
|
+
import_tools: [
|
|
1015
|
+
{ name: "html_to_markdown", description: "Convert HTML back to Markdown" },
|
|
1016
|
+
],
|
|
1017
|
+
}, null, 2),
|
|
1018
|
+
},
|
|
1019
|
+
],
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
if (uri === "markdown-formatter://conversion-guide") {
|
|
1023
|
+
return {
|
|
1024
|
+
contents: [
|
|
1025
|
+
{
|
|
1026
|
+
uri,
|
|
1027
|
+
mimeType: "text/plain",
|
|
1028
|
+
text: [
|
|
1029
|
+
"Markdown Formatter — Conversion Guide",
|
|
1030
|
+
"======================================",
|
|
1031
|
+
"",
|
|
1032
|
+
"Choose a format based on your use case:",
|
|
1033
|
+
"",
|
|
1034
|
+
"For sharing documents:",
|
|
1035
|
+
" - PDF — Best for print-ready, read-only distribution",
|
|
1036
|
+
" - DOCX — Best for editable documents in Microsoft Word",
|
|
1037
|
+
" - HTML — Best for web viewing and embedding",
|
|
1038
|
+
" - Email HTML — For email campaigns with inlined styles (Outlook, Gmail)",
|
|
1039
|
+
"",
|
|
1040
|
+
"For data extraction:",
|
|
1041
|
+
" - CSV — Lightweight tabular data from Markdown tables",
|
|
1042
|
+
" - XLSX — Full Excel workbook with formatted tables",
|
|
1043
|
+
" - JSON — Machine-readable structured representation",
|
|
1044
|
+
" - XML — XML-based data interchange",
|
|
1045
|
+
"",
|
|
1046
|
+
"For visual output:",
|
|
1047
|
+
" - PNG — Screenshot image for chat or social media",
|
|
1048
|
+
" - PDF — Paginated visual output for printing",
|
|
1049
|
+
"",
|
|
1050
|
+
"For text processing:",
|
|
1051
|
+
" - TXT — Plain text with all formatting stripped",
|
|
1052
|
+
" - MD — Clean/harmonized Markdown",
|
|
1053
|
+
" - LaTeX — For academic papers and typesetting",
|
|
1054
|
+
" - RTF — For legacy word processors and email clients",
|
|
1055
|
+
"",
|
|
1056
|
+
"For platform-specific sharing:",
|
|
1057
|
+
" - Slack — Paste into Slack messages (*bold*, _italic_, <url|text>)",
|
|
1058
|
+
" - Discord — Discord-compatible markdown (styled headers, code blocks)",
|
|
1059
|
+
" - JIRA — Atlassian JIRA ticket descriptions and comments",
|
|
1060
|
+
" - Confluence — Atlassian Confluence wiki pages",
|
|
1061
|
+
" - MediaWiki — Wikipedia and MediaWiki-based wikis",
|
|
1062
|
+
" - BBCode — Forum posts (phpBB, vBulletin, etc.)",
|
|
1063
|
+
" - Textile — Redmine and some CMS platforms",
|
|
1064
|
+
" - Org Mode — Emacs Org Mode files",
|
|
1065
|
+
"",
|
|
1066
|
+
"For documentation systems:",
|
|
1067
|
+
" - AsciiDoc — Alternative lightweight markup (used by Antora, etc.)",
|
|
1068
|
+
" - RST — reStructuredText for Sphinx/Python documentation",
|
|
1069
|
+
"",
|
|
1070
|
+
"For document analysis:",
|
|
1071
|
+
" - extract_code_blocks — Pull code snippets from docs or LLM output",
|
|
1072
|
+
" - extract_links — Get all URLs for link checking or SEO analysis",
|
|
1073
|
+
" - generate_toc — Auto-generate Table of Contents from headings",
|
|
1074
|
+
" - analyze_document — Word count, reading time, element statistics",
|
|
1075
|
+
" - extract_structure — Full document architecture overview",
|
|
1076
|
+
"",
|
|
1077
|
+
"For repair and quality:",
|
|
1078
|
+
" - repair_markdown — Fix broken LLM output (unclosed fences, bad tables)",
|
|
1079
|
+
" - lint_markdown — Find issues with severity/rule/fixable info",
|
|
1080
|
+
"",
|
|
1081
|
+
"For import:",
|
|
1082
|
+
" - html_to_markdown — Convert HTML content back to Markdown",
|
|
1083
|
+
"",
|
|
1084
|
+
"Tips:",
|
|
1085
|
+
" - Binary formats (PDF, DOCX, XLSX, PNG) should use output_path",
|
|
1086
|
+
" - PDF and PNG require a Chromium browser on the system",
|
|
1087
|
+
" - Set PUPPETEER_EXECUTABLE_PATH to override browser detection",
|
|
1088
|
+
" - Use harmonize_markdown to clean up formatting before conversion",
|
|
1089
|
+
" - Use repair_markdown to fix broken LLM output before processing",
|
|
1090
|
+
" - Use lint_markdown to check quality before sharing documents",
|
|
1091
|
+
].join("\n"),
|
|
1092
|
+
},
|
|
1093
|
+
],
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
1097
|
+
});
|
|
1098
|
+
// ── Tool execution ───────────────────────────────────────────────────
|
|
198
1099
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
199
1100
|
try {
|
|
200
1101
|
const { name, arguments: args } = request.params;
|
|
201
1102
|
const markdown = args.markdown;
|
|
202
1103
|
const outputPath = args.output_path;
|
|
203
|
-
|
|
204
|
-
|
|
1104
|
+
// Tools that don't require the markdown parameter
|
|
1105
|
+
const noMarkdownTools = ['html_to_markdown'];
|
|
1106
|
+
if (!markdown && !noMarkdownTools.includes(name)) {
|
|
205
1107
|
throw new Error("Markdown content is required");
|
|
206
1108
|
}
|
|
207
1109
|
if (name === "harmonize_markdown") {
|
|
@@ -293,7 +1195,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
293
1195
|
if (name === "convert_to_html") {
|
|
294
1196
|
return handleOutput(htmlDoc, outputPath);
|
|
295
1197
|
}
|
|
296
|
-
const browser = await puppeteer.launch({ headless: true });
|
|
1198
|
+
const browser = await puppeteer.launch({ headless: true, executablePath: await findChrome() });
|
|
297
1199
|
const page = await browser.newPage();
|
|
298
1200
|
await page.setContent(htmlDoc);
|
|
299
1201
|
let resultBuffer;
|
|
@@ -370,6 +1272,91 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
370
1272
|
</html>`;
|
|
371
1273
|
return { content: [{ type: "text", text: htmlDoc }] };
|
|
372
1274
|
}
|
|
1275
|
+
// ── Platform converter handlers ──
|
|
1276
|
+
if (name === "convert_to_slack") {
|
|
1277
|
+
return handleOutput(markdownToSlack(markdown), outputPath);
|
|
1278
|
+
}
|
|
1279
|
+
if (name === "convert_to_discord") {
|
|
1280
|
+
return handleOutput(markdownToDiscord(markdown), outputPath);
|
|
1281
|
+
}
|
|
1282
|
+
if (name === "convert_to_jira") {
|
|
1283
|
+
return handleOutput(markdownToJira(markdown), outputPath);
|
|
1284
|
+
}
|
|
1285
|
+
if (name === "convert_to_confluence") {
|
|
1286
|
+
return handleOutput(markdownToConfluence(markdown), outputPath);
|
|
1287
|
+
}
|
|
1288
|
+
if (name === "convert_to_asciidoc") {
|
|
1289
|
+
return handleOutput(markdownToAsciiDoc(markdown), outputPath);
|
|
1290
|
+
}
|
|
1291
|
+
if (name === "convert_to_rst") {
|
|
1292
|
+
return handleOutput(markdownToRST(markdown), outputPath);
|
|
1293
|
+
}
|
|
1294
|
+
if (name === "convert_to_mediawiki") {
|
|
1295
|
+
return handleOutput(markdownToMediaWiki(markdown), outputPath);
|
|
1296
|
+
}
|
|
1297
|
+
if (name === "convert_to_bbcode") {
|
|
1298
|
+
return handleOutput(markdownToBBCode(markdown), outputPath);
|
|
1299
|
+
}
|
|
1300
|
+
if (name === "convert_to_textile") {
|
|
1301
|
+
return handleOutput(markdownToTextile(markdown), outputPath);
|
|
1302
|
+
}
|
|
1303
|
+
if (name === "convert_to_orgmode") {
|
|
1304
|
+
return handleOutput(markdownToOrgMode(markdown), outputPath);
|
|
1305
|
+
}
|
|
1306
|
+
// ── Email HTML handler ──
|
|
1307
|
+
if (name === "convert_to_email_html") {
|
|
1308
|
+
const emailHtml = await markdownToEmailHtml(markdown);
|
|
1309
|
+
return handleOutput(emailHtml, outputPath);
|
|
1310
|
+
}
|
|
1311
|
+
// ── Import handler ──
|
|
1312
|
+
if (name === "html_to_markdown") {
|
|
1313
|
+
const html = args.html;
|
|
1314
|
+
if (!html)
|
|
1315
|
+
throw new Error("HTML content is required");
|
|
1316
|
+
const md = htmlToMarkdown(html);
|
|
1317
|
+
return handleOutput(md, outputPath);
|
|
1318
|
+
}
|
|
1319
|
+
// ── Repair / Lint handlers ──
|
|
1320
|
+
if (name === "repair_markdown") {
|
|
1321
|
+
const repaired = repairMarkdown(markdown);
|
|
1322
|
+
return handleOutput(repaired, outputPath);
|
|
1323
|
+
}
|
|
1324
|
+
if (name === "lint_markdown") {
|
|
1325
|
+
const issues = lintMarkdown(markdown);
|
|
1326
|
+
return {
|
|
1327
|
+
content: [{ type: "text", text: JSON.stringify(issues, null, 2) }],
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
// ── Analysis handlers ──
|
|
1331
|
+
if (name === "extract_code_blocks") {
|
|
1332
|
+
const blocks = extractCodeBlocks(markdown);
|
|
1333
|
+
return {
|
|
1334
|
+
content: [{ type: "text", text: JSON.stringify(blocks, null, 2) }],
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
if (name === "extract_links") {
|
|
1338
|
+
const links = extractLinks(markdown);
|
|
1339
|
+
return {
|
|
1340
|
+
content: [{ type: "text", text: JSON.stringify(links, null, 2) }],
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
if (name === "generate_toc") {
|
|
1344
|
+
const maxDepth = args.max_depth || 6;
|
|
1345
|
+
const toc = generateTOC(markdown, maxDepth);
|
|
1346
|
+
return handleOutput(toc, outputPath);
|
|
1347
|
+
}
|
|
1348
|
+
if (name === "analyze_document") {
|
|
1349
|
+
const stats = analyzeDocument(markdown);
|
|
1350
|
+
return {
|
|
1351
|
+
content: [{ type: "text", text: JSON.stringify(stats, null, 2) }],
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
if (name === "extract_structure") {
|
|
1355
|
+
const structure = extractStructure(markdown);
|
|
1356
|
+
return {
|
|
1357
|
+
content: [{ type: "text", text: JSON.stringify(structure, null, 2) }],
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
373
1360
|
throw new Error(`Unknown tool: ${name}`);
|
|
374
1361
|
}
|
|
375
1362
|
catch (error) {
|
|
@@ -379,23 +1366,5 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
379
1366
|
};
|
|
380
1367
|
}
|
|
381
1368
|
});
|
|
382
|
-
function zodSchemaToToolInput(schema) {
|
|
383
|
-
const shape = schema.shape;
|
|
384
|
-
const properties = {};
|
|
385
|
-
const required = [];
|
|
386
|
-
for (const key in shape) {
|
|
387
|
-
const field = shape[key];
|
|
388
|
-
const isOptional = field.isOptional?.() || field instanceof z.ZodOptional;
|
|
389
|
-
properties[key] = { type: "string" };
|
|
390
|
-
if (!isOptional) {
|
|
391
|
-
required.push(key);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return {
|
|
395
|
-
type: "object",
|
|
396
|
-
properties,
|
|
397
|
-
required
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
1369
|
const transport = new StdioServerTransport();
|
|
401
1370
|
await server.connect(transport);
|