webpage-to-markdown
Convert any webpage into Markdown format using a specified URL. Simplify web content into readable, sharable Markdown text for easier editing and integration.
Instructions
Convert a webpage to markdown
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL of the webpage to convert |
Input Schema (JSON Schema)
{
"properties": {
"url": {
"description": "URL of the webpage to convert",
"type": "string"
}
},
"required": [
"url"
],
"type": "object"
}
Implementation Reference
- src/server.ts:39-123 (handler)Dispatches tool calls by name. For "webpage-to-markdown", validates URL input, performs security checks on the URL, and invokes Markdownify.toMarkdown to perform the conversion.server.setRequestHandler( CallToolRequestSchema, async (request: CallToolRequest) => { const { name, arguments: args } = request.params; const validatedArgs = RequestPayloadSchema.parse(args); try { let result; switch (name) { case tools.YouTubeToMarkdownTool.name: case tools.BingSearchResultToMarkdownTool.name: case tools.WebpageToMarkdownTool.name: if (!validatedArgs.url) { throw new Error("URL is required for this tool"); } const parsedUrl = new URL(validatedArgs.url); if (!["http:", "https:"].includes(parsedUrl.protocol)) { throw new Error("Only http: and https: schemes are allowed."); } if (is_ip_private(parsedUrl.hostname)) { throw new Error(`Fetching ${validatedArgs.url} is potentially dangerous, aborting.`); } result = await Markdownify.toMarkdown({ url: validatedArgs.url, projectRoot: validatedArgs.projectRoot, uvPath: validatedArgs.uvPath || process.env.UV_PATH, }); break; case tools.PDFToMarkdownTool.name: case tools.ImageToMarkdownTool.name: case tools.AudioToMarkdownTool.name: case tools.DocxToMarkdownTool.name: case tools.XlsxToMarkdownTool.name: case tools.PptxToMarkdownTool.name: if (!validatedArgs.filepath) { throw new Error("File path is required for this tool"); } result = await Markdownify.toMarkdown({ filePath: validatedArgs.filepath, projectRoot: validatedArgs.projectRoot, uvPath: validatedArgs.uvPath || process.env.UV_PATH, }); break; case tools.GetMarkdownFileTool.name: if (!validatedArgs.filepath) { throw new Error("File path is required for this tool"); } result = await Markdownify.get({ filePath: validatedArgs.filepath, }); break; default: throw new Error("Tool not found"); } return { content: [ { type: "text", text: `Output file: ${result.path}` }, { type: "text", text: `Converted content:` }, { type: "text", text: result.text }, ], isError: false, }; } catch (e) { if (e instanceof Error) { return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true, }; } else { console.error(e); return { content: [{ type: "text", text: `Error: Unknown error occurred` }], isError: true, }; } } },
- src/tools.ts:49-62 (schema)Defines the input schema for the "webpage-to-markdown" tool, requiring a URL parameter.export const WebpageToMarkdownTool = ToolSchema.parse({ name: "webpage-to-markdown", description: "Convert a webpage to markdown", inputSchema: { type: "object", properties: { url: { type: "string", description: "URL of the webpage to convert", }, }, required: ["url"], }, });
- src/server.ts:33-37 (registration)Registers the "webpage-to-markdown" tool (along with others from tools.ts) by including it in the list of available tools returned by ListToolsRequest.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: Object.values(tools), }; });
- src/Markdownify.ts:74-124 (helper)Implements the core conversion logic: fetches the webpage at the given URL, saves it to a temporary file, executes the 'markitdown' tool via 'uv run' to convert it to markdown, saves the output to a temp markdown file, and returns the path and content.static async toMarkdown({ filePath, url, projectRoot = path.resolve(__dirname, ".."), uvPath = "~/.local/bin/uv", }: { filePath?: string; url?: string; projectRoot?: string; uvPath?: string; }): Promise<MarkdownResult> { try { let inputPath: string; let isTemporary = false; if (url) { const response = await fetch(url); let extension = null; if (url.endsWith(".pdf")) { extension = "pdf"; } const arrayBuffer = await response.arrayBuffer(); const content = Buffer.from(arrayBuffer); inputPath = await this.saveToTempFile(content, extension); isTemporary = true; } else if (filePath) { inputPath = filePath; } else { throw new Error("Either filePath or url must be provided"); } const text = await this._markitdown(inputPath, projectRoot, uvPath); const outputPath = await this.saveToTempFile(text); if (isTemporary) { fs.unlinkSync(inputPath); } return { path: outputPath, text }; } catch (e: unknown) { if (e instanceof Error) { throw new Error(`Error processing to Markdown: ${e.message}`); } else { throw new Error("Error processing to Markdown: Unknown error occurred"); } } }