doc-splitter
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@doc-splittersplit 'calculus-notes.pdf' into study chunks"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ducsplit
Conceptual document splitter for verified, study-sized chunks — CLI and MCP.
ducsplit splits large PDF and DOCX documents into study-sized conceptual chunks, not blind page ranges. It is built for developers using AI coding assistants (Claude Code, Codex, Cursor, Grok, OpenCode, or any MCP-capable host) who need to break textbooks, lecture notes, and manuals into sessions an agent can actually work with.
Repository: github.com/alifazelidehkordi/ducsplit
Table of Contents
Related MCP server: BigContext MCP
Why This Exists
Long study documents overwhelm AI assistants: they exceed context windows, trigger lost-in-the-middle failures, and waste tokens. Simple page slicing makes it worse — it cuts through arguments, divorces tables from their explanations, and ignores how the author actually structured the material.
ducsplit combines deterministic document parsing with host-agent reasoning:
The tool extracts structured elements from PDF or DOCX into a shared intermediate representation (IR).
It proposes structurally safe boundary candidates — only after complete paragraphs, headings, lists, or tables.
Your host AI agent reads the surrounding content and chooses the best conceptual cut (or extends the window if the topic continues).
Output is verified for missing, duplicated, or mismatched content.
Each chunk can be analyzed into bilingual Persian/English study metadata.
Final study indexes link to every session and include a practical Study Focus column.
ducsplit does not bundle its own LLM. The host agent supplies judgment; ducsplit supplies parsing, constraints, persistence, writing, and verification.
Key Features
Conceptual splitting — targets 5–10 page study sessions, but lets concept completeness override page count.
Safe-cut constraints — the LLM can only choose from deterministic candidates, preventing mid-paragraph, mid-list, and mid-table cuts.
Dual PDF parsing —
pymupdf4llmfor Markdown-like extraction plus OpenDataLoader for layout reconciliation when Java is available.DOCX support — headings, paragraphs, lists, tables, and embedded images via
python-docx.CLI and MCP — use
doc-splitterdirectly or expose it as an MCP server to AI coding assistants.Verified output — checks element coverage, duplicates, word-count drift, table rows, image references, and PDF page coverage.
Markdown and PDF chunks — write semantic Markdown chunks, extracted PDF chunks, or both.
Boundary overlap for PDFs — includes adjacent boundary pages to reduce loss when conceptual cuts occur mid-page.
Agent-authored bilingual study indexes — provides verified context for the host agent to write
study-index-fa.mdandstudy-index-en.mdwith session links, study focus, page ranges, and estimated reading time.Agent-decision enforcement — rejects auto-generated reasons (
auto-cut,auto from section_headings), template study-focus, and index commits without reading every chunk file.Realistic study-time estimates — defaults to 80 words per minute (study speed) rather than casual reading speed (200 wpm) for technical/medical content.
Architecture
flowchart TD
A[PDF or DOCX input] --> B[Format Detector]
B -->|PDF| C[pymupdf4llm Parser]
B -->|PDF| D[OpenDataLoader Layout Parser]
C --> E[Document IR]
D --> F[PDF Reconciler]
F --> E
B -->|DOCX| G[python-docx Parser]
G --> E
E --> H[Structure Analyzer]
H --> I[Safe Boundary Candidate Generator]
I --> J{Host AI Agent}
J -->|cut| K[Boundary Session]
J -->|extend| I
K --> L[Writer]
L -->|markdown| M[.md Chunks]
L -->|pdf| N[.pdf Chunks]
L --> O[manifest.json]
O --> P[Verifier]
P --> Q[verification-report.json]
M --> R{Host AI Agent}
N --> R
R --> S[Chunk Analysis Store]
S --> T[Index Generator]
T --> U[study-index-fa.md]
T --> V[study-index-en.md]Requirements
Dependency | Version | Purpose |
Python | 3.10+ | Core pipeline and CLI |
Java | 11+ | OpenDataLoader PDF layout reconciliation (recommended) |
Node.js | 18+ | MCP server only |
Host AI agent | — | Boundary decisions and chunk content analysis |
Java is recommended for better PDF reconciliation. Parsing falls back to pymupdf4llm alone if OpenDataLoader cannot run.
Installation
git clone https://github.com/alifazelidehkordi/ducsplit.git
cd ducsplit
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
npm install
java -version # must succeed for full PDF reconciliationThe Python package exposes the CLI:
doc-splitter --helpIf the command is not on your shell path:
python -m doc_splitter.cli --helpQuick Start: CLI
Start a split session:
doc-splitter run \
--input ./book.pdf \
--out ./output/book \
--min-pages 5 \
--max-pages 10This parses the document, writes ir.json, creates .split-session.json, and prints the first boundary decision context.
Repeat the boundary loop until the context reports status: "complete":
doc-splitter boundary-context --out ./output/bookAsk your host agent to read the JSON, choose one safe candidate, and return either:
{
"action": "cut",
"element_id": "el-042",
"reason": "The current explanation ends here; the next section starts a different topic."
}Commit the decision:
doc-splitter commit-boundary \
--out ./output/book \
--action cut \
--element-id el-042 \
--reason "The current explanation ends here; the next section starts a different topic."If the concept continues beyond the current window:
doc-splitter commit-boundary \
--out ./output/book \
--action extend \
--reason "The same mechanism continues into the next example."After boundaries are complete, write and verify chunks:
doc-splitter write --out ./output/bookAnalyze each chunk:
doc-splitter analysis-context --out ./output/book --chunk-id 1Commit the host agent's bilingual analysis:
doc-splitter commit-analysis \
--out ./output/book \
--chunk-id 1 \
--topic-fa "تنظیم گلوکز و پاسخ انسولین" \
--topic-en "Glucose Regulation and Insulin Response" \
--study-focus-fa "مسیرهای اصلی تنظیم قند خون، نقش انسولین و تفاوت پاسخ طبیعی و پاتولوژیک را مرور کنید." \
--study-focus-en "Review the main glucose-control pathways, insulin's role, and how normal and pathological responses differ." \
--coherence confident \
--reason "The chunk covers one continuous regulatory mechanism."Ask the host agent to write the final indexes after every chunk has analysis:
doc-splitter index --out ./output/book
doc-splitter commit-index \
--out ./output/book \
--fa-file ./agent-written-study-index-fa.md \
--en-file ./agent-written-study-index-en.mdPDF-native chunks
doc-splitter run \
--input ./book.pdf \
--out ./output/book-pdf \
--output-format pdf \
--overlap-pages 1Quick Start: MCP
After npm install, register the MCP server with your host CLI (replace the path if you cloned elsewhere):
REPO=/absolute/path/to/ducsplit
claude mcp add doc-splitter -s user -- node "$REPO/server.js"
codex mcp add doc-splitter -- node "$REPO/server.js"
grok mcp add doc-splitter -s user -- node "$REPO/server.js"
opencode mcp add doc-splitter -- node "$REPO/server.js"Or use the helper script:
./scripts/install-mcp.shFor project-level MCP configuration, use .mcp.json:
{
"mcpServers": {
"doc-splitter": {
"command": "node",
"args": ["/absolute/path/to/ducsplit/server.js"],
"env": {
"DOC_SPLITTER_PYTHON": "/absolute/path/to/ducsplit/.venv/bin/python3"
}
}
}
}Then ask your agent:
Use the
doc-splitterMCP tools to splitbook.pdfinto 5–10 page conceptual Markdown chunks underoutput/book. Choose only safe boundary candidates, write the chunks, verify integrity, analyze every chunk in Persian and English, then author and commit the study indexes.
CLI Reference
Commands
Command | Purpose |
| Parse a document and start a boundary session. |
| Parse only and write |
| Print the current content window, instructions, and safe cut candidates. |
| Commit a |
| Write chunks and run verification. |
| Re-run verification against existing chunks and manifest. |
| Read one chunk's content by numeric ID. |
| Print full chunk content and analysis instructions. |
| Store bilingual topic, study focus, coherence, and reason for one chunk. |
| Return context for agent-authored |
| Store final Persian and English indexes written by the host agent. |
Common Options
Available on run, parse, boundary-context, commit-boundary, write, verify, and index unless noted.
Option | Default | Description |
|
| Output/session directory. |
|
| Target minimum chunk size (converted to words via |
|
| Target maximum chunk size; guidance for the host agent. |
|
| Study reading-speed estimate (wpm) for index time calculations. Use 80–100 for technical/medical content, 150–200 for general reading. |
|
| Chunk output format. PDF output requires PDF input. |
|
| Extra neighboring pages around PDF boundary pages. |
run
doc-splitter run --input ./book.pdf --out ./output/bookRequired: --input PATH (source .pdf or .docx).
parse
doc-splitter parse --input ./book.docx --out ./output/debugWrites ir.json without starting a boundary workflow.
boundary-context
Returns JSON with status, chunk_number, content_window, safe_candidates, instructions, min_pages, and max_pages. The host agent must choose only from safe_candidates.
commit-boundary
Option | Required | Description |
| yes |
|
| for | Safe candidate element ID. |
| no | Human-readable rationale stored for auditability. |
write / verify
write writes chunk files, manifest.json, and verification-report.json. Exits non-zero if verification fails.
verify checks:
every expected IR element appears exactly once
no unknown elements are present
chunk word counts match the source within tolerance
Markdown tables preserve expected rows
Markdown image references are present
PDF outputs cover all non-skipped source pages
commit-analysis
coherence must be confident or needs_review. When all chunks have analysis, semantic-review-report.json is written.
index
Requires every chunk to have committed content analysis, including both study-focus fields. Returns verified chunk metadata and instructions for the host agent. It does not write the index prose.
commit-index
Stores the final study-index-fa.md and study-index-en.md bodies authored by the host agent. The command validates that every chunk file is referenced.
MCP Tools
Tool | Inputs | Mutates? | Description |
|
| yes | Parses a PDF/DOCX and starts the boundary session. |
| optional | no | Returns the current content window and safe cut candidates. |
|
| yes | Commits a boundary cut or extends the window. |
| optional | yes | Writes chunk files and runs verification. |
|
| no | Reads generated chunk content. |
| optional | no | Re-runs verification. |
|
| no | Returns full chunk content for analysis. |
|
| yes | Stores bilingual chunk analysis. |
| optional | no | Returns context for agent-authored Persian and English study indexes. |
|
| yes | Stores final Persian and English study indexes written by the host agent. |
The MCP server is a thin Node.js wrapper around the Python CLI. It uses DOC_SPLITTER_PYTHON when set; otherwise it runs python3.
Configuration
CLI / MCP Options
Setting | CLI Option | Default | Notes |
Output directory |
|
| Session state, IR, chunks, reports, indexes. |
Minimum pages |
|
| Filters early safe candidates. |
Maximum pages |
|
| Target guidance for the host agent. |
Output format |
|
|
|
Boundary overlap |
|
| PDF outputs only. |
Reading speed |
|
| Index time estimates; 80 wpm for technical/medical study, 150+ for general content. |
Internal Defaults
Defined in src/doc_splitter/config.py. Not all have CLI flags yet.
Setting | Default | Purpose |
|
| Initial content window shown to the host agent. |
|
| Pages added when the host chooses |
|
| Converts page targets into word-count windows. |
|
| Extracts and preserves image references. |
|
| Scanned pages may be skipped. |
|
| Missing-text pages recorded in verification output. |
|
| Allows small word-count drift during verification. |
|
| Minimum word-count tolerance. |
|
| Minimum chunks for chapter grouping in indexes. |
|
| Maximum semantic filename slug length. |
Output Structure
A typical Markdown run:
output/book/
├── 01_intro-to-glucose-regulation.md
├── 02-insulin-signaling-and-feedback.md
├── images/
├── ir.json
├── manifest.json
├── verification-report.json
├── semantic-review-report.json
├── study-index-fa.md
├── study-index-en.md
└── .split-session.jsonA PDF or both run may also include .pdf files per chunk.
Important Files
File | Description |
| Parsed document intermediate representation. |
| Boundary decisions, stage, config snapshot, chunk analyses. |
| Chunk list, filenames, page ranges, element IDs, boundary reasons. |
| Integrity report: coverage, word-count checks, skipped pages, reconciliation notes. |
| Summary of chunk analyses and any |
| Persian study index (Overview, chapter table, Study Focus per session). |
| English study index. |
| Extracted image assets referenced by Markdown chunks. |
Study Index Structure
Each agent-authored study-index-*.md should include:
Overview — session count, PDF page coverage, total study time
Session table — topic links, page ranges, estimated time, and Study Focus
Optional grouping — chapters or sections only when they naturally fit the document
Document-specific study guidance — only when useful for that source
Host-Agent Workflow
Boundary Loop
ducsplitparses the document into ordered elements.It computes a window starting at the current cursor.
It finds safe cut candidates after complete headings, paragraphs, lists, or tables.
The host agent reads the content window and candidate list.
The host agent chooses
cutwith an allowedelement_id, orextendif the concept is incomplete.ducsplitvalidates the decision and moves the cursor.The loop continues until the document is fully covered.
Example context returned to the host agent:
{
"status": "needs_agent_decision",
"chunk_number": 4,
"content_window": "...",
"safe_candidates": [
{
"element_id": "el-042",
"after_type": "paragraph",
"snippet": "This completes the comparison of...",
"cumulative_word_count": 9850
}
],
"min_pages": 5,
"max_pages": 10
}The LLM must not invent boundaries. Committing an element_id not in safe_candidates fails.
Analysis Loop
analysis-contextreturns full chunk content and neighboring titles.The host agent writes a concise bilingual topic and practical study focus.
topic_enbecomes the final chunk filename slug.commit-analysisstores the result in.split-session.json, renames the chunk from the agent-selected topic, and updatesmanifest.json.Chunks marked
needs_reviewappear insemantic-review-report.jsonand block final index commit until the boundary/coherence issue is resolved.Every
get_chunkcall is tracked. The agent must read all chunk files beforecommit-indexis accepted.indexreturns context for the final index-writing pass, includingchunks_unreadso the agent knows which files remain.The host agent writes both complete Markdown indexes and stores them with
commit-index.
The study focus should answer: What should the learner master in this session?
Good:
{
"topic_en": "Insulin Signaling and Glucose Uptake",
"study_focus_en": "Master the insulin receptor cascade, GLUT4 translocation, and how defects in the pathway explain insulin resistance."
}Weak:
{
"topic_en": "Insulin",
"study_focus_en": "This section is about insulin."
}Output Format Trade-Offs
Format | Best For | Trade-Offs |
| AI reading, search, notes | Loses exact PDF visual layout. |
| Preserving original page appearance | Boundaries are page-extracted; mid-page cuts need overlap. |
| Text plus original page fidelity | More disk space; may duplicate boundary pages. |
For PDF output, conceptual chunks are decided by element boundaries, but written PDFs include whole pages. --overlap-pages reduces context loss at boundaries at the cost of duplicated pages between neighbors.
Edge Cases and Limitations
Scanned PDFs — OCR is disabled by default. Pages without extractable text are skipped and reported.
Password-protected PDFs — not supported.
DOCX page numbers — estimated from word count; DOCX has no stable rendered page numbers.
Non-Latin filenames — semantic slugs are ASCII-folded; fallback is
section-N.Very short documents — may produce fewer or smaller chunks than the 5–10 page target.
Very long concepts — the host agent should choose
extenduntil a coherent cut appears.Tables and lists — treated atomically; the tool avoids cutting through them.
OpenDataLoader failures — parsing continues with
pymupdf4llm; recorded in reconciliation notes.PDF boundary precision — PDF chunks are page-level extracts, not element-level visual crops.
Troubleshooting
Problem | Likely Cause | Fix |
| Input is not | Convert or use a supported extension. |
| PDF requires a password. | Save an unlocked copy and rerun. |
| Java missing or not on | Install a JDK; confirm |
| OpenDataLoader failed; fallback succeeded. | Review reconciliation notes; fix Java if layout fidelity matters. |
Verification fails (missing elements) | Chunks or manifest inconsistent. | Re-run |
Verification fails (word-count mismatch) | Parser and written chunks diverged. | Inspect Markdown around tables/images; file an issue with sample input. |
|
| Use |
| Not every chunk has committed analysis. | Run |
| Index committed without reading all chunk files via | Call |
| Reason contains | Write a real conceptual reason explaining where the topic ends and why. |
| Analysis reason is auto-generated. | Read the chunk and provide your own coherence assessment. |
| Index contains template like | Write unique educational study focus for each session. |
MCP server cannot import Python package | Wrong Python interpreter. | Set |
Temporary-file errors | No writable temp directory. | Set |
Development
ducsplit/
├── server.js # MCP server
├── pyproject.toml # Python package metadata
├── package.json # Node/MCP dependencies
├── scripts/install-mcp.sh # MCP registration helper
├── src/doc_splitter/
│ ├── cli.py # CLI entry point
│ ├── orchestrator.py # Pipeline coordination
│ ├── config.py # SplitConfig defaults
│ ├── format_detector.py # PDF/DOCX detection
│ ├── ir/ # Intermediate representation
│ ├── parsers/ # PDF/DOCX parsers and reconciliation
│ ├── boundary/ # Safe candidates and boundary session
│ ├── writers/ # Markdown and PDF writers
│ ├── content/ # Chunk analysis workflow
│ ├── verifier.py # Integrity verification
│ └── index_generator.py # Agent-authored index context/commit
└── tests/Run tests:
source .venv/bin/activate
python -m pytest -qRun the MCP server directly (waits for stdio MCP protocol messages):
node server.jsRecommended workflow:
Add or update parser/writer behavior.
Add focused tests under
tests/.Run
python -m pytest -q.Test a small real PDF or DOCX through the CLI.
Inspect
ir.json,manifest.json, andverification-report.json.If MCP behavior changed, test through an MCP host with
DOC_SPLITTER_PYTHONpointing at the local venv.
Design Principles
LLM judgment is constrained — the agent decides among safe options; it does not rewrite parser state freely.
Agent laziness is rejected — auto-generated reasons (
auto-cut,auto from section_headings), template study-focus, and index commits without reading chunk files are caught by validators and refused.Verification is mandatory — generated chunks are auditable and checked for loss or duplication.
Concepts beat page counts — 5–10 pages is a target, not a hard rule.
No bundled LLM —
ducsplitdoes not call an external LLM API; the host agent does.PDF fidelity and semantic precision differ — Markdown is best for semantic processing; PDF output is best for visual study continuity.
License
No license file is currently included. Until one is added, the repository is public but not explicitly open-source licensed. Recommended next step: add an OSI-approved license (MIT or Apache-2.0).
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/alifazelidehkordi/ducsplit'
If you have feedback or need assistance with the MCP directory API, please join our Discord server