Skip to main content
Glama

markdown_to_mindmap

Convert Markdown documents into interactive mind maps to visualize and organize hierarchical information for better understanding and planning.

Instructions

Convert a Markdown document into an interactive mind map

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
markdownYesMarkdown content to convert into a mind map
openNoWhether to open the generated mind map in a browser (default: false)

Implementation Reference

  • The core handler function for the 'markdown_to_mindmap' tool. It generates a unique HTML filename, calls the createMarkmap helper with the input markdown and open flag, and returns the resulting file path as JSON or an error message.
    async ({ markdown, open }) => {
        try {
            const filename = `markmap-${Date.now()}.html`;
            const outputPath = join(this.context.output, filename);
    
            const result = await createMarkmap({
                content: markdown,
                output: outputPath,
                openIt: open
            });
    
            return {
                content: [
                    {
                        type: "text",
                        text: JSON.stringify({
                            filePath: result.filePath
                        })
                    }
                ]
            };
        } catch (error: any) {
            return {
                content: [
                    {
                        type: "text",
                        text: JSON.stringify({
                            error: "Failed to generate markmap",
                            message: error.message
                        })
                    }
                ]
            };
        }
    }
  • Zod schema defining the input parameters: 'markdown' (string) and 'open' (boolean, default false).
        markdown: z
            .string()
            .describe("Markdown content to convert into a mind map"),
        open: z
            .boolean()
            .default(false)
            .describe(
                "Whether to open the generated mind map in a browser (default: false)"
            )
    },
  • The register() method in MarkmapToolRegistry where the 'markdown_to_mindmap' tool is registered with the MCP server, including name, description, input schema, and handler.
    public register(): void {
        this.server.tool(
            "markdown_to_mindmap",
            "Convert a Markdown document into an interactive mind map",
            {
                markdown: z
                    .string()
                    .describe("Markdown content to convert into a mind map"),
                open: z
                    .boolean()
                    .default(false)
                    .describe(
                        "Whether to open the generated mind map in a browser (default: false)"
                    )
            },
            async ({ markdown, open }) => {
                try {
                    const filename = `markmap-${Date.now()}.html`;
                    const outputPath = join(this.context.output, filename);
    
                    const result = await createMarkmap({
                        content: markdown,
                        output: outputPath,
                        openIt: open
                    });
    
                    return {
                        content: [
                            {
                                type: "text",
                                text: JSON.stringify({
                                    filePath: result.filePath
                                })
                            }
                        ]
                    };
                } catch (error: any) {
                    return {
                        content: [
                            {
                                type: "text",
                                text: JSON.stringify({
                                    error: "Failed to generate markmap",
                                    message: error.message
                                })
                            }
                        ]
                    };
                }
            }
        );
    }
  • src/index.ts:69-69 (registration)
    Top-level registration call in the main entry point that initializes the tool registry and registers all markmap tools including 'markdown_to_mindmap'.
    registerMarkmapTools(server, { output: outputPath });
  • Supporting helper function that performs the actual markdown-to-markmap conversion, HTML generation with enhanced UI features (export toolbar, fit view, etc.), file writing, and optional browser opening. Called by the tool handler.
    export async function createMarkmap(
        options: CreateMarkmapOptions
    ): Promise<CreateMarkmapResult> {
        const { content, output, openIt = false } = options;
    
        // If no output path is provided, generate a default file path in the temp directory
        const filePath = output || join(tmpdir(), `markmap-${randomUUID()}.html`);
    
        const transformer = new Transformer([...builtInPlugins]);
        const { root, features } = transformer.transform(content);
        const assets = transformer.getUsedAssets(features);
        const html = fillTemplate(root, assets, undefined);
    
        // Add markmap-toolbar related code
        const toolbarCode = `
        <link
          rel="stylesheet"
          href="https://cdn.jsdelivr.net/npm/markmap-toolbar@0.18.10/dist/style.css"
        />
    
        <script src="https://cdn.jsdelivr.net/npm/markmap-toolbar@0.18.10/dist/index.js"></script>
        <script>
          ((r) => {
              setTimeout(r);
          })(() => {
              const { markmap, mm } = window;
              const toolbar = new markmap.Toolbar();
              toolbar.attach(mm);
              const el = toolbar.render();
              el.setAttribute(
                  "style",
                  "position:absolute;bottom:20px;right:20px"
              );
              document.body.append(el);
              
              // Ensure the mind map fits the current view
              setTimeout(() => {
                if (mm && typeof mm.fit === 'function') {
                  mm.fit();
                }
              }, 1200);
          });
        </script>
      `;
    
        // Add scripts and styles for additional features
        const additionalCode = `
        <!-- Add html-to-image library -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js"></script>
    
        <!-- Hidden element to store original Markdown content -->
        <textarea id="original-markdown" style="display:none;">${content}</textarea>
    
        <style>
          /* Export toolbar styles */
          .mm-export-toolbar {
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 1000;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 8px;
            padding: 8px 16px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            display: flex;
            gap: 10px;
          }
          .mm-export-btn {
            padding: 6px 12px;
            border: none;
            border-radius: 4px;
            background-color: #3498db;
            color: white;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s;
          }
          .mm-export-btn:hover {
            background-color: #2980b9;
          }
          .mm-copy-btn {
            background-color: #27ae60;
          }
          .mm-copy-btn:hover {
            background-color: #219653;
          }
          @media print {
            .mm-export-toolbar { display: none !important; }
            .mm-toolbar { display: none !important; }
            svg.markmap, svg#mindmap, #mindmap svg { 
              display: block !important;
              visibility: visible !important; 
              opacity: 1 !important;
              height: 100vh !important;
              width: 100% !important;
              max-width: 100% !important;
              max-height: 100vh !important;
              overflow: visible !important;
              page-break-inside: avoid !important;
            }
            body, html {
              height: 100% !important;
              width: 100% !important;
              margin: 0 !important;
              padding: 0 !important;
              overflow: visible !important;
            }
          }
        </style>
    
        <script>
          (function() {
            // Create bottom export toolbar
            const exportToolbar = document.createElement('div');
            exportToolbar.className = 'mm-export-toolbar';
            document.body.appendChild(exportToolbar);
            
            // Export as PNG image
            const pngBtn = document.createElement('button');
            pngBtn.className = 'mm-export-btn png-export';
            pngBtn.innerHTML = 'Export PNG';
            pngBtn.title = 'Export as PNG image';
            pngBtn.onclick = () => {
              exportToImage('png');
            };
            exportToolbar.appendChild(pngBtn);
    
            // Export as JPG image
            const jpgBtn = document.createElement('button');
            jpgBtn.className = 'mm-export-btn jpg-export';
            jpgBtn.innerHTML = 'Export JPG';
            jpgBtn.title = 'Export as JPG image';
            jpgBtn.onclick = () => {
              exportToImage('jpeg');
            };
            exportToolbar.appendChild(jpgBtn);
            
            // Export as SVG image
            const svgBtn = document.createElement('button');
            svgBtn.className = 'mm-export-btn svg-export';
            svgBtn.innerHTML = 'Export SVG';
            svgBtn.title = 'Export as SVG image';
            svgBtn.onclick = () => {
              exportToImage('svg');
            };
            exportToolbar.appendChild(svgBtn);
    
            // Copy original Markdown button
            const copyBtn = document.createElement('button');
            copyBtn.className = 'mm-export-btn mm-copy-btn copy-markdown';
            copyBtn.innerHTML = 'Copy Markdown';
            copyBtn.title = 'Copy original Markdown content';
            copyBtn.onclick = copyOriginalMarkdown;
            exportToolbar.appendChild(copyBtn);
    
            // Function to copy original Markdown content
            function copyOriginalMarkdown() {
              try {
                const markdownElement = document.getElementById('original-markdown');
                if (!markdownElement) {
                  throw new Error('Original Markdown content not found');
                }
                
                const markdownContent = markdownElement.value;
                
                // Copy to clipboard
                navigator.clipboard.writeText(markdownContent)
                  .then(() => {
                    const originalText = copyBtn.innerHTML;
                    copyBtn.innerHTML = '✓ Copied';
                    copyBtn.style.backgroundColor = '#2ecc71';
                    
                    setTimeout(() => {
                      copyBtn.innerHTML = originalText;
                      copyBtn.style.backgroundColor = '';
                    }, 2000);
                  })
                  .catch(err => {
                    console.error('Copy failed:', err);
                    alert('Failed to copy to clipboard, please check browser permissions');
                  });
              } catch (e) {
                console.error('Error copying Markdown:', e);
                alert('Unable to copy Markdown: ' + e.message);
              }
            }
    
            // Function to export image
            function exportToImage(format) {
              try {
                const node = window.mm.svg._groups[0][0];
                
                if (!node) {
                  throw new Error('Cannot find mind map SVG element');
                }
    
                window.mm.fit().then(() => {
                  const options = {
                    backgroundColor: "#ffffff", 
                    quality: 1.0,
                    width: node.getBoundingClientRect().width,
                    height: node.getBoundingClientRect().height
                  };
                  
                  const exportPromise = format === 'svg' 
                    ? htmlToImage.toSvg(node, options)
                    : format === 'jpeg' 
                      ? htmlToImage.toJpeg(node, options) 
                      : htmlToImage.toPng(node, options);
                  
                  exportPromise
                    .then((dataUrl) => {
                      const link = document.createElement('a');
                      const timestamp = new Date().toISOString().slice(0, 10);
                      link.download = \`markmap-\${timestamp}.\${format === 'jpeg' ? 'jpg' : format === 'svg' ? 'svg' : 'png'}\`;
                      link.href = dataUrl;
                      link.click();
                    })
                    .catch((err) => console.error("Export failed:", err));
                })
                .catch((err) => {
                    throw err;
                });
                  
              } catch (e) {
                console.error('Error exporting image:', e);
                alert('Image export failed: ' + e.message);
              }
            }
          })();
        </script>
      `;
    
        const updatedContent = html.replace(
            "</body>",
            `${toolbarCode}\n${additionalCode}\n</body>`
        );
    
        await fs.writeFile(filePath, updatedContent);
    
        if (openIt) {
            await open(filePath);
        }
    
        return {
            filePath,
            content: updatedContent
        };
    }

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jinzcdev/markmap-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server