DocSlicer

by DocSlicer (open source) · Claude Desktop, Claude Code, OpenCode, Python, Windows, macOS, Linux

MCP MCP Servers Open Source v0.2.4 · 19.08.2026 активный

Быстрый детерминированный парсер и чанкер документов для RAG и агентных пайплайнов. Включает MCP-сервер для навигации агентов по длинным документам с точностью.

v0.2.4
19.08.2026 current

Установка
pip install docslicer

pip install 'docslicer[html]'    # HTML / URL parsing via Playwright
playwright install chromium      # one-time browser install (Chromium only)

pip install 'docslicer[ocr]'     # scanned PDF support via Tesseract + OpenCV
apt install tesseract-ocr        # Linux: Tesseract engine
brew install tesseract           # macOS: Tesseract engine

pip install 'docslicer[mcp]'     # MCP server for LLM clients
pip install 'docslicer[llm]'     # exact token counts via tiktoken
pip install 'docslicer[crypto]'  # password-protected Office files
pip install 'docslicer[parquet]' # Parquet export support
показать оригинал переведено ИИ

DocSlicer

PyPI Python versions License: AGPL v3 Commercial license available

Install in VS Code Add to Cursor Download .mcpb for Claude Desktop

Молниеносной (31 страниц/секунду), детерминированный парсер и чанкер документов для деловых документов. Без вызовов LLM или тяжелых ML-моделей.

DocSlicer преобразует PDF, документы Word, HTML-страницы и файлы PowerPoint в чистые фрагменты, структурированные блоки, таблицы, диаграммы, markdown и навигационную иерархию заголовков.

Лучший результат на BizDocBench (0.88 в целом против 0.70 у следующего лучшего инструмента). Точность таблиц 0.80, достоверность содержимого 0.98, распознавание заголовков и сохранение иерархии 0.85, а также производительность извлечения для RAG 0.76.

Два способа использования:

  • Как библиотека Python — классический RAG. Чанкер с учётом макета предоставляет чистые, неперекрывающиеся фрагменты, каждый из которых содержит полный путь заголовков, готовый для встраивания. Перейти к API ↓
  • Как сервер MCP — RAG без векторизации. Когда вам нужно получить ответ из документа прямо сейчас. Claude, Cursor или VS Code извлекают структуру, выбирают нужный раздел и читают только его — без векторизации и без полного 200-страничного документа в контекстном окне. Перейти к настройке ↓

Быстрый старт

import docslicer

def main():
    result = docslicer.parse_document("annual_report.pdf")

    # Inspect the outline first
    result.hierarchy.to_outline()
    # - PART I — FINANCIAL INFORMATION
    #   - Item 1. Financial Statements
    #     - Notes to Condensed Consolidated Financial Statements
    #       - Note 4 – Financial Instruments
    #         - Derivative Instruments and Hedging
    #           - Foreign Exchange Rate Risk
    #           - Interest Rate Risk
    #         - Accounts Receivable
    #           - Trade Receivables
    #   - Item 2. Management's Discussion and Analysis
    #     - Liquidity and Capital Resources
    # - PART II — OTHER INFORMATION
    #   ...

    # Pull only the chunks you need
    risk_section = result.find_heading("Risk Factors")[0]
    chunks = result.chunks_under(risk_section)

    # Tables come back structured, not as flat text
    for table in result.tables_under(risk_section):
        print(table.markdown)

if __name__ == "__main__":
    main()

Функции

  • Без LLM, VLM или ML-моделей — полностью детерминирован; нет весов моделей для загрузки, не требуется GPU, нет задержки при запуске
  • Лёгкий — колесо ~630 КБ без тяжёлых ML-зависимостей
  • Дружественный для агентов — снижает расход токенов на длинные документы: сначала агент изучает структуру, затем загружает только релевантные фрагменты в контекст, вместо того чтобы подавать 500-страничный документ дословно; идеально подходит для юридических текстов, технических процедур, финансовых отчётов и документов соответствия
  • Глубокая извлекаемость иерархии — работает как с пронумерованными (1., 1.2., 1.2.3), так и с свободными заголовками; использует размер шрифта, жирность и структуру документа — не вывод; обрабатывает повторное вхождение после разрывов приложений и повторяющиеся заголовки навигации на страницах
  • Чанки с учётом структуры — разделение на заголовки и границы абзацев, сохраняющее семантическую связность
  • Нулевое перекрытие символов — по умолчанию фрагменты не перекрываются; нет дублирующихся токенов в вашем контекстном окне
  • Единый объект результата — chunks, blocks, tables, charts, metadata и hierarchy в одном месте
  • Структурированные таблицы — таблицы возвращаются как ячейки, а не как плоский текст; экспорт в Markdown, JSONL или melt-формат
  • Несколько форматов экспорта — CSV, Markdown, JSONL, Parquet, JSON, чистый текст и DataFrame
  • Сохранение порядка чтения — включая многоколоночные макеты PDF
  • Поддержка pdf, docx, pptx и html — включая страницы, отрисованные с помощью JavaScript, через Playwright
  • Надёжное извлечение URL — всегда отрисовывает страницы в реальном браузере, обрабатывая баннеры cookies и защиту от ботов из коробки; также сохраняет стилистические сигналы, такие как жирность, которые сырые HTML опускают, обеспечивая более точное распознавание заголовков и качество фрагментов
  • Резервная OCR-обработка — автоматически обнаруживает отсканированные страницы и переключается на Tesseract, если дополнение установлено

Бенчмарки

Измерено с помощью BizDocBench — открытого эталона для анализа многформатных деловых документов. Все оценки от 0 до 1 (чем выше, тем лучше); pages_per_sec_aggregate — это пропускная способность по всей коллекции.

Инструмент Оценка Покрытие Скорость Иерархия Достоверность Таблицы Извлечение Страниц/сек
docslicer 0.8796 1.0000 0.8836 0.8466 0.9824 0.8047 0.7601 31.27
docling 0.7036 1.0000 0.3805 0.4905 0.8927 0.7467 0.7111 3.46
markitdown 0.5838 1.0000 0.8513 0.0604 0.7972 0.2584 0.5357 27.42
unstructured 0.5798 0.9091 0.1073 0.4327 0.9057 0.4812 0.6430 0.52
opendataloader 0.5359 0.5844 1.0000 0.3853 0.6484 0.2655 0.3317 117.26
pymupdf4llm 0.4519 0.5974 0.6492 0.1089 0.6456 0.3551 0.3552 11.84
mineru 0.4107 0.5974 0.1353 0.4220 0.6176 0.3012 0.3910 0.70
marker 0.3735 0.5974 0.1598 0.1926 0.6121 0.3012 0.3778 0.87
---

Установка

pip install docslicer

Базовая установка не требует множества зависимостей. Дополнительные функции доступны как дополнения (extras):

pip install 'docslicer[html]'    # HTML / URL parsing via Playwright
playwright install chromium       # one-time browser install (Chromium only)

pip install 'docslicer[ocr]'     # scanned PDF support via Tesseract + OpenCV
# The tesserocr wheel bundles libtesseract but NOT the language models,
# so install the Tesseract engine to provide them (docslicer auto-detects the path):
# Linux:  apt install tesseract-ocr
# macOS:  brew install tesseract

pip install 'docslicer[mcp]'     # MCP server for LLM clients (Claude, Cursor, …)
pip install 'docslicer[llm]'     # exact token counts via tiktoken (exact_tokens=True)
pip install 'docslicer[crypto]'  # password-protected Office files (msoffcrypto-tool)
pip install 'docslicer[parquet]' # Parquet export support

Дополнения можно объединять: pip install 'docslicer[html,ocr,llm]'.

Требуется Python 3.10+


Что вы получаете (ParseResult)

parse_document возвращает объект ParseResult:

result.chunks      # list[Chunk]   — heading-aware text chunks, ready for embedding
result.blocks      # list[Block]   — paragraph/heading/table blocks before chunking
result.tables      # list[Table]   — structured tables with cells, spans, and markdown
result.charts      # list[Chart]   — charts as extracted data points (docx/pptx)
result.metadata    # DocumentMetadata — title, author, language, page count, OCR flag
result.hierarchy   # HierarchyTree — navigable tree of all headings

Каждый Chunk содержит:

chunk.text          # str   — chunk text
chunk.path          # list  — full heading breadcrumb from root to nearest heading
chunk.heading       # str   — nearest heading above this chunk
chunk.section       # str   — body | toc | exhibit | header | footer | coverpage | …
chunk.page_number   # int   — 1-based physical page
chunk.page_label    # str   — "A-6", "iv", "F-3" — as printed on the page
chunk.table_ids     # list  — IDs of tables referenced in this chunk
chunk.chart_ids     # list  — IDs of charts referenced in this chunk (docx/pptx)
chunk.link_url      # list  — URLs found in this chunk
chunk.bbox          # BBox  — bounding box (PDF only)

Каждый фрагмент содержит полный путь заголовков, независимо от уровня вложенности. Например, абзац, вложенный на шесть уровней в финансовом документе:

chunk.path == [
    "# PART I — FINANCIAL INFORMATION",
    "## Item 1. Financial Statements",
    "### Notes to Condensed Consolidated Financial Statements (Unaudited)",
    "#### Note 4 – Financial Instruments",
    "##### Accounts Receivable",
    "###### Trade Receivables",
]

Это позволяет последующей обработке фильтровать или группировать фрагменты по любому уровню иерархии без повторного анализа документа.


Поддерживаемые форматы

Формат Расширение Примечания
PDF .pdf Текстовые и отсканированные документы (требуется дополнение ocr для отсканированных)
Word .docx Полная иерархия стилей и структуры
HTML .html, URL Статические файлы и страницы, отображённые с помощью JavaScript (требуется дополнение html для URL)
PowerPoint .pptx Слайды, заметки докладчика, графики

Не поддерживаются: .doc, .ppt (устаревшие форматы Office), .xlsx.


Разбор документов

parse_document автоматически определяет формат по расширению файла или магическим байтам. Передайте путь к файлу, URL, raw bytes или объект, похожий на файл:

result = docslicer.parse_document("contract.docx")
result = docslicer.parse_document("report.pdf")
result = docslicer.parse_document("https://www.sec.gov/Archives/edgar/data/.../10-K.htm")
result = docslicer.parse_document(file_bytes)

Параметры разбора и содержимого

parse_document (а также функции для конкретных форматов) принимают параметры, управляющие тем, что и как разбирается, перед разбиением на фрагменты. Параметры, специфичные для формата, приходятся повсюду для единообразного API, но действуют только для соответствующего формата.

result = docslicer.parse_document(
    "contract.docx",
    password="admin123",           # decrypt password-protected files; .docx and .pptx needs [crypto] extra
    max_workers=4,                 # process-pool width for PDF extraction/OCR (default: auto by CPU cores)
    include_headers_footers=True,  # docx: include header/footer content (default False)
    include_footnotes=True,        # docx: include footnotes (default True)
    include_comments=True,         # docx: include review comments (default False)
    include_speaker_notes=True,    # pptx: include slide speaker notes (default True)
    use_browser=True,              # html/URL: render in a real browser (default True)
)

Параметры разбиения на фрагменты

result = docslicer.parse_document(
    "report.pdf",
    max_chunk_size=2000,          # hard cap, default 3200
    optimal_chunk_size=800,       # target size, default 1500
    min_chunk_size=400,           # soft floor, default 700
    chunking=False,               # skip chunking, return blocks only (faster)
    merge_small_chunks=True,      # merge chunks below min_chunk_size (default True)
    table_representation="jsonl", # "markdown" (default) | "jsonl" | "melted"
    exact_tokens=True,            # exact tiktoken (cl100k_base) counts; needs [llm] extra, else char/4 estimate
    extra_fields=["is_bold", "font_size", "font_name"],  # surface internal pipeline columns on each chunk/block via .extra
)

Как работает merge_small_chunks

Поскольку DocSlicer учитывает структуру документа, изначально он создаёт один фрагмент на каждый заголовок или абзац. Для документов с множеством коротких разделов это может привести к появлению множества мелких фрагментов. При merge_small_chunks=True (по умолчанию) сестринские разделы под одним родительским заголовком объединяются до достижения min_chunk_size — но никогда не пересекают границы заголовков в другой родитель.

Например, эти пять коротких разделов все относятся к ## Products and Services Performance:

### Mac          → "Mac net sales decreased …"            (~120 chars)
### iPad         → "iPad net sales increased …"           (~180 chars)
### Wearables    → "Wearables net sales decreased …"      (~130 chars)
### Services     → "Services net sales increased …"       (~160 chars)

Вместо четырёх крошечных фрагментов они объединяются в один связный фрагмент, который всё ещё содержит правильный path для каждого абзаца. Установите merge_small_chunks=False, если вам нужно получить один фрагмент на каждый раздел, независимо от его размера.


Форматы представления таблиц

table_representation управляет тем, как таблицы сериализуются в текст фрагментов. Для финансовой таблицы с многострочными заголовками столбцов:

"markdown" (по умолчанию) — сохраняет исходный двумерный макет:


|           | Three Months Ended    | Three Months Ended    |
|           | December 27, 2025     | December 28, 2024     |
|-----------|----------------------:|----------------------:|
| iPhone ®  |              $85,269  |              $69,138  |
| Mac ®     |               8,386   |               8,987   |
| iPad ®    |               8,595   |               8,088   |
| …         |                   …   |                   …   |

"melted" — одна строка на ячейку, заголовки объединены с помощью >. Хорошо подходит для разреженных или сводных таблиц, где важно извлекать отдельные ячейки:

iPhone ® | Three Months Ended > December 27, 2025 | $85,269
iPhone ® | Three Months Ended > December 28, 2024 | $69,138
Mac ® | Three Months Ended > December 27, 2025 | 8,386
Mac ® | Three Months Ended > December 28, 2024 | 8,987
iPad ® | Three Months Ended > December 27, 2025 | 8,595
iPad ® | Three Months Ended > December 28, 2024 | 8,088
…

"jsonl" — один JSON-объект на строку, многострочные заголовки объединены с помощью _. Полезно, когда фрагменты передаются в конвейеры структурного извлечения или инструментов:

{"Metric": "iPhone ®", "Three Months Ended_December 27, 2025": "$85,269", "Three Months Ended_December 28, 2024": "$69,138"}
{"Metric": "Mac ®", "Three Months Ended_December 27, 2025": "8,386", "Three Months Ended_December 28, 2024": "8,987"}
{"Metric": "iPad ®", "Three Months Ended_December 27, 2025": "8,595", "Three Months Ended_December 28, 2024": "8,088"}
…

Пакетная обработка

Укажите parse_all на папку (или передайте список путей/URL). Он возвращает пары (источник, результат), и файл, который не удалось разобрать, возвращает Exception вместо прерывания всей партии. Любой аргумент parse_document — размеры фрагментов, include_*, и т.д. — передаётся для каждого документа.

for path, result in docslicer.parse_all("documents/", recursive=True, max_chunk_size=2000):
    if isinstance(result, Exception):
        print(f"Failed {path}: {result}")
    else:
        print(f"{path}: {len(result.chunks)} chunks")

Повторное использование конфигурации для разных документов

DocumentParser хранит фиксированную ParseConfig для множества документов и поддерживает один браузер для входов HTML/URL (запускается лениво при первом разборе HTML), поэтому партия URL-адресов запускает Chromium один раз, а не для каждого документа. Используйте его как контекстный менеджер, чтобы браузер всегда освобождался:

from docslicer import DocumentParser, ParseConfig

config = ParseConfig(max_chunk_size=1500, optimal_chunk_size=600)

with DocumentParser(config) as parser:
    for path, result in parser.parse_all(paths):   # or parser.parse(path) for one
        ...

Два уровня параллелизма

Существует два независимых параметра, и они комбинируются:

  • ParseConfig(max_workers=N) — внутри одного документа: параллелизирует извлечение слов из PDF, построение ячеек и OCR по процессам (по умолчанию: авто, размер определяется количеством ядер процессора). Лучше всего, когда документы велики.
  • DocumentParser(config, workers=N) — между документами: распределяет целые документы по N процессам-работникам, каждый со своей конфигурацией и браузером. Лучше всего, если у вас много документов. Результаты приходят в порядке отправки (этот путь не ленив по отдельным документам).

Установка workers в одиночку по умолчанию задаёт max_workers=1 для каждого работника, чтобы избежать перераспределения ресурсов на машине; установите оба параметра явно, чтобы запустить оба уровня параллелизма одновременно. Путь с workers не может передать сессию браузера или обратный вызов on_stage между процессами — не устанавливайте workers, если вам нужны эти функции.

Охраняйте точку входа. DocSlicer использует ProcessPoolExecutor каждый раз, когда есть реальная процессорная работа для распределения — любой PDF более ~50 страниц, любой отсканированный/OCR PDF любой длины, а также оба параметра параллелизма выше. Это не опция: даже простой вызов docslicer.parse_document("big.pdf") активирует его. На macOS и Windows Python создает воркеров путем повторного импорта вашего скрипта сверху вниз, поэтому разбор, выполняемый на уровне модуля, заставляет каждый воркер повторно выполнять его и снова запускаться — что приводит к ошибке RuntimeError: An attempt has been made to start a new process before the current process ... bootstrapping phase. Поместите ваш код разбора внутрь функции, защищённой условием if __name__ == "__main__"::

```python def main(): with DocumentParser(config, workers=4) as parser: for path, result in parser.parse_all(paths): ...

if name == "main": main() ```


Навигация по иерархии

Большинство библиотек разбиения на части дают вам плоский список текстовых сегментов. DocSlicer также предоставляет навигируемое дерево структуры заголовков документа, извлечённое детерминированным образом из самого документа.

Это особенно полезно для агентов и конвейеров поиска, работающих с длинными документами: вместо того чтобы загружать весь документ в контекст, агент может сначала изучить структуру, определить, какие разделы релевантны, а затем извлечь только соответствующие части — сохраняя использование токенов пропорциональным задаче.

Просмотр структуры

# Print the full heading tree
result.hierarchy.to_outline()

# Walk all top-level sections and see how much content each contains
for node in result.hierarchy.level(1):
    print(node.text, "→", len(result.chunks_under(node)), "chunks")

Переход в раздел

.level(n) возвращает все заголовки на глубине n. Передайте parent, чтобы ограничить область поиска конкретным поддеревом — типичный шаблон для агента, навигирующего по длинному документу:

# All top-level headings
l1 = result.hierarchy.level(1)

# Pick one, then list its subsections
section = result.find_heading("Financial Statements")[0]
for node in result.hierarchy.level(2, parent=section):
    print(node.text, f"(p.{node.page_number})")

# Drill one level deeper
subsection = result.hierarchy.level(2, parent=section)[0]
for node in result.hierarchy.level(3, parent=subsection):
    print(node.text)

Получение содержимого под заголовком

find_heading совпадает с любым узлом, текст которого содержит поисковый запрос (без учёта регистра). Все методы извлечения по умолчанию рекурсивно обходят подразделы.

node = result.find_heading("Financial Instruments")[0]

chunks = result.chunks_under(node)              # text chunks, ready for embedding or prompting
chunks = result.chunks_under(node, recursive=False)  # direct heading only, no subsections
tables = result.tables_under(node)              # structured tables in this section
charts = result.charts_under(node)              # charts (with extracted data points) in this section
blocks = result.blocks_under(node)              # raw paragraph/heading blocks

Навигация по страницам

result.chunks_by_page(14)        # by page number
result.chunks_by_page("F-3")     # by printed page label
result.blocks_by_page(14)
result.tables_by_page(14)
result.charts_by_page(14)

Разбор один раз, навигация много раз

Результат разбора — это просто данные, поэтому вы можете сохранить его и загрузить позже. Если агент задаёт много вопросов о том же документе, нет необходимости повторно разбирать его при каждом вопросе:

from pathlib import Path
import docslicer

cache = Path("annual_report.json")

if cache.exists():
    result = docslicer.ParseResult.load(cache)
else:
    result = docslicer.parse_document("annual_report.pdf")
    result.save(cache)

Перезагруженный результат поддерживает полный API — hierarchy, find_heading, chunks_under, tables — поэтому долгоживущая сессия агента или документный сервер могут держать документы открытыми между запросами без повторного разбора.


Экспорт

save() определяет, что писать, исходя из пути, который вы ему передаёте.

# Save the whole result and reload it later — keeps the heading hierarchy
result.save("result.json")                     # same output as result.to_json()
result = docslicer.ParseResult.load("result.json")

# A single collection, in the format you name
result.save("chunks.csv")
result.save("charts.jsonl")       # stems: chunks | blocks | tables | charts | metadata
result.export_chunks_jsonl("chunks.jsonl")

# One file per collection
result.save("output/")
# → output/chunks.parquet, blocks.parquet, tables.parquet, metadata.json
#   (+ charts.parquet when the document has charts)
#   Falls back to .csv unless the [parquet] extra is installed.

# Render as Markdown or plain text
md = result.export_to_markdown(include_tables=True)
txt = result.export_to_text()

# DataFrames
df = result.chunks_df()

Только result.json проходит полный цикл — формы коллекций и каталогов пишут плоские строки без иерархии заголовков, поэтому ParseResult.load() не может их прочитать обратно.

Режим отладки

result = docslicer.parse_document("report.pdf", debug=True)

# result.pipeline_steps is an ordered dict of step name → DataFrame
for name, df in result.pipeline_steps.items():
    print(name, df.shape)
    df.to_csv(f"debug/{name}.csv", index=False)

# PDF steps:        words → shapes → cells → lines → table_cells → blocks → chunks
# DOCX/PPTX steps:  runs → chart_points → paragraphs → lines → table_cells → blocks → chunks

OCR

parse_document автоматически обнаруживает отсканированные страницы и переключается на OCR, если установлен дополнительный пакет [ocr]. Никакой дополнительной конфигурации не требуется — result.metadata.has_ocr сообщает вам, был ли использован OCR.

pip install 'docslicer[ocr]'
# tesserocr binds libtesseract directly, so install the Tesseract dev libraries first:
# Linux:  apt install tesseract-ocr libtesseract-dev libleptonica-dev pkg-config
# macOS:  brew install tesseract leptonica

MCP-сервер

DocSlicer поставляется с MCP-сервером, поэтому клиенты ИИ (Claude Desktop, Claude Code, Cursor и т.д.) могут напрямую разбирать и читать документы.

pip install 'docslicer[mcp]'
docslicer-mcp                    # stdio — what desktop clients launch
docslicer-mcp --transport http --port 8000

Claude Desktop / Cowork — установка в один клик

Скачайте docslicer-X.Y.Z.mcpb из последнего релиза и дважды щёлкните по нему, или перетащите его на окно Claude Desktop. Выберите папку, которой DocSlicer разрешено читать и писать во время установки; никаких файлов конфигурации и собственного Python не требуется — uv настраивает интерпретатор.

Другие клиенты

Каждый клиент ниже запускает сервер через stdio. uvx не требует ничего установленного заранее:

{
  "mcpServers": {
    "docslicer": {
      "command": "uvx",
      "args": ["--from", "docslicer[mcp]", "docslicer-mcp"],
      "env": { "DOCSLICER_MCP_ROOT": "/Users/you/Documents" }
    }
  }
}

Если вы предпочитаете установить один раз и пропустить разрешение зависимостей при каждом запуске, используйте pip install 'docslicer[mcp]' (или uv tool install) и установите "command": "docslicer-mcp" без args.

Клиент Где разместить конфигурацию
Claude Code claude mcp add docslicer -- uvx --from 'docslicer[mcp]' docslicer-mcp
Cursor ~/.cursor/mcp.json, или .cursor/mcp.json для каждого проекта
VS Code .vscode/mcp.json (используйте ключ servers вместо mcpServers)
Windsurf ~/.codeium/windsurf/mcp_config.json
Zed settings.json, в разделе context_servers

Для клиентов, запущенных через графический интерфейс, предпочтительнее использовать .mcpb. Приложение, запущенное из док-станции, не наследует ваш PATH в терминале — на macOS это исключает /opt/homebrew/bin — поэтому простой uvx или docslicer-mcp могут работать в


terminal and fail when the client spawns it. Use an absolute path (which uvx) if you hit this. The extension sidesteps it entirely.

How it works

A parsed document is far larger than a model's context window, so the server never returns one in a single call. parse registers the document and hands back a doc_id handle plus a heading outline. Every other tool takes that handle and returns a bounded slice — the model pulls in only what it needs.

Tool Returns
parse doc_id handle, title, page count, heading outline
get_outline The outline again, for when it scrolls out of context
read The text under one or more headings, named from the outline
search Headings to read, ranked, each with a snippet
to_markdown Writes the whole document to disk; returns the path

Every outline line carries what reading it would cost:

- Financial statements  ~48k
  - Note 14 — Segment reporting  ~900
  - Note 15 — Income taxes  ~2.1k

That figure is the same estimate read reports back, so a budget made from the outline holds when it is spent. Sizes are cumulative — a parent never costs less than the children beneath it — which is what makes "descend or just read it" a decision the model can make before spending the context rather than after.

read takes heading text exactly as the outline prints it. Where a heading appears twice, prefixing any ancestor disambiguates it ("Notes > Revenue"); the full chain is never required. Returned text is interleaved with [Page X] markers using the document's own page labels (S-23, iv), so a quotation can be cited to the page it actually came from rather than to wherever its section began.

search is the fallback for when the outline does not settle the question — headings that name nothing useful (Note 14, Item 7A), or a figure buried in a table no heading mentions. It combines a whole-word literal match with BM25 over the chunks, and returns places, not answers: each hit is a heading to pass to read. Query terms that appear nowhere in the document are reported back, so a query that scored well on one rare word can be recognised as the bad query it was.

to_markdown is the escape hatch for when the user wants the document itself rather than an answer drawn from it. It writes to disk and returns a path, so nothing enters the model's context and document size stops mattering.

Parsed results are cached on disk, so re-parsing the same file with the same options is free. The cache key includes the file's size and mtime — edit the document and the next parse re-parses it automatically.

Configuration

Variable Effect
DOCSLICER_MCP_ROOT Restrict file sources and written output to this directory tree. Several may be given, separated by : (; on Windows)
DOCSLICER_MCP_ALLOW_CLAUDE_DIR Set to 0 to drop the Claude desktop app's own directory from the allowed roots (default 1)
DOCSLICER_MCP_ALLOW_URLS Set to 0 to reject http(s) sources
DOCSLICER_MCP_CACHE Where parsed results are persisted (default ~/.cache/docslicer-mcp)
DOCSLICER_MCP_CACHE_MAX_MB Cache size ceiling, oldest pruned first (default 2048; 0 disables)

Set DOCSLICER_MCP_ROOT when exposing the server to anything but yourself — without it, any readable path on the machine is parseable, and to_markdown can write anywhere the server process can.

Documents dropped into a chat. Attaching a file to a Claude conversation does not hand the server the path you know it by: the app first copies it into a per-session workspace under its own data directory (~/Library/Application Support/Claude on macOS, %APPDATA%\Claude on Windows), which is nowhere near the folder you would have picked as your root. That directory is therefore allowed alongside DOCSLICER_MCP_ROOT, so both routes work — the folder you chose, and whatever you drop into the chat. It is only ever added to a root you set; leaving DOCSLICER_MCP_ROOT unset still means no sandbox at all, not a sandbox of that one directory. Set DOCSLICER_MCP_ALLOW_CLAUDE_DIR=0 to opt out and accept only your own roots.

to_markdown writes beside the source document, except for a document dropped into a chat: that copy lives in a session folder you cannot navigate to, so the markdown goes to your first DOCSLICER_MCP_ROOT instead.


Command line

docslicer parses one document to JSON on stdout — for a quick look at a file, or to pipe into jq.

docslicer report.pdf                   # chunks as JSON
docslicer report.pdf -o chunks.json    # write to a file
docslicer report.pdf --no-chunking     # blocks instead of chunks

Он использует те же параметры разбора и разделения, что и parse_document; запустите docslicer --help для получения полного списка.


Функции, специфичные для форматов

Если вы знаете формат заранее и хотите явно указать на ошибку при неожиданном вводе, используйте варианты, специфичные для форматов. Они принимают те же аргументы, что и parse_document:

docslicer.parse_pdf("report.pdf")
docslicer.parse_docx("contract.docx")
docslicer.parse_pptx("deck.pptx")
docslicer.parse_html("filing.html")

Политика конфиденциальности

Политика: https://docslicer.ai/privacy

Что собирается. Ничего. DocSlicer не имеет телеметрии, аналитики, отчётов о сбоях или отслеживания использования, и не требует аккаунта, лицензионного ключа или регистрации.

Как используются ваши документы. Разбор выполняется полностью на вашем собственном устройстве, в локальном процессе. Содержимое документов используется только для создения структуры, текстовых фрагментов, результатов поиска и markdown, которые вы запрашивали, и возвращается только вызывающему коду. Документы никогда не загружаются в DocSlicer или третьи стороны. При работе как сервер MCP DOCSLICER_MCP_ROOT ограничивает, какой каталог можно прочитать и в который можно записать данные.

Где данные хранятся и как долго. Результаты разбора кэшируются на вашем собственном диске — по умолчанию ~/.cache/docslicer-mcp, настраивается с помощью DOCSLICER_MCP_CACHE. Кэш сокращается до заданного максимального размера (DOCSLICER_MCP_CACHE_MAX_MB, по умолчанию 2048 МБ); в противном случае он сохраняется, пока вы не удалите его вручную, при этом удаление каталога безвозвратно уничижает данные, не оставляя копий в других местах. Ничего не записывается за пределы каталога кэша и любого пути вывода, который вы укажете.

Доступ к сети и третьи стороны. Для локального файла не выполняется сетевых запросов. Запросы выходят с вашего устройства только при передаче источника http(s): этот URL загружается напрямую с того хоста, который вы указали, а для HTML-страниц Playwright может загрузить дополнительные ресурсы, на которые ссылается страница, как это делал бы браузер. Запросы к sec.gov отправляют заголовок User-Agent, идентифицирующий клиента, как требует политика справедливого доступа SEC. Эти хосты являются третьими сторонами, выбранными вами, а не DocSlicer, и их собственные политики управляют тем, что они логируют. Установите DOCSLICER_MCP_ALLOW_URLS=0, чтобы полностью отклонять удалённые источники.

Клиенты третьих сторон. Когда DocSlicer работает как сервер MCP, клиент (Claude, Cursor, …) обрабатывает диалог в соответствии с собственной политикой конфиденциальности. DocSlicer не становится стороной этого диалога и не получает от него ничего.

Контакты. Вопросы конфиденциальности: jelle@docslicer.ai · Задачи: https://github.com/DocSlicer/DocSlicer/issues


Лицензия

DocSlicer имеет двойную лицензию:

  • AGPL-3.0 — бесплатна для использования, изменения и распространения при соблюдении условий AGPL, включая предоставление полного исходного кода любого приложения, использующего DocSlicer, его пользователям (включая доступ по сети).
  • Коммерческая лицензия — для внедрения DocSlicer в закрытый или коммерческий продукт либо предложения его как части хостинговой/SaaS-услуги без раскрытия исходного кода.

Подробности см. в LICENSE-COMMERCIAL.md, или свяжитесь с нами по поводу коммерческой лицензии.


mcp-name: io.github.DocSlicer/docslicer

Войдите, чтобы оставить комментарий