# Migration and Release Notes This skill targets MarkItDown 0.1.6. The timeline below summarizes changes that affect user code and operational guidance. ## Release Timeline ### 0.1.0 — March 22, 2025 Major architecture release: - Optional dependency feature groups introduced - Plugin architecture introduced - Conversions moved to in-memory streams; temporary files removed - EPUB support added - CLI extension, MIME, and charset hints added - `--keep-data-uris` added Breaking changes: - Install `[all]` for behavior comparable to earlier all-in-one installs. - `convert_stream()` now requires a binary stream. - `DocumentConverter` implementations now receive binary streams plus `StreamInfo`, not file paths. ### 0.1.1 — March 25, 2025 - `convert_url()` renamed to `convert_uri()`. - `file:` and `data:` URI handling added. - `convert_url()` retained as a compatibility alias. ### 0.1.2 — May 28, 2025 - DOCX math-equation rendering - Dedicated CSV-to-Markdown conversion - XML/OMML parsing switched to `defusedxml` - Document Intelligence credential/API-version improvements - Streamable HTTP MCP support - YouTube transcript fixes - Python requirement updated to 3.10+ ### 0.1.3 — August 26, 2025 - Safer ExifTool handling, requiring version 12.24 or later - MCP plugin enablement through `MARKITDOWN_ENABLE_PLUGINS` - DOCX linked-image fixes - Document Intelligence HTML type handling - Custom LLM prompt forwarding fix - Additional HTML/PPTX robustness ### 0.1.4 — December 1, 2025 Security maintenance release: - Mammoth updated to address CVE-2025-11849 - `pdfminer.six` updated to address GHSA-wf5f-4jwr-ppcp ### 0.1.5 — February 20, 2026 - Better aligned and wide PDF tables - Partially numbered PDF-list fix - `text/markdown` added to the HTTP Accept header - Windows ONNX Runtime pin removed ### 0.1.6 — May 26, 2026 - Official OCR layer/plugin for embedded images and scanned PDFs - PDF page cleanup to fix linear memory growth - Deeply nested HTML recursion fix - Azure Content Understanding converter - Expanded security guidance for broad I/O and MCP binding ## Upgrade Installation Create a clean environment for the comparison: ```bash uv venv --python 3.12 .venv-markitdown source .venv-markitdown/bin/activate uv pip install "markitdown[all]==0.1.6" ``` Do not test a migration in an environment that still contains unknown third-party plugins. ## Code Replacements ### Result content Old/compatibility: ```python content = result.text_content ``` Current: ```python content = result.markdown ``` `text_content` still works in 0.1.6 but is explicitly documented in source as a soft-deprecated alias. ### Local conversion Broad: ```python result = converter.convert(user_value) ``` Narrow local path: ```python result = converter.convert_local(validated_path) ``` Use `convert_stream()` for validated uploaded bytes and `convert_response()` after an application-controlled download. ### Streams Old: ```python from io import StringIO result = converter.convert_stream(StringIO("text")) ``` Current: ```python from io import BytesIO from markitdown import StreamInfo result = converter.convert_stream( BytesIO(b"text"), stream_info=StreamInfo( extension=".txt", mimetype="text/plain", charset="utf-8", ), ) ``` ### URI API Old: ```python result = converter.convert_url(uri) ``` Current: ```python result = converter.convert_uri(validated_uri) ``` Prefer caller-controlled fetching plus `convert_response()` for HTTP(S). ### Hints Legacy: ```python result = converter.convert_stream(stream, file_extension=".pdf") ``` Current: ```python from markitdown import StreamInfo result = converter.convert_stream( stream, stream_info=StreamInfo( extension=".pdf", mimetype="application/pdf", filename="upload.pdf", ), ) ``` The legacy `file_extension`/`url` parameters still exist but are marked for migration in source. ## Custom Converter Migration Pre-0.1 converter: ```python class OldConverter(DocumentConverter): def convert(self, file_path): ... ``` 0.1.x converter: ```python from typing import Any, BinaryIO from markitdown import DocumentConverter, DocumentConverterResult, StreamInfo class CurrentConverter(DocumentConverter): def accepts( self, file_stream: BinaryIO, stream_info: StreamInfo, **kwargs: Any, ) -> bool: ... def convert( self, file_stream: BinaryIO, stream_info: StreamInfo, **kwargs: Any, ) -> DocumentConverterResult: return DocumentConverterResult(markdown="...") ``` If `accepts()` peeks at bytes, restore the original stream position before returning. ## Plugin Packaging Migration Outdated entry-point group: ```toml [project.entry-points."markitdown.plugins"] ``` Current group: ```toml [project.entry-points."markitdown.plugin"] example = "example_markitdown_plugin" ``` The plugin module must export: ```python __plugin_interface_version__ = 1 def register_converters(markitdown, **kwargs): ... ``` Use `pyproject.toml`; old `setup.py`-only examples are no longer the preferred packaging pattern. ## Installation Guidance Migration Outdated: ```bash uv pip install markitdown uv pip install "markitdown[all]" ``` Repository-standard reproducible install: ```bash uv pip install "markitdown[all]==0.1.6" ``` The base package no longer implies every format dependency. Select an extra or `[all]`. ## OCR Guidance Migration Remove these stale claims: - "Built-in PDF conversion uses Tesseract" - "All images are OCR'd locally" - "GIF and WebP are handled by the built-in image converter" Current behavior: - Built-in PDF extracts an existing text layer. - Built-in JPEG/PNG conversion extracts metadata and optionally requests an LLM description. - `markitdown-ocr==0.1.0` uses an external vision-capable client for embedded images and scanned-PDF page fallback. - Azure Document Intelligence and Content Understanding provide cloud OCR/extraction. The official OCR plugin README's `--llm-client`/`--llm-model` CLI example is not accepted by the 0.1.6 core CLI parser. Configure the plugin in Python. ## Azure Migration Current constructors accept explicit credentials: ```python MarkItDown( docintel_endpoint="https://...", docintel_credential=credential, ) MarkItDown( cu_endpoint="https://...", cu_credential=credential, ) ``` Without an explicit credential, the 0.1.6 converters use the named `AZURE_API_KEY` if present and otherwise `DefaultAzureCredential`. Do not rely on undocumented variable names such as `AZURE_DOCUMENT_INTELLIGENCE_KEY` for these constructors. Content Understanding is new in 0.1.6: ```python from markitdown import MarkItDown converter = MarkItDown( cu_endpoint="https://...", cu_analyzer_id="optional-custom-analyzer", ) ``` ## Security Migration Replace: - User-controlled `convert(value)` calls - Broad URI access - Automatic plugin enablement - Undisclosed LLM/cloud fallback - Secrets embedded in examples - MCP binding to non-local interfaces With: - Narrow conversion APIs - Path and destination allowlists - Explicit size/time/resource limits - Reviewed, pinned, opt-in plugins - User-approved external processing - Named credentials through secure provider configuration - STDIO or localhost-only MCP in a sandbox ## Regression Checklist - [ ] Install 0.1.6 in a clean environment - [ ] Replace `.text_content` with `.markdown` - [ ] Replace text streams with binary streams - [ ] Replace `convert_url()` with `convert_uri()` or controlled fetch - [ ] Update custom converter signatures - [ ] Update plugin entry-point group - [ ] Pin format extras - [ ] Test PDF tables and multi-column reading order - [ ] Test DOCX math and linked images - [ ] Test PPTX grouped shapes and notes - [ ] Confirm plugins remain disabled by default - [ ] Confirm no conversion unexpectedly calls network/cloud - [ ] Compare semantic output on a representative corpus ## Sources - Releases: https://github.com/microsoft/markitdown/releases - 0.1.0 migration notes: https://github.com/microsoft/markitdown/releases/tag/v0.1.0 - 0.1.6 release: https://github.com/microsoft/markitdown/releases/tag/v0.1.6