Skip to content

Commit 4a0648b

Browse files
Ahoo-WangafourneyJonahDelmant3tradependabot[bot]
authored
chore: merge upstream 0.1.6 (#50)
* Resolved an issue with linked images in docx [mammoth] (microsoft#1405) * Fixed documentation typos in _base_converter.py (microsoft#1393) * Ensure safe ExifTool usage: require >= 12.24 (microsoft#1399) * feat: add version verification for ExifTool to ensure security compliance * fix: improve ExifTool version verification --------- * Bump actions/checkout from 4 to 5 (microsoft#1394) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. * Add HTML support to DocumentIntelligenceConverter (microsoft#1352) * fix: correctly pass custom llm prompt parameter (microsoft#1319) * fix: correctly pass custom llm prompt parameter * Update README.md (microsoft#1335) Fix typo in README.md * Update README.md (microsoft#1350) ISSUE microsoft#1339 * Update README.md (microsoft#1191) Fix: Subtle spelling mistake fixed. * Adding support for data-src Attribute (microsoft#1226) * supportfordata-src * docs: correct minor typos (microsoft#1173) * fix docx parse error(\n in alt) (microsoft#1163) * Handle PPTX shapes where position is None (microsoft#1161) * Handle shapes where position is None * Fixed recursion error, and place no-coord shapes at front * feat: add checkbox support to Markdown converter (microsoft#1208) This change introduces functionality to convert HTML checkbox input elements (<input type=checkbox>) into Markdown checkbox syntax ([ ] or [x]). Co-authored-by: Meirna Kamal <meirna.kamal@vodafone.com> * Test if mammoth resolves rlinks. (microsoft#1451) * Upgrade mammoth to 1.11.0 (microsoft#1452) * Bump versions of mammoth and pdfminer.six (microsoft#1492) * Updated pyproject to require a minimum version of pdfminer.six to ensure CVE-2025-64512 is patched. * [MS] Update PDF table extraction to support aligned Markdown (microsoft#1499) * Added PDF table extraction feature with aligned Markdown (microsoft#1419) * Add PDF test files and enhance extraction tests - Added a medical report scan PDF for testing scanned PDF handling. - Included a retail purchase receipt PDF to validate receipt extraction functionality. - Introduced a multipage invoice PDF to test extraction of complex invoice structures. - Added a borderless table PDF for testing inventory reconciliation report extraction. - Implemented comprehensive tests for PDF table extraction, ensuring proper structure and data integrity. - Enhanced existing tests to validate the order and presence of extracted content across various PDF types. * fix: update dependencies for PDF processing and improve table extraction logic * Bumped version of pdfminer.six --------- Authored-by: Ashok <ashh010101@gmail.com> * Fix: PDF parsing doesn't support partially numbered lists (microsoft#1525) * Fix: PDF parsing doesn't support partially numbered lists * Refactor: Move import of PARTIAL_NUMBERING_PATTERN to the top of the test file * Refactor: Improve assertion formatting in partial numbering tests * [MS] Extend table support for wide tables (microsoft#1552) * feat: enhance PDF table extraction to support complex forms and add new test cases * feat: enhance PDF table extraction with adaptive column clustering and add comprehensive test cases * fix: correct formatting and improve assertions in PDF table tests * Add text/markdown to Accept header (microsoft#1554) * Remove onnxruntime<=1.20.1 Windows pin (microsoft#1551) * Bump version for release. (microsoft#1564) * [MS] Add OCR layer service for embedded images and PDF scans (microsoft#1541) * Add OCR test data and implement tests for various document formats - Created HTML file with multiple images for testing OCR extraction. - Added several PDF files with different layouts and image placements to validate OCR functionality. - Introduced PPTX files with complex layouts and images at various positions for comprehensive testing. - Included XLSX files with multiple images and complex layouts to ensure accurate OCR extraction. - Implemented a new test suite in `test_ocr.py` to validate OCR functionality across all document types, ensuring context preservation and accuracy. * Enhance OCR functionality and validation in document converters - Refactor image extraction and processing in PDF, PPTX, and XLSX converters for improved readability and consistency. - Implement detailed validation for OCR text positioning relative to surrounding text in test cases. - Introduce comprehensive tests for expected OCR results across various document types, ensuring no base64 images are present. - Improve error handling and logging for better debugging during OCR extraction. * Add support for scanned PDFs with full-page OCR fallback and implement tests * Bump version to 0.1.6b1 in __about__.py * Refactor OCR services to support LLM Vision, update README and tests accordingly * Add OCR-enabled converters and ensure consistent OCR format across document types * Refactor converters to improve import organization and enhance OCR functionality across DOCX, PDF, PPTX, and XLSX converters * Refactor exception imports for consistency across converters and tests * Fix OCR tests to match MockOCRService output and fix cross-platform file URI handling * Bump version to 0.1.6b1 in __about__.py * Skip DOCX/XLSX/PPTX OCR tests when optional dependencies are missing * Add comprehensive OCR test suite for various document formats - Introduced multiple test documents for PDF, DOCX, XLSX, and PPTX formats, covering scenarios with images at the start, middle, and end. - Implemented tests for complex layouts, multi-page documents, and documents with multiple images. - Created a new test script `test_ocr.py` to validate OCR functionality, ensuring context preservation and accurate text extraction. - Added expected OCR results for validation against ground truth. - Included tests for scanned documents to verify OCR fallback mechanisms. * Remove obsolete HTML test files and refactor test cases for file URIs and OCR format consistency - Deleted `html_image_start.html` and `html_multiple_images.html` as they are no longer needed. - Updated `test_file_uris` in `test_module_misc.py` to simplify assertions by removing unnecessary `url2pathname` usage. - Removed `test_ocr_format_consistency.py` as it is no longer relevant to the current testing framework. * Refactor OCR processing in PdfConverterWithOCR and enhance unit tests for multipage PDFs * Revert * Revert * Update REDMEs * Refactor import statements for consistency and improve formatting in converter and test files * Fix O(n) memory growth in PDF conversion by calling page.close() afte… (microsoft#1612) * Fix O(n) memory growth in PDF conversion by calling page.close() after each page * Refactor PDF memory optimization tests for improved readability and consistency * Add memory benchmarking tests for PDF conversion with page.close() fix * Remove unnecessary blank lines in PDF memory optimization tests for cleaner code * Bump version to 0.1.6b2 in __about__.py * Update PDF conversion tests to include mimetype in StreamInfo * Updated warning about binding to non-local interfaces. (microsoft#1653) * fix: handle deeply nested HTML that triggers RecursionError (microsoft#1644) * fix: handle deeply nested HTML that triggers RecursionError (microsoft#1636) Large HTML files with deep DOM nesting (e.g., SEC EDGAR filings) cause markdownify's recursive DOM traversal to exceed Python's default recursion limit (1000). Previously this RecursionError was caught by the top-level _convert() dispatcher, which then fell through to PlainTextConverter — silently returning the raw HTML as 'markdown' with no warning. This fix catches RecursionError in HtmlConverter.convert() and falls back to BeautifulSoup's iterative get_text() method, which handles arbitrary nesting depths. A warning is emitted so callers know the output is plain text rather than full markdown. Root cause chain: 1. HtmlConverter.convert() calls markdownify.convert_soup() (recursive) 2. Deeply nested HTML (>~400 levels) triggers RecursionError 3. _convert() catches all Exceptions, stores in failed_attempts 4. PlainTextConverter.accepts() matches text/html via 'text/' prefix 5. PlainTextConverter.convert() returns raw HTML bytes as text 6. Caller receives 'markdown' that is actually unconverted HTML * refactor: address review feedback on RecursionError fallback - Move 'import warnings' to module top level (was inside except block) - Make test environment-independent by temporarily lowering sys.setrecursionlimit(200) instead of relying on depth=500 being sufficient on all platforms; original limit restored in finally block - Add strict=True keyword argument to opt out of the plain-text fallback and let RecursionError propagate to the caller * test: use result.markdown instead of deprecated result.text_content --------- Co-authored-by: jigangz <jigangz@github.com> * Clarify security posture in READMEs (microsoft#1807) * feat: Add Azure Content Understanding converter (microsoft#1865) * inital version * improve mime type detection * prebuilt-image custom analzyer route to image * enhance cu priority over di * fix: apply black formatting * update cache of known prebuilt name and README improvement * add test cases, run black * update readme and deriving content_type from the resolved file_type * update readme * Bump version to 0.1.6 (microsoft#1914) --------- Co-authored-by: afourney <adamfo@microsoft.com> Co-authored-by: JonahDelman <jonah.delman@gmail.com> Co-authored-by: t3tra <admin@t3tra.net> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: safen0s <99965118+safen0s@users.noreply.github.com> Co-authored-by: Stefan Rink <stefan-rink@users.noreply.github.com> Co-authored-by: [W]DOS_ <40659600+W-DOS0@users.noreply.github.com> Co-authored-by: Utkarsh kumar <m83610278@gmail.com> Co-authored-by: Ebrahim Tayabali <47640402+ebrahimHakimuddin@users.noreply.github.com> Co-authored-by: Noah Zhu <118643158+Noah-Zhuhaotian@users.noreply.github.com> Co-authored-by: Dmitry <98899785+mdqst@users.noreply.github.com> Co-authored-by: Yuzhong Zhang <141388234+BetterAndBetterII@users.noreply.github.com> Co-authored-by: Richard Ye <33409792+richardye101@users.noreply.github.com> Co-authored-by: Meirna <61427701+Meirna-kamal@users.noreply.github.com> Co-authored-by: Meirna Kamal <meirna.kamal@vodafone.com> Co-authored-by: lesyk <lesyk@users.noreply.github.com> Co-authored-by: Bas Nijholt <basnijholt@gmail.com> Co-authored-by: jigangz <115519042+jigangz@users.noreply.github.com> Co-authored-by: jigangz <jigangz@github.com> Co-authored-by: Chien Yuan Chang <ds.chienyuanchang@gmail.com>
1 parent 960416e commit 4a0648b

87 files changed

Lines changed: 7044 additions & 63 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
packages/markitdown/tests/test_files/** linguist-vendored
22
packages/markitdown-sample-plugin/tests/test_files/** linguist-vendored
3+
4+
# Treat PDF files as binary to prevent line ending conversion
5+
*.pdf binary

.github/workflows/pre-commit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
pre-commit:
66
runs-on: ubuntu-latest
77
steps:
8-
- uses: actions/checkout@v4
8+
- uses: actions/checkout@v5
99
- name: Set up Python
1010
uses: actions/setup-python@v5
1111
with:

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
tests:
66
runs-on: ubuntu-latest
77
steps:
8-
- uses: actions/checkout@v4
8+
- uses: actions/checkout@v5
99
- uses: actions/setup-python@v5
1010
with:
1111
python-version: |

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ coverage.xml
5252
.hypothesis/
5353
.pytest_cache/
5454
cover/
55+
.test-logs/
5556

5657
# Translations
5758
*.mo

README.md

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44
![PyPI - Downloads](https://img.shields.io/pypi/dd/markitdown)
55
[![Built by AutoGen Team](https://img.shields.io/badge/Built%20by-AutoGen%20Team-blue)](https://github.com/microsoft/autogen)
66

7-
> [!TIP]
8-
> MarkItDown now offers an MCP (Model Context Protocol) server for integration with LLM applications like Claude Desktop. See [markitdown-mcp](https://github.com/microsoft/markitdown/tree/main/packages/markitdown-mcp) for more information.
9-
107
> [!IMPORTANT]
11-
> Breaking changes between 0.0.1 to 0.1.0:
12-
> * Dependencies are now organized into optional feature-groups (further details below). Use `pip install 'markitdown[all]'` to have backward-compatible behavior.
13-
> * convert\_stream() now requires a binary file-like object (e.g., a file opened in binary mode, or an io.BytesIO object). This is a breaking change from the previous version, where it previously also accepted text file-like objects, like io.StringIO.
14-
> * The DocumentConverter class interface has changed to read from file-like streams rather than file paths. *No temporary files are created anymore*. If you are the maintainer of a plugin, or custom DocumentConverter, you likely need to update your code. Otherwise, if only using the MarkItDown class or CLI (as in these examples), you should not need to change anything.
8+
> MarkItDown performs I/O with the privileges of the current process. Like open() or requests.get(), it will access resources that the process itself can access. Sanitize your inputs in untrusted environments, and call the narrowest `convert_*` function needed for your use case (e.g., `convert_stream()`, or `convert_local()`). See the [Security Considerations](#security-considerations) section of the documentation for more information.
159
1610
MarkItDown is a lightweight Python utility for converting various files to Markdown for use with LLMs and related text analysis pipelines. To this end, it is most comparable to [textract](https://github.com/deanmalmgren/textract), but with a focus on preserving important document structure and content as Markdown (including: headings, lists, tables, links, etc.) While the output is often reasonably presentable and human-friendly, it is meant to be consumed by text analysis tools -- and may not be the best option for high-fidelity document conversions for human consumption.
1711

@@ -113,6 +107,7 @@ At the moment, the following optional dependencies are available:
113107
* `[pdf]` Installs dependencies for PDF files
114108
* `[outlook]` Installs dependencies for Outlook messages
115109
* `[az-doc-intel]` Installs dependencies for Azure Document Intelligence
110+
* `[az-content-understanding]` Installs dependencies for Azure Content Understanding
116111
* `[audio-transcription]` Installs dependencies for audio transcription of wav and mp3 files
117112
* `[youtube-transcription]` Installs dependencies for fetching YouTube video transcription
118113

@@ -132,6 +127,115 @@ markitdown --use-plugins path-to-file.pdf
132127

133128
To find available plugins, search GitHub for the hashtag `#markitdown-plugin`. To develop a plugin, see `packages/markitdown-sample-plugin`.
134129

130+
#### markitdown-ocr Plugin
131+
132+
The `markitdown-ocr` plugin adds OCR support to PDF, DOCX, PPTX, and XLSX converters, extracting text from embedded images using LLM Vision — the same `llm_client` / `llm_model` pattern that MarkItDown already uses for image descriptions. No new ML libraries or binary dependencies required.
133+
134+
**Installation:**
135+
136+
```bash
137+
pip install markitdown-ocr
138+
pip install openai # or any OpenAI-compatible client
139+
```
140+
141+
**Usage:**
142+
143+
Pass the same `llm_client` and `llm_model` you would use for image descriptions:
144+
145+
```python
146+
from markitdown import MarkItDown
147+
from openai import OpenAI
148+
149+
md = MarkItDown(
150+
enable_plugins=True,
151+
llm_client=OpenAI(),
152+
llm_model="gpt-4o",
153+
)
154+
result = md.convert("document_with_images.pdf")
155+
print(result.text_content)
156+
```
157+
158+
If no `llm_client` is provided the plugin still loads, but OCR is silently skipped and the standard built-in converter is used instead.
159+
160+
See [`packages/markitdown-ocr/README.md`](packages/markitdown-ocr/README.md) for detailed documentation.
161+
162+
### Azure Content Understanding
163+
164+
[Azure Content Understanding](https://learn.microsoft.com/azure/ai-services/content-understanding/) provides higher-quality conversion with structured field extraction (YAML front matter), multi-modal support (documents, images, audio, video), and configurable analyzers.
165+
166+
Install: `pip install 'markitdown[az-content-understanding]'`
167+
168+
#### When to use Content Understanding
169+
170+
Content Understanding is ideal when you need capabilities beyond what built-in or Document Intelligence converters provide:
171+
172+
- **Audio and video files** — CU is the only option for video, and the higher-quality cloud option for audio. Built-in converters have no video support and only basic audio transcription.
173+
- **Structured field extraction**[Prebuilt](https://learn.microsoft.com/azure/ai-services/content-understanding/concepts/prebuilt-analyzers) or [custom-built](https://learn.microsoft.com/azure/ai-services/content-understanding/how-to/customize-analyzer-content-understanding-studio?tabs=portal) analyzers extract domain-specific fields (invoice amounts, receipt dates, contract clauses) serialized as YAML front matter. Neither built-in nor Doc Intel integration exposes fields.
174+
- **Higher-quality document extraction** — Cloud-based layout analysis and OCR for scanned PDFs, complex tables, and multi-page documents.
175+
- **Single API for all modalities** — One `cu_endpoint` handles documents, images, audio, and video with automatic analyzer routing.
176+
177+
| Capability | Built-in converters | Azure Document Intelligence | Azure Content Understanding |
178+
|------------|---------------------|-----------------------------|-----------------------------|
179+
| Document conversion | Offline, format-specific extraction | Cloud layout extraction | Cloud multimodal extraction |
180+
| Structured fields | Not available | Not exposed by this integration | YAML front matter from analyzer fields |
181+
| Custom analyzers | Not available | Not configurable in this integration | Supported with `cu_analyzer_id` |
182+
| Audio and video | Basic audio, no video | Not supported | Audio and video analyzers |
183+
| Cost | Local compute only | Billable Azure API calls | Billable Azure API calls |
184+
185+
**CLI:**
186+
187+
```bash
188+
markitdown path-to-file.pdf --use-cu --cu-endpoint "<content_understanding_endpoint>"
189+
```
190+
191+
**Python API:**
192+
193+
```python
194+
from markitdown import MarkItDown
195+
196+
# Zero-config — auto-selects analyzer per file type
197+
md = MarkItDown(cu_endpoint="<content_understanding_endpoint>")
198+
result = md.convert("report.pdf") # documents → prebuilt-documentSearch
199+
result = md.convert("meeting.mp4") # video → prebuilt-videoSearch
200+
result = md.convert("call.wav") # audio → prebuilt-audioSearch
201+
print(result.markdown)
202+
```
203+
204+
**With a custom analyzer** (for domain-specific field extraction):
205+
206+
```python
207+
md = MarkItDown(
208+
cu_endpoint="<content_understanding_endpoint>",
209+
cu_analyzer_id="my-invoice-analyzer",
210+
)
211+
result = md.convert("invoice.pdf")
212+
print(result.markdown)
213+
# Output includes YAML front matter with extracted fields:
214+
# ---
215+
# contentType: document
216+
# fields:
217+
# VendorName: CONTOSO LTD.
218+
# InvoiceDate: '2019-11-15'
219+
# ---
220+
# <!-- page 1 -->
221+
# ...
222+
```
223+
224+
When `cu_analyzer_id` is set, the converter automatically scopes it to compatible file types based on the analyzer's modality. Incompatible types (e.g., audio files with a document analyzer) auto-route to default prebuilt analyzers.
225+
226+
**Cost note:** Each `convert()` call for a CU-routed format is a billable Azure API call. Use `cu_file_types` to restrict which formats route to CU:
227+
228+
```python
229+
from markitdown.converters import ContentUnderstandingFileType
230+
231+
md = MarkItDown(
232+
cu_endpoint="<content_understanding_endpoint>",
233+
cu_file_types=[ContentUnderstandingFileType.PDF], # only PDFs use CU
234+
)
235+
```
236+
237+
More information about Azure Content Understanding can be found [here](https://learn.microsoft.com/azure/ai-services/content-understanding/).
238+
135239
### Azure Document Intelligence
136240

137241
To use Microsoft Document Intelligence for conversion:
@@ -164,14 +268,14 @@ result = md.convert("test.pdf")
164268
print(result.text_content)
165269
```
166270

167-
To use Large Language Models for image descriptions, provide `llm_client` and `llm_model`:
271+
To use Large Language Models for image descriptions (currently only for pptx and image files), provide `llm_client` and `llm_model`:
168272

169273
```python
170274
from markitdown import MarkItDown
171275
from openai import OpenAI
172276

173277
client = OpenAI()
174-
md = MarkItDown(llm_client=client, llm_model="gpt-4o")
278+
md = MarkItDown(llm_client=client, llm_model="gpt-4o", llm_prompt="optional custom prompt")
175279
result = md.convert("example.jpg")
176280
print(result.text_content)
177281
```
@@ -199,7 +303,7 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
199303

200304
### How to Contribute
201305

202-
You can help by looking at issues or helping review PRs. Any issue or PR is welcome, but we have also marked some as 'open for contribution' and 'open for reviewing' to help facilitate community contributions. These are ofcourse just suggestions and you are welcome to contribute in any way you like.
306+
You can help by looking at issues or helping review PRs. Any issue or PR is welcome, but we have also marked some as 'open for contribution' and 'open for reviewing' to help facilitate community contributions. These are of course just suggestions and you are welcome to contribute in any way you like.
203307

204308
<div align="center">
205309

@@ -235,6 +339,14 @@ You can help by looking at issues or helping review PRs. Any issue or PR is welc
235339

236340
- Run pre-commit checks before submitting a PR: `pre-commit run --all-files`
237341

342+
### Security Considerations
343+
344+
MarkItDown performs I/O with the privileges of the current process. Like `open()` or `requests.get()`, it will access resources that the process itself can access.
345+
346+
**Sanitize your inputs:** Do not pass untrusted input directly to MarkItDown. If any part of the input may be controlled by an untrusted user or system, such as in hosted or server-side applications, it must be validated and restricted before calling MarkItDown. Depending on your environment, this may include restricting file paths, limiting URI schemes and network destinations, and blocking access to private, loopback, link-local, or metadata-service addresses.
347+
348+
**Call only the conversion method you need:** Prefer the narrowest conversion API that fits your use case. MarkItDown's `convert()` method is intentionally permissive and can handle local files, remote URIs, and byte streams. If your application only needs to read local files, call `convert_local()` instead. If you need more control over URI fetching, call `requests.get()` yourself and pass the response object to `convert_response()`. For maximum control, open a stream to the input you want converted and call `convert_stream()`.
349+
238350
### Contributing 3rd-party Plugins
239351

240352
You can also contribute by creating and sharing 3rd party plugins. See `packages/markitdown-sample-plugin` for more details.

packages/markitdown-api/src/markitdown_api/commons.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ def blank_then_none(s: str) -> str | None:
1818

1919

2020
def _build_markitdown(llm_options: Optional[LlmOptions] = None) -> MarkItDown:
21-
base_url = api_key = llm_client = llm_model = None
21+
base_url = api_key = llm_client = llm_model = llm_prompt = None
2222
if llm_options:
2323
base_url = blank_then_none(llm_options.open_ai_base_url)
2424
api_key = blank_then_none(llm_options.open_ai_api_key)
2525
llm_model = blank_then_none(llm_options.model)
26+
llm_prompt = blank_then_none(llm_options.prompt)
2627
if not llm_model:
2728
llm_model = blank_then_none(os.environ.get("LLM_MODEL"))
2829

@@ -35,6 +36,7 @@ def _build_markitdown(llm_options: Optional[LlmOptions] = None) -> MarkItDown:
3536
enable_builtins=True,
3637
llm_client=llm_client,
3738
llm_model=llm_model,
39+
llm_prompt=llm_prompt,
3840
)
3941
return markitdown
4042

packages/markitdown-mcp/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# MarkItDown-MCP
22

3+
> [!IMPORTANT]
4+
> The MarkItDown-MCP package is meant for **local use**, with local trusted agents. In particular, when running the MCP server with Streamable HTTP or SSE, it binds to `localhost` by default, and is not exposed to other machines on the network or Internet. In this configuration, it is meant to be a direct alternative to the STDIO transport, which may be more convenient in some cases. DO NOT bind the server to other interfaces unless you understand the [security implications](#security-considerations) of doing so.
5+
6+
37
[![PyPI](https://img.shields.io/pypi/v/markitdown-mcp.svg)](https://pypi.org/project/markitdown-mcp/)
48
![PyPI - Downloads](https://img.shields.io/pypi/dd/markitdown-mcp)
59
[![Built by AutoGen Team](https://img.shields.io/badge/Built%20by-AutoGen%20Team-blue)](https://github.com/microsoft/autogen)
@@ -18,14 +22,14 @@ pip install markitdown-mcp
1822

1923
## Usage
2024

21-
To run the MCP server, using STDIO (default) use the following command:
25+
To run the MCP server, using STDIO (default), use the following command:
2226

2327

2428
```bash
2529
markitdown-mcp
2630
```
2731

28-
To run the MCP server, using Streamable HTTP and SSE use the following command:
32+
To run the MCP server, using Streamable HTTP and SSE, use the following command:
2933

3034
```bash
3135
markitdown-mcp --http --host 127.0.0.1 --port 3001
@@ -54,7 +58,7 @@ Once mounted, all files under data will be accessible under `/workdir` in the co
5458

5559
It is recommended to use the Docker image when running the MCP server for Claude Desktop.
5660

57-
Follow [these instrutions](https://modelcontextprotocol.io/quickstart/user#for-claude-desktop-users) to access Claude's `claude_desktop_config.json` file.
61+
Follow [these instructions](https://modelcontextprotocol.io/quickstart/user#for-claude-desktop-users) to access Claude's `claude_desktop_config.json` file.
5862

5963
Edit it to include the following JSON entry:
6064

@@ -96,13 +100,13 @@ If you want to mount a directory, adjust it accordingly:
96100

97101
## Debugging
98102

99-
To debug the MCP server you can use the `mcpinspector` tool.
103+
To debug the MCP server you can use the `MCP Inspector` tool.
100104

101105
```bash
102106
npx @modelcontextprotocol/inspector
103107
```
104108

105-
You can then connect to the insepctor through the specified host and port (e.g., `http://localhost:5173/`).
109+
You can then connect to the inspector through the specified host and port (e.g., `http://localhost:5173/`).
106110

107111
If using STDIO:
108112
* select `STDIO` as the transport type,
@@ -127,8 +131,7 @@ Finally:
127131

128132
## Security Considerations
129133

130-
The server does not support authentication, and runs with the privileges if the user running it. For this reason, when running in SSE or Streamable HTTP mode, it is recommended to run the server bound to `localhost` (default).
131-
134+
The server does not support authentication, and runs with the privileges of the user running it. For this reason, when running in SSE or Streamable HTTP mode, the server binds by default to `localhost`. Even still, it is important to recognize that the server can be accessed by any process or users on the same local machine, and that the `convert_to_markdown` tool can be used to read any file that the server's user has access to, or any data from the network. If you require additional security, consider running the server in a sandboxed environment, such as a virtual machine or container, and ensure that the user permissions are properly configured to limit access to sensitive files and network segments. Above all, DO NOT bind the server to other interfaces (non-localhost) unless you understand the security implications of doing so.
132135

133136
## Trademarks
134137

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2024-present Adam Fourney <adamfo@microsoft.com>
22
#
33
# SPDX-License-Identifier: MIT
4-
__version__ = "0.0.1a4"
4+
__version__ = "0.0.1a5"

packages/markitdown-mcp/src/markitdown_mcp/__main__.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,23 @@ def main():
113113
sys.exit(1)
114114

115115
if use_http:
116+
host = args.host if args.host else "127.0.0.1"
117+
if args.host and args.host not in ("127.0.0.1", "localhost"):
118+
print(
119+
"\n"
120+
"WARNING: The server is being bound to a non-localhost interface "
121+
f"({host}).\n"
122+
"This exposes the server to other machines on the network or Internet.\n"
123+
"The server has NO authentication and runs with your user's privileges.\n"
124+
"Any process or user that can reach this interface can read files and\n"
125+
"fetch network resources accessible to this user.\n"
126+
"Only proceed if you understand the security implications.\n",
127+
file=sys.stderr,
128+
)
116129
starlette_app = create_starlette_app(mcp_server, debug=True)
117130
uvicorn.run(
118131
starlette_app,
119-
host=args.host if args.host else "127.0.0.1",
132+
host=host,
120133
port=args.port if args.port else 3001,
121134
)
122135
else:

packages/markitdown-ocr/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Microsoft Corporation.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE

0 commit comments

Comments
 (0)