mdengine 0.3.0__tar.gz → 0.5.0__tar.gz
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.
- {mdengine-0.3.0 → mdengine-0.5.0}/PKG-INFO +98 -11
- {mdengine-0.3.0 → mdengine-0.5.0}/README.md +64 -9
- {mdengine-0.3.0 → mdengine-0.5.0}/pyproject.toml +60 -2
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/__init__.py +1 -1
- mdengine-0.5.0/src/md_generator/db/__init__.py +5 -0
- mdengine-0.5.0/src/md_generator/db/adapters/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/db/adapters/factory.py +40 -0
- mdengine-0.5.0/src/md_generator/db/adapters/mongo_adapter.py +142 -0
- mdengine-0.5.0/src/md_generator/db/adapters/mysql_adapter.py +310 -0
- mdengine-0.5.0/src/md_generator/db/adapters/oracle_adapter.py +330 -0
- mdengine-0.5.0/src/md_generator/db/adapters/postgres_adapter.py +290 -0
- mdengine-0.5.0/src/md_generator/db/adapters/sql_common.py +102 -0
- mdengine-0.5.0/src/md_generator/db/api/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/db/api/main.py +178 -0
- mdengine-0.5.0/src/md_generator/db/api/mcp_server.py +29 -0
- mdengine-0.5.0/src/md_generator/db/api/run.py +15 -0
- mdengine-0.5.0/src/md_generator/db/api/schemas.py +82 -0
- mdengine-0.5.0/src/md_generator/db/api/settings.py +31 -0
- mdengine-0.5.0/src/md_generator/db/cli/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/db/cli/main.py +162 -0
- mdengine-0.5.0/src/md_generator/db/config/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/db/config/default.yaml +37 -0
- mdengine-0.5.0/src/md_generator/db/core/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/db/core/base_adapter.py +73 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/dot_emitter.py +50 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/filter.py +65 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/mermaid_emitter.py +39 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/mermaid_render.py +27 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/model.py +65 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/pipeline.py +199 -0
- mdengine-0.5.0/src/md_generator/db/core/erd/render.py +35 -0
- mdengine-0.5.0/src/md_generator/db/core/extractor.py +537 -0
- mdengine-0.5.0/src/md_generator/db/core/job_manager.py +287 -0
- mdengine-0.5.0/src/md_generator/db/core/markdown_writer.py +429 -0
- mdengine-0.5.0/src/md_generator/db/core/models.py +163 -0
- mdengine-0.5.0/src/md_generator/db/core/run_config.py +140 -0
- mdengine-0.5.0/src/md_generator/db/core/util.py +22 -0
- mdengine-0.5.0/src/md_generator/db/core/zip_export.py +25 -0
- mdengine-0.5.0/src/md_generator/db/mcp/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/db/mcp/server.py +62 -0
- mdengine-0.5.0/src/md_generator/db/mcp/sse.py +9 -0
- mdengine-0.5.0/src/md_generator/db/mcp/stream.py +18 -0
- mdengine-0.5.0/src/md_generator/engine_cli.py +30 -0
- mdengine-0.5.0/src/md_generator/graph/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/graph/adapters/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/graph/adapters/factory.py +16 -0
- mdengine-0.5.0/src/md_generator/graph/adapters/neo4j_adapter.py +310 -0
- mdengine-0.5.0/src/md_generator/graph/adapters/networkx_adapter.py +105 -0
- mdengine-0.5.0/src/md_generator/graph/api/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/graph/api/main.py +181 -0
- mdengine-0.5.0/src/md_generator/graph/api/mcp_server.py +29 -0
- mdengine-0.5.0/src/md_generator/graph/api/run.py +15 -0
- mdengine-0.5.0/src/md_generator/graph/api/schemas.py +70 -0
- mdengine-0.5.0/src/md_generator/graph/api/settings.py +31 -0
- mdengine-0.5.0/src/md_generator/graph/cli/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/graph/cli/main.py +138 -0
- mdengine-0.5.0/src/md_generator/graph/config/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/graph/config/default.yaml +30 -0
- mdengine-0.5.0/src/md_generator/graph/core/__init__.py +3 -0
- mdengine-0.5.0/src/md_generator/graph/core/base_adapter.py +35 -0
- mdengine-0.5.0/src/md_generator/graph/core/extractor.py +93 -0
- mdengine-0.5.0/src/md_generator/graph/core/graph_builder.py +72 -0
- mdengine-0.5.0/src/md_generator/graph/core/job_manager.py +280 -0
- mdengine-0.5.0/src/md_generator/graph/core/markdown_writer.py +280 -0
- mdengine-0.5.0/src/md_generator/graph/core/models.py +37 -0
- mdengine-0.5.0/src/md_generator/graph/core/run_config.py +174 -0
- mdengine-0.5.0/src/md_generator/graph/core/viz.py +119 -0
- mdengine-0.5.0/src/md_generator/graph/core/zip_export.py +24 -0
- mdengine-0.5.0/src/md_generator/graph/mcp/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/graph/mcp/server.py +118 -0
- mdengine-0.5.0/src/md_generator/graph/mcp/sse.py +8 -0
- mdengine-0.5.0/src/md_generator/graph/mcp/stream.py +5 -0
- mdengine-0.5.0/src/md_generator/media/youtube/__init__.py +34 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/main.py +140 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/mcp_server.py +31 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/mcp_setup.py +48 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/run.py +30 -0
- mdengine-0.5.0/src/md_generator/media/youtube/api/settings.py +24 -0
- mdengine-0.5.0/src/md_generator/media/youtube/converter.py +140 -0
- mdengine-0.5.0/src/md_generator/media/youtube/formatter.py +58 -0
- mdengine-0.5.0/src/md_generator/media/youtube/metadata.py +210 -0
- mdengine-0.5.0/src/md_generator/media/youtube/service.py +200 -0
- mdengine-0.5.0/src/md_generator/media/youtube/transcript.py +100 -0
- mdengine-0.5.0/src/md_generator/playwright/__init__.py +6 -0
- mdengine-0.5.0/src/md_generator/playwright/api/__init__.py +1 -0
- mdengine-0.5.0/src/md_generator/playwright/api/convert_runner.py +71 -0
- mdengine-0.5.0/src/md_generator/playwright/api/jobs.py +92 -0
- mdengine-0.5.0/src/md_generator/playwright/api/main.py +295 -0
- mdengine-0.5.0/src/md_generator/playwright/api/mcp_server.py +37 -0
- mdengine-0.5.0/src/md_generator/playwright/api/mcp_setup.py +58 -0
- mdengine-0.5.0/src/md_generator/playwright/api/run.py +29 -0
- mdengine-0.5.0/src/md_generator/playwright/api/settings.py +26 -0
- mdengine-0.5.0/src/md_generator/playwright/assets.py +119 -0
- mdengine-0.5.0/src/md_generator/playwright/chunker.py +53 -0
- mdengine-0.5.0/src/md_generator/playwright/cli.py +131 -0
- mdengine-0.5.0/src/md_generator/playwright/extractor.py +24 -0
- mdengine-0.5.0/src/md_generator/playwright/html_to_md.py +25 -0
- mdengine-0.5.0/src/md_generator/playwright/options.py +35 -0
- mdengine-0.5.0/src/md_generator/playwright/pipeline.py +65 -0
- mdengine-0.5.0/src/md_generator/playwright/playwright_fetcher.py +107 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/PKG-INFO +98 -11
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/SOURCES.txt +98 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/entry_points.txt +13 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/requires.txt +36 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/LICENSE +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/setup.cfg +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/convert_runner.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/jobs.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/query_options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/convert_impl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/archive/options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/query_options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/staging.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/api/zip_bundle.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/backends/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/backends/base.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/backends/easy.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/backends/paddle.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/backends/tesseract.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/convert_impl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/emit.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/io_util.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/image/utils.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/run.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/formatter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/audio/service.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/document_converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/job_store.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/run.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/formatter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/video/service.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/media/whisper_language.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/api/zip_bundle.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/md_emit.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/pdf_extract.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/pdf/utils.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/convert_runner.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/jobs.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/query_options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/convert_impl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/embedded_extract.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/ooxml_media.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/post_assets.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/text_formatting.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/vendor_pdf_md/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/vendor_pdf_md/convert.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/vendor_word_md/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/vendor_word_md/convert.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/ppt/zip_deep.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/convert_runner.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/jobs.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/query_options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/convert_impl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/format_detect.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/md_emit_json.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/md_emit_txt.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/md_emit_xml.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/text/options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/convert_runner.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/jobs.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/mcp_setup.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/query_options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/api/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/assets.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/convert_impl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/crawl.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/extract.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/fetch.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/html_to_md.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/options.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/page_convert.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/post_convert_assets.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/url/robots_util.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/api/convert_util.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/api/jobs.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/api/main.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/api/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/artifact.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/word/settings.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/api/__init__.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/api/app.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/convert_config.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/converter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/converter_core.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/excel_reader.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/markdown_emitter.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/md_generator/xlsx/mcp_server.py +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/dependency_links.txt +0 -0
- {mdengine-0.3.0 → mdengine-0.5.0}/src/mdengine.egg-info/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mdengine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, and web URLs to Markdown.
|
|
5
5
|
Author: mdengine contributors
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/vishal7090/md-generator
|
|
8
8
|
Project-URL: Repository, https://github.com/vishal7090/md-generator
|
|
9
9
|
Project-URL: Issues, https://github.com/vishal7090/md-generator/issues
|
|
10
|
-
Keywords: markdown,pdf,docx,pptx,xlsx,ocr,zip,url,html
|
|
10
|
+
Keywords: markdown,pdf,docx,pptx,xlsx,ocr,zip,url,html,youtube,playwright,database
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
13
|
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
@@ -74,6 +74,31 @@ Requires-Dist: imageio-ffmpeg>=0.5.1; extra == "audio"
|
|
|
74
74
|
Provides-Extra: video
|
|
75
75
|
Requires-Dist: openai-whisper>=20231117; extra == "video"
|
|
76
76
|
Requires-Dist: imageio-ffmpeg>=0.5.1; extra == "video"
|
|
77
|
+
Provides-Extra: youtube
|
|
78
|
+
Requires-Dist: youtube-transcript-api>=0.6.0; extra == "youtube"
|
|
79
|
+
Requires-Dist: httpx>=0.27.0; extra == "youtube"
|
|
80
|
+
Requires-Dist: beautifulsoup4>=4.12.0; extra == "youtube"
|
|
81
|
+
Requires-Dist: lxml>=5.0.0; extra == "youtube"
|
|
82
|
+
Provides-Extra: playwright
|
|
83
|
+
Requires-Dist: playwright>=1.49.0; extra == "playwright"
|
|
84
|
+
Requires-Dist: httpx>=0.27.0; extra == "playwright"
|
|
85
|
+
Requires-Dist: beautifulsoup4>=4.12.0; extra == "playwright"
|
|
86
|
+
Requires-Dist: lxml>=5.0.0; extra == "playwright"
|
|
87
|
+
Requires-Dist: markdownify>=0.14.0; extra == "playwright"
|
|
88
|
+
Requires-Dist: readability-lxml>=0.8.1; extra == "playwright"
|
|
89
|
+
Requires-Dist: Pillow>=10.0.0; extra == "playwright"
|
|
90
|
+
Provides-Extra: db
|
|
91
|
+
Requires-Dist: sqlalchemy>=2.0.0; extra == "db"
|
|
92
|
+
Requires-Dist: pyyaml>=6.0.0; extra == "db"
|
|
93
|
+
Requires-Dist: psycopg2-binary>=2.9.9; extra == "db"
|
|
94
|
+
Requires-Dist: pymysql>=1.1.0; extra == "db"
|
|
95
|
+
Requires-Dist: oracledb>=2.0.0; extra == "db"
|
|
96
|
+
Requires-Dist: pymongo>=4.6.0; extra == "db"
|
|
97
|
+
Requires-Dist: mermaid-py>=0.8.0; extra == "db"
|
|
98
|
+
Provides-Extra: graph
|
|
99
|
+
Requires-Dist: networkx>=3.2.0; extra == "graph"
|
|
100
|
+
Requires-Dist: neo4j>=5.14.0; extra == "graph"
|
|
101
|
+
Requires-Dist: pyyaml>=6.0.0; extra == "graph"
|
|
77
102
|
Provides-Extra: api
|
|
78
103
|
Requires-Dist: fastapi>=0.115.0; extra == "api"
|
|
79
104
|
Requires-Dist: uvicorn[standard]>=0.32.0; extra == "api"
|
|
@@ -86,9 +111,15 @@ Requires-Dist: fastmcp>=2.3.0; extra == "mcp"
|
|
|
86
111
|
Provides-Extra: dev
|
|
87
112
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
88
113
|
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
114
|
+
Requires-Dist: beautifulsoup4>=4.12.0; extra == "dev"
|
|
115
|
+
Requires-Dist: lxml>=5.0.0; extra == "dev"
|
|
116
|
+
Requires-Dist: youtube-transcript-api>=0.6.0; extra == "dev"
|
|
89
117
|
Requires-Dist: mdengine[api]; extra == "dev"
|
|
90
118
|
Requires-Dist: mdengine[mcp]; extra == "dev"
|
|
91
119
|
Requires-Dist: mdengine[url]; extra == "dev"
|
|
120
|
+
Requires-Dist: mdengine[playwright]; extra == "dev"
|
|
121
|
+
Requires-Dist: mdengine[db]; extra == "dev"
|
|
122
|
+
Requires-Dist: mdengine[graph]; extra == "dev"
|
|
92
123
|
Provides-Extra: all
|
|
93
124
|
Requires-Dist: pymupdf>=1.24.0; extra == "all"
|
|
94
125
|
Requires-Dist: pdfplumber>=0.11.0; extra == "all"
|
|
@@ -114,11 +145,12 @@ Requires-Dist: fastmcp>=2.3.0; extra == "all"
|
|
|
114
145
|
Requires-Dist: beautifulsoup4>=4.12.0; extra == "all"
|
|
115
146
|
Requires-Dist: lxml_html_clean>=0.4.0; extra == "all"
|
|
116
147
|
Requires-Dist: readability-lxml>=0.8.1; extra == "all"
|
|
148
|
+
Requires-Dist: youtube-transcript-api>=0.6.0; extra == "all"
|
|
117
149
|
Dynamic: license-file
|
|
118
150
|
|
|
119
151
|
# mdengine
|
|
120
152
|
|
|
121
|
-
Single Python distribution for converting **PDF**, **Word (.docx)**, **PowerPoint (.pptx)**, **Excel (.xlsx/.xlsm)**, **images** (OCR), **plain text / JSON / XML**, **ZIP archives**,
|
|
153
|
+
Single Python distribution for converting **PDF**, **Word (.docx)**, **PowerPoint (.pptx)**, **Excel (.xlsx/.xlsm)**, **images** (OCR), **plain text / JSON / XML**, **ZIP archives**, **audio / video** (Whisper transcription → Markdown), **database metadata** (SQL + Mongo), and **graphs** (Neo4j / NetworkX → Markdown) into **Markdown** (and related assets). Install only the extras you need; everything imports under the **`md_generator`** package.
|
|
122
154
|
|
|
123
155
|
- **PyPI name:** `mdengine` (import package: `md_generator`)
|
|
124
156
|
- **Source:** [github.com/vishal7090/md-generator](https://github.com/vishal7090/md-generator)
|
|
@@ -196,6 +228,7 @@ pip install "mdengine[all]"
|
|
|
196
228
|
| `video` | **Video → Markdown** (ffmpeg extracts mono 16 kHz WAV, then same Whisper stack as `audio`) |
|
|
197
229
|
| `api` | FastAPI, uvicorn, httpx, pydantic-settings |
|
|
198
230
|
| `mcp` | MCP servers (`mcp`, `fastmcp` where used) |
|
|
231
|
+
| `graph` | **Graph → Markdown** (Neo4j Bolt + NetworkX GraphML/GML): `networkx`, `neo4j`, `pyyaml` |
|
|
199
232
|
| `dev` | pytest + API/MCP test helpers |
|
|
200
233
|
| `all` | Large superset of dependencies (use only if you need everything) |
|
|
201
234
|
|
|
@@ -210,7 +243,7 @@ All converters can be run from a terminal after you install the package (with th
|
|
|
210
243
|
### 1. Install (once)
|
|
211
244
|
|
|
212
245
|
```bash
|
|
213
|
-
pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, …
|
|
246
|
+
pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, db, graph, …
|
|
214
247
|
# or from a clone:
|
|
215
248
|
pip install -e ".[pdf,word,archive]"
|
|
216
249
|
```
|
|
@@ -238,10 +271,26 @@ If the shell reports “command not found”, ensure the Python **Scripts** dire
|
|
|
238
271
|
| `md-url` | `md_generator.url.converter:main` | `md-url https://example.com/doc ./web-out --artifact-layout` |
|
|
239
272
|
| `md-audio` | `md_generator.media.audio.converter:main` | `md-audio clip.mp3 transcript.md --model base` |
|
|
240
273
|
| `md-video` | `md_generator.media.video.converter:main` | `md-video clip.mp4 transcript.md --model base` |
|
|
274
|
+
| `md-youtube` | `md_generator.media.youtube.converter:main` | `md-youtube "https://youtu.be/…" out.md --transcript-lang en` |
|
|
241
275
|
| `md-audio-api` | `md_generator.media.audio.api.run:main` | REST + MCP on port **8011** (see [Audio and video to Markdown](#audio-and-video-to-markdown)) |
|
|
242
276
|
| `md-video-api` | `md_generator.media.video.api.run:main` | REST + MCP on port **8012** |
|
|
277
|
+
| `md-youtube-api` | `md_generator.media.youtube.api.run:main` | REST + MCP on port **8013** (JSON `url` body; see same section) |
|
|
243
278
|
| `md-audio-mcp` | `md_generator.media.audio.api.mcp_server:main` | Standalone MCP (`--transport stdio` \| `sse` \| `streamable-http`) |
|
|
244
279
|
| `md-video-mcp` | `md_generator.media.video.api.mcp_server:main` | Same for video |
|
|
280
|
+
| `md-youtube-mcp` | `md_generator.media.youtube.api.mcp_server:main` | Same for YouTube (`youtube_url_to_markdown`) |
|
|
281
|
+
| `md-db` | `md_generator.db.cli.main:main` | `pip install "mdengine[db]"` then `md-db --config db.yaml` (or `mdengine db-to-md …`) |
|
|
282
|
+
| `md-db-api` | `md_generator.db.api.run:main` | FastAPI on port **8010** (`DB_TO_MD_PORT`): `POST /db-to-md/run`, `/db-to-md/job`, SSE `/db-to-md/job/{id}/events` |
|
|
283
|
+
| `md-db-mcp` | `md_generator.db.api.mcp_server:main` | Standalone MCP for metadata export tools |
|
|
284
|
+
| `md-graph` | `md_generator.graph.cli.main:main` | `pip install "mdengine[graph]"` then `md-graph --source neo4j --uri bolt://…` (or `mdengine graph-to-md …`) |
|
|
285
|
+
| `md-graph-api` | `md_generator.graph.api.run:main` | FastAPI on port **8012** (`GRAPH_TO_MD_PORT`): `POST /graph-to-md/run`, `/graph-to-md/job`, SSE `/graph-to-md/job/{id}/events` |
|
|
286
|
+
| `md-graph-mcp` | `md_generator.graph.api.mcp_server:main` | Standalone MCP for graph export tools |
|
|
287
|
+
| `mdengine` | `md_generator.engine_cli:main` | `mdengine db-to-md …` / `mdengine graph-to-md …` (delegates to `md-db` / `md-graph`) |
|
|
288
|
+
|
|
289
|
+
**db-to-md ER diagrams:** add **`erd`** to the export feature list (YAML `features.include`, API body, or CLI `--include …,erd`). **Preferred:** **Graphviz** (`dot` on `PATH`, or **`GRAPHVIZ_DOT`**) produces `erd/*.dot`, `erd/*.png`, and `erd/*.svg`. **If Graphviz is missing,** the exporter falls back to **Mermaid** (`erDiagram`): it writes `erd/*.mermaid` plus a fenced **`erd/*.md`** for GitHub-style preview. With **`mermaid-py`** (included in `mdengine[db]`), it also requests **PNG/SVG** via mermaid.ink (requires network unless you self-host mermaid.ink and set **`MERMAID_INK_SERVER`** per [mermaid-py](https://pypi.org/project/mermaid-py/)). Tune **`erd.max_tables`** (default 100) and **`erd.scope`** (`full` \| `per_schema` \| `per_table`) under `erd:` in YAML; CLI: `--erd-max-tables`, `--erd-scope`. Async job SSE uses `progress_update` with `current` starting with `erd:`.
|
|
290
|
+
|
|
291
|
+
**db-to-md split exports and README merge:** with **`output.split_files: true`**, set **`output.write_combined_feature_markdown: true`** to also write root-level combined Markdown (for example `tables.md`, `functions.md`, `indexes.md`, and feature-specific paths such as `oracle/packages.md` or `mongodb/collections.md` when those features run). Set **`output.readme_feature_merge`** to **`inline`** (append full bundle bodies into `README.md`) or **`toc`** (append a linked list to those files). If merge is not **`none`** and split files are on, combined bundle writes are turned on automatically when loading config. CLI: `--write-combined-feature-markdown`, `--readme-feature-merge none|inline|toc`.
|
|
292
|
+
|
|
293
|
+
**graph-to-md (Neo4j + NetworkX):** library lives under [`md_generator/graph/`](src/md_generator/graph/). **Sources:** **`networkx`** (GraphML/GML via `graph.graph_file` or `--graph-file`) or **`neo4j`** (`graph.uri`, `graph.user`, `graph.password`, optional `graph.database` for `session(database=…)`). **Output layout:** by default **`output.combine_markdown: true`** writes **`nodes.md`**, **`relationship.md`**, and **`graph_summary.md`** (summary plus embedded nodes and relationships). Set **`combine_markdown: false`** or CLI **`--individual` / `--markdown-layout individual`** for per-entity files under **`nodes/`** and **`relationships/`**. **Diagrams:** **`viz.mermaid: true`** (default) writes **`graph/graph.mmd`** and embeds a fenced Mermaid block in the export **`README.md`** (no Graphviz required). **`viz.enabled: true`** or CLI **`--viz`** also writes **`graph/graph.dot`** and runs **`dot`** for PNG/SVG/PDF when Graphviz is on `PATH` (or **`GRAPHVIZ_DOT`**). CLI **`--no-mermaid`** disables Mermaid; **`--depth`**, **`--start-node`**, **`--max-nodes`**, **`--max-edges`** bound traversal. Packaged defaults: [`src/md_generator/graph/config/default.yaml`](src/md_generator/graph/config/default.yaml). Tests: **`graph-to-md/tests/`**; API image: [`graph-to-md/Dockerfile.api`](graph-to-md/Dockerfile.api).
|
|
245
294
|
|
|
246
295
|
Every command accepts **`-h` / `--help`** for full flags (artifact layout, OCR, ZIP options, etc.).
|
|
247
296
|
|
|
@@ -261,6 +310,7 @@ md-zip archive.zip ./unzipped-md
|
|
|
261
310
|
md-url https://example.com/page ./page-bundle --artifact-layout
|
|
262
311
|
md-audio ./voice.mp3 ./voice.md --model tiny
|
|
263
312
|
md-video ./screen.mp4 ./screen.md --model base
|
|
313
|
+
pip install "mdengine[graph]" && md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output ./graph-out --viz
|
|
264
314
|
```
|
|
265
315
|
|
|
266
316
|
**Windows PowerShell** (same commands; use backslashes for paths if you prefer)
|
|
@@ -271,6 +321,8 @@ md-zip .\archive.zip .\zip-out
|
|
|
271
321
|
md-url https://example.com/page .\page-bundle --artifact-layout
|
|
272
322
|
md-audio .\voice.mp3 .\voice.md --model tiny
|
|
273
323
|
md-video .\screen.mp4 .\screen.md --model base
|
|
324
|
+
pip install "mdengine[graph]"
|
|
325
|
+
md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output .\graph-out --viz
|
|
274
326
|
```
|
|
275
327
|
|
|
276
328
|
**Windows CMD**
|
|
@@ -455,6 +507,7 @@ Library code lives under **`md_generator.media`**: shared probing in [`document_
|
|
|
455
507
|
```bash
|
|
456
508
|
pip install "mdengine[audio,api,mcp]" # audio CLI + HTTP + MCP
|
|
457
509
|
pip install "mdengine[video,api,mcp]" # video CLI + HTTP + MCP (same ML stack as audio)
|
|
510
|
+
pip install "mdengine[youtube,api,mcp]" # YouTube URL → Markdown (captions + metadata; optional Whisper fallback)
|
|
458
511
|
```
|
|
459
512
|
|
|
460
513
|
### Python library
|
|
@@ -483,6 +536,18 @@ md = svc.to_markdown(Path("input.mp4"), title=None)
|
|
|
483
536
|
svc.write_markdown(Path("input.mp4"), Path("out/transcript.md"))
|
|
484
537
|
```
|
|
485
538
|
|
|
539
|
+
**YouTube** — captions API + page metadata (BeautifulSoup / oEmbed); optional **yt-dlp + Whisper** when captions are missing (`mdengine[audio]` and `yt-dlp` on `PATH`, or `MD_YOUTUBE_YTDLP`):
|
|
540
|
+
|
|
541
|
+
```python
|
|
542
|
+
from md_generator.media.youtube import YouTubeToMarkdownService
|
|
543
|
+
|
|
544
|
+
svc = YouTubeToMarkdownService(whisper_model="base")
|
|
545
|
+
md = svc.to_markdown("https://www.youtube.com/watch?v=VIDEO_ID", transcript_languages=["en"])
|
|
546
|
+
svc.write_markdown("https://youtu.be/VIDEO_ID", Path("out/youtube.md"))
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
For file-based pipelines, [`YouTubeConverter`](src/md_generator/media/youtube/converter.py) reads a `.url` / `.yturl` / `.youtube` file (or a `.txt` whose first non-comment line is a YouTube URL) and implements [`DocumentConverter`](src/md_generator/media/document_converter.py).
|
|
550
|
+
|
|
486
551
|
Public symbols are also re-exported from [`md_generator.media`](src/md_generator/media/__init__.py) for ffprobe helpers (`ffprobe_json`, `VideoProbeResult`, …).
|
|
487
552
|
|
|
488
553
|
### REST API (FastAPI)
|
|
@@ -497,13 +562,15 @@ Each service exposes the same job pattern as other converters:
|
|
|
497
562
|
| `GET /convert/jobs/{job_id}/download` | Markdown when `done`; workspace removed after download. |
|
|
498
563
|
|
|
499
564
|
**Audio** defaults: `MD_AUDIO_MAX_UPLOAD_MB=200`, `MD_AUDIO_MAX_SYNC_UPLOAD_MB=40`, `MD_AUDIO_API_PORT=8011`.
|
|
500
|
-
**Video** defaults: `MD_VIDEO_MAX_UPLOAD_MB=500`, `MD_VIDEO_MAX_SYNC_UPLOAD_MB=80`, `MD_VIDEO_API_PORT=8012`.
|
|
565
|
+
**Video** defaults: `MD_VIDEO_MAX_UPLOAD_MB=500`, `MD_VIDEO_MAX_SYNC_UPLOAD_MB=80`, `MD_VIDEO_API_PORT=8012`.
|
|
566
|
+
**YouTube** uses **JSON** (not multipart): `POST /convert/sync` and `POST /convert/jobs` accept `{"url":"https://www.youtube.com/watch?v=…","title":null,"transcript_languages":["en"],"enable_audio_fallback":true,"whisper_model":"base","language":null}`. Defaults: `MD_YOUTUBE_API_PORT=8013`, `MD_YOUTUBE_JOB_TTL_SECONDS`, `MD_YOUTUBE_CORS_ORIGINS`, `MD_YOUTUBE_TEMP_DIR`.
|
|
501
567
|
|
|
502
568
|
Run with the bundled runners (each call builds the app with **`factory=True`** for a clean MCP session manager):
|
|
503
569
|
|
|
504
570
|
```bash
|
|
505
571
|
md-audio-api --host 127.0.0.1 --port 8011
|
|
506
572
|
md-video-api --host 127.0.0.1 --port 8012
|
|
573
|
+
md-youtube-api --host 127.0.0.1 --port 8013
|
|
507
574
|
```
|
|
508
575
|
|
|
509
576
|
Or with Uvicorn directly (the ASGI app is built by **`create_app()`** so each worker gets its own MCP session manager):
|
|
@@ -511,6 +578,7 @@ Or with Uvicorn directly (the ASGI app is built by **`create_app()`** so each wo
|
|
|
511
578
|
```bash
|
|
512
579
|
uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
|
|
513
580
|
uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
|
|
581
|
+
uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
|
|
514
582
|
```
|
|
515
583
|
|
|
516
584
|
The module also defines **`app = create_app()`** for a single-process target: `uvicorn md_generator.media.audio.api.main:app` (no `--factory`).
|
|
@@ -519,7 +587,7 @@ Swagger is at **`/docs`** when the app is running.
|
|
|
519
587
|
|
|
520
588
|
### MCP (stdio, SSE, streamable HTTP)
|
|
521
589
|
|
|
522
|
-
1. **With FastAPI** — start `md-audio-api` or `md-
|
|
590
|
+
1. **With FastAPI** — start `md-audio-api`, `md-video-api`, or `md-youtube-api`; mount Streamable HTTP MCP at **`http://<host>:<port>/mcp`** (same host as REST).
|
|
523
591
|
2. **Standalone** — process speaks MCP only:
|
|
524
592
|
|
|
525
593
|
```bash
|
|
@@ -527,16 +595,18 @@ md-audio-mcp --transport stdio
|
|
|
527
595
|
md-audio-mcp --transport sse
|
|
528
596
|
md-audio-mcp --transport streamable-http
|
|
529
597
|
md-video-mcp --transport stdio
|
|
598
|
+
md-youtube-mcp --transport stdio
|
|
530
599
|
```
|
|
531
600
|
|
|
532
601
|
**Audio MCP tools:** `transcribe_audio_path`, `transcribe_audio_base64`.
|
|
533
|
-
**Video MCP tools:** `transcribe_video_path`, `transcribe_video_base64`.
|
|
602
|
+
**Video MCP tools:** `transcribe_video_path`, `transcribe_video_base64`.
|
|
603
|
+
**YouTube MCP tool:** `youtube_url_to_markdown`.
|
|
534
604
|
|
|
535
|
-
Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python -m md_generator.media.video.api.mcp_server`.
|
|
605
|
+
Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python -m md_generator.media.video.api.mcp_server`, `python -m md_generator.media.youtube.api.mcp_server`.
|
|
536
606
|
|
|
537
607
|
### Thin shims (repo clone)
|
|
538
608
|
|
|
539
|
-
[`audio-to-md/converter.py`](audio-to-md/converter.py)
|
|
609
|
+
[`audio-to-md/converter.py`](audio-to-md/converter.py), [`video-to-md/converter.py`](video-to-md/converter.py), and [`youtube-to-md/converter.py`](youtube-to-md/converter.py) delegate to the same `main` as `md-audio` / `md-video` / `md-youtube`. Tests and `pytest.ini` live under `audio-to-md/tests/`, `video-to-md/tests/`, and `youtube-to-md/tests/`. [`db-to-md/converter.py`](db-to-md/converter.py) delegates to `md-db`; tests live under `db-to-md/tests/`. **graph-to-md** uses `md-graph` / `mdengine graph-to-md` directly (no thin `converter.py` shim); tests live under [`graph-to-md/tests/`](graph-to-md/tests/).
|
|
540
610
|
|
|
541
611
|
---
|
|
542
612
|
|
|
@@ -565,8 +635,12 @@ Install `mdengine[api]` plus the format extra(s), then run the **`app`** object
|
|
|
565
635
|
| Text/JSON/XML | `md_generator.text.api.main:app` | `text`, `api`, `mcp` |
|
|
566
636
|
| ZIP | `md_generator.archive.api.main:app` | `archive`, `api`, `mcp` (+ extras for nested office/PDF) |
|
|
567
637
|
| URL / HTML | `md_generator.url.api.main:app` | `url`, `api`, `mcp` |
|
|
638
|
+
| Playwright / SPA | `md_generator.playwright.api.main:app` | `playwright`, `api`, `mcp` |
|
|
639
|
+
| Database metadata | `md_generator.db.api.main:app` | `db`, `api`, `mcp` |
|
|
640
|
+
| Graph metadata (Neo4j / NetworkX) | `md_generator.graph.api.main:app` | `graph`, `api`, `mcp` |
|
|
568
641
|
| Audio (Whisper) | `md_generator.media.audio.api.main:create_app` (use **`--factory`**) or `…main:app` | `audio`, `api`, `mcp` |
|
|
569
642
|
| Video (Whisper) | `md_generator.media.video.api.main:create_app` (use **`--factory`**) or `…main:app` | `video`, `api`, `mcp` |
|
|
643
|
+
| YouTube | `md_generator.media.youtube.api.main:create_app` (use **`--factory`**) or `…main:app` | `youtube`, `api`, `mcp` |
|
|
570
644
|
|
|
571
645
|
Examples:
|
|
572
646
|
|
|
@@ -575,10 +649,15 @@ uvicorn md_generator.pdf.api.main:app --host 127.0.0.1 --port 8001
|
|
|
575
649
|
uvicorn md_generator.word.api.main:app --host 127.0.0.1 --port 8002
|
|
576
650
|
uvicorn md_generator.archive.api.main:app --host 127.0.0.1 --port 8010
|
|
577
651
|
uvicorn md_generator.url.api.main:app --host 127.0.0.1 --port 8011
|
|
652
|
+
uvicorn md_generator.playwright.api.main:app --host 127.0.0.1 --port 8014
|
|
653
|
+
uvicorn md_generator.graph.api.main:app --host 127.0.0.1 --port 8012
|
|
578
654
|
uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
|
|
579
655
|
uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
|
|
656
|
+
uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
|
|
580
657
|
```
|
|
581
658
|
|
|
659
|
+
**Port note:** **`md-graph-api`** and **`md-video-api`** both default to **8012**; set **`GRAPH_TO_MD_PORT`** or **`MD_VIDEO_API_PORT`** when you need both on one machine.
|
|
660
|
+
|
|
582
661
|
### MCP over HTTP on the same server
|
|
583
662
|
|
|
584
663
|
These apps mount an MCP HTTP app at **`/mcp`** (Streamable HTTP / framework-specific). Start the API as above, then point an MCP client at `http://<host>:<port>/mcp` where supported.
|
|
@@ -596,8 +675,12 @@ Prefixes differ per service (often read from a `.env` file next to the process):
|
|
|
596
675
|
| Text | `TXT_JSON_XML_TO_MD_` | same pattern |
|
|
597
676
|
| XLSX | `XLSX_TO_MD_` | `XLSX_TO_MD_TEMP_DIR`, `XLSX_TO_MD_CORS_ORIGINS`, etc. (see `md_generator.xlsx.api.app`) |
|
|
598
677
|
| URL | `URL_TO_MD_` | `URL_TO_MD_MAX_SYNC_URLS`, `URL_TO_MD_MAX_SYNC_CRAWL_PAGES`, `URL_TO_MD_MAX_JOB_URLS`, `URL_TO_MD_JOB_TTL_SECONDS`, `URL_TO_MD_TEMP_DIR`, `URL_TO_MD_CORS_ORIGINS` |
|
|
678
|
+
| Playwright / SPA | `PLAYWRIGHT_TO_MD_` | `PLAYWRIGHT_TO_MD_MAX_SYNC_URLS`, `PLAYWRIGHT_TO_MD_MAX_JOB_URLS`, `PLAYWRIGHT_TO_MD_JOB_TTL_SECONDS`, `PLAYWRIGHT_TO_MD_TEMP_DIR`, `PLAYWRIGHT_TO_MD_CORS_ORIGINS`, `PLAYWRIGHT_TO_MD_API_HOST`, `PLAYWRIGHT_TO_MD_API_PORT` (default **8014**) |
|
|
679
|
+
| Database metadata | `DB_TO_MD_` | `DB_TO_MD_JOB_SQLITE_PATH`, `DB_TO_MD_JOB_WORKSPACE_ROOT`, `DB_TO_MD_CORS_ORIGINS`, `DB_TO_MD_MAX_SYNC_ZIP_MB`, `DB_TO_MD_HOST`, `DB_TO_MD_PORT` (default **8010**) |
|
|
680
|
+
| Graph metadata | `GRAPH_TO_MD_` | `GRAPH_TO_MD_JOB_SQLITE_PATH`, `GRAPH_TO_MD_JOB_WORKSPACE_ROOT`, `GRAPH_TO_MD_CORS_ORIGINS`, `GRAPH_TO_MD_MAX_SYNC_ZIP_MB`, `GRAPH_TO_MD_HOST`, `GRAPH_TO_MD_PORT` (default **8012**) |
|
|
599
681
|
| Audio API | `MD_AUDIO_` | `MD_AUDIO_MAX_UPLOAD_MB`, `MD_AUDIO_MAX_SYNC_UPLOAD_MB`, `MD_AUDIO_JOB_TTL_SECONDS`, `MD_AUDIO_TEMP_DIR`, `MD_AUDIO_CORS_ORIGINS`, `MD_AUDIO_API_HOST`, `MD_AUDIO_API_PORT` |
|
|
600
682
|
| Video API | `MD_VIDEO_` | Same pattern as audio with `MD_VIDEO_*` (defaults: larger upload/sync caps, port **8012**) |
|
|
683
|
+
| YouTube API | `MD_YOUTUBE_` | `MD_YOUTUBE_JOB_TTL_SECONDS`, `MD_YOUTUBE_TEMP_DIR`, `MD_YOUTUBE_CORS_ORIGINS`, `MD_YOUTUBE_API_HOST`, `MD_YOUTUBE_API_PORT` (default **8013**); optional `MD_YOUTUBE_YTDLP` path for audio fallback |
|
|
601
684
|
|
|
602
685
|
Exact variable names match the `ApiSettings` / helper functions in each `api/settings` or `api/app` module.
|
|
603
686
|
|
|
@@ -621,8 +704,12 @@ Two usage patterns:
|
|
|
621
704
|
| PPTX | `python -m md_generator.ppt.api.mcp_server` (see module docstring for flags) |
|
|
622
705
|
| Image | `python -m md_generator.image.api.mcp_server` (see module for CLI) |
|
|
623
706
|
| URL / HTML | `python -m md_generator.url.api.mcp_server` / `--transport sse` / `--transport streamable-http` |
|
|
707
|
+
| Playwright / SPA | `md-playwright-mcp` or `python -m md_generator.playwright.api.mcp_server` / `--transport sse` / `--transport streamable-http` |
|
|
624
708
|
| Audio | `md-audio-mcp` or `python -m md_generator.media.audio.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
625
709
|
| Video | `md-video-mcp` or `python -m md_generator.media.video.api.mcp_server` — same transports |
|
|
710
|
+
| YouTube | `md-youtube-mcp` or `python -m md_generator.media.youtube.api.mcp_server` — same transports |
|
|
711
|
+
| Database metadata | `md-db-mcp` or `python -m md_generator.db.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
712
|
+
| Graph (Neo4j / NetworkX) | `md-graph-mcp` or `python -m md_generator.graph.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
626
713
|
|
|
627
714
|
**Word** and **XLSX** also ship a small runner script in the repo:
|
|
628
715
|
|
|
@@ -647,7 +734,7 @@ pip install -e ".[dev,all]" # or a smaller subset of extras
|
|
|
647
734
|
python -m pytest
|
|
648
735
|
```
|
|
649
736
|
|
|
650
|
-
Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`)
|
|
737
|
+
Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`) and **`graph-to-md/tests/`**; `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
|
|
651
738
|
|
|
652
739
|
---
|
|
653
740
|
|
|
@@ -657,7 +744,7 @@ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/test
|
|
|
657
744
|
|------|------|
|
|
658
745
|
| `LICENSE` | MIT license text |
|
|
659
746
|
| `CODE_OF_CONDUCT.md` | [Contributor Covenant](https://www.contributor-covenant.org/) 2.1 |
|
|
660
|
-
| `src/md_generator/` | **Library source** (all formats + `api` subpackages); **audio/video** under [`media/audio/`](src/md_generator/media/audio/) and [`media/video/`](src/md_generator/media/video/) |
|
|
747
|
+
| `src/md_generator/` | **Library source** (all formats + `api` subpackages); **audio/video** under [`media/audio/`](src/md_generator/media/audio/) and [`media/video/`](src/md_generator/media/video/); **graph-to-md** under [`graph/`](src/md_generator/graph/) |
|
|
661
748
|
| `pyproject.toml` | Packaging, extras, CLI entry points, pytest |
|
|
662
749
|
| `*-to-md/` | **Docs, tests, fixtures**, thin `converter.py` shims, some `run.py` helpers |
|
|
663
750
|
| `README.md` | This document |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mdengine
|
|
2
2
|
|
|
3
|
-
Single Python distribution for converting **PDF**, **Word (.docx)**, **PowerPoint (.pptx)**, **Excel (.xlsx/.xlsm)**, **images** (OCR), **plain text / JSON / XML**, **ZIP archives**,
|
|
3
|
+
Single Python distribution for converting **PDF**, **Word (.docx)**, **PowerPoint (.pptx)**, **Excel (.xlsx/.xlsm)**, **images** (OCR), **plain text / JSON / XML**, **ZIP archives**, **audio / video** (Whisper transcription → Markdown), **database metadata** (SQL + Mongo), and **graphs** (Neo4j / NetworkX → Markdown) into **Markdown** (and related assets). Install only the extras you need; everything imports under the **`md_generator`** package.
|
|
4
4
|
|
|
5
5
|
- **PyPI name:** `mdengine` (import package: `md_generator`)
|
|
6
6
|
- **Source:** [github.com/vishal7090/md-generator](https://github.com/vishal7090/md-generator)
|
|
@@ -78,6 +78,7 @@ pip install "mdengine[all]"
|
|
|
78
78
|
| `video` | **Video → Markdown** (ffmpeg extracts mono 16 kHz WAV, then same Whisper stack as `audio`) |
|
|
79
79
|
| `api` | FastAPI, uvicorn, httpx, pydantic-settings |
|
|
80
80
|
| `mcp` | MCP servers (`mcp`, `fastmcp` where used) |
|
|
81
|
+
| `graph` | **Graph → Markdown** (Neo4j Bolt + NetworkX GraphML/GML): `networkx`, `neo4j`, `pyyaml` |
|
|
81
82
|
| `dev` | pytest + API/MCP test helpers |
|
|
82
83
|
| `all` | Large superset of dependencies (use only if you need everything) |
|
|
83
84
|
|
|
@@ -92,7 +93,7 @@ All converters can be run from a terminal after you install the package (with th
|
|
|
92
93
|
### 1. Install (once)
|
|
93
94
|
|
|
94
95
|
```bash
|
|
95
|
-
pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, …
|
|
96
|
+
pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, db, graph, …
|
|
96
97
|
# or from a clone:
|
|
97
98
|
pip install -e ".[pdf,word,archive]"
|
|
98
99
|
```
|
|
@@ -120,10 +121,26 @@ If the shell reports “command not found”, ensure the Python **Scripts** dire
|
|
|
120
121
|
| `md-url` | `md_generator.url.converter:main` | `md-url https://example.com/doc ./web-out --artifact-layout` |
|
|
121
122
|
| `md-audio` | `md_generator.media.audio.converter:main` | `md-audio clip.mp3 transcript.md --model base` |
|
|
122
123
|
| `md-video` | `md_generator.media.video.converter:main` | `md-video clip.mp4 transcript.md --model base` |
|
|
124
|
+
| `md-youtube` | `md_generator.media.youtube.converter:main` | `md-youtube "https://youtu.be/…" out.md --transcript-lang en` |
|
|
123
125
|
| `md-audio-api` | `md_generator.media.audio.api.run:main` | REST + MCP on port **8011** (see [Audio and video to Markdown](#audio-and-video-to-markdown)) |
|
|
124
126
|
| `md-video-api` | `md_generator.media.video.api.run:main` | REST + MCP on port **8012** |
|
|
127
|
+
| `md-youtube-api` | `md_generator.media.youtube.api.run:main` | REST + MCP on port **8013** (JSON `url` body; see same section) |
|
|
125
128
|
| `md-audio-mcp` | `md_generator.media.audio.api.mcp_server:main` | Standalone MCP (`--transport stdio` \| `sse` \| `streamable-http`) |
|
|
126
129
|
| `md-video-mcp` | `md_generator.media.video.api.mcp_server:main` | Same for video |
|
|
130
|
+
| `md-youtube-mcp` | `md_generator.media.youtube.api.mcp_server:main` | Same for YouTube (`youtube_url_to_markdown`) |
|
|
131
|
+
| `md-db` | `md_generator.db.cli.main:main` | `pip install "mdengine[db]"` then `md-db --config db.yaml` (or `mdengine db-to-md …`) |
|
|
132
|
+
| `md-db-api` | `md_generator.db.api.run:main` | FastAPI on port **8010** (`DB_TO_MD_PORT`): `POST /db-to-md/run`, `/db-to-md/job`, SSE `/db-to-md/job/{id}/events` |
|
|
133
|
+
| `md-db-mcp` | `md_generator.db.api.mcp_server:main` | Standalone MCP for metadata export tools |
|
|
134
|
+
| `md-graph` | `md_generator.graph.cli.main:main` | `pip install "mdengine[graph]"` then `md-graph --source neo4j --uri bolt://…` (or `mdengine graph-to-md …`) |
|
|
135
|
+
| `md-graph-api` | `md_generator.graph.api.run:main` | FastAPI on port **8012** (`GRAPH_TO_MD_PORT`): `POST /graph-to-md/run`, `/graph-to-md/job`, SSE `/graph-to-md/job/{id}/events` |
|
|
136
|
+
| `md-graph-mcp` | `md_generator.graph.api.mcp_server:main` | Standalone MCP for graph export tools |
|
|
137
|
+
| `mdengine` | `md_generator.engine_cli:main` | `mdengine db-to-md …` / `mdengine graph-to-md …` (delegates to `md-db` / `md-graph`) |
|
|
138
|
+
|
|
139
|
+
**db-to-md ER diagrams:** add **`erd`** to the export feature list (YAML `features.include`, API body, or CLI `--include …,erd`). **Preferred:** **Graphviz** (`dot` on `PATH`, or **`GRAPHVIZ_DOT`**) produces `erd/*.dot`, `erd/*.png`, and `erd/*.svg`. **If Graphviz is missing,** the exporter falls back to **Mermaid** (`erDiagram`): it writes `erd/*.mermaid` plus a fenced **`erd/*.md`** for GitHub-style preview. With **`mermaid-py`** (included in `mdengine[db]`), it also requests **PNG/SVG** via mermaid.ink (requires network unless you self-host mermaid.ink and set **`MERMAID_INK_SERVER`** per [mermaid-py](https://pypi.org/project/mermaid-py/)). Tune **`erd.max_tables`** (default 100) and **`erd.scope`** (`full` \| `per_schema` \| `per_table`) under `erd:` in YAML; CLI: `--erd-max-tables`, `--erd-scope`. Async job SSE uses `progress_update` with `current` starting with `erd:`.
|
|
140
|
+
|
|
141
|
+
**db-to-md split exports and README merge:** with **`output.split_files: true`**, set **`output.write_combined_feature_markdown: true`** to also write root-level combined Markdown (for example `tables.md`, `functions.md`, `indexes.md`, and feature-specific paths such as `oracle/packages.md` or `mongodb/collections.md` when those features run). Set **`output.readme_feature_merge`** to **`inline`** (append full bundle bodies into `README.md`) or **`toc`** (append a linked list to those files). If merge is not **`none`** and split files are on, combined bundle writes are turned on automatically when loading config. CLI: `--write-combined-feature-markdown`, `--readme-feature-merge none|inline|toc`.
|
|
142
|
+
|
|
143
|
+
**graph-to-md (Neo4j + NetworkX):** library lives under [`md_generator/graph/`](src/md_generator/graph/). **Sources:** **`networkx`** (GraphML/GML via `graph.graph_file` or `--graph-file`) or **`neo4j`** (`graph.uri`, `graph.user`, `graph.password`, optional `graph.database` for `session(database=…)`). **Output layout:** by default **`output.combine_markdown: true`** writes **`nodes.md`**, **`relationship.md`**, and **`graph_summary.md`** (summary plus embedded nodes and relationships). Set **`combine_markdown: false`** or CLI **`--individual` / `--markdown-layout individual`** for per-entity files under **`nodes/`** and **`relationships/`**. **Diagrams:** **`viz.mermaid: true`** (default) writes **`graph/graph.mmd`** and embeds a fenced Mermaid block in the export **`README.md`** (no Graphviz required). **`viz.enabled: true`** or CLI **`--viz`** also writes **`graph/graph.dot`** and runs **`dot`** for PNG/SVG/PDF when Graphviz is on `PATH` (or **`GRAPHVIZ_DOT`**). CLI **`--no-mermaid`** disables Mermaid; **`--depth`**, **`--start-node`**, **`--max-nodes`**, **`--max-edges`** bound traversal. Packaged defaults: [`src/md_generator/graph/config/default.yaml`](src/md_generator/graph/config/default.yaml). Tests: **`graph-to-md/tests/`**; API image: [`graph-to-md/Dockerfile.api`](graph-to-md/Dockerfile.api).
|
|
127
144
|
|
|
128
145
|
Every command accepts **`-h` / `--help`** for full flags (artifact layout, OCR, ZIP options, etc.).
|
|
129
146
|
|
|
@@ -143,6 +160,7 @@ md-zip archive.zip ./unzipped-md
|
|
|
143
160
|
md-url https://example.com/page ./page-bundle --artifact-layout
|
|
144
161
|
md-audio ./voice.mp3 ./voice.md --model tiny
|
|
145
162
|
md-video ./screen.mp4 ./screen.md --model base
|
|
163
|
+
pip install "mdengine[graph]" && md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output ./graph-out --viz
|
|
146
164
|
```
|
|
147
165
|
|
|
148
166
|
**Windows PowerShell** (same commands; use backslashes for paths if you prefer)
|
|
@@ -153,6 +171,8 @@ md-zip .\archive.zip .\zip-out
|
|
|
153
171
|
md-url https://example.com/page .\page-bundle --artifact-layout
|
|
154
172
|
md-audio .\voice.mp3 .\voice.md --model tiny
|
|
155
173
|
md-video .\screen.mp4 .\screen.md --model base
|
|
174
|
+
pip install "mdengine[graph]"
|
|
175
|
+
md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output .\graph-out --viz
|
|
156
176
|
```
|
|
157
177
|
|
|
158
178
|
**Windows CMD**
|
|
@@ -337,6 +357,7 @@ Library code lives under **`md_generator.media`**: shared probing in [`document_
|
|
|
337
357
|
```bash
|
|
338
358
|
pip install "mdengine[audio,api,mcp]" # audio CLI + HTTP + MCP
|
|
339
359
|
pip install "mdengine[video,api,mcp]" # video CLI + HTTP + MCP (same ML stack as audio)
|
|
360
|
+
pip install "mdengine[youtube,api,mcp]" # YouTube URL → Markdown (captions + metadata; optional Whisper fallback)
|
|
340
361
|
```
|
|
341
362
|
|
|
342
363
|
### Python library
|
|
@@ -365,6 +386,18 @@ md = svc.to_markdown(Path("input.mp4"), title=None)
|
|
|
365
386
|
svc.write_markdown(Path("input.mp4"), Path("out/transcript.md"))
|
|
366
387
|
```
|
|
367
388
|
|
|
389
|
+
**YouTube** — captions API + page metadata (BeautifulSoup / oEmbed); optional **yt-dlp + Whisper** when captions are missing (`mdengine[audio]` and `yt-dlp` on `PATH`, or `MD_YOUTUBE_YTDLP`):
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
from md_generator.media.youtube import YouTubeToMarkdownService
|
|
393
|
+
|
|
394
|
+
svc = YouTubeToMarkdownService(whisper_model="base")
|
|
395
|
+
md = svc.to_markdown("https://www.youtube.com/watch?v=VIDEO_ID", transcript_languages=["en"])
|
|
396
|
+
svc.write_markdown("https://youtu.be/VIDEO_ID", Path("out/youtube.md"))
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
For file-based pipelines, [`YouTubeConverter`](src/md_generator/media/youtube/converter.py) reads a `.url` / `.yturl` / `.youtube` file (or a `.txt` whose first non-comment line is a YouTube URL) and implements [`DocumentConverter`](src/md_generator/media/document_converter.py).
|
|
400
|
+
|
|
368
401
|
Public symbols are also re-exported from [`md_generator.media`](src/md_generator/media/__init__.py) for ffprobe helpers (`ffprobe_json`, `VideoProbeResult`, …).
|
|
369
402
|
|
|
370
403
|
### REST API (FastAPI)
|
|
@@ -379,13 +412,15 @@ Each service exposes the same job pattern as other converters:
|
|
|
379
412
|
| `GET /convert/jobs/{job_id}/download` | Markdown when `done`; workspace removed after download. |
|
|
380
413
|
|
|
381
414
|
**Audio** defaults: `MD_AUDIO_MAX_UPLOAD_MB=200`, `MD_AUDIO_MAX_SYNC_UPLOAD_MB=40`, `MD_AUDIO_API_PORT=8011`.
|
|
382
|
-
**Video** defaults: `MD_VIDEO_MAX_UPLOAD_MB=500`, `MD_VIDEO_MAX_SYNC_UPLOAD_MB=80`, `MD_VIDEO_API_PORT=8012`.
|
|
415
|
+
**Video** defaults: `MD_VIDEO_MAX_UPLOAD_MB=500`, `MD_VIDEO_MAX_SYNC_UPLOAD_MB=80`, `MD_VIDEO_API_PORT=8012`.
|
|
416
|
+
**YouTube** uses **JSON** (not multipart): `POST /convert/sync` and `POST /convert/jobs` accept `{"url":"https://www.youtube.com/watch?v=…","title":null,"transcript_languages":["en"],"enable_audio_fallback":true,"whisper_model":"base","language":null}`. Defaults: `MD_YOUTUBE_API_PORT=8013`, `MD_YOUTUBE_JOB_TTL_SECONDS`, `MD_YOUTUBE_CORS_ORIGINS`, `MD_YOUTUBE_TEMP_DIR`.
|
|
383
417
|
|
|
384
418
|
Run with the bundled runners (each call builds the app with **`factory=True`** for a clean MCP session manager):
|
|
385
419
|
|
|
386
420
|
```bash
|
|
387
421
|
md-audio-api --host 127.0.0.1 --port 8011
|
|
388
422
|
md-video-api --host 127.0.0.1 --port 8012
|
|
423
|
+
md-youtube-api --host 127.0.0.1 --port 8013
|
|
389
424
|
```
|
|
390
425
|
|
|
391
426
|
Or with Uvicorn directly (the ASGI app is built by **`create_app()`** so each worker gets its own MCP session manager):
|
|
@@ -393,6 +428,7 @@ Or with Uvicorn directly (the ASGI app is built by **`create_app()`** so each wo
|
|
|
393
428
|
```bash
|
|
394
429
|
uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
|
|
395
430
|
uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
|
|
431
|
+
uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
|
|
396
432
|
```
|
|
397
433
|
|
|
398
434
|
The module also defines **`app = create_app()`** for a single-process target: `uvicorn md_generator.media.audio.api.main:app` (no `--factory`).
|
|
@@ -401,7 +437,7 @@ Swagger is at **`/docs`** when the app is running.
|
|
|
401
437
|
|
|
402
438
|
### MCP (stdio, SSE, streamable HTTP)
|
|
403
439
|
|
|
404
|
-
1. **With FastAPI** — start `md-audio-api` or `md-
|
|
440
|
+
1. **With FastAPI** — start `md-audio-api`, `md-video-api`, or `md-youtube-api`; mount Streamable HTTP MCP at **`http://<host>:<port>/mcp`** (same host as REST).
|
|
405
441
|
2. **Standalone** — process speaks MCP only:
|
|
406
442
|
|
|
407
443
|
```bash
|
|
@@ -409,16 +445,18 @@ md-audio-mcp --transport stdio
|
|
|
409
445
|
md-audio-mcp --transport sse
|
|
410
446
|
md-audio-mcp --transport streamable-http
|
|
411
447
|
md-video-mcp --transport stdio
|
|
448
|
+
md-youtube-mcp --transport stdio
|
|
412
449
|
```
|
|
413
450
|
|
|
414
451
|
**Audio MCP tools:** `transcribe_audio_path`, `transcribe_audio_base64`.
|
|
415
|
-
**Video MCP tools:** `transcribe_video_path`, `transcribe_video_base64`.
|
|
452
|
+
**Video MCP tools:** `transcribe_video_path`, `transcribe_video_base64`.
|
|
453
|
+
**YouTube MCP tool:** `youtube_url_to_markdown`.
|
|
416
454
|
|
|
417
|
-
Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python -m md_generator.media.video.api.mcp_server`.
|
|
455
|
+
Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python -m md_generator.media.video.api.mcp_server`, `python -m md_generator.media.youtube.api.mcp_server`.
|
|
418
456
|
|
|
419
457
|
### Thin shims (repo clone)
|
|
420
458
|
|
|
421
|
-
[`audio-to-md/converter.py`](audio-to-md/converter.py)
|
|
459
|
+
[`audio-to-md/converter.py`](audio-to-md/converter.py), [`video-to-md/converter.py`](video-to-md/converter.py), and [`youtube-to-md/converter.py`](youtube-to-md/converter.py) delegate to the same `main` as `md-audio` / `md-video` / `md-youtube`. Tests and `pytest.ini` live under `audio-to-md/tests/`, `video-to-md/tests/`, and `youtube-to-md/tests/`. [`db-to-md/converter.py`](db-to-md/converter.py) delegates to `md-db`; tests live under `db-to-md/tests/`. **graph-to-md** uses `md-graph` / `mdengine graph-to-md` directly (no thin `converter.py` shim); tests live under [`graph-to-md/tests/`](graph-to-md/tests/).
|
|
422
460
|
|
|
423
461
|
---
|
|
424
462
|
|
|
@@ -447,8 +485,12 @@ Install `mdengine[api]` plus the format extra(s), then run the **`app`** object
|
|
|
447
485
|
| Text/JSON/XML | `md_generator.text.api.main:app` | `text`, `api`, `mcp` |
|
|
448
486
|
| ZIP | `md_generator.archive.api.main:app` | `archive`, `api`, `mcp` (+ extras for nested office/PDF) |
|
|
449
487
|
| URL / HTML | `md_generator.url.api.main:app` | `url`, `api`, `mcp` |
|
|
488
|
+
| Playwright / SPA | `md_generator.playwright.api.main:app` | `playwright`, `api`, `mcp` |
|
|
489
|
+
| Database metadata | `md_generator.db.api.main:app` | `db`, `api`, `mcp` |
|
|
490
|
+
| Graph metadata (Neo4j / NetworkX) | `md_generator.graph.api.main:app` | `graph`, `api`, `mcp` |
|
|
450
491
|
| Audio (Whisper) | `md_generator.media.audio.api.main:create_app` (use **`--factory`**) or `…main:app` | `audio`, `api`, `mcp` |
|
|
451
492
|
| Video (Whisper) | `md_generator.media.video.api.main:create_app` (use **`--factory`**) or `…main:app` | `video`, `api`, `mcp` |
|
|
493
|
+
| YouTube | `md_generator.media.youtube.api.main:create_app` (use **`--factory`**) or `…main:app` | `youtube`, `api`, `mcp` |
|
|
452
494
|
|
|
453
495
|
Examples:
|
|
454
496
|
|
|
@@ -457,10 +499,15 @@ uvicorn md_generator.pdf.api.main:app --host 127.0.0.1 --port 8001
|
|
|
457
499
|
uvicorn md_generator.word.api.main:app --host 127.0.0.1 --port 8002
|
|
458
500
|
uvicorn md_generator.archive.api.main:app --host 127.0.0.1 --port 8010
|
|
459
501
|
uvicorn md_generator.url.api.main:app --host 127.0.0.1 --port 8011
|
|
502
|
+
uvicorn md_generator.playwright.api.main:app --host 127.0.0.1 --port 8014
|
|
503
|
+
uvicorn md_generator.graph.api.main:app --host 127.0.0.1 --port 8012
|
|
460
504
|
uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
|
|
461
505
|
uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
|
|
506
|
+
uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
|
|
462
507
|
```
|
|
463
508
|
|
|
509
|
+
**Port note:** **`md-graph-api`** and **`md-video-api`** both default to **8012**; set **`GRAPH_TO_MD_PORT`** or **`MD_VIDEO_API_PORT`** when you need both on one machine.
|
|
510
|
+
|
|
464
511
|
### MCP over HTTP on the same server
|
|
465
512
|
|
|
466
513
|
These apps mount an MCP HTTP app at **`/mcp`** (Streamable HTTP / framework-specific). Start the API as above, then point an MCP client at `http://<host>:<port>/mcp` where supported.
|
|
@@ -478,8 +525,12 @@ Prefixes differ per service (often read from a `.env` file next to the process):
|
|
|
478
525
|
| Text | `TXT_JSON_XML_TO_MD_` | same pattern |
|
|
479
526
|
| XLSX | `XLSX_TO_MD_` | `XLSX_TO_MD_TEMP_DIR`, `XLSX_TO_MD_CORS_ORIGINS`, etc. (see `md_generator.xlsx.api.app`) |
|
|
480
527
|
| URL | `URL_TO_MD_` | `URL_TO_MD_MAX_SYNC_URLS`, `URL_TO_MD_MAX_SYNC_CRAWL_PAGES`, `URL_TO_MD_MAX_JOB_URLS`, `URL_TO_MD_JOB_TTL_SECONDS`, `URL_TO_MD_TEMP_DIR`, `URL_TO_MD_CORS_ORIGINS` |
|
|
528
|
+
| Playwright / SPA | `PLAYWRIGHT_TO_MD_` | `PLAYWRIGHT_TO_MD_MAX_SYNC_URLS`, `PLAYWRIGHT_TO_MD_MAX_JOB_URLS`, `PLAYWRIGHT_TO_MD_JOB_TTL_SECONDS`, `PLAYWRIGHT_TO_MD_TEMP_DIR`, `PLAYWRIGHT_TO_MD_CORS_ORIGINS`, `PLAYWRIGHT_TO_MD_API_HOST`, `PLAYWRIGHT_TO_MD_API_PORT` (default **8014**) |
|
|
529
|
+
| Database metadata | `DB_TO_MD_` | `DB_TO_MD_JOB_SQLITE_PATH`, `DB_TO_MD_JOB_WORKSPACE_ROOT`, `DB_TO_MD_CORS_ORIGINS`, `DB_TO_MD_MAX_SYNC_ZIP_MB`, `DB_TO_MD_HOST`, `DB_TO_MD_PORT` (default **8010**) |
|
|
530
|
+
| Graph metadata | `GRAPH_TO_MD_` | `GRAPH_TO_MD_JOB_SQLITE_PATH`, `GRAPH_TO_MD_JOB_WORKSPACE_ROOT`, `GRAPH_TO_MD_CORS_ORIGINS`, `GRAPH_TO_MD_MAX_SYNC_ZIP_MB`, `GRAPH_TO_MD_HOST`, `GRAPH_TO_MD_PORT` (default **8012**) |
|
|
481
531
|
| Audio API | `MD_AUDIO_` | `MD_AUDIO_MAX_UPLOAD_MB`, `MD_AUDIO_MAX_SYNC_UPLOAD_MB`, `MD_AUDIO_JOB_TTL_SECONDS`, `MD_AUDIO_TEMP_DIR`, `MD_AUDIO_CORS_ORIGINS`, `MD_AUDIO_API_HOST`, `MD_AUDIO_API_PORT` |
|
|
482
532
|
| Video API | `MD_VIDEO_` | Same pattern as audio with `MD_VIDEO_*` (defaults: larger upload/sync caps, port **8012**) |
|
|
533
|
+
| YouTube API | `MD_YOUTUBE_` | `MD_YOUTUBE_JOB_TTL_SECONDS`, `MD_YOUTUBE_TEMP_DIR`, `MD_YOUTUBE_CORS_ORIGINS`, `MD_YOUTUBE_API_HOST`, `MD_YOUTUBE_API_PORT` (default **8013**); optional `MD_YOUTUBE_YTDLP` path for audio fallback |
|
|
483
534
|
|
|
484
535
|
Exact variable names match the `ApiSettings` / helper functions in each `api/settings` or `api/app` module.
|
|
485
536
|
|
|
@@ -503,8 +554,12 @@ Two usage patterns:
|
|
|
503
554
|
| PPTX | `python -m md_generator.ppt.api.mcp_server` (see module docstring for flags) |
|
|
504
555
|
| Image | `python -m md_generator.image.api.mcp_server` (see module for CLI) |
|
|
505
556
|
| URL / HTML | `python -m md_generator.url.api.mcp_server` / `--transport sse` / `--transport streamable-http` |
|
|
557
|
+
| Playwright / SPA | `md-playwright-mcp` or `python -m md_generator.playwright.api.mcp_server` / `--transport sse` / `--transport streamable-http` |
|
|
506
558
|
| Audio | `md-audio-mcp` or `python -m md_generator.media.audio.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
507
559
|
| Video | `md-video-mcp` or `python -m md_generator.media.video.api.mcp_server` — same transports |
|
|
560
|
+
| YouTube | `md-youtube-mcp` or `python -m md_generator.media.youtube.api.mcp_server` — same transports |
|
|
561
|
+
| Database metadata | `md-db-mcp` or `python -m md_generator.db.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
562
|
+
| Graph (Neo4j / NetworkX) | `md-graph-mcp` or `python -m md_generator.graph.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
|
|
508
563
|
|
|
509
564
|
**Word** and **XLSX** also ship a small runner script in the repo:
|
|
510
565
|
|
|
@@ -529,7 +584,7 @@ pip install -e ".[dev,all]" # or a smaller subset of extras
|
|
|
529
584
|
python -m pytest
|
|
530
585
|
```
|
|
531
586
|
|
|
532
|
-
Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`)
|
|
587
|
+
Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`) and **`graph-to-md/tests/`**; `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
|
|
533
588
|
|
|
534
589
|
---
|
|
535
590
|
|
|
@@ -539,7 +594,7 @@ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/test
|
|
|
539
594
|
|------|------|
|
|
540
595
|
| `LICENSE` | MIT license text |
|
|
541
596
|
| `CODE_OF_CONDUCT.md` | [Contributor Covenant](https://www.contributor-covenant.org/) 2.1 |
|
|
542
|
-
| `src/md_generator/` | **Library source** (all formats + `api` subpackages); **audio/video** under [`media/audio/`](src/md_generator/media/audio/) and [`media/video/`](src/md_generator/media/video/) |
|
|
597
|
+
| `src/md_generator/` | **Library source** (all formats + `api` subpackages); **audio/video** under [`media/audio/`](src/md_generator/media/audio/) and [`media/video/`](src/md_generator/media/video/); **graph-to-md** under [`graph/`](src/md_generator/graph/) |
|
|
543
598
|
| `pyproject.toml` | Packaging, extras, CLI entry points, pytest |
|
|
544
599
|
| `*-to-md/` | **Docs, tests, fixtures**, thin `converter.py` shims, some `run.py` helpers |
|
|
545
600
|
| `README.md` | This document |
|
|
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mdengine"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0"
|
|
8
8
|
description = "Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, and web URLs to Markdown."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
license = "MIT"
|
|
12
12
|
license-files = ["LICENSE"]
|
|
13
13
|
authors = [{ name = "mdengine contributors" }]
|
|
14
|
-
keywords = ["markdown", "pdf", "docx", "pptx", "xlsx", "ocr", "zip", "url", "html"]
|
|
14
|
+
keywords = ["markdown", "pdf", "docx", "pptx", "xlsx", "ocr", "zip", "url", "html", "youtube", "playwright", "database"]
|
|
15
15
|
classifiers = [
|
|
16
16
|
"Programming Language :: Python :: 3",
|
|
17
17
|
"Programming Language :: Python :: 3 :: Only",
|
|
@@ -76,6 +76,36 @@ url-full = [
|
|
|
76
76
|
audio = ["openai-whisper>=20231117", "imageio-ffmpeg>=0.5.1"]
|
|
77
77
|
# Same ML stack as audio; ships a bundled ``ffmpeg`` binary when the system has none.
|
|
78
78
|
video = ["openai-whisper>=20231117", "imageio-ffmpeg>=0.5.1"]
|
|
79
|
+
youtube = [
|
|
80
|
+
"youtube-transcript-api>=0.6.0",
|
|
81
|
+
"httpx>=0.27.0",
|
|
82
|
+
"beautifulsoup4>=4.12.0",
|
|
83
|
+
"lxml>=5.0.0",
|
|
84
|
+
]
|
|
85
|
+
# Playwright-rendered SPA → Markdown (install browsers: playwright install chromium).
|
|
86
|
+
playwright = [
|
|
87
|
+
"playwright>=1.49.0",
|
|
88
|
+
"httpx>=0.27.0",
|
|
89
|
+
"beautifulsoup4>=4.12.0",
|
|
90
|
+
"lxml>=5.0.0",
|
|
91
|
+
"markdownify>=0.14.0",
|
|
92
|
+
"readability-lxml>=0.8.1",
|
|
93
|
+
"Pillow>=10.0.0",
|
|
94
|
+
]
|
|
95
|
+
db = [
|
|
96
|
+
"sqlalchemy>=2.0.0",
|
|
97
|
+
"pyyaml>=6.0.0",
|
|
98
|
+
"psycopg2-binary>=2.9.9",
|
|
99
|
+
"pymysql>=1.1.0",
|
|
100
|
+
"oracledb>=2.0.0",
|
|
101
|
+
"pymongo>=4.6.0",
|
|
102
|
+
"mermaid-py>=0.8.0",
|
|
103
|
+
]
|
|
104
|
+
graph = [
|
|
105
|
+
"networkx>=3.2.0",
|
|
106
|
+
"neo4j>=5.14.0",
|
|
107
|
+
"pyyaml>=6.0.0",
|
|
108
|
+
]
|
|
79
109
|
api = [
|
|
80
110
|
"fastapi>=0.115.0",
|
|
81
111
|
"uvicorn[standard]>=0.32.0",
|
|
@@ -87,9 +117,15 @@ mcp = ["mcp>=1.2.0", "fastmcp>=2.3.0"]
|
|
|
87
117
|
dev = [
|
|
88
118
|
"pytest>=8.0.0",
|
|
89
119
|
"httpx>=0.27.0",
|
|
120
|
+
"beautifulsoup4>=4.12.0",
|
|
121
|
+
"lxml>=5.0.0",
|
|
122
|
+
"youtube-transcript-api>=0.6.0",
|
|
90
123
|
"mdengine[api]",
|
|
91
124
|
"mdengine[mcp]",
|
|
92
125
|
"mdengine[url]",
|
|
126
|
+
"mdengine[playwright]",
|
|
127
|
+
"mdengine[db]",
|
|
128
|
+
"mdengine[graph]",
|
|
93
129
|
]
|
|
94
130
|
all = [
|
|
95
131
|
"pymupdf>=1.24.0",
|
|
@@ -116,6 +152,7 @@ all = [
|
|
|
116
152
|
"beautifulsoup4>=4.12.0",
|
|
117
153
|
"lxml_html_clean>=0.4.0",
|
|
118
154
|
"readability-lxml>=0.8.1",
|
|
155
|
+
"youtube-transcript-api>=0.6.0",
|
|
119
156
|
]
|
|
120
157
|
|
|
121
158
|
[project.urls]
|
|
@@ -138,10 +175,27 @@ md-audio-api = "md_generator.media.audio.api.run:main"
|
|
|
138
175
|
md-video-api = "md_generator.media.video.api.run:main"
|
|
139
176
|
md-audio-mcp = "md_generator.media.audio.api.mcp_server:main"
|
|
140
177
|
md-video-mcp = "md_generator.media.video.api.mcp_server:main"
|
|
178
|
+
md-youtube = "md_generator.media.youtube.converter:main"
|
|
179
|
+
md-youtube-api = "md_generator.media.youtube.api.run:main"
|
|
180
|
+
md-youtube-mcp = "md_generator.media.youtube.api.mcp_server:main"
|
|
181
|
+
md-playwright = "md_generator.playwright.cli:main"
|
|
182
|
+
md-playwright-api = "md_generator.playwright.api.run:main"
|
|
183
|
+
md-playwright-mcp = "md_generator.playwright.api.mcp_server:main"
|
|
184
|
+
md-db = "md_generator.db.cli.main:main"
|
|
185
|
+
md-db-api = "md_generator.db.api.run:main"
|
|
186
|
+
md-db-mcp = "md_generator.db.api.mcp_server:main"
|
|
187
|
+
md-graph = "md_generator.graph.cli.main:main"
|
|
188
|
+
md-graph-api = "md_generator.graph.api.run:main"
|
|
189
|
+
md-graph-mcp = "md_generator.graph.api.mcp_server:main"
|
|
190
|
+
mdengine = "md_generator.engine_cli:main"
|
|
141
191
|
|
|
142
192
|
[tool.setuptools.packages.find]
|
|
143
193
|
where = ["src"]
|
|
144
194
|
|
|
195
|
+
[tool.setuptools.package-data]
|
|
196
|
+
"md_generator.db.config" = ["*.yaml"]
|
|
197
|
+
"md_generator.graph.config" = ["*.yaml"]
|
|
198
|
+
|
|
145
199
|
[tool.pytest.ini_options]
|
|
146
200
|
pythonpath = ["src"]
|
|
147
201
|
testpaths = [
|
|
@@ -155,5 +209,9 @@ testpaths = [
|
|
|
155
209
|
"url-to-md/tests",
|
|
156
210
|
"audio-to-md/tests",
|
|
157
211
|
"video-to-md/tests",
|
|
212
|
+
"youtube-to-md/tests",
|
|
213
|
+
"playwright-to-md/tests",
|
|
214
|
+
"db-to-md/tests",
|
|
215
|
+
"graph-to-md/tests",
|
|
158
216
|
]
|
|
159
217
|
markers = ["integration: optional dependency or slower checks"]
|