MarkItDown MCP package는 MarkItDown 변환기를 MCP 서버로 노출하고 convert_to_markdown(uri) 도구 하나를 제공한다.
저도 처음엔 이걸 보고 살짝 마음이 흔들렸다.
문서를 LLM용 markdown으로 바꾸는 도구를 MCP 서버로 붙여두면, 에이전트가 PDF, PPTX, DOCX, HTML을 알아서 읽고 정리하는 그림이 바로 떠오르기 때문이다.
문서가 들어온다.
에이전트가 MCP로 변환한다.
markdown으로 읽는다.
요약한다.
끝.
이렇게 쓰면 되게 깔끔해 보인다.
근데 운영자는 보통 여기서 표정이 조금 굳는다.
왜냐하면 MCP 서버는 한 번 연결하면 “필요할 때 실행하는 CLI”가 아니라 “에이전트가 부를 수 있는 상시 도구”가 되기 때문이다.
그리고 공식 markitdown-mcp 문서가 말하는 도구는 꽤 강하다.
convert_to_markdown(uri)는 http:, https:, file:, data: URI를 받을 수 있다.
공식 문서의 보안 섹션도 분명히 말한다.
서버는 인증을 지원하지 않고, 실행한 사용자 권한으로 돈다.
같은 로컬 머신의 다른 프로세스나 사용자도 접근할 수 있고, 도구는 서버 사용자 권한으로 접근 가능한 파일이나 네트워크 데이터를 읽을 수 있다.
이쯤 되면 질문이 바뀐다.
MarkItDown이 좋은 도구냐가 아니다.
이 변환기를 매번 CLI로 부를지, Python API로 감쌀지, MCP 서버로 열어둘지 결정해야 한다.
이 글은 그 분기표다.
2026년 4월 17일 기준 Microsoft MarkItDown 공식 GitHub, markitdown-mcp, markitdown-ocr, PyPI 버전, 그리고 로컬 도움말 확인을 바탕으로 정리했다.
기존에 쓴 MarkItDown 2026 — PDF·PPTX·HTML을 LLM용 markdown으로 바꿀 때 어디까지 믿어도 될까가 변환 품질 쪽 글이었다면, 이번 글은 운영 선택 쪽 글이다.
한마디로 말하면 이렇다.
MarkItDown MCP 서버는 문서 변환을 에이전트 도구로 계속 호출해야 하는 워크플로에는 좋고, 내가 파일 몇 개 바꿔서 넣는 작업에는 자주 과하다.
먼저 답
- MarkItDown 자체는 LLM과 텍스트 분석 파이프라인용 markdown 변환기다.
markitdown-mcp는 그 변환 기능을 MCP 서버로 노출한다.- 공식 문서 기준 MCP 서버는 STDIO, Streamable HTTP, SSE를 지원하고, HTTP 모드 기본 host는
127.0.0.1, port는3001이다. - MCP tool은
convert_to_markdown(uri)하나이고,http:,https:,file:,data:URI를 받을 수 있다. - 그래서 보안 핵심은 “MCP가 편하다”가 아니라 “누가 어떤 URI를 넣을 수 있나”다.
- OCR은 기본 의존성 문제가 아니라 플러그인과 LLM Vision 비용 문제로 봐야 한다.
- 선택 의존성은
[all]로 한 번에 넣기보다 PDF, DOCX, PPTX, XLSX처럼 필요한 포맷만 나누는 편이 운영에 좋다. - 내 기준으로는 반복 자동화와 agent 호출이 있으면 MCP, 일회성 변환이면 CLI, 서비스 내부 파이프라인이면 Python API가 먼저다.
짧게 줄이면 이거다.
MarkItDown MCP 서버는 문서 변환기를 “도구”로 만드는 선택이고, CLI는 문서 변환기를 “명령”으로 쓰는 선택이다.
둘은 비슷해 보여도 운영 경계가 다르다.
이번에 직접 확인한 것
2026년 4월 17일 KST 기준으로 PyPI와 로컬 설치 도움말을 확인했다.
로컬 확인은 새 가상환경에서 했다.
python3 -m venv .tmp/markitdown-mcp-check/.venv
.tmp/markitdown-mcp-check/.venv/bin/pip install markitdown-mcp markitdown-ocr openai
.tmp/markitdown-mcp-check/.venv/bin/markitdown-mcp --help
.tmp/markitdown-mcp-check/.venv/bin/markitdown --list-plugins
확인된 버전은 이랬다.
| package | 확인 버전 | 메모 |
|---|---|---|
markitdown |
0.1.5 |
PyPI와 로컬 설치 기준 일치 |
markitdown-mcp |
0.0.1a4 |
MCP 서버 패키지 |
markitdown-ocr |
0.1.0 |
OCR 플러그인 |
markitdown-mcp --help에서는 옵션이 단순하게 보였다.
STDIO가 기본이고, --http를 켜면 Streamable HTTP와 SSE transport로 뜬다.
--sse는 deprecated alias로 표시됐다.
기본 host는 127.0.0.1, port는 3001이다.
이 기본값은 꽤 중요하다.
공식 문서도 HTTP나 SSE 모드에서 서버가 기본적으로 localhost에 바인딩되며, 외부 인터페이스에 열지 말라고 강조한다.
markitdown --list-plugins를 실행하니 ocr 플러그인이 잡혔다.
다만 플러그인은 설치됐다고 바로 항상 쓰이는 게 아니다.
CLI 도움말에도 -p 또는 --use-plugins 옵션으로 3rd-party plugin을 켜라고 되어 있다.
즉 설치, 발견, 활성화는 서로 다른 단계다.
이거 은근히 중요하다.
“설치했는데 왜 OCR 안 돼요” 같은 질문의 절반은 여기서 나온다.
MarkItDown은 변환기고, MCP 서버는 권한면이다
MarkItDown README는 이 프로젝트를 여러 파일을 markdown으로 바꾸는 Python utility로 설명한다.
목표도 비교적 명확하다.
사람이 보는 고정밀 문서 재현보다 LLM과 텍스트 분석 파이프라인이 먹기 쉬운 구조를 만드는 쪽이다.
README가 언급하는 지원 입력도 넓다.
PDF, PowerPoint, Word, Excel, 이미지, 오디오, HTML, CSV, JSON, XML, ZIP, YouTube URL, EPUB 등이 나온다.
여기까지만 보면 “문서 전처리 도구”다.
그런데 MCP 서버로 노출하는 순간 성격이 바뀐다.
에이전트가 이 변환기를 도구로 호출할 수 있게 된다.
이때 핵심은 변환 품질보다 권한이다.
CLI는 사람이 명령을 친다.
MCP는 모델이 도구 호출을 제안하고, 호스트가 그것을 실행한다.
둘 다 결과는 markdown일 수 있다.
하지만 사고 경로가 다르다.
CLI에서 잘못된 파일을 넣으면 보통 내가 한 번 잘못 친 것이다.
MCP에서 file: URI와 http: URI가 열린 상태로 도구가 노출되면, 프롬프트나 문서 내용이 도구 호출 방향에 영향을 줄 수 있다.
그 차이를 무시하면 MCP는 편의가 아니라 읽기 권한 확대가 된다.
그래서 이 글의 첫 번째 원칙은 단순하다.
MarkItDown을 MCP로 붙일 때는 “무슨 파일을 변환하나”보다 “누가 URI를 만들 수 있나”부터 봐야 한다.
CLI, Python API, MCP 서버 분기표
내가 쓰는 첫 번째 분기표는 아래다.
| 선택지 | 맞는 상황 | 좋은 점 | 조심할 점 |
|---|---|---|---|
| CLI | 사람이 파일 몇 개를 직접 변환 | 단순하고 예측 가능하다 | 반복 자동화가 커지면 스크립트가 지저분해진다 |
| Python API | 서비스나 배치 파이프라인 내부에서 변환 | 입력 검증과 로깅을 코드로 통제하기 쉽다 | 앱 코드와 변환 의존성이 묶인다 |
| MCP server | 에이전트가 필요할 때 문서 변환 도구를 호출 | agent workflow에 자연스럽게 붙는다 | URI 권한, 로컬 파일 접근, 네트워크 접근을 따로 설계해야 한다 |
개인 작업이라면 CLI가 제일 오래 간다.
문서 폴더에 있는 PDF 몇 개를 markdown으로 바꾸고 Obsidian에 넣는 정도라면 MCP는 대부분 과하다.
이때는 markitdown file.pdf -o file.md 같은 명령이 더 낫다.
팀 배치 작업이라면 Python API가 편하다.
어떤 파일 확장자를 허용할지, 실패하면 어느 큐로 보낼지, 결과 markdown을 어디에 저장할지 코드로 제어할 수 있다.
반면 MCP는 에이전트가 도구를 직접 고르는 워크플로에 맞는다.
예를 들어 “이 폴더에 들어온 새 문서를 보고, 필요한 문서만 markdown으로 바꾼 뒤 요약 리포트를 만들라” 같은 작업이다.
그럴 때는 MCP가 자연스럽다.
에이전트 입장에서는 문서 변환이 별도 사람이 돌리는 사전 작업이 아니라, 자기 작업 중간에 부르는 도구가 된다.
문제는 자연스러운 만큼 경계도 흐려진다는 점이다.
그래서 MCP는 마지막에 붙이는 포장지가 아니라, 권한 설계와 같이 들어가야 한다.
MCP 서버가 값이 나는 경우
MarkItDown MCP 서버가 값이 나는 경우는 꽤 분명하다.
첫째, 에이전트가 어떤 문서를 변환할지 실행 중에 결정해야 할 때다.
예를 들어 여러 파일이 들어온 고객 자료 폴더에서, 에이전트가 먼저 파일 목록을 보고 필요한 것만 변환해야 하는 경우다.
사람이 미리 모든 파일을 markdown으로 바꿔두는 것보다 도구 호출이 낫다.
둘째, 문서 변환이 여러 agent step 중 하나일 때다.
파일 선택, 변환, 요약, 근거 인덱스 생성, 최종 리포트 작성이 한 흐름이라면 MCP가 잘 맞는다.
변환 도구가 agent loop 안에 있어야 흐름이 단순해진다.
셋째, host가 MCP tool call을 기록하고 승인할 수 있을 때다.
어떤 URI를 변환했는지, 어떤 파일에서 결과가 나왔는지, 실패했는지 성공했는지 남길 수 있다면 MCP의 운영 가치가 커진다.
넷째, 여러 클라이언트가 같은 변환 도구 계약을 공유해야 할 때다.
Claude Desktop, 내부 에이전트, 테스트 도구가 같은 convert_to_markdown 계약을 본다면 MCP 서버가 공통 접점이 될 수 있다.
다섯째, 파일 변환을 “에이전트가 쓸 수 있는 능력”으로 제공하고 싶을 때다.
이 경우 MCP는 단순 호출 방식이 아니라 제품 UX의 일부가 된다.
예를 들어 사용자가 파일을 넣고 “이 자료의 핵심 리스크만 뽑아줘”라고 하면, 뒤에서 변환, 요약, 근거 추적이 자연스럽게 이어진다.
이런 워크플로라면 MCP는 꽤 그럴듯하다.
하지만 여기서도 조건이 붙는다.
파일 접근 범위와 네트워크 접근 범위가 좁아야 한다.
그 조건이 없으면 좋은 도구가 아니라 넓은 문이 된다.
MCP 서버가 과한 경우
반대로 과한 경우도 많다.
첫째, 변환할 파일을 사람이 이미 알고 있을 때다.
report.pdf 하나를 markdown으로 바꾸는 일에 MCP 서버를 켜두는 건 보통 과하다.
명령 한 줄이면 끝날 일을 서버 운영으로 바꾸는 셈이다.
둘째, 변환 결과를 사람이 직접 확인하고 붙여넣는 워크플로다.
자동 agent loop가 없다면 MCP의 장점이 줄어든다.
셋째, 입력 파일이 민감한데 sandbox나 container 경계가 없을 때다.
공식 문서도 추가 보안이 필요하면 VM이나 container 같은 sandboxed environment를 고려하라고 한다.
이 말은 겁주기가 아니다.
file: URI를 받을 수 있는 도구는 생각보다 강하다.
넷째, HTTP/SSE를 외부 인터페이스로 열고 싶은 경우다.
공식 문서는 non-localhost interface에 바인딩하지 말라고 강하게 말한다.
인증도 없고, 실행 사용자 권한으로 돈다.
그 상태로 외부에 열면 MCP 서버가 아니라 파일/네트워크 읽기 엔드포인트가 될 수 있다.
다섯째, OCR이 필요한데 LLM Vision 비용과 실패 처리를 설계하지 않은 경우다.
markitdown-ocr은 로컬 OCR 엔진을 새로 넣는 구조가 아니라 LLM Vision을 쓴다.
문서가 많으면 변환 비용이 곧 모델 호출 비용으로 바뀐다.
이 비용을 모르면 나중에 “왜 문서 변환 비용이 이렇게 나오지”가 된다.
문서 변환하다가 회계팀이 문서화되는 순간이다.
그건 조금 서늘하다.
URI 권한이 진짜 핵심이다
markitdown-mcp 문서에서 제일 중요한 줄은 tool 이름보다 URI 범위다.
도구는 convert_to_markdown(uri) 하나다.
그리고 uri는 http:, https:, file:, data:가 가능하다.
이건 편하다.
웹 문서도 읽고, 로컬 파일도 읽고, data URI도 넣을 수 있다.
근데 바로 그 이유 때문에 위험하다.
운영 기준으로는 URI scheme별로 등급을 나눠야 한다.
| URI scheme | 쓰임 | 운영 위험 |
|---|---|---|
file: |
로컬 파일 변환 | 서버 사용자 권한으로 읽을 수 있는 파일 범위가 문제 |
http: / https: |
원격 문서 변환 | 내부 네트워크, metadata endpoint, 민감 URL 접근 위험 |
data: |
인라인 데이터 변환 | 큰 payload, 악성/과대 입력, 로그 노출 위험 |
이 표만 봐도 답이 나온다.
MCP 서버를 그냥 켜두는 게 아니라, 어떤 scheme을 허용할지부터 정해야 한다.
공식 서버가 모든 정책을 대신해준다고 생각하면 안 된다.
host, wrapper, container, network rule, user permission으로 감싸야 한다.
예를 들어 내 기준은 이렇다.
개인 로컬 테스트는 STDIO + 좁은 작업 폴더.
팀 내부 자동화는 container + read-only mount + allowlisted directory.
HTTP 변환은 기본 차단.
정말 필요하면 egress allowlist와 timeout, size limit을 둔다.
외부 공개 HTTP 서버는 금지.
이렇게 써놓으면 조금 과해 보인다.
근데 convert_to_markdown(uri)의 힘을 생각하면 과한 게 아니다.
딱 그만큼만 조심하는 것이다.
Docker를 권장하는 이유
공식 MCP README는 Claude Desktop에서 접근할 때 Docker image 사용을 권장한다.
이 이유는 실무적으로도 납득된다.
MCP 서버가 로컬 사용자 권한으로 파일을 읽을 수 있다면, Docker mount로 읽을 범위를 좁히는 게 훨씬 안전하다.
예를 들어 /home/user/data만 /workdir로 mount한다면, container 안에서는 그 아래 파일만 작업 대상으로 삼기 쉽다.
물론 Docker가 마법 방패는 아니다.
잘못 mount하면 똑같이 넓어진다.
/를 통째로 mount하면 “컨테이너 썼다”는 문장만 남고 경계는 사라진다.
그래서 Docker의 핵심은 이미지가 아니라 mount다.
| mount 방식 | 추천도 | 이유 |
|---|---|---|
| 특정 작업 폴더 read-only mount | 높음 | 변환 대상이 좁고 예측 가능하다 |
| 특정 작업 폴더 read-write mount | 중간 | output까지 container 안에서 만들 때만 |
| 홈 디렉터리 전체 mount | 낮음 | 민감 파일이 같이 노출될 수 있다 |
| 루트 전체 mount | 거의 금지 | 격리 의미가 크게 줄어든다 |
MarkItDown은 변환 도구라서 보통 read-only mount만으로도 충분하다.
결과 markdown은 stdout으로 받아 host가 저장하게 만들 수 있다.
굳이 container 안에서 여기저기 쓰게 둘 필요가 없다.
이 원칙 하나만 지켜도 MCP 서버 운영 난이도가 많이 내려간다.
선택 의존성은 [all]보다 작게 나누는 게 낫다
MarkItDown README는 선택 의존성을 feature group으로 나눠둔다.
[all]을 설치하면 예전처럼 모든 optional dependencies를 한 번에 넣는 쪽이다.
하지만 운영에서는 항상 [all]이 답은 아니다.
공식 README에 나온 선택 그룹은 이런 식이다.
| extra | 용도 |
|---|---|
[pptx] |
PowerPoint |
[docx] |
Word |
[xlsx] |
Excel |
[xls] |
오래된 Excel |
[pdf] |
|
[outlook] |
Outlook message |
[az-doc-intel] |
Azure Document Intelligence |
[audio-transcription] |
wav/mp3 audio transcription |
[youtube-transcription] |
YouTube transcript |
[all] |
모든 optional dependencies |
개인 테스트라면 [all]이 편하다.
근데 운영 서버나 자동화에서는 필요한 포맷만 넣는 편이 낫다.
이유는 세 가지다.
첫째, dependency surface가 줄어든다.
둘째, 설치와 cold start가 가벼워진다.
셋째, 장애 원인을 추적하기 쉬워진다.
예를 들어 사내 지식베이스가 PDF, DOCX, PPTX만 받는다면 이렇게 시작하는 편이 좋다.
pip install 'markitdown[pdf,docx,pptx]'
Excel까지 필요해지면 그때 [xlsx]를 추가하면 된다.
오디오나 YouTube 전사는 별도 lane으로 빼는 편이 더 낫다.
오디오 전사는 ffmpeg 같은 시스템 의존성과 모델 비용이 섞일 수 있다.
로컬 확인에서도 pydub이 ffmpeg 또는 avconv를 찾지 못했다는 경고를 냈다.
이건 당장 PDF 변환에는 치명적이지 않을 수 있지만, 오디오 워크플로에서는 운영 체크 항목이다.
문서 변환 서버에 오디오 전사까지 조용히 얹어두면 나중에 디버깅이 피곤해진다.
피곤한 디버깅은 늘 조용히 찾아온다.
OCR 플러그인은 켜는 순간 비용 구조가 바뀐다
markitdown-ocr README는 이 플러그인이 PDF, DOCX, PPTX, XLSX 안의 이미지에서 텍스트를 추출한다고 설명한다.
방식은 LLM Vision이다.
기존 MarkItDown의 llm_client와 llm_model 패턴을 그대로 쓴다.
공식 문서도 새 ML library나 binary dependency가 필요한 구조는 아니라고 말한다.
이건 장점이다.
하지만 동시에 비용 구조가 바뀐다는 뜻이다.
기본 변환은 주로 로컬 라이브러리 비용이다.
OCR 플러그인을 켜고 LLM Vision을 쓰면 모델 호출 비용, 속도, quota, 실패 처리 문제가 생긴다.
공식 OCR README도 llm_client나 llm_model이 없으면 OCR이 silently skipped되고 표준 built-in converter로 fallback된다고 설명한다.
이 부분은 정말 조심해야 한다.
“OCR 켰다”와 “OCR이 실제로 수행됐다”는 다른 말이다.
운영 로그에는 최소한 아래를 남기는 편이 좋다.
- OCR 플러그인 설치 여부
--use-plugins또는enable_plugins=True여부llm_client전달 여부llm_model이름- OCR block 개수
- OCR 실패 warning 개수
- 변환당 모델 호출 비용
이 정도를 안 남기면 나중에 결과가 이상할 때 답이 안 나온다.
OCR이 안 된 건지, 이미지 자체가 없던 건지, 모델 호출이 실패한 건지, quota가 막힌 건지 구분이 안 된다.
문서 파이프라인에서 제일 억울한 실패가 이거다.
겉으로는 markdown이 잘 나왔는데, 이미지 속 핵심 텍스트만 빠진 경우.
이건 사람이 안 보면 티가 늦게 난다.
그래서 OCR 플러그인은 자동으로 전부 켜는 기능이 아니라, 품질과 비용을 같이 보는 옵션으로 둬야 한다.
플러그인은 기본 비활성이라는 점을 잊지 말자
MarkItDown README는 3rd-party plugins가 기본적으로 disabled라고 설명한다.
설치된 plugin 목록은 markitdown --list-plugins로 볼 수 있고, 실제 변환에 쓰려면 --use-plugins를 붙여야 한다.
Python API에서는 MarkItDown(enable_plugins=True)처럼 명시해야 한다.
이 설계는 좋다.
하지만 운영자에게는 체크포인트가 생긴다.
| 단계 | 확인 방법 | 흔한 착각 |
|---|---|---|
| 설치 | pip install markitdown-ocr |
설치하면 바로 OCR 된다고 생각 |
| 발견 | markitdown --list-plugins |
목록에 보이면 항상 활성이라고 생각 |
| 활성화 | --use-plugins 또는 enable_plugins=True |
활성화만 하면 모델 호출도 된다고 생각 |
| 실행 | llm_client, llm_model 전달 |
OCR 실패도 결과 markdown이 나오니 놓침 |
특히 MCP 서버와 결합하면 더 헷갈릴 수 있다.
MCP 서버를 띄운 환경에 plugin이 설치되어 있는지, 서버 실행 커맨드가 plugin을 쓰도록 구성되어 있는지, LLM client 설정이 들어갔는지 확인해야 한다.
단순히 내 터미널에서 markitdown --list-plugins가 보인다고 MCP 서버 실행 환경도 같다고 보면 안 된다.
가상환경, Docker image, host Python이 서로 다르면 결과도 달라진다.
이건 진짜 자주 난다.
내 터미널에서는 되는데 에이전트에서는 안 되는 그 맛.
별로 맛있지 않다.
내가 쓰는 운영 분기표
이 글의 핵심 표를 정리하면 아래다.
| 상황 | 추천 선택 | 이유 |
|---|---|---|
| PDF 몇 개를 수동 변환 | CLI | 가장 단순하고 빠르다 |
| Obsidian import 전처리 | CLI 또는 작은 script | 사람이 폴더를 알고 있으면 MCP가 과하다 |
| 주기적 문서 수집 배치 | Python API | 입력 검증, 로그, 실패 처리를 코드로 잡기 쉽다 |
| 에이전트가 필요한 문서를 직접 골라야 함 | MCP server | agent loop 안에서 변환 도구를 호출할 수 있다 |
| Claude Desktop에서 로컬 문서 변환 도구로 쓰기 | Docker 기반 MCP | mount 범위를 좁혀야 한다 |
| 민감 파일이 많은 업무용 노트북 | MCP 신중 | file: URI와 사용자 권한 범위를 먼저 줄여야 한다 |
| OCR이 많은 스캔 PDF | OCR plugin + 비용 로그 | LLM Vision 비용과 실패 처리가 필요하다 |
| 고정밀 레이아웃 재현 | MarkItDown 단독 부적합 | LLM용 구조 추출과 배포용 재현은 다르다 |
내 기준으로 첫 질문은 이거다.
에이전트가 변환 대상을 실행 중에 골라야 하나.
아니면 사람이 이미 알고 있나.
사람이 알고 있으면 CLI가 먼저다.
에이전트가 골라야 하면 MCP를 검토한다.
그다음 질문은 이거다.
변환 대상의 파일 접근 범위를 좁힐 수 있나.
좁힐 수 없으면 MCP는 미룬다.
이 두 질문만으로도 절반은 정리된다.
최소 안전 설정 예시
개인 로컬에서 가볍게 붙인다면 나는 이렇게 시작한다.
{
"mcpServers": {
"markitdown": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"/Users/me/agent-input:/workdir:ro",
"markitdown-mcp:latest"
]
}
}
}
핵심은 :ro다.
읽기 전용 mount로 시작하자는 뜻이다.
공식 README 예시는 -v /home/user/data:/workdir 형태를 보여주지만, 실제 운영에서는 read-only가 더 마음 편하다.
결과 markdown은 MCP host 쪽에서 받아 저장하거나, 별도 검토 단계에서 처리하면 된다.
HTTP 모드를 꼭 써야 한다면 기본값처럼 127.0.0.1에 묶는다.
markitdown-mcp --http --host 127.0.0.1 --port 3001
여기서 0.0.0.0은 쉽게 쓰면 안 된다.
공식 문서도 다른 인터페이스에 bind하지 말라고 강조한다.
인증이 없는 도구 서버를 네트워크에 열어두는 건 편의가 아니라 숙제다.
그리고 숙제는 누가 풀어야 한다.
대부분 그 누가는 미래의 나다.
문서 변환 품질과 운영 품질은 다르다
기존 MarkItDown 글에서 직접 PDF와 PPTX를 변환해봤을 때, 텍스트 추출 자체는 꽤 쓸 만했다.
하지만 페이지 번호, 폼피드 흔적, 슬라이드 레이아웃 붕괴 같은 문제도 바로 보였다.
이번 글의 관점은 한 단계 더 위다.
문서 변환 품질이 괜찮다고 MCP 운영 품질이 괜찮은 건 아니다.
품질은 이런 질문이다.
문장이 잘 뽑히나.
표가 어느 정도 살아 있나.
이미지 속 텍스트가 필요한가.
운영은 이런 질문이다.
누가 이 도구를 호출할 수 있나.
어떤 파일을 읽을 수 있나.
어떤 네트워크로 나갈 수 있나.
실패 로그는 어디에 남나.
OCR 비용은 누가 본다.
두 질문을 섞으면 사고가 난다.
문서가 잘 변환되니까 MCP도 켜두자.
이 문장은 절반만 맞다.
정확한 문장은 이쪽이다.
문서가 잘 변환되고, 호출 범위를 좁힐 수 있고, 로그와 비용을 볼 수 있다면 MCP로 켜둘 만하다.
실수 TOP 7
1. MCP 서버를 그냥 로컬 유틸처럼 본다
MCP 서버는 에이전트가 호출 가능한 도구다.
CLI보다 권한 경계가 더 중요하다.
2. file: URI를 가볍게 본다
file: URI는 서버 사용자 권한으로 읽을 수 있는 파일 범위와 연결된다.
작업 폴더를 좁히지 않으면 생각보다 넓다.
3. HTTP 모드를 외부에 연다
공식 문서는 localhost 기본값과 non-localhost bind 주의를 분명히 말한다.
인증 없는 변환 서버를 네트워크에 열면 별도 보안 설계가 필요하다.
4. [all]을 운영 기본값으로 둔다
테스트는 편하지만 운영에서는 불필요한 dependency와 장애 표면이 늘어난다.
필요한 포맷별 extra로 시작하는 게 낫다.
5. OCR 플러그인을 비용 없이 보는 실수
markitdown-ocr은 LLM Vision을 쓴다.
문서가 많으면 모델 비용과 quota가 변환 파이프라인 비용이 된다.
6. 플러그인 설치와 활성화를 헷갈린다
설치됐다고 자동 활성화되는 게 아니다.
--use-plugins, enable_plugins=True, llm_client, llm_model을 따로 확인해야 한다.
7. 결과 markdown만 보고 성공했다고 믿는다
OCR이 skip돼도 기본 변환 결과는 나올 수 있다.
이미지 속 텍스트가 중요한 문서라면 OCR block과 warning을 따로 봐야 한다.
도입 전 체크리스트
- 변환 대상 파일을 사람이 미리 아는가, 에이전트가 실행 중에 골라야 하는가.
- CLI 한 줄로 끝나는 일을 MCP 서버로 키우고 있지 않은가.
- MCP 서버가 접근 가능한 로컬 파일 범위를 정했는가.
- Docker나 VM으로 sandbox를 둘 수 있는가.
- mount는 read-only로 시작할 수 있는가.
http:,https:,file:,data:URI 중 무엇을 허용할지 정했는가.- HTTP/SSE 모드는 localhost에만 bind되는가.
- 외부 인터페이스 bind가 필요한 이유를 문서로 설명할 수 있는가.
- optional dependency는
[all]대신 필요한 extra로 나눴는가. - OCR이 필요한 문서와 필요 없는 문서를 분리했는가.
- OCR 플러그인 활성화 여부와 모델 호출 로그를 남기는가.
- 변환 실패, OCR 실패, 네트워크 실패를 서로 다르게 기록하는가.
- 결과 markdown을 사람이 검토하는 샘플링 기준이 있는가.
- 민감 문서를 변환한 뒤 artifact 보존 기간을 정했는가.
이 체크리스트가 길어 보이면, 아직 MCP 서버까지는 이른 걸 수도 있다.
그럴 때는 CLI와 작은 script로 시작해도 된다.
좋은 자동화는 보통 작은 명령에서 시작한다.
커지면 서버가 되고, 더 커지면 운영 문서가 된다.
운영 문서까지 생길 마음이 없으면 서버도 조금 천천히 가는 게 낫다.
내 결론
MarkItDown MCP 서버는 좋은 방향이다.
문서 변환이 에이전트 워크플로 안으로 들어오는 건 자연스러운 흐름이다.
특히 PDF, PPTX, DOCX, HTML, 이미지, 오디오 같은 입력이 섞이는 팀이라면 markdown 중간 레이어는 꽤 쓸모 있다.
하지만 MCP 서버는 변환기를 편하게 부르는 방법이면서 동시에 권한면이다.
이걸 잊으면 문제가 생긴다.
convert_to_markdown(uri) 하나가 얼마나 많은 걸 읽을 수 있는지 먼저 봐야 한다.
공식 문서가 localhost 기본값, 인증 없음, 사용자 권한, container/sandbox 권장을 길게 적은 이유도 여기에 있다.
내 추천은 단순하다.
처음엔 CLI로 변환 품질을 본다.
반복 배치가 생기면 Python API로 감싼다.
에이전트가 변환 대상을 직접 골라야 할 때 MCP 서버를 검토한다.
그때는 Docker read-only mount, localhost bind, URI scheme 제한, OCR 비용 로그를 같이 설계한다.
이 네 가지가 없으면 아직 서버가 아니라 실험이다.
실험은 괜찮다.
다만 실험을 운영처럼 켜두면 언젠가 운영이 실험처럼 흔들린다.
그게 늘 문제다.
FAQ
MarkItDown MCP 서버는 MarkItDown CLI보다 무조건 좋은가?
아니다.
CLI는 사람이 명령을 직접 실행하는 단순한 방식이고, MCP 서버는 에이전트가 도구로 호출하는 방식이다.
반복 agent workflow가 없으면 CLI가 더 낫다.
markitdown-mcp는 어떤 도구를 제공하나?
공식 문서 기준으로 convert_to_markdown(uri) 도구 하나를 제공한다.
URI는 http:, https:, file:, data:를 받을 수 있다.
그래서 URI 입력 검증과 접근 범위 제한이 핵심이다.
HTTP 모드로 띄워도 되나?
로컬에서만 쓰고 127.0.0.1에 bind한다면 검토할 수 있다.
공식 문서는 HTTP/SSE 모드가 기본적으로 localhost에 묶이며, 보안 의미를 이해하지 못하면 다른 인터페이스에 bind하지 말라고 경고한다.
외부 네트워크에 열어야 한다면 인증, 네트워크 제한, sandbox, logging을 별도로 설계해야 한다.
Docker를 꼭 써야 하나?
꼭은 아니다.
다만 파일 접근 범위를 좁히려면 Docker나 VM 같은 격리가 유용하다.
특히 Claude Desktop 같은 로컬 클라이언트에서 문서 폴더만 mount해서 쓰려면 Docker가 안전한 출발점이다.
OCR 플러그인은 언제 써야 하나?
스캔 PDF, 이미지가 많이 들어간 PPTX, 이미지 속 표나 텍스트가 중요한 문서라면 써볼 만하다.
하지만 markitdown-ocr은 LLM Vision을 쓰므로 모델 비용, quota, 실패 로그를 같이 봐야 한다.
pip install markitdown[all]로 끝내면 안 되나?
개인 테스트라면 괜찮다.
운영에서는 필요한 포맷별 extra만 설치하는 편이 낫다.
PDF, DOCX, PPTX만 필요하면 markitdown[pdf,docx,pptx]처럼 시작하고, 필요할 때 확장하는 쪽이 디버깅하기 쉽다.
MarkItDown 결과를 그대로 RAG에 넣어도 되나?
가능은 하지만 바로 넣기 전에 샘플 검토가 필요하다.
페이지 번호, 줄바꿈, 슬라이드 레이아웃 붕괴, OCR 누락 같은 노이즈가 생길 수 있다.
RAG용이라면 변환 후 정리, 청킹, 근거 파일명 보존까지 같이 설계하는 편이 좋다.
관련 글
- MarkItDown 2026 — PDF·PPTX·HTML을 LLM용 markdown으로 바꿀 때 어디까지 믿어도 될까
- MCP 서버를 더 붙이기 전에 먼저 지워야 할 것 2026 — 연결 수보다 운영 기준이 중요한 이유
- Claude Code MCP vs script 2026 — 내부 도구 연결할 때 언제 커스텀 툴이 과하고 언제 셸이면 충분할까