mdengine 0.4.0__tar.gz → 0.6.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.
Files changed (288) hide show
  1. {mdengine-0.4.0 → mdengine-0.6.0}/PKG-INFO +66 -8
  2. {mdengine-0.4.0 → mdengine-0.6.0}/README.md +44 -5
  3. {mdengine-0.4.0 → mdengine-0.6.0}/pyproject.toml +43 -3
  4. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/__init__.py +1 -1
  5. mdengine-0.6.0/src/md_generator/db/__init__.py +5 -0
  6. mdengine-0.6.0/src/md_generator/db/adapters/__init__.py +3 -0
  7. mdengine-0.6.0/src/md_generator/db/adapters/factory.py +46 -0
  8. mdengine-0.6.0/src/md_generator/db/adapters/mongo_adapter.py +142 -0
  9. mdengine-0.6.0/src/md_generator/db/adapters/mysql_adapter.py +310 -0
  10. mdengine-0.6.0/src/md_generator/db/adapters/oracle_adapter.py +330 -0
  11. mdengine-0.6.0/src/md_generator/db/adapters/postgres_adapter.py +290 -0
  12. mdengine-0.6.0/src/md_generator/db/adapters/sql_common.py +102 -0
  13. mdengine-0.6.0/src/md_generator/db/adapters/sqlite_adapter.py +107 -0
  14. mdengine-0.6.0/src/md_generator/db/api/__init__.py +3 -0
  15. mdengine-0.6.0/src/md_generator/db/api/main.py +266 -0
  16. mdengine-0.6.0/src/md_generator/db/api/mcp_server.py +29 -0
  17. mdengine-0.6.0/src/md_generator/db/api/run.py +15 -0
  18. mdengine-0.6.0/src/md_generator/db/api/schemas.py +82 -0
  19. mdengine-0.6.0/src/md_generator/db/api/settings.py +32 -0
  20. mdengine-0.6.0/src/md_generator/db/api/sqlite_upload.py +87 -0
  21. mdengine-0.6.0/src/md_generator/db/cli/__init__.py +1 -0
  22. mdengine-0.6.0/src/md_generator/db/cli/main.py +162 -0
  23. mdengine-0.6.0/src/md_generator/db/config/__init__.py +1 -0
  24. mdengine-0.6.0/src/md_generator/db/config/default.yaml +37 -0
  25. mdengine-0.6.0/src/md_generator/db/core/__init__.py +3 -0
  26. mdengine-0.6.0/src/md_generator/db/core/base_adapter.py +73 -0
  27. mdengine-0.6.0/src/md_generator/db/core/erd/__init__.py +3 -0
  28. mdengine-0.6.0/src/md_generator/db/core/erd/dot_emitter.py +50 -0
  29. mdengine-0.6.0/src/md_generator/db/core/erd/filter.py +65 -0
  30. mdengine-0.6.0/src/md_generator/db/core/erd/mermaid_emitter.py +39 -0
  31. mdengine-0.6.0/src/md_generator/db/core/erd/mermaid_render.py +27 -0
  32. mdengine-0.6.0/src/md_generator/db/core/erd/model.py +65 -0
  33. mdengine-0.6.0/src/md_generator/db/core/erd/pipeline.py +199 -0
  34. mdengine-0.6.0/src/md_generator/db/core/erd/render.py +35 -0
  35. mdengine-0.6.0/src/md_generator/db/core/extractor.py +537 -0
  36. mdengine-0.6.0/src/md_generator/db/core/job_manager.py +331 -0
  37. mdengine-0.6.0/src/md_generator/db/core/markdown_writer.py +429 -0
  38. mdengine-0.6.0/src/md_generator/db/core/models.py +163 -0
  39. mdengine-0.6.0/src/md_generator/db/core/run_config.py +145 -0
  40. mdengine-0.6.0/src/md_generator/db/core/util.py +34 -0
  41. mdengine-0.6.0/src/md_generator/db/core/zip_export.py +25 -0
  42. mdengine-0.6.0/src/md_generator/db/mcp/__init__.py +1 -0
  43. mdengine-0.6.0/src/md_generator/db/mcp/server.py +62 -0
  44. mdengine-0.6.0/src/md_generator/db/mcp/sse.py +9 -0
  45. mdengine-0.6.0/src/md_generator/db/mcp/stream.py +18 -0
  46. mdengine-0.6.0/src/md_generator/engine_cli.py +34 -0
  47. mdengine-0.6.0/src/md_generator/graph/__init__.py +3 -0
  48. mdengine-0.6.0/src/md_generator/graph/adapters/__init__.py +3 -0
  49. mdengine-0.6.0/src/md_generator/graph/adapters/factory.py +16 -0
  50. mdengine-0.6.0/src/md_generator/graph/adapters/neo4j_adapter.py +310 -0
  51. mdengine-0.6.0/src/md_generator/graph/adapters/networkx_adapter.py +105 -0
  52. mdengine-0.6.0/src/md_generator/graph/api/__init__.py +1 -0
  53. mdengine-0.6.0/src/md_generator/graph/api/main.py +181 -0
  54. mdengine-0.6.0/src/md_generator/graph/api/mcp_server.py +29 -0
  55. mdengine-0.6.0/src/md_generator/graph/api/run.py +15 -0
  56. mdengine-0.6.0/src/md_generator/graph/api/schemas.py +70 -0
  57. mdengine-0.6.0/src/md_generator/graph/api/settings.py +31 -0
  58. mdengine-0.6.0/src/md_generator/graph/cli/__init__.py +1 -0
  59. mdengine-0.6.0/src/md_generator/graph/cli/main.py +138 -0
  60. mdengine-0.6.0/src/md_generator/graph/config/__init__.py +1 -0
  61. mdengine-0.6.0/src/md_generator/graph/config/default.yaml +30 -0
  62. mdengine-0.6.0/src/md_generator/graph/core/__init__.py +3 -0
  63. mdengine-0.6.0/src/md_generator/graph/core/base_adapter.py +35 -0
  64. mdengine-0.6.0/src/md_generator/graph/core/extractor.py +93 -0
  65. mdengine-0.6.0/src/md_generator/graph/core/graph_builder.py +72 -0
  66. mdengine-0.6.0/src/md_generator/graph/core/job_manager.py +280 -0
  67. mdengine-0.6.0/src/md_generator/graph/core/markdown_writer.py +280 -0
  68. mdengine-0.6.0/src/md_generator/graph/core/models.py +37 -0
  69. mdengine-0.6.0/src/md_generator/graph/core/run_config.py +174 -0
  70. mdengine-0.6.0/src/md_generator/graph/core/viz.py +119 -0
  71. mdengine-0.6.0/src/md_generator/graph/core/zip_export.py +24 -0
  72. mdengine-0.6.0/src/md_generator/graph/mcp/__init__.py +1 -0
  73. mdengine-0.6.0/src/md_generator/graph/mcp/server.py +118 -0
  74. mdengine-0.6.0/src/md_generator/graph/mcp/sse.py +8 -0
  75. mdengine-0.6.0/src/md_generator/graph/mcp/stream.py +5 -0
  76. mdengine-0.6.0/src/md_generator/openapi/__init__.py +5 -0
  77. mdengine-0.6.0/src/md_generator/openapi/api/__init__.py +1 -0
  78. mdengine-0.6.0/src/md_generator/openapi/api/main.py +84 -0
  79. mdengine-0.6.0/src/md_generator/openapi/api/mcp_server.py +29 -0
  80. mdengine-0.6.0/src/md_generator/openapi/api/run.py +15 -0
  81. mdengine-0.6.0/src/md_generator/openapi/api/schemas.py +33 -0
  82. mdengine-0.6.0/src/md_generator/openapi/api/settings.py +21 -0
  83. mdengine-0.6.0/src/md_generator/openapi/cli/__init__.py +1 -0
  84. mdengine-0.6.0/src/md_generator/openapi/cli/main.py +75 -0
  85. mdengine-0.6.0/src/md_generator/openapi/config/__init__.py +1 -0
  86. mdengine-0.6.0/src/md_generator/openapi/config/default.yaml +14 -0
  87. mdengine-0.6.0/src/md_generator/openapi/converters/__init__.py +5 -0
  88. mdengine-0.6.0/src/md_generator/openapi/converters/swagger2_to_openapi3.py +453 -0
  89. mdengine-0.6.0/src/md_generator/openapi/core/__init__.py +1 -0
  90. mdengine-0.6.0/src/md_generator/openapi/core/extractor.py +207 -0
  91. mdengine-0.6.0/src/md_generator/openapi/core/run_config.py +100 -0
  92. mdengine-0.6.0/src/md_generator/openapi/core/zip_export.py +24 -0
  93. mdengine-0.6.0/src/md_generator/openapi/enrichers/__init__.py +5 -0
  94. mdengine-0.6.0/src/md_generator/openapi/enrichers/rules.py +133 -0
  95. mdengine-0.6.0/src/md_generator/openapi/enrichers/sample_body.py +73 -0
  96. mdengine-0.6.0/src/md_generator/openapi/generators/__init__.py +9 -0
  97. mdengine-0.6.0/src/md_generator/openapi/generators/dependency_graph.py +54 -0
  98. mdengine-0.6.0/src/md_generator/openapi/loaders/__init__.py +5 -0
  99. mdengine-0.6.0/src/md_generator/openapi/loaders/spec_loader.py +115 -0
  100. mdengine-0.6.0/src/md_generator/openapi/mcp/__init__.py +1 -0
  101. mdengine-0.6.0/src/md_generator/openapi/mcp/server.py +71 -0
  102. mdengine-0.6.0/src/md_generator/openapi/models/__init__.py +25 -0
  103. mdengine-0.6.0/src/md_generator/openapi/models/domain.py +106 -0
  104. mdengine-0.6.0/src/md_generator/openapi/normalizers/__init__.py +6 -0
  105. mdengine-0.6.0/src/md_generator/openapi/normalizers/operations.py +287 -0
  106. mdengine-0.6.0/src/md_generator/openapi/normalizers/schema_flatten.py +104 -0
  107. mdengine-0.6.0/src/md_generator/openapi/parsers/__init__.py +5 -0
  108. mdengine-0.6.0/src/md_generator/openapi/parsers/openapi_parser.py +18 -0
  109. mdengine-0.6.0/src/md_generator/openapi/resolvers/__init__.py +5 -0
  110. mdengine-0.6.0/src/md_generator/openapi/resolvers/ref_resolver.py +16 -0
  111. mdengine-0.6.0/src/md_generator/openapi/writers/__init__.py +5 -0
  112. mdengine-0.6.0/src/md_generator/openapi/writers/markdown_writer.py +253 -0
  113. {mdengine-0.4.0 → mdengine-0.6.0}/src/mdengine.egg-info/PKG-INFO +66 -8
  114. {mdengine-0.4.0 → mdengine-0.6.0}/src/mdengine.egg-info/SOURCES.txt +108 -0
  115. {mdengine-0.4.0 → mdengine-0.6.0}/src/mdengine.egg-info/entry_points.txt +10 -0
  116. {mdengine-0.4.0 → mdengine-0.6.0}/src/mdengine.egg-info/requires.txt +22 -0
  117. {mdengine-0.4.0 → mdengine-0.6.0}/LICENSE +0 -0
  118. {mdengine-0.4.0 → mdengine-0.6.0}/setup.cfg +0 -0
  119. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/__init__.py +0 -0
  120. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/__init__.py +0 -0
  121. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/convert_runner.py +0 -0
  122. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/jobs.py +0 -0
  123. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/main.py +0 -0
  124. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/mcp_server.py +0 -0
  125. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/mcp_setup.py +0 -0
  126. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/query_options.py +0 -0
  127. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/api/settings.py +0 -0
  128. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/convert_impl.py +0 -0
  129. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/converter.py +0 -0
  130. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/archive/options.py +0 -0
  131. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/__init__.py +0 -0
  132. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/__init__.py +0 -0
  133. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/main.py +0 -0
  134. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/mcp_server.py +0 -0
  135. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/query_options.py +0 -0
  136. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/settings.py +0 -0
  137. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/staging.py +0 -0
  138. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/api/zip_bundle.py +0 -0
  139. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/backends/__init__.py +0 -0
  140. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/backends/base.py +0 -0
  141. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/backends/easy.py +0 -0
  142. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/backends/paddle.py +0 -0
  143. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/backends/tesseract.py +0 -0
  144. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/convert_impl.py +0 -0
  145. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/converter.py +0 -0
  146. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/emit.py +0 -0
  147. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/io_util.py +0 -0
  148. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/image/utils.py +0 -0
  149. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/__init__.py +0 -0
  150. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/__init__.py +0 -0
  151. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/__init__.py +0 -0
  152. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/main.py +0 -0
  153. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/mcp_server.py +0 -0
  154. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/mcp_setup.py +0 -0
  155. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/run.py +0 -0
  156. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/api/settings.py +0 -0
  157. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/converter.py +0 -0
  158. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/formatter.py +0 -0
  159. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/audio/service.py +0 -0
  160. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/document_converter.py +0 -0
  161. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/job_store.py +0 -0
  162. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/__init__.py +0 -0
  163. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/__init__.py +0 -0
  164. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/main.py +0 -0
  165. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/mcp_server.py +0 -0
  166. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/mcp_setup.py +0 -0
  167. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/run.py +0 -0
  168. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/api/settings.py +0 -0
  169. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/converter.py +0 -0
  170. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/formatter.py +0 -0
  171. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/video/service.py +0 -0
  172. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/whisper_language.py +0 -0
  173. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/__init__.py +0 -0
  174. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/__init__.py +0 -0
  175. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/main.py +0 -0
  176. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/mcp_server.py +0 -0
  177. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/mcp_setup.py +0 -0
  178. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/run.py +0 -0
  179. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/api/settings.py +0 -0
  180. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/converter.py +0 -0
  181. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/formatter.py +0 -0
  182. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/metadata.py +0 -0
  183. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/service.py +0 -0
  184. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/media/youtube/transcript.py +0 -0
  185. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/__init__.py +0 -0
  186. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/api/__init__.py +0 -0
  187. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/api/main.py +0 -0
  188. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/api/mcp_server.py +0 -0
  189. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/api/settings.py +0 -0
  190. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/api/zip_bundle.py +0 -0
  191. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/converter.py +0 -0
  192. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/md_emit.py +0 -0
  193. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/pdf_extract.py +0 -0
  194. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/pdf/utils.py +0 -0
  195. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/__init__.py +0 -0
  196. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/__init__.py +0 -0
  197. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/convert_runner.py +0 -0
  198. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/jobs.py +0 -0
  199. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/main.py +0 -0
  200. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/mcp_server.py +0 -0
  201. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/mcp_setup.py +0 -0
  202. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/run.py +0 -0
  203. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/api/settings.py +0 -0
  204. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/assets.py +0 -0
  205. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/chunker.py +0 -0
  206. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/cli.py +0 -0
  207. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/extractor.py +0 -0
  208. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/html_to_md.py +0 -0
  209. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/options.py +0 -0
  210. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/pipeline.py +0 -0
  211. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/playwright/playwright_fetcher.py +0 -0
  212. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/__init__.py +0 -0
  213. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/__init__.py +0 -0
  214. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/convert_runner.py +0 -0
  215. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/jobs.py +0 -0
  216. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/main.py +0 -0
  217. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/mcp_server.py +0 -0
  218. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/mcp_setup.py +0 -0
  219. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/query_options.py +0 -0
  220. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/api/settings.py +0 -0
  221. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/convert_impl.py +0 -0
  222. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/converter.py +0 -0
  223. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/embedded_extract.py +0 -0
  224. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/ooxml_media.py +0 -0
  225. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/options.py +0 -0
  226. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/post_assets.py +0 -0
  227. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/text_formatting.py +0 -0
  228. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/vendor_pdf_md/__init__.py +0 -0
  229. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/vendor_pdf_md/convert.py +0 -0
  230. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/vendor_word_md/__init__.py +0 -0
  231. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/vendor_word_md/convert.py +0 -0
  232. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/ppt/zip_deep.py +0 -0
  233. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/__init__.py +0 -0
  234. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/__init__.py +0 -0
  235. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/convert_runner.py +0 -0
  236. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/jobs.py +0 -0
  237. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/main.py +0 -0
  238. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/mcp_server.py +0 -0
  239. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/mcp_setup.py +0 -0
  240. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/query_options.py +0 -0
  241. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/api/settings.py +0 -0
  242. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/convert_impl.py +0 -0
  243. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/converter.py +0 -0
  244. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/format_detect.py +0 -0
  245. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/md_emit_json.py +0 -0
  246. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/md_emit_txt.py +0 -0
  247. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/md_emit_xml.py +0 -0
  248. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/text/options.py +0 -0
  249. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/__init__.py +0 -0
  250. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/__init__.py +0 -0
  251. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/convert_runner.py +0 -0
  252. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/jobs.py +0 -0
  253. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/main.py +0 -0
  254. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/mcp_server.py +0 -0
  255. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/mcp_setup.py +0 -0
  256. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/query_options.py +0 -0
  257. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/api/settings.py +0 -0
  258. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/assets.py +0 -0
  259. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/convert_impl.py +0 -0
  260. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/converter.py +0 -0
  261. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/crawl.py +0 -0
  262. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/extract.py +0 -0
  263. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/fetch.py +0 -0
  264. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/html_to_md.py +0 -0
  265. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/options.py +0 -0
  266. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/page_convert.py +0 -0
  267. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/post_convert_assets.py +0 -0
  268. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/url/robots_util.py +0 -0
  269. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/__init__.py +0 -0
  270. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/api/__init__.py +0 -0
  271. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/api/convert_util.py +0 -0
  272. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/api/jobs.py +0 -0
  273. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/api/main.py +0 -0
  274. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/api/mcp_server.py +0 -0
  275. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/artifact.py +0 -0
  276. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/converter.py +0 -0
  277. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/word/settings.py +0 -0
  278. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/__init__.py +0 -0
  279. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/api/__init__.py +0 -0
  280. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/api/app.py +0 -0
  281. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/convert_config.py +0 -0
  282. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/converter.py +0 -0
  283. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/converter_core.py +0 -0
  284. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/excel_reader.py +0 -0
  285. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/markdown_emitter.py +0 -0
  286. {mdengine-0.4.0 → mdengine-0.6.0}/src/md_generator/xlsx/mcp_server.py +0 -0
  287. {mdengine-0.4.0 → mdengine-0.6.0}/src/mdengine.egg-info/dependency_links.txt +0 -0
  288. {mdengine-0.4.0 → mdengine-0.6.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.4.0
4
- Summary: Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, and web URLs to Markdown.
3
+ Version: 0.6.0
4
+ Summary: Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, web URLs, databases, graphs, and OpenAPI specs 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,youtube,playwright
10
+ Keywords: markdown,pdf,docx,pptx,xlsx,ocr,zip,url,html,youtube,playwright,database,openapi
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3 :: Only
13
13
  Classifier: Topic :: Text Processing :: Markup :: Markdown
@@ -87,6 +87,22 @@ Requires-Dist: lxml>=5.0.0; extra == "playwright"
87
87
  Requires-Dist: markdownify>=0.14.0; extra == "playwright"
88
88
  Requires-Dist: readability-lxml>=0.8.1; extra == "playwright"
89
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"
102
+ Provides-Extra: openapi
103
+ Requires-Dist: pyyaml>=6.0.0; extra == "openapi"
104
+ Requires-Dist: prance>=23.6.0; extra == "openapi"
105
+ Requires-Dist: openapi-spec-validator>=0.7.0; extra == "openapi"
90
106
  Provides-Extra: api
91
107
  Requires-Dist: fastapi>=0.115.0; extra == "api"
92
108
  Requires-Dist: uvicorn[standard]>=0.32.0; extra == "api"
@@ -106,6 +122,9 @@ Requires-Dist: mdengine[api]; extra == "dev"
106
122
  Requires-Dist: mdengine[mcp]; extra == "dev"
107
123
  Requires-Dist: mdengine[url]; extra == "dev"
108
124
  Requires-Dist: mdengine[playwright]; extra == "dev"
125
+ Requires-Dist: mdengine[db]; extra == "dev"
126
+ Requires-Dist: mdengine[graph]; extra == "dev"
127
+ Requires-Dist: mdengine[openapi]; extra == "dev"
109
128
  Provides-Extra: all
110
129
  Requires-Dist: pymupdf>=1.24.0; extra == "all"
111
130
  Requires-Dist: pdfplumber>=0.11.0; extra == "all"
@@ -136,7 +155,7 @@ Dynamic: license-file
136
155
 
137
156
  # mdengine
138
157
 
139
- Single Python distribution for converting **PDF**, **Word (.docx)**, **PowerPoint (.pptx)**, **Excel (.xlsx/.xlsm)**, **images** (OCR), **plain text / JSON / XML**, **ZIP archives**, and **audio / video** (Whisper transcription → Markdown) into **Markdown** (and related assets). Install only the extras you need; everything imports under the **`md_generator`** package.
158
+ 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.
140
159
 
141
160
  - **PyPI name:** `mdengine` (import package: `md_generator`)
142
161
  - **Source:** [github.com/vishal7090/md-generator](https://github.com/vishal7090/md-generator)
@@ -214,6 +233,7 @@ pip install "mdengine[all]"
214
233
  | `video` | **Video → Markdown** (ffmpeg extracts mono 16 kHz WAV, then same Whisper stack as `audio`) |
215
234
  | `api` | FastAPI, uvicorn, httpx, pydantic-settings |
216
235
  | `mcp` | MCP servers (`mcp`, `fastmcp` where used) |
236
+ | `graph` | **Graph → Markdown** (Neo4j Bolt + NetworkX GraphML/GML): `networkx`, `neo4j`, `pyyaml` |
217
237
  | `dev` | pytest + API/MCP test helpers |
218
238
  | `all` | Large superset of dependencies (use only if you need everything) |
219
239
 
@@ -228,7 +248,7 @@ All converters can be run from a terminal after you install the package (with th
228
248
  ### 1. Install (once)
229
249
 
230
250
  ```bash
231
- pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, …
251
+ pip install "mdengine[pdf,word]" # adjust extras: ppt, xlsx, image, archive, text, db, graph, …
232
252
  # or from a clone:
233
253
  pip install -e ".[pdf,word,archive]"
234
254
  ```
@@ -263,6 +283,28 @@ If the shell reports “command not found”, ensure the Python **Scripts** dire
263
283
  | `md-audio-mcp` | `md_generator.media.audio.api.mcp_server:main` | Standalone MCP (`--transport stdio` \| `sse` \| `streamable-http`) |
264
284
  | `md-video-mcp` | `md_generator.media.video.api.mcp_server:main` | Same for video |
265
285
  | `md-youtube-mcp` | `md_generator.media.youtube.api.mcp_server:main` | Same for YouTube (`youtube_url_to_markdown`) |
286
+ | `md-db` | `md_generator.db.cli.main:main` | `pip install "mdengine[db]"` then `md-db --config db.yaml` (or `mdengine db-to-md …`) |
287
+ | `md-db-api` | `md_generator.db.api.run:main` | FastAPI on port **8010** (`DB_TO_MD_PORT`): `POST /db-to-md/run`, `POST /db-to-md/run/sqlite` (upload + ZIP), `POST /db-to-md/job`, `POST /db-to-md/job/sqlite` (upload + async job), SSE `/db-to-md/job/{id}/events` |
288
+ | `md-db-mcp` | `md_generator.db.api.mcp_server:main` | Standalone MCP for metadata export tools |
289
+ | `md-graph` | `md_generator.graph.cli.main:main` | `pip install "mdengine[graph]"` then `md-graph --source neo4j --uri bolt://…` (or `mdengine graph-to-md …`) |
290
+ | `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` |
291
+ | `md-graph-mcp` | `md_generator.graph.api.mcp_server:main` | Standalone MCP for graph export tools |
292
+ | `md-openapi` | `md_generator.openapi.cli.main:main` | `pip install "mdengine[openapi]"` then `md-openapi generate --file openapi.yaml --output ./docs` (or `mdengine openapi-to-md generate …`) |
293
+ | `md-openapi-api` | `md_generator.openapi.api.run:main` | FastAPI on port **8015** (`OPENAPI_TO_MD_PORT`): `POST /openapi-to-md/generate` (OpenAPI upload → ZIP), `/health`, MCP at **`/mcp`** |
294
+ | `md-openapi-mcp` | `md_generator.openapi.api.mcp_server:main` | Standalone MCP: `api_validate_openapi_yaml`, `api_generate_readme_markdown`, `api_run_sync_zip_base64` |
295
+ | `mdengine` | `md_generator.engine_cli:main` | `mdengine db-to-md …` / `mdengine graph-to-md …` / `mdengine openapi-to-md generate …` |
296
+
297
+ **openapi-to-md (`md-openapi`):** OpenAPI **3.x** is parsed directly; **Swagger 2.0** (`swagger: "2.0"`) documents are **converted in-process** to OpenAPI 3.0.3 (deterministic, in-repo converter) before `$ref` resolution. Edge-heavy specs (unusual OAuth2 flows, vendor extensions) may still need fixes after conversion.
298
+
299
+ **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:`.
300
+
301
+ **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`.
302
+
303
+ **db-to-md SQLite:** set **`database.type: sqlite`** and **`database.uri`** to a SQLAlchemy URL such as **`sqlite:///my.db`** or **`sqlite:////C:/data/my.db`**. The default SQLite catalog is **`main`**; packaged YAML that still has **`schema: public`** is normalized to **`main`** when the type is SQLite. CLI: **`--type sqlite`**. Stored routines, sequences, and partitions are not used by SQLite and stay empty; tables, indexes, views, triggers, and ERD (via FK introspection) follow the same export path as other SQL engines.
304
+
305
+ **db-to-md API SQLite upload:** **`POST /db-to-md/run/sqlite`** — `multipart/form-data` with field **`file`** (the `.sqlite` / `.db` bytes; must start with the standard `SQLite format 3` header) and optional **`config`** (JSON string with the same shape as a normal run body minus `database`: `schema`, `output`, `features`, `execution`, `limits`, `erd`). Returns the metadata ZIP immediately. **`POST /db-to-md/job/sqlite`** — same form fields; saves the file under the job workspace and runs the existing job pipeline (`GET /db-to-md/job/{id}/download` when complete). Upload size cap: env **`DB_TO_MD_MAX_SQLITE_UPLOAD_MB`** (default **256**). Large ZIPs may still require the async job path if they exceed **`DB_TO_MD_MAX_SYNC_ZIP_MB`** on the sync upload route.
306
+
307
+ **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).
266
308
 
267
309
  Every command accepts **`-h` / `--help`** for full flags (artifact layout, OCR, ZIP options, etc.).
268
310
 
@@ -282,6 +324,7 @@ md-zip archive.zip ./unzipped-md
282
324
  md-url https://example.com/page ./page-bundle --artifact-layout
283
325
  md-audio ./voice.mp3 ./voice.md --model tiny
284
326
  md-video ./screen.mp4 ./screen.md --model base
327
+ pip install "mdengine[graph]" && md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output ./graph-out --viz
285
328
  ```
286
329
 
287
330
  **Windows PowerShell** (same commands; use backslashes for paths if you prefer)
@@ -292,6 +335,8 @@ md-zip .\archive.zip .\zip-out
292
335
  md-url https://example.com/page .\page-bundle --artifact-layout
293
336
  md-audio .\voice.mp3 .\voice.md --model tiny
294
337
  md-video .\screen.mp4 .\screen.md --model base
338
+ pip install "mdengine[graph]"
339
+ md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output .\graph-out --viz
295
340
  ```
296
341
 
297
342
  **Windows CMD**
@@ -575,7 +620,7 @@ Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python
575
620
 
576
621
  ### Thin shims (repo clone)
577
622
 
578
- [`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/`.
623
+ [`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/). [`openapi-to-md/converter.py`](openapi-to-md/converter.py) delegates to `md-openapi`; tests live under [`openapi-to-md/tests/`](openapi-to-md/tests/); example OpenAPI and output notes: [`openapi-to-md/examples/`](openapi-to-md/examples/).
579
624
 
580
625
  ---
581
626
 
@@ -605,6 +650,9 @@ Install `mdengine[api]` plus the format extra(s), then run the **`app`** object
605
650
  | ZIP | `md_generator.archive.api.main:app` | `archive`, `api`, `mcp` (+ extras for nested office/PDF) |
606
651
  | URL / HTML | `md_generator.url.api.main:app` | `url`, `api`, `mcp` |
607
652
  | Playwright / SPA | `md_generator.playwright.api.main:app` | `playwright`, `api`, `mcp` |
653
+ | Database metadata | `md_generator.db.api.main:app` | `db`, `api`, `mcp` |
654
+ | Graph metadata (Neo4j / NetworkX) | `md_generator.graph.api.main:app` | `graph`, `api`, `mcp` |
655
+ | OpenAPI → Markdown | `md_generator.openapi.api.main:app` | `openapi`, `api`, `mcp` |
608
656
  | Audio (Whisper) | `md_generator.media.audio.api.main:create_app` (use **`--factory`**) or `…main:app` | `audio`, `api`, `mcp` |
609
657
  | Video (Whisper) | `md_generator.media.video.api.main:create_app` (use **`--factory`**) or `…main:app` | `video`, `api`, `mcp` |
610
658
  | YouTube | `md_generator.media.youtube.api.main:create_app` (use **`--factory`**) or `…main:app` | `youtube`, `api`, `mcp` |
@@ -617,11 +665,15 @@ uvicorn md_generator.word.api.main:app --host 127.0.0.1 --port 8002
617
665
  uvicorn md_generator.archive.api.main:app --host 127.0.0.1 --port 8010
618
666
  uvicorn md_generator.url.api.main:app --host 127.0.0.1 --port 8011
619
667
  uvicorn md_generator.playwright.api.main:app --host 127.0.0.1 --port 8014
668
+ uvicorn md_generator.graph.api.main:app --host 127.0.0.1 --port 8012
669
+ uvicorn md_generator.openapi.api.main:app --host 127.0.0.1 --port 8015
620
670
  uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
621
671
  uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
622
672
  uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
623
673
  ```
624
674
 
675
+ **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. **`md-openapi-api`** defaults to **8015** (`OPENAPI_TO_MD_PORT`) so it does not collide with **`md-youtube-api`** (**8013**) or **`md-playwright-api`** (**8014**).
676
+
625
677
  ### MCP over HTTP on the same server
626
678
 
627
679
  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.
@@ -640,6 +692,9 @@ Prefixes differ per service (often read from a `.env` file next to the process):
640
692
  | XLSX | `XLSX_TO_MD_` | `XLSX_TO_MD_TEMP_DIR`, `XLSX_TO_MD_CORS_ORIGINS`, etc. (see `md_generator.xlsx.api.app`) |
641
693
  | 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` |
642
694
  | 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**) |
695
+ | 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**) |
696
+ | 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**) |
697
+ | OpenAPI → Markdown | `OPENAPI_TO_MD_` | `OPENAPI_TO_MD_CORS_ORIGINS`, `OPENAPI_TO_MD_MAX_SYNC_ZIP_MB`, `OPENAPI_TO_MD_HOST`, `OPENAPI_TO_MD_PORT` (default **8015**) |
643
698
  | 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` |
644
699
  | Video API | `MD_VIDEO_` | Same pattern as audio with `MD_VIDEO_*` (defaults: larger upload/sync caps, port **8012**) |
645
700
  | 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 |
@@ -670,6 +725,9 @@ Two usage patterns:
670
725
  | Audio | `md-audio-mcp` or `python -m md_generator.media.audio.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
671
726
  | Video | `md-video-mcp` or `python -m md_generator.media.video.api.mcp_server` — same transports |
672
727
  | YouTube | `md-youtube-mcp` or `python -m md_generator.media.youtube.api.mcp_server` — same transports |
728
+ | Database metadata | `md-db-mcp` or `python -m md_generator.db.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
729
+ | Graph (Neo4j / NetworkX) | `md-graph-mcp` or `python -m md_generator.graph.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
730
+ | OpenAPI → Markdown | `md-openapi-mcp` or `python -m md_generator.openapi.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
673
731
 
674
732
  **Word** and **XLSX** also ship a small runner script in the repo:
675
733
 
@@ -694,7 +752,7 @@ pip install -e ".[dev,all]" # or a smaller subset of extras
694
752
  python -m pytest
695
753
  ```
696
754
 
697
- Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`); `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
755
+ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`), **`graph-to-md/tests/`**, and **`openapi-to-md/tests/`**; `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
698
756
 
699
757
  ---
700
758
 
@@ -704,7 +762,7 @@ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/test
704
762
  |------|------|
705
763
  | `LICENSE` | MIT license text |
706
764
  | `CODE_OF_CONDUCT.md` | [Contributor Covenant](https://www.contributor-covenant.org/) 2.1 |
707
- | `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/) |
765
+ | `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/) |
708
766
  | `pyproject.toml` | Packaging, extras, CLI entry points, pytest |
709
767
  | `*-to-md/` | **Docs, tests, fixtures**, thin `converter.py` shims, some `run.py` helpers |
710
768
  | `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**, and **audio / video** (Whisper transcription → Markdown) into **Markdown** (and related assets). Install only the extras you need; everything imports under the **`md_generator`** package.
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
  ```
@@ -127,6 +128,28 @@ If the shell reports “command not found”, ensure the Python **Scripts** dire
127
128
  | `md-audio-mcp` | `md_generator.media.audio.api.mcp_server:main` | Standalone MCP (`--transport stdio` \| `sse` \| `streamable-http`) |
128
129
  | `md-video-mcp` | `md_generator.media.video.api.mcp_server:main` | Same for video |
129
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`, `POST /db-to-md/run/sqlite` (upload + ZIP), `POST /db-to-md/job`, `POST /db-to-md/job/sqlite` (upload + async 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
+ | `md-openapi` | `md_generator.openapi.cli.main:main` | `pip install "mdengine[openapi]"` then `md-openapi generate --file openapi.yaml --output ./docs` (or `mdengine openapi-to-md generate …`) |
138
+ | `md-openapi-api` | `md_generator.openapi.api.run:main` | FastAPI on port **8015** (`OPENAPI_TO_MD_PORT`): `POST /openapi-to-md/generate` (OpenAPI upload → ZIP), `/health`, MCP at **`/mcp`** |
139
+ | `md-openapi-mcp` | `md_generator.openapi.api.mcp_server:main` | Standalone MCP: `api_validate_openapi_yaml`, `api_generate_readme_markdown`, `api_run_sync_zip_base64` |
140
+ | `mdengine` | `md_generator.engine_cli:main` | `mdengine db-to-md …` / `mdengine graph-to-md …` / `mdengine openapi-to-md generate …` |
141
+
142
+ **openapi-to-md (`md-openapi`):** OpenAPI **3.x** is parsed directly; **Swagger 2.0** (`swagger: "2.0"`) documents are **converted in-process** to OpenAPI 3.0.3 (deterministic, in-repo converter) before `$ref` resolution. Edge-heavy specs (unusual OAuth2 flows, vendor extensions) may still need fixes after conversion.
143
+
144
+ **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:`.
145
+
146
+ **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`.
147
+
148
+ **db-to-md SQLite:** set **`database.type: sqlite`** and **`database.uri`** to a SQLAlchemy URL such as **`sqlite:///my.db`** or **`sqlite:////C:/data/my.db`**. The default SQLite catalog is **`main`**; packaged YAML that still has **`schema: public`** is normalized to **`main`** when the type is SQLite. CLI: **`--type sqlite`**. Stored routines, sequences, and partitions are not used by SQLite and stay empty; tables, indexes, views, triggers, and ERD (via FK introspection) follow the same export path as other SQL engines.
149
+
150
+ **db-to-md API SQLite upload:** **`POST /db-to-md/run/sqlite`** — `multipart/form-data` with field **`file`** (the `.sqlite` / `.db` bytes; must start with the standard `SQLite format 3` header) and optional **`config`** (JSON string with the same shape as a normal run body minus `database`: `schema`, `output`, `features`, `execution`, `limits`, `erd`). Returns the metadata ZIP immediately. **`POST /db-to-md/job/sqlite`** — same form fields; saves the file under the job workspace and runs the existing job pipeline (`GET /db-to-md/job/{id}/download` when complete). Upload size cap: env **`DB_TO_MD_MAX_SQLITE_UPLOAD_MB`** (default **256**). Large ZIPs may still require the async job path if they exceed **`DB_TO_MD_MAX_SYNC_ZIP_MB`** on the sync upload route.
151
+
152
+ **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).
130
153
 
131
154
  Every command accepts **`-h` / `--help`** for full flags (artifact layout, OCR, ZIP options, etc.).
132
155
 
@@ -146,6 +169,7 @@ md-zip archive.zip ./unzipped-md
146
169
  md-url https://example.com/page ./page-bundle --artifact-layout
147
170
  md-audio ./voice.mp3 ./voice.md --model tiny
148
171
  md-video ./screen.mp4 ./screen.md --model base
172
+ pip install "mdengine[graph]" && md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output ./graph-out --viz
149
173
  ```
150
174
 
151
175
  **Windows PowerShell** (same commands; use backslashes for paths if you prefer)
@@ -156,6 +180,8 @@ md-zip .\archive.zip .\zip-out
156
180
  md-url https://example.com/page .\page-bundle --artifact-layout
157
181
  md-audio .\voice.mp3 .\voice.md --model tiny
158
182
  md-video .\screen.mp4 .\screen.md --model base
183
+ pip install "mdengine[graph]"
184
+ md-graph --source neo4j --uri neo4j://localhost:7687 --user neo4j --password secret --database neo4j --output .\graph-out --viz
159
185
  ```
160
186
 
161
187
  **Windows CMD**
@@ -439,7 +465,7 @@ Equivalent modules: `python -m md_generator.media.audio.api.mcp_server`, `python
439
465
 
440
466
  ### Thin shims (repo clone)
441
467
 
442
- [`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/`.
468
+ [`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/). [`openapi-to-md/converter.py`](openapi-to-md/converter.py) delegates to `md-openapi`; tests live under [`openapi-to-md/tests/`](openapi-to-md/tests/); example OpenAPI and output notes: [`openapi-to-md/examples/`](openapi-to-md/examples/).
443
469
 
444
470
  ---
445
471
 
@@ -469,6 +495,9 @@ Install `mdengine[api]` plus the format extra(s), then run the **`app`** object
469
495
  | ZIP | `md_generator.archive.api.main:app` | `archive`, `api`, `mcp` (+ extras for nested office/PDF) |
470
496
  | URL / HTML | `md_generator.url.api.main:app` | `url`, `api`, `mcp` |
471
497
  | Playwright / SPA | `md_generator.playwright.api.main:app` | `playwright`, `api`, `mcp` |
498
+ | Database metadata | `md_generator.db.api.main:app` | `db`, `api`, `mcp` |
499
+ | Graph metadata (Neo4j / NetworkX) | `md_generator.graph.api.main:app` | `graph`, `api`, `mcp` |
500
+ | OpenAPI → Markdown | `md_generator.openapi.api.main:app` | `openapi`, `api`, `mcp` |
472
501
  | Audio (Whisper) | `md_generator.media.audio.api.main:create_app` (use **`--factory`**) or `…main:app` | `audio`, `api`, `mcp` |
473
502
  | Video (Whisper) | `md_generator.media.video.api.main:create_app` (use **`--factory`**) or `…main:app` | `video`, `api`, `mcp` |
474
503
  | YouTube | `md_generator.media.youtube.api.main:create_app` (use **`--factory`**) or `…main:app` | `youtube`, `api`, `mcp` |
@@ -481,11 +510,15 @@ uvicorn md_generator.word.api.main:app --host 127.0.0.1 --port 8002
481
510
  uvicorn md_generator.archive.api.main:app --host 127.0.0.1 --port 8010
482
511
  uvicorn md_generator.url.api.main:app --host 127.0.0.1 --port 8011
483
512
  uvicorn md_generator.playwright.api.main:app --host 127.0.0.1 --port 8014
513
+ uvicorn md_generator.graph.api.main:app --host 127.0.0.1 --port 8012
514
+ uvicorn md_generator.openapi.api.main:app --host 127.0.0.1 --port 8015
484
515
  uvicorn md_generator.media.audio.api.main:create_app --factory --host 127.0.0.1 --port 8011
485
516
  uvicorn md_generator.media.video.api.main:create_app --factory --host 127.0.0.1 --port 8012
486
517
  uvicorn md_generator.media.youtube.api.main:create_app --factory --host 127.0.0.1 --port 8013
487
518
  ```
488
519
 
520
+ **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. **`md-openapi-api`** defaults to **8015** (`OPENAPI_TO_MD_PORT`) so it does not collide with **`md-youtube-api`** (**8013**) or **`md-playwright-api`** (**8014**).
521
+
489
522
  ### MCP over HTTP on the same server
490
523
 
491
524
  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.
@@ -504,6 +537,9 @@ Prefixes differ per service (often read from a `.env` file next to the process):
504
537
  | XLSX | `XLSX_TO_MD_` | `XLSX_TO_MD_TEMP_DIR`, `XLSX_TO_MD_CORS_ORIGINS`, etc. (see `md_generator.xlsx.api.app`) |
505
538
  | 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` |
506
539
  | 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**) |
540
+ | 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**) |
541
+ | 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**) |
542
+ | OpenAPI → Markdown | `OPENAPI_TO_MD_` | `OPENAPI_TO_MD_CORS_ORIGINS`, `OPENAPI_TO_MD_MAX_SYNC_ZIP_MB`, `OPENAPI_TO_MD_HOST`, `OPENAPI_TO_MD_PORT` (default **8015**) |
507
543
  | 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` |
508
544
  | Video API | `MD_VIDEO_` | Same pattern as audio with `MD_VIDEO_*` (defaults: larger upload/sync caps, port **8012**) |
509
545
  | 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 |
@@ -534,6 +570,9 @@ Two usage patterns:
534
570
  | Audio | `md-audio-mcp` or `python -m md_generator.media.audio.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
535
571
  | Video | `md-video-mcp` or `python -m md_generator.media.video.api.mcp_server` — same transports |
536
572
  | YouTube | `md-youtube-mcp` or `python -m md_generator.media.youtube.api.mcp_server` — same transports |
573
+ | Database metadata | `md-db-mcp` or `python -m md_generator.db.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
574
+ | Graph (Neo4j / NetworkX) | `md-graph-mcp` or `python -m md_generator.graph.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
575
+ | OpenAPI → Markdown | `md-openapi-mcp` or `python -m md_generator.openapi.api.mcp_server` — `--transport stdio` (default), `sse`, `streamable-http` |
537
576
 
538
577
  **Word** and **XLSX** also ship a small runner script in the repo:
539
578
 
@@ -558,7 +597,7 @@ pip install -e ".[dev,all]" # or a smaller subset of extras
558
597
  python -m pytest
559
598
  ```
560
599
 
561
- Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`); `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
600
+ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/tests/`), **`graph-to-md/tests/`**, and **`openapi-to-md/tests/`**; `pyproject.toml` configures `pythonpath = ["src"]` so `md_generator` resolves without a separate `PYTHONPATH`.
562
601
 
563
602
  ---
564
603
 
@@ -568,7 +607,7 @@ Tests live under each legacy folder’s `tests/` directory (e.g. `pdf-to-md/test
568
607
  |------|------|
569
608
  | `LICENSE` | MIT license text |
570
609
  | `CODE_OF_CONDUCT.md` | [Contributor Covenant](https://www.contributor-covenant.org/) 2.1 |
571
- | `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/) |
610
+ | `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/) |
572
611
  | `pyproject.toml` | Packaging, extras, CLI entry points, pytest |
573
612
  | `*-to-md/` | **Docs, tests, fixtures**, thin `converter.py` shims, some `run.py` helpers |
574
613
  | `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.4.0"
8
- description = "Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, and web URLs to Markdown."
7
+ version = "0.6.0"
8
+ description = "Convert PDF, Office, images, audio, video, text/JSON/XML, ZIP archives, web URLs, databases, graphs, and OpenAPI specs 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", "youtube", "playwright"]
14
+ keywords = ["markdown", "pdf", "docx", "pptx", "xlsx", "ocr", "zip", "url", "html", "youtube", "playwright", "database", "openapi"]
15
15
  classifiers = [
16
16
  "Programming Language :: Python :: 3",
17
17
  "Programming Language :: Python :: 3 :: Only",
@@ -92,6 +92,25 @@ playwright = [
92
92
  "readability-lxml>=0.8.1",
93
93
  "Pillow>=10.0.0",
94
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
+ ]
109
+ openapi = [
110
+ "pyyaml>=6.0.0",
111
+ "prance>=23.6.0",
112
+ "openapi-spec-validator>=0.7.0",
113
+ ]
95
114
  api = [
96
115
  "fastapi>=0.115.0",
97
116
  "uvicorn[standard]>=0.32.0",
@@ -110,6 +129,9 @@ dev = [
110
129
  "mdengine[mcp]",
111
130
  "mdengine[url]",
112
131
  "mdengine[playwright]",
132
+ "mdengine[db]",
133
+ "mdengine[graph]",
134
+ "mdengine[openapi]",
113
135
  ]
114
136
  all = [
115
137
  "pymupdf>=1.24.0",
@@ -165,10 +187,25 @@ md-youtube-mcp = "md_generator.media.youtube.api.mcp_server:main"
165
187
  md-playwright = "md_generator.playwright.cli:main"
166
188
  md-playwright-api = "md_generator.playwright.api.run:main"
167
189
  md-playwright-mcp = "md_generator.playwright.api.mcp_server:main"
190
+ md-db = "md_generator.db.cli.main:main"
191
+ md-db-api = "md_generator.db.api.run:main"
192
+ md-db-mcp = "md_generator.db.api.mcp_server:main"
193
+ md-graph = "md_generator.graph.cli.main:main"
194
+ md-graph-api = "md_generator.graph.api.run:main"
195
+ md-graph-mcp = "md_generator.graph.api.mcp_server:main"
196
+ md-openapi = "md_generator.openapi.cli.main:main"
197
+ md-openapi-api = "md_generator.openapi.api.run:main"
198
+ md-openapi-mcp = "md_generator.openapi.api.mcp_server:main"
199
+ mdengine = "md_generator.engine_cli:main"
168
200
 
169
201
  [tool.setuptools.packages.find]
170
202
  where = ["src"]
171
203
 
204
+ [tool.setuptools.package-data]
205
+ "md_generator.db.config" = ["*.yaml"]
206
+ "md_generator.graph.config" = ["*.yaml"]
207
+ "md_generator.openapi.config" = ["*.yaml"]
208
+
172
209
  [tool.pytest.ini_options]
173
210
  pythonpath = ["src"]
174
211
  testpaths = [
@@ -184,5 +221,8 @@ testpaths = [
184
221
  "video-to-md/tests",
185
222
  "youtube-to-md/tests",
186
223
  "playwright-to-md/tests",
224
+ "db-to-md/tests",
225
+ "graph-to-md/tests",
226
+ "openapi-to-md/tests",
187
227
  ]
188
228
  markers = ["integration: optional dependency or slower checks"]
@@ -1,5 +1,5 @@
1
1
  """md_generator: PDF, Office, image, text, and ZIP to Markdown conversion."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.6.0"
4
4
 
5
5
  __all__ = ["__version__"]
@@ -0,0 +1,5 @@
1
+ """Database metadata to Markdown (LLM-ready, deterministic)."""
2
+
3
+ from md_generator.db.core.models import RunMetadata
4
+
5
+ __all__ = ["RunMetadata"]
@@ -0,0 +1,3 @@
1
+ from md_generator.db.adapters.factory import create_adapter
2
+
3
+ __all__ = ["create_adapter"]
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from sqlalchemy.engine.url import make_url
6
+
7
+ from md_generator.db.adapters.mongo_adapter import MongoAdapter
8
+ from md_generator.db.adapters.mysql_adapter import MysqlAdapter
9
+ from md_generator.db.adapters.oracle_adapter import OracleAdapter
10
+ from md_generator.db.adapters.postgres_adapter import PostgresAdapter
11
+ from md_generator.db.adapters.sqlite_adapter import SqliteAdapter
12
+ from md_generator.db.core.base_adapter import BaseAdapter
13
+
14
+
15
+ def create_adapter(
16
+ db_type: str,
17
+ uri: str,
18
+ *,
19
+ schema: str | None = None,
20
+ database: str | None = None,
21
+ limits: dict[str, Any] | None = None,
22
+ ) -> BaseAdapter:
23
+ lim = dict(limits or {})
24
+ t = db_type.lower().strip()
25
+ if t in ("postgres", "postgresql"):
26
+ sch = schema or "public"
27
+ return PostgresAdapter(uri, sch, lim)
28
+ if t in ("mysql", "mariadb"):
29
+ sch = schema or make_url(uri).database
30
+ if not sch:
31
+ raise ValueError("MySQL requires database in URI path or --schema")
32
+ return MysqlAdapter(uri, sch, lim)
33
+ if t in ("oracle",):
34
+ if not schema:
35
+ raise ValueError("Oracle requires schema (owner) in config or --schema")
36
+ return OracleAdapter(uri, schema, lim)
37
+ if t in ("mongo", "mongodb"):
38
+ if not database:
39
+ raise ValueError("MongoDB requires database name in config or --database")
40
+ return MongoAdapter(uri, database, lim)
41
+ if t in ("sqlite",):
42
+ sch = (schema or "main").strip()
43
+ if sch.lower() == "public":
44
+ sch = "main"
45
+ return SqliteAdapter(uri, sch, lim)
46
+ raise ValueError(f"Unsupported database type: {db_type!r}")