docslicer 0.2.1__tar.gz → 0.2.2__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 (157) hide show
  1. {docslicer-0.2.1/src/docslicer.egg-info → docslicer-0.2.2}/PKG-INFO +111 -7
  2. {docslicer-0.2.1 → docslicer-0.2.2}/README.md +110 -6
  3. {docslicer-0.2.1 → docslicer-0.2.2}/pyproject.toml +1 -1
  4. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/__init__.py +1 -1
  5. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_orchestrator.py +1 -0
  6. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_result.py +2 -0
  7. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/cli.py +7 -2
  8. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/mcp/_store.py +9 -2
  9. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/mcp/server.py +208 -84
  10. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/shared_orchestrator.py +7 -1
  11. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_08_chunk_builder.py +11 -7
  12. {docslicer-0.2.1 → docslicer-0.2.2/src/docslicer.egg-info}/PKG-INFO +111 -7
  13. {docslicer-0.2.1 → docslicer-0.2.2}/LICENSE +0 -0
  14. {docslicer-0.2.1 → docslicer-0.2.2}/LICENSE-COMMERCIAL.md +0 -0
  15. {docslicer-0.2.1 → docslicer-0.2.2}/setup.cfg +0 -0
  16. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_config.py +0 -0
  17. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/__init__.py +0 -0
  18. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/color_utils.py +0 -0
  19. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/cpu.py +0 -0
  20. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_aggregation/__init__.py +0 -0
  21. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_aggregation/registry_aggregator.py +0 -0
  22. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_aggregation/text_merge.py +0 -0
  23. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_export/__init__.py +0 -0
  24. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_export/export_debug.py +0 -0
  25. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/df_export/reorder_columns.py +0 -0
  26. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/__init__.py +0 -0
  27. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/yaml_compilers/__init__.py +0 -0
  28. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/yaml_compilers/exhibit_patterns.py +0 -0
  29. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/yaml_compilers/hierarchy_type_patterns.py +0 -0
  30. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/yaml_compilers/page_label_patterns.py +0 -0
  31. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/io/yaml_loader.py +0 -0
  32. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/__init__.py +0 -0
  33. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/gutter_detector.py +0 -0
  34. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/layouts.py +0 -0
  35. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/line_merger.py +0 -0
  36. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/line_number_detector.py +0 -0
  37. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/reading_order.py +0 -0
  38. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/layout/shape_processor.py +0 -0
  39. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/oxm_package.py +0 -0
  40. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/parallel.py +0 -0
  41. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/password.py +0 -0
  42. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/safe_call.py +0 -0
  43. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/table/__init__.py +0 -0
  44. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/table/table_header.py +0 -0
  45. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/table/table_normalize.py +0 -0
  46. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/table/table_schema.py +0 -0
  47. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/text_utils.py +0 -0
  48. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/_utils/timing.py +0 -0
  49. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/config/common_author_names.csv +0 -0
  50. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/config/exhibit_patterns.yaml +0 -0
  51. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/config/hierarchy_type_patterns.yaml +0 -0
  52. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/config/page_label_patterns.yaml +0 -0
  53. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/__init__.py +0 -0
  54. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/docx_orchestrator.py +0 -0
  55. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/native_metadata.py +0 -0
  56. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_01_package_reader.py +0 -0
  57. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_02_run_extractor.py +0 -0
  58. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_03_chart_point_builder.py +0 -0
  59. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_04_table_cell_builder.py +0 -0
  60. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_05_paragraph_builder.py +0 -0
  61. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_06_line_builder.py +0 -0
  62. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/docx/step_07_style_prefiller.py +0 -0
  63. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/__init__.py +0 -0
  64. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/extract_boxes.js +0 -0
  65. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/html_orchestrator.py +0 -0
  66. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/native_metadata.py +0 -0
  67. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_01_box_extractor.py +0 -0
  68. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_01_static_box_extractor.py +0 -0
  69. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_02_box_cleaner.py +0 -0
  70. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_03_page_label_detector.py +0 -0
  71. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_04_line_builder.py +0 -0
  72. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_05_table_extractor.py +0 -0
  73. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/html/step_06_style_prefiller.py +0 -0
  74. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/mcp/__init__.py +0 -0
  75. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/__init__.py +0 -0
  76. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/consolidate.py +0 -0
  77. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/generator.py +0 -0
  78. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/ocr_detector.py +0 -0
  79. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/page_analysis.py +0 -0
  80. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/schema.py +0 -0
  81. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/metadata/text_fallback.py +0 -0
  82. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/__init__.py +0 -0
  83. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/_availability.py +0 -0
  84. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/ocr_orchestrator.py +0 -0
  85. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/step_01_word_extractor.py +0 -0
  86. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/step_02_word_colorizer.py +0 -0
  87. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/step_03_shape_extractor.py +0 -0
  88. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/step_04_text_cleaner.py +0 -0
  89. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/ocr/step_05_font_size_estimator.py +0 -0
  90. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/__init__.py +0 -0
  91. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/__init__.py +0 -0
  92. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/coordinates.py +0 -0
  93. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/form_fields.py +0 -0
  94. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/form_label_link.py +0 -0
  95. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/line_classification.py +0 -0
  96. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/page_rotation.py +0 -0
  97. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/script_thresholds.py +0 -0
  98. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/struct_context.py +0 -0
  99. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/_utils/struct_tree.py +0 -0
  100. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/native_metadata.py +0 -0
  101. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/pdf_orchestrator.py +0 -0
  102. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_01_word_extractor.py +0 -0
  103. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_02_image_extractor.py +0 -0
  104. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_03_shape_extractor.py +0 -0
  105. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_04_link_extractor.py +0 -0
  106. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_05_struct_group.py +0 -0
  107. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_06_style_prefiller.py +0 -0
  108. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_07_stream_group.py +0 -0
  109. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_08_reading_order.py +0 -0
  110. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_09_word_relationships.py +0 -0
  111. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_10_cell_builder.py +0 -0
  112. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_11_page_label_detector.py +0 -0
  113. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_12_cell_grouper.py +0 -0
  114. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_13_line_builder.py +0 -0
  115. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pdf/step_14_table_builder.py +0 -0
  116. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/__init__.py +0 -0
  117. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/native_metadata.py +0 -0
  118. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/pptx_orchestrator.py +0 -0
  119. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_01_package_reader.py +0 -0
  120. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_02_run_extractor.py +0 -0
  121. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_03_chart_point_builder.py +0 -0
  122. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_04_table_cell_builder.py +0 -0
  123. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_05_paragraph_builder.py +0 -0
  124. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_06_reading_order.py +0 -0
  125. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_07_line_builder.py +0 -0
  126. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/pptx/step_08_style_prefiller.py +0 -0
  127. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/__init__.py +0 -0
  128. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/config.py +0 -0
  129. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/cookie_consent.js +0 -0
  130. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/dispatcher.py +0 -0
  131. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/fetchers/__init__.py +0 -0
  132. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/fetchers/http_fetcher.py +0 -0
  133. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/fetchers/sec_fetcher.py +0 -0
  134. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/models.py +0 -0
  135. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/scraping/stealth_init.js +0 -0
  136. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/__init__.py +0 -0
  137. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_01_navigation_detector.py +0 -0
  138. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_02_toc_detector.py +0 -0
  139. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_03_exhibit_detector.py +0 -0
  140. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_04_section_classifier.py +0 -0
  141. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_05_heading_detector.py +0 -0
  142. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_06_hierarchy_builder.py +0 -0
  143. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer/shared/step_07_block_merger.py +0 -0
  144. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer.egg-info/SOURCES.txt +0 -0
  145. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer.egg-info/dependency_links.txt +0 -0
  146. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer.egg-info/entry_points.txt +0 -0
  147. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer.egg-info/requires.txt +0 -0
  148. {docslicer-0.2.1 → docslicer-0.2.2}/src/docslicer.egg-info/top_level.txt +0 -0
  149. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_api.py +0 -0
  150. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_charts.py +0 -0
  151. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_document_parser.py +0 -0
  152. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_errors.py +0 -0
  153. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_exports.py +0 -0
  154. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_loose_box_reconstruction.py +0 -0
  155. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_packaging.py +0 -0
  156. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_smoke.py +0 -0
  157. {docslicer-0.2.1 → docslicer-0.2.2}/tests/test_table_cell_newlines.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docslicer
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Deterministic hierarchical document parser and chunker
5
5
  Author-email: "Market Framer Inc." <jelle@docslicer.ai>
6
6
  License-Expression: AGPL-3.0-only
@@ -60,7 +60,9 @@ Dynamic: license-file
60
60
 
61
61
  # DocSlicer
62
62
 
63
- [![PyPI](https://img.shields.io/pypi/v/docslicer.svg)](https://pypi.org/project/docslicer/) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![Commercial license available](https://img.shields.io/badge/License-Commercial-green.svg)](LICENSE-COMMERCIAL.md)
63
+ [![PyPI](https://img.shields.io/pypi/v/docslicer.svg)](https://pypi.org/project/docslicer/) [![Python versions](https://img.shields.io/pypi/pyversions/docslicer.svg)](https://pypi.org/project/docslicer/) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![Commercial license available](https://img.shields.io/badge/License-Commercial-green.svg)](LICENSE-COMMERCIAL.md)
64
+
65
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-0098FF?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=docslicer&config=%7B%22name%22%3A%22docslicer%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22docslicer%5Bmcp%5D%22%2C%22docslicer-mcp%22%5D%7D) [![Add to Cursor](https://img.shields.io/badge/Cursor-Add_MCP_server-000000?logo=cursor&logoColor=white)](https://cursor.com/install-mcp?name=docslicer&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJkb2NzbGljZXJbbWNwXSIsImRvY3NsaWNlci1tY3AiXX0%3D) [![Download .mcpb for Claude Desktop](https://img.shields.io/badge/Claude_Desktop-Download_.mcpb-D97757?logo=claude&logoColor=white)](https://github.com/DocSlicer/DocSlicer/releases/latest)
64
66
 
65
67
  Lightning-fast (31 pages/sec), deterministic document parser and chunker for business documents. No LLM calls or heavy ML models.
66
68
 
@@ -68,9 +70,12 @@ DocSlicer turns PDFs, Word documents, HTML pages, and PowerPoint files into clea
68
70
 
69
71
  Top score on [BizDocBench](https://github.com/DocSlicer/BizDocBench) (0.88 overall vs 0.70 for the next-best tool). 0.80 table accuracy, 0.98 content faithfulness, 0.85 heading recognition and hierarchy preservation, and 0.76 RAG retrieval performance.
70
72
 
71
- **Add DocSlicer to your AI pipeline:**
72
- - Classic RAG: the layout-aware chunker gives you clean non-overlapping chunks, each carrying its full heading breadcrumb, ready to embed.
73
- - Vectorless RAG: for when you want an answer out of a document right now. The agent pulls the outline, picks the section it needs, and navigates to the correct section of text without embedding the whole document
73
+ **Two ways to use it:**
74
+
75
+ - **As a Python library — classic RAG.** The layout-aware chunker gives you clean, non-overlapping chunks, each carrying its full heading breadcrumb, ready to embed. [Jump to the API ↓](#parsing)
76
+ - **As an MCP server — vectorless RAG.** For when you want an answer out of a document right now. Claude, Cursor, or VS Code pulls the outline, picks the section it needs, and reads only that — no embedding, and no 200-page document in the context window. [Jump to setup ↓](#mcp-server)
77
+
78
+ ### Quick start
74
79
 
75
80
  ```python
76
81
  import docslicer
@@ -562,19 +567,49 @@ docslicer-mcp # stdio — what desktop clients launch
562
567
  docslicer-mcp --transport http --port 8000
563
568
  ```
564
569
 
565
- Register it with a client by adding to its MCP config:
570
+ ### Claude Desktop / Cowork — one-click install
571
+
572
+ Download `docslicer-X.Y.Z.mcpb` from the
573
+ [latest release](https://github.com/DocSlicer/DocSlicer/releases/latest) and
574
+ double-click it, or drag it onto the Claude Desktop window. You pick the folder
575
+ DocSlicer is allowed to read and write during install; no config file, and no
576
+ Python of your own — `uv` provisions the interpreter.
577
+
578
+ ### Other clients
579
+
580
+ Every client below launches the server over stdio. `uvx` needs nothing
581
+ installed ahead of time:
566
582
 
567
583
  ```jsonc
568
584
  {
569
585
  "mcpServers": {
570
586
  "docslicer": {
571
- "command": "docslicer-mcp",
587
+ "command": "uvx",
588
+ "args": ["--from", "docslicer[mcp]", "docslicer-mcp"],
572
589
  "env": { "DOCSLICER_MCP_ROOT": "/Users/you/Documents" }
573
590
  }
574
591
  }
575
592
  }
576
593
  ```
577
594
 
595
+ If you'd rather install it once and skip the resolve on every launch, use
596
+ `pip install 'docslicer[mcp]'` (or `uv tool install`) and set
597
+ `"command": "docslicer-mcp"` with no `args`.
598
+
599
+ | Client | Where the config goes |
600
+ | --- | --- |
601
+ | Claude Code | `claude mcp add docslicer -- uvx --from 'docslicer[mcp]' docslicer-mcp` |
602
+ | Cursor | `~/.cursor/mcp.json`, or `.cursor/mcp.json` per project |
603
+ | VS Code | `.vscode/mcp.json` (use a `servers` key instead of `mcpServers`) |
604
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
605
+ | Zed | `settings.json`, under `context_servers` |
606
+
607
+ > **On GUI-launched clients, prefer the `.mcpb`.** An app started from the dock
608
+ > does not inherit your shell `PATH` — on macOS that excludes
609
+ > `/opt/homebrew/bin` — so a bare `uvx` or `docslicer-mcp` can work in a
610
+ > terminal and fail when the client spawns it. Use an absolute path
611
+ > (`which uvx`) if you hit this. The extension sidesteps it entirely.
612
+
578
613
  ### How it works
579
614
 
580
615
  A parsed document is far larger than a model's context window, so the server
@@ -641,6 +676,22 @@ can write anywhere the server process can.
641
676
 
642
677
  ---
643
678
 
679
+ ## Command line
680
+
681
+ `docslicer` parses one document to JSON on stdout — for a quick look at a file,
682
+ or to pipe into `jq`.
683
+
684
+ ```bash
685
+ docslicer report.pdf # chunks as JSON
686
+ docslicer report.pdf -o chunks.json # write to a file
687
+ docslicer report.pdf --no-chunking # blocks instead of chunks
688
+ ```
689
+
690
+ It takes the same parsing and chunking options as `parse_document`; run
691
+ `docslicer --help` for the full list.
692
+
693
+ ---
694
+
644
695
  ## Format-specific functions
645
696
 
646
697
  If you know the format upfront and want explicit failure on unexpected input, use the
@@ -655,6 +706,47 @@ docslicer.parse_html("filing.html")
655
706
 
656
707
  ---
657
708
 
709
+ ## Privacy Policy
710
+
711
+ Full policy: <https://docslicer.ai/privacy>
712
+
713
+ **What is collected.** Nothing. DocSlicer has no telemetry, analytics, crash
714
+ reporting, or usage tracking, and requires no account, licence key, or
715
+ registration.
716
+
717
+ **How your documents are used.** Parsing runs entirely on your own machine, in a
718
+ local process. Document contents are used only to produce the outline, text
719
+ slices, search results, and markdown you ask for, and are returned only to the
720
+ caller. Documents are never uploaded to DocSlicer or to any third party. When
721
+ running as an MCP server, `DOCSLICER_MCP_ROOT` bounds which directory tree may
722
+ be read from and written to.
723
+
724
+ **Where data is stored, and for how long.** Parsed results are cached on your
725
+ own disk — by default `~/.cache/docslicer-mcp`, configurable with
726
+ `DOCSLICER_MCP_CACHE`. The cache is pruned to a size ceiling
727
+ (`DOCSLICER_MCP_CACHE_MAX_MB`, default 2048 MB); otherwise it persists until you
728
+ delete it, and deleting the directory removes it permanently with no copy
729
+ retained elsewhere. Nothing is written outside the cache directory and any
730
+ output path you supply.
731
+
732
+ **Network access and third parties.** No network request is made for a local
733
+ file. Requests leave your machine only when you pass an `http(s)` source: that
734
+ URL is fetched directly from the host you named, and for HTML pages Playwright
735
+ may load the subresources that page references, exactly as a browser would.
736
+ Requests to `sec.gov` send a `User-Agent` header identifying the client, as the
737
+ SEC fair-access policy requires. These hosts are third parties chosen by you,
738
+ not by DocSlicer, and their own policies govern what they log. Set
739
+ `DOCSLICER_MCP_ALLOW_URLS=0` to reject remote sources entirely.
740
+
741
+ **Third-party clients.** When DocSlicer runs as an MCP server, the client
742
+ (Claude, Cursor, …) handles the conversation under its own privacy policy.
743
+ DocSlicer is not a party to that and receives nothing from it.
744
+
745
+ **Contact.** Privacy questions: jelle@docslicer.ai · Issues:
746
+ <https://github.com/DocSlicer/DocSlicer/issues>
747
+
748
+ ---
749
+
658
750
  ## License
659
751
 
660
752
  DocSlicer is **dual-licensed**:
@@ -663,3 +755,15 @@ DocSlicer is **dual-licensed**:
663
755
  - **[Commercial license](LICENSE-COMMERCIAL.md)** — for embedding DocSlicer in a closed-source or proprietary product, or offering it as part of a hosted/SaaS service without releasing your source.
664
756
 
665
757
  See [LICENSE-COMMERCIAL.md](LICENSE-COMMERCIAL.md) for details, or reach out about a commercial license.
758
+
759
+ ---
760
+
761
+ <!--
762
+ Ownership marker for the official MCP registry (registry.modelcontextprotocol.io).
763
+ The registry verifies a PyPI package by looking for this exact line in the
764
+ project description, which is this README — so it only takes effect once a
765
+ release carrying it is published. Namespace matches the GitHub org that owns
766
+ the repository. Leave it in place; removing it breaks re-publication.
767
+ -->
768
+
769
+ mcp-name: io.github.DocSlicer/docslicer
@@ -1,6 +1,8 @@
1
1
  # DocSlicer
2
2
 
3
- [![PyPI](https://img.shields.io/pypi/v/docslicer.svg)](https://pypi.org/project/docslicer/) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![Commercial license available](https://img.shields.io/badge/License-Commercial-green.svg)](LICENSE-COMMERCIAL.md)
3
+ [![PyPI](https://img.shields.io/pypi/v/docslicer.svg)](https://pypi.org/project/docslicer/) [![Python versions](https://img.shields.io/pypi/pyversions/docslicer.svg)](https://pypi.org/project/docslicer/) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![Commercial license available](https://img.shields.io/badge/License-Commercial-green.svg)](LICENSE-COMMERCIAL.md)
4
+
5
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-0098FF?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=docslicer&config=%7B%22name%22%3A%22docslicer%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22docslicer%5Bmcp%5D%22%2C%22docslicer-mcp%22%5D%7D) [![Add to Cursor](https://img.shields.io/badge/Cursor-Add_MCP_server-000000?logo=cursor&logoColor=white)](https://cursor.com/install-mcp?name=docslicer&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJkb2NzbGljZXJbbWNwXSIsImRvY3NsaWNlci1tY3AiXX0%3D) [![Download .mcpb for Claude Desktop](https://img.shields.io/badge/Claude_Desktop-Download_.mcpb-D97757?logo=claude&logoColor=white)](https://github.com/DocSlicer/DocSlicer/releases/latest)
4
6
 
5
7
  Lightning-fast (31 pages/sec), deterministic document parser and chunker for business documents. No LLM calls or heavy ML models.
6
8
 
@@ -8,9 +10,12 @@ DocSlicer turns PDFs, Word documents, HTML pages, and PowerPoint files into clea
8
10
 
9
11
  Top score on [BizDocBench](https://github.com/DocSlicer/BizDocBench) (0.88 overall vs 0.70 for the next-best tool). 0.80 table accuracy, 0.98 content faithfulness, 0.85 heading recognition and hierarchy preservation, and 0.76 RAG retrieval performance.
10
12
 
11
- **Add DocSlicer to your AI pipeline:**
12
- - Classic RAG: the layout-aware chunker gives you clean non-overlapping chunks, each carrying its full heading breadcrumb, ready to embed.
13
- - Vectorless RAG: for when you want an answer out of a document right now. The agent pulls the outline, picks the section it needs, and navigates to the correct section of text without embedding the whole document
13
+ **Two ways to use it:**
14
+
15
+ - **As a Python library — classic RAG.** The layout-aware chunker gives you clean, non-overlapping chunks, each carrying its full heading breadcrumb, ready to embed. [Jump to the API ↓](#parsing)
16
+ - **As an MCP server — vectorless RAG.** For when you want an answer out of a document right now. Claude, Cursor, or VS Code pulls the outline, picks the section it needs, and reads only that — no embedding, and no 200-page document in the context window. [Jump to setup ↓](#mcp-server)
17
+
18
+ ### Quick start
14
19
 
15
20
  ```python
16
21
  import docslicer
@@ -502,19 +507,49 @@ docslicer-mcp # stdio — what desktop clients launch
502
507
  docslicer-mcp --transport http --port 8000
503
508
  ```
504
509
 
505
- Register it with a client by adding to its MCP config:
510
+ ### Claude Desktop / Cowork — one-click install
511
+
512
+ Download `docslicer-X.Y.Z.mcpb` from the
513
+ [latest release](https://github.com/DocSlicer/DocSlicer/releases/latest) and
514
+ double-click it, or drag it onto the Claude Desktop window. You pick the folder
515
+ DocSlicer is allowed to read and write during install; no config file, and no
516
+ Python of your own — `uv` provisions the interpreter.
517
+
518
+ ### Other clients
519
+
520
+ Every client below launches the server over stdio. `uvx` needs nothing
521
+ installed ahead of time:
506
522
 
507
523
  ```jsonc
508
524
  {
509
525
  "mcpServers": {
510
526
  "docslicer": {
511
- "command": "docslicer-mcp",
527
+ "command": "uvx",
528
+ "args": ["--from", "docslicer[mcp]", "docslicer-mcp"],
512
529
  "env": { "DOCSLICER_MCP_ROOT": "/Users/you/Documents" }
513
530
  }
514
531
  }
515
532
  }
516
533
  ```
517
534
 
535
+ If you'd rather install it once and skip the resolve on every launch, use
536
+ `pip install 'docslicer[mcp]'` (or `uv tool install`) and set
537
+ `"command": "docslicer-mcp"` with no `args`.
538
+
539
+ | Client | Where the config goes |
540
+ | --- | --- |
541
+ | Claude Code | `claude mcp add docslicer -- uvx --from 'docslicer[mcp]' docslicer-mcp` |
542
+ | Cursor | `~/.cursor/mcp.json`, or `.cursor/mcp.json` per project |
543
+ | VS Code | `.vscode/mcp.json` (use a `servers` key instead of `mcpServers`) |
544
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
545
+ | Zed | `settings.json`, under `context_servers` |
546
+
547
+ > **On GUI-launched clients, prefer the `.mcpb`.** An app started from the dock
548
+ > does not inherit your shell `PATH` — on macOS that excludes
549
+ > `/opt/homebrew/bin` — so a bare `uvx` or `docslicer-mcp` can work in a
550
+ > terminal and fail when the client spawns it. Use an absolute path
551
+ > (`which uvx`) if you hit this. The extension sidesteps it entirely.
552
+
518
553
  ### How it works
519
554
 
520
555
  A parsed document is far larger than a model's context window, so the server
@@ -581,6 +616,22 @@ can write anywhere the server process can.
581
616
 
582
617
  ---
583
618
 
619
+ ## Command line
620
+
621
+ `docslicer` parses one document to JSON on stdout — for a quick look at a file,
622
+ or to pipe into `jq`.
623
+
624
+ ```bash
625
+ docslicer report.pdf # chunks as JSON
626
+ docslicer report.pdf -o chunks.json # write to a file
627
+ docslicer report.pdf --no-chunking # blocks instead of chunks
628
+ ```
629
+
630
+ It takes the same parsing and chunking options as `parse_document`; run
631
+ `docslicer --help` for the full list.
632
+
633
+ ---
634
+
584
635
  ## Format-specific functions
585
636
 
586
637
  If you know the format upfront and want explicit failure on unexpected input, use the
@@ -595,6 +646,47 @@ docslicer.parse_html("filing.html")
595
646
 
596
647
  ---
597
648
 
649
+ ## Privacy Policy
650
+
651
+ Full policy: <https://docslicer.ai/privacy>
652
+
653
+ **What is collected.** Nothing. DocSlicer has no telemetry, analytics, crash
654
+ reporting, or usage tracking, and requires no account, licence key, or
655
+ registration.
656
+
657
+ **How your documents are used.** Parsing runs entirely on your own machine, in a
658
+ local process. Document contents are used only to produce the outline, text
659
+ slices, search results, and markdown you ask for, and are returned only to the
660
+ caller. Documents are never uploaded to DocSlicer or to any third party. When
661
+ running as an MCP server, `DOCSLICER_MCP_ROOT` bounds which directory tree may
662
+ be read from and written to.
663
+
664
+ **Where data is stored, and for how long.** Parsed results are cached on your
665
+ own disk — by default `~/.cache/docslicer-mcp`, configurable with
666
+ `DOCSLICER_MCP_CACHE`. The cache is pruned to a size ceiling
667
+ (`DOCSLICER_MCP_CACHE_MAX_MB`, default 2048 MB); otherwise it persists until you
668
+ delete it, and deleting the directory removes it permanently with no copy
669
+ retained elsewhere. Nothing is written outside the cache directory and any
670
+ output path you supply.
671
+
672
+ **Network access and third parties.** No network request is made for a local
673
+ file. Requests leave your machine only when you pass an `http(s)` source: that
674
+ URL is fetched directly from the host you named, and for HTML pages Playwright
675
+ may load the subresources that page references, exactly as a browser would.
676
+ Requests to `sec.gov` send a `User-Agent` header identifying the client, as the
677
+ SEC fair-access policy requires. These hosts are third parties chosen by you,
678
+ not by DocSlicer, and their own policies govern what they log. Set
679
+ `DOCSLICER_MCP_ALLOW_URLS=0` to reject remote sources entirely.
680
+
681
+ **Third-party clients.** When DocSlicer runs as an MCP server, the client
682
+ (Claude, Cursor, …) handles the conversation under its own privacy policy.
683
+ DocSlicer is not a party to that and receives nothing from it.
684
+
685
+ **Contact.** Privacy questions: jelle@docslicer.ai · Issues:
686
+ <https://github.com/DocSlicer/DocSlicer/issues>
687
+
688
+ ---
689
+
598
690
  ## License
599
691
 
600
692
  DocSlicer is **dual-licensed**:
@@ -603,3 +695,15 @@ DocSlicer is **dual-licensed**:
603
695
  - **[Commercial license](LICENSE-COMMERCIAL.md)** — for embedding DocSlicer in a closed-source or proprietary product, or offering it as part of a hosted/SaaS service without releasing your source.
604
696
 
605
697
  See [LICENSE-COMMERCIAL.md](LICENSE-COMMERCIAL.md) for details, or reach out about a commercial license.
698
+
699
+ ---
700
+
701
+ <!--
702
+ Ownership marker for the official MCP registry (registry.modelcontextprotocol.io).
703
+ The registry verifies a PyPI package by looking for this exact line in the
704
+ project description, which is this README — so it only takes effect once a
705
+ release carrying it is published. Namespace matches the GitHub org that owns
706
+ the repository. Leave it in place; removing it breaks re-publication.
707
+ -->
708
+
709
+ mcp-name: io.github.DocSlicer/docslicer
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "docslicer"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "Deterministic hierarchical document parser and chunker"
9
9
  readme = "README.md"
10
10
  license = "AGPL-3.0-only"
@@ -20,7 +20,7 @@ try:
20
20
  from importlib.metadata import version as _pkg_version
21
21
  __version__ = _pkg_version("docslicer")
22
22
  except Exception:
23
- __version__ = "0.2.0"
23
+ __version__ = "0.2.2"
24
24
 
25
25
  from ._config import ParseConfig
26
26
  from ._result import ParseResult, Chunk, Block, Table, TableCell, Chart, ChartPoint, BBox, HierarchyNode, HierarchyTree
@@ -306,6 +306,7 @@ def _build_blocks(df_blocks: pd.DataFrame, extra_fields: list[str] | None = None
306
306
  link_url=_str_list(row, "link_url"),
307
307
  table_ids=_str_list(row, "table_id"),
308
308
  chart_ids=_str_list(row, "chart_id"),
309
+ token_count=int(row.get("token_count", 0) or 0),
309
310
  extra=_extra(row, _extra_fields),
310
311
  ))
311
312
  return out
@@ -134,6 +134,7 @@ class Block:
134
134
  link_url: list[str] # unique URLs found in block
135
135
  table_ids: list[str] # table IDs referenced in block
136
136
  chart_ids: list[str] = field(default_factory=list) # chart IDs referenced in block (docx/pptx)
137
+ token_count: int = 0 # counted like Chunk.token_count, for budgeting a read
137
138
  extra: dict = field(default_factory=dict) # caller-requested extra fields from the pipeline df
138
139
 
139
140
  @classmethod
@@ -151,6 +152,7 @@ class Block:
151
152
  link_url=d.get("link_url", []),
152
153
  table_ids=[_norm_id(v) for v in d.get("table_ids", [])],
153
154
  chart_ids=[_norm_id(v) for v in d.get("chart_ids", [])],
155
+ token_count=d.get("token_count", 0),
154
156
  extra=d.get("extra", {}),
155
157
  )
156
158
 
@@ -112,10 +112,15 @@ def main():
112
112
  print(f"Error: {exc}", file=sys.stderr)
113
113
  sys.exit(1)
114
114
 
115
- out = json.dumps([c.to_dict() for c in result.chunks], indent=2)
115
+ # --no-chunking stops the pipeline before chunks exist, so blocks are the
116
+ # unit it has to return; serializing chunks regardless printed an empty
117
+ # list for the one flag whose whole purpose is to produce output faster.
118
+ records = result.blocks if args.no_chunking else result.chunks
119
+ label = "blocks" if args.no_chunking else "chunks"
120
+ out = json.dumps([r.to_dict() for r in records], indent=2)
116
121
 
117
122
  if args.output:
118
123
  Path(args.output).write_text(out, encoding="utf-8")
119
- print(f"Wrote {len(result.chunks)} chunks to {args.output}")
124
+ print(f"Wrote {len(records)} {label} to {args.output}")
120
125
  else:
121
126
  print(out)
@@ -21,6 +21,7 @@ from collections import OrderedDict
21
21
  from dataclasses import dataclass
22
22
  from pathlib import Path
23
23
 
24
+ from .. import __version__
24
25
  from .._result import ParseResult
25
26
 
26
27
  _MEMORY_LIMIT = 8 # ParseResults kept hot in RAM
@@ -137,8 +138,14 @@ def resolve_output(path: str, base: Path | None = None) -> Path:
137
138
 
138
139
 
139
140
  def make_doc_id(source: str, options: dict) -> str:
140
- """Stable handle for a (source, options, file-version) triple."""
141
- fingerprint = {"source": source, "options": options}
141
+ """Stable handle for a (source, options, file-version, docslicer-version) quad.
142
+
143
+ The version is in the fingerprint because a cached parse is a snapshot of
144
+ what the pipeline produced at the time, fields and all. A release that adds
145
+ one — block token counts, say — would otherwise be served stale records
146
+ missing it, and a missing field reads as a zero rather than an error.
147
+ """
148
+ fingerprint = {"source": source, "options": options, "docslicer": __version__}
142
149
  if not is_url(source):
143
150
  try:
144
151
  stat = Path(source).stat()