第 3 课
把 MarkItDown 交给 AI 智能体:MCP stdio 与 HTTP
安装 markitdown-mcp,用 MCP Python SDK 2.x 写客户端走 stdio 列出 convert_to_markdown 工具并转换本地 Excel,再开 HTTP 模式转换 data: URI 和网页,用 file:///etc/os-release 验证它没有身份验证、能读本机文件,最后按官方说明了解 Claude Desktop 的 Docker 配置和 MCP Inspector 调试。
课程目录第 3 / 3 课
学习位置仅保存在当前浏览器,有效期 180 天。
图文教材
本课对照的官方页面:markitdown-mcp 说明 、PyPI:markitdown-mcp 、MCP Python SDK 。测试环境:2026-11-05,Linux x86_64 云主机,Python 3.13.5,markitdown 0.1.9,markitdown-mcp 0.0.1a8,安装时自动带上的 MCP Python SDK 是 2.3.0。用 Python 客户端连接 stdio 和 HTTP 两种模式都实测过;Claude Desktop、Docker、MCP Inspector 三部分测试机没有对应环境,按官方说明整理,标注了「未实测」。
前两课是你自己调用 MarkItDown。这一课把它包装成一个 MCP 服务器,让 Claude Desktop 这类 AI 应用或你自己写的智能体在需要读文档时直接调用。官方的 markitdown-mcp 包只提供一个工具:convert_to_markdown(uri),参数 uri 可以是 http:、https:、file: 或 data: 开头的地址。
第 1 步:安装 markitdown-mcp
继续用前两课的虚拟环境:
cd ~/markitdown-lab && source .venv/bin/activate
pip install markitdown-mcp==0.0.1a8
pip show mcp | grep Version
mkdir -p l3 && cd l3
对照结果:
Version: 2.3.0
markitdown-mcp 依赖 mcp(MCP 官方 Python SDK),安装时会一起装上。下面的客户端脚本就用这个 SDK 来写。
第 2 步:用 stdio 模式调用
stdio 是默认模式:客户端启动 markitdown-mcp 进程,通过标准输入输出和它通信,不占端口。新建 mcp_stdio.py:
import asyncio
from pathlib import Path
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
server = StdioServerParameters(command="markitdown-mcp")
xlsx = Path("../files/test.xlsx").resolve().as_uri()
async def main():
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as s:
info = await s.initialize()
print("server:", info.server_info.name)
for t in (await s.list_tools()).tools:
print("tool:", t.name, list(t.input_schema["properties"]))
r = await s.call_tool("convert_to_markdown", {"uri": xlsx})
print("isError =", r.is_error)
print("\n".join(r.content[0].text.splitlines()[:4]))
asyncio.run(main())
运行 python mcp_stdio.py,对照结果(终端里还会夹杂几行服务器日志,这里略去):
server: markitdown
tool: convert_to_markdown ['uri']
isError = False
## Sheet1
| Alpha | Beta | Gamma | Delta |
| --- | --- | --- | --- |
| 89 | 82 | 100 | 12 |
本地文件要写成 file:///绝对路径 的形式,脚本里用 Path(...).resolve().as_uri() 来生成。这里的属性名 server_info、input_schema、is_error 是 MCP Python SDK 2.x 的写法;如果你装的是 1.x,对应写法是 serverInfo、inputSchema、isError(1.x 写法未实测)。
第 3 步:用 HTTP 模式调用
有的客户端只能连接网络地址,这时用 Streamable HTTP 模式。开一个新终端(同样先激活虚拟环境)启动服务器:
markitdown-mcp --http --host 127.0.0.1 --port 3001
对照结果(节选):
StreamableHTTP session manager started
INFO: Uvicorn running on http://127.0.0.1:3001 (Press CTRL+C to quit)
服务器的地址是 http://127.0.0.1:3001/mcp。回到原来的终端,先准备一个 data: URI。它把文件内容直接写在地址里,适合传小段数据:
printf '名称,价格\nA,1\nB,2\n' | base64
对照结果:
5ZCN56ewLOS7t+agvApBLDEKQiwyCg==
新建 mcp_http.py,分别转换这段 CSV 和一个网页:
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
URL = "http://127.0.0.1:3001/mcp"
DATA = "data:text/csv;base64,5ZCN56ewLOS7t+agvApBLDEKQiwyCg=="
async def main():
async with streamable_http_client(URL) as (read, write, *_):
async with ClientSession(read, write) as s:
await s.initialize()
for uri in [DATA, "https://example.com/"]:
r = await s.call_tool("convert_to_markdown", {"uri": uri})
print(f"== {uri[:30]} isError={r.is_error}")
for line in r.content[0].text.splitlines()[:4]:
print(line[:60])
asyncio.run(main())
对照结果:
== data:text/csv;base64,5ZCN56ewL isError=False
| 名称 | 价格 |
| --- | --- |
| A | 1 |
| B | 2 |
== https://example.com/ isError=False
This domain is for use in documentation examples without nee
CSV 被转成了 Markdown 表格。streamable_http_client 也是 SDK 2.x 的名字;1.x 里叫 streamablehttp_client(未实测)。服务器同时提供 /sse 地址,供只支持旧 SSE 传输的客户端使用。
第 4 步:弄清楚安全边界
这个服务器没有任何身份验证,并且以启动它的用户的权限运行。官方说明特别提醒:convert_to_markdown 能读取这个用户能访问的任何文件,也能访问任何网址。新建 risk.py 验证一下:
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
async def main():
url = "http://127.0.0.1:3001/mcp"
async with streamable_http_client(url) as (read, write, *_):
async with ClientSession(read, write) as s:
await s.initialize()
r = await s.call_tool("convert_to_markdown",
{"uri": "file:///etc/os-release"})
print(r.content[0].text.splitlines()[0])
asyncio.run(main())
对照结果(测试机是 Debian,你的系统会不同):
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
任何连上这个端口的程序都能这样读取文件。所以要注意三点:
- HTTP 模式默认只监听
127.0.0.1,可以用ss -ltn | grep 3001确认。不要把--host改成0.0.0.0或其他网卡地址。 - 只连接你信任的 AI 应用和智能体。
- 需要更强的隔离时,按官方建议放进虚拟机或容器里运行,并只挂载需要的目录。
做完这一步,回到运行服务器的终端按 Ctrl+C 停止它。
第 5 步:接入 Claude Desktop(未实测)
官方推荐在 Claude Desktop 里用 Docker 运行这个服务器。测试机没有 Docker 和 Claude Desktop,以下按官方说明整理,没有实测。先在 markitdown 仓库的 packages/markitdown-mcp 目录里构建镜像:
git clone https://github.com/microsoft/markitdown.git
cd markitdown/packages/markitdown-mcp
docker build -t markitdown-mcp:latest .
然后打开 Claude Desktop 的 claude_desktop_config.json(官方给出的查找方法见 MCP 文档的 Claude Desktop 用户部分),加入下面这段。-v 把本机目录挂载到容器里的 /workdir,请换成你自己的目录:
{
"mcpServers": {
"markitdown": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"/home/user/data:/workdir",
"markitdown-mcp:latest"
]
}
}
}
挂载之后,本机 /home/user/data/example.txt 在容器里的地址是 file:///workdir/example.txt。重启 Claude Desktop 后,可以在对话里说「把 /workdir/example.txt 转成 Markdown 并总结」。
如果不用 Docker,也可以把 command 写成虚拟环境里 markitdown-mcp 的绝对路径(例如 /home/你的用户名/markitdown-lab/.venv/bin/markitdown-mcp),args 留空。这种写法本课没有实测,而且服务器能读到你账号下的所有文件,安全上不如 Docker。
第 6 步:用 MCP Inspector 调试(未实测)
官方的调试方法是用 MCP Inspector 图形界面:
npx @modelcontextprotocol/inspector
打开它给出的本地地址后,传输类型选 STDIO,命令填 markitdown-mcp,点 Connect;如果服务器是 HTTP 模式,就选 Streamable HTTP,地址填 http://127.0.0.1:3001/mcp。连上之后在 Tools 页点 List Tools,选 convert_to_markdown,填一个 URI 运行。第 2、3 步的 Python 脚本做的是同样的检查,没有图形界面时用脚本就够了。
小结
pip install markitdown-mcp后,直接运行markitdown-mcp就是 stdio 模式;加--http --host 127.0.0.1 --port 3001就是 HTTP 模式,地址是/mcp。- 只有一个工具
convert_to_markdown(uri),支持http:、https:、file:、data:四种地址。 - 服务器没有身份验证,能读取运行它的用户能读的所有文件,只能在本机给信任的客户端用。
- Claude Desktop 官方推荐用 Docker 运行,并只挂载需要的目录。
