帕西瓦尔
Parsival是一个基于MCP Python SDK的生产环境友好、基于工具的文件解析微服务。它旨在将常见的文档格式转换为丰富的结构化输出(Markdown、JSON、文本),并对流处理和代理集成进行性能调优和安全强化。
- 支持的输入格式:PDF、DOCX、DOC、PPTX、XLSX、CSV、HTML、MD、TXT
- 对大型文档的流式解析支持
- 缓存层:内存LRU+可选Redis
- 对损坏/加密文档的稳健处理、大小限制、子流程隔离
- 插件式解析器注册表和后处理管道
______________________________________________________________________
目录
______________________________________________________________________
快速启动
克隆存储库
git clone https://github.com/Aldrin-Joan/Parsival-mcp.git
cd Parsival-mcpPython虚拟环境
Linux/macOS:
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txtWindows(PowerShell):
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt运行服务器
推荐(本地stdio MCP):
python -m src.mcp_entrypoint这使用 MCP_TRANSPORT=stdio 默认情况下,在项目工具中,stdout专用于MCP协议流量。
验证支持的格式
from src.app import list_supported_formats
print(list_supported_formats())______________________________________________________________________
特性
- 使用专用解析器插件进行多格式文件解析
- 以Markdown、JSON或原始文本输出
- 流解析器模式(
stream=True)对于早期块 - Redis支持缓存,具有本地LRU回退功能
- 可配置的文件大小上限和解析器超时
- LibreOffice转换路径
.doc支持 - 通过以下方式进行过程中和工人过程隔离
ProcessPoolExecutor - 富有的
ParseResult带有元数据、错误和可恢复性标志的模型 - 可插拔的后处理管道:元数据丰富、表规范化、图像提取
______________________________________________________________________
建筑
逻辑层
src/app.py-工具定义和解析编排src/core-配置、缓存、路由、执行器、安全src/parsers-特定格式解析逻辑src/post_processors-结果富集管道src/serialisers-输出封送(Markdown、JSON、文本)src/tools-公共工具API包装器
堆芯流量
- 客户端调用MCP工具(例如。,
read_file). src/tools/read_file.py通过验证路径validate_safe_path().src.app.parse_file()用途FormatRouter推断FileFormat.- 解析器从以下位置获取
src.parsers.registry. core.executor.run_parse_in_pool()在进程池中执行解析器。PostProcessingPipeline使输出正常化。- 缓存密钥生成于
ContentHashStore从文件哈希+选项。 - 返回序列化响应。
格式检测(路由器)
magicMIME嗅探(如果可用)- 扩展图(例如。,
.pdf,.docx,.pptx) - CSV/HTML/Markdown的内容启发式
支持的工具
read_fileget_metadataextract_tableextract_imagesconvert_to_markdownsearch_filelist_supported_formats
______________________________________________________________________
存储库布局
.
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
├── requirements.txt
├── src/
│ ├── app.py
│ ├── config.py
│ ├── core/
│ ├── parsers/
│ ├── post_processors/
│ ├── serialisers/
│ ├── tools/
│ └── models/
└── tests/
├── unit/
└── benchmarks/src/config.py-环境驱动设置对象src/core/cache.py-内存+Redis缓存层src/core/router.py-文件格式确定src/core/executor.py-具有线程限制的进程池执行src/parsers/*-按格式解析逻辑src/post_processors/*-丰富解析结果src/serialisers/*-Markdown/JSON/文本序列化器src/tools/*-MCP请求的工具包装器
______________________________________________________________________
配置
所需包
- python>=3.11
- 中列出的软件包
requirements.txt
可选服务
- Redis(用于共享缓存)
- LibreOffice(for
.doc转换;安装在Dockerfile中)
环境变量(MCP_ 前缀)
| 变量 | 默认值 | 描述 |
|---|---|---|
MCP_APP_NAME | Parsival | 应用程序名称(当前代码中未使用) |
MCP_PROCESS_POOL_SIZE | 4 | 解析的最大工作进程数 |
MCP_MAX_FILE_SIZE_MB | 500 | 非流解析的最大文件字节数 |
MCP_MAX_STREAM_FILE_SIZE_MB | 2048 | 流解析的最大文件字节数 |
MCP_HYBRID_HASH_THRESHOLD_MB | 50 | 缓存键中完整哈希值与部分哈希值的阈值 |
MCP_REDIS_ENABLED | false | 启用Redis缓存后端 |
MCP_REDIS_URL | None | Redis服务器的URL |
MCP_REDIS_TTL | 3600 | Redis密钥TTL(秒) |
MCP_SENTRY_ENABLED | false | 启用Sentry(未捆绑在代码路径中) |
MCP_SENTRY_DSN | None | 哨兵DSN |
MCP_LIBREOFFICE_PATH | None | 覆盖LibreOffice路径 |
MCP_MAX_LIBREOFFICE_WORKERS | 2 | 最大并发LibreOffice转换数 |
MCP_SUBPROCESS_TIMEOUT_SEC | 30 | 文档解析器中的子进程超时 |
MCP_ALLOWED_DIRECTORIES | [., /tmp] | 允许用于文件读取路径的目录 |
MCP_WORKSPACE_ROOT | . | 根目录安全边界 |
MCP_TRANSPORT | stdio | MCP传输模式(仅限stdio) |
来自解析器的无前缀环境变量
| 变量 | 默认值 | 用途 |
|---|---|---|
LIBREOFFICE_BINARY | soffice | LibreOffice CLI二进制文件 |
LIBREOFFICE_TIMEOUT_SEC | 30 | 转换过程超时 |
LIBREOFFICE_SECONDARY_KILL_TIMEOUT_SEC | 5 | 在终止信号缓冲区之前等待 |
LIBREOFFICE_MAX_CONCURRENT | 2 | 并发转换 |
______________________________________________________________________
本地开发
安装
pip install -r requirements.txt运行单元测试
pytest -q运行stdio烟雾测试
python scripts/tool_smoke_test_stdio.py运行基准测试
pytest -q tests/benchmarks/test_benchmarks.py静态检查
ruff check .
python -m mypy src tests添加预提交
pip install pre-commit
pre-commit install
pre-commit run --all-files______________________________________________________________________
在Docker中运行
构建
docker build -t parsival:latest .跑
运行(stdio模式,不需要端口映射):
docker run --rm -i -e PYTHONUNBUFFERED=1 -e MCP_TRANSPORT=stdio -e PYTHONPATH=/app parsival:latest使用docker compose运行
运行stdio服务:
docker compose up parsival作曲(单主机)
docker compose up --build容器包括LibreOffice和 python-magic DOC/DOCX和格式嗅探所需的依赖关系。
______________________________________________________________________
API和工具
Parsival通过stdio公开MCP工具。使用您首选的MCP客户端按名称调用工具。
read_file
path:stroutput_format:“markdown”|“json”|“text”(默认为“markdown”)page_range:\[开始,结束\](1-索引)include_images:bool(默认为true)max_tokens_hint:intstream:bool(默认值为false)
退货 ReadFileResult (状态、格式、内容、元数据、错误、cachehit、request_id)。
get_metadata
path:str- 退货
DocumentMetadata对象(文件格式、页面计数、表格计数等)
extract_table
path:strtable_index:intsheet_name:可选\[str\]- 退货
TableResult
extract_images
path:strpage_range:可选\[tuple\[int,int\]\]max_dimension:可选\[int\]- 退货列表\[
ImageRef\]
convert_to_markdown
path:str- 返回标记字符串
search_file
path:strquery:strtop_k:int- 在章节文本上使用BM25排名(通过
rank-bm25)
list_supported_formats
- 无参数
- 退货可用
FileFormat值和服务器版本
______________________________________________________________________
解析器详细信息
支持的文件格式
- PDF:
src/parsers/pdf_parser.py(PyMuPDF+可选pdfplumber桌子) - DOCX:
src/parsers/docx_parser.py(python docx) - 医生:
src/parsers/doc_parser.py(LibreOffice转换+DOCX解析器) - XLSX:
src/parsers/xlsx_parser.py(波兰openpyxl) - CSV:
src/parsers/csv_parser.py(波兰,utf-8后撤) - PPTX:
src/parsers/pptx_parser.py(python pptx) - HTML:
src/parsers/html_parser.py(美汤+降价) - TXT/MD:
src/parsers/text_parser.py(纯文本启发式)
解析工作流
parse_file确定格式FormatRouter.detect.- 解析器返回
ParseResult,包括sections,tables,images,metadata,errors. stream=True分派解析器stream_chunks,绕过缓存预取。max_tokens_hint是解析后应用的软截断。
错误处理
- 损坏/加密的文档返回
ParseStatus.FAILED和ParseError代码(例如。encrypted,corrupt). - 超大文件返回
ParseStatus.OVERSIZE(元数据中的源路径/大小)。 - 解析流防止在读取和结果刷新之间更改文件状态。
______________________________________________________________________
缓存行为
- 内置缓存密钥
src/core/cache.py作为SHA256(file) + ':' + SHA256(opts). - 考虑的选项:output_format、page_range、include_images、max_tokens_hint、max_dision。
- 内存LRU缓存
cachetools.LRUCache样本大小基于ParseResult的JSON大小。 - Redis后端如果
MCP_REDIS_ENABLED=true和MCP_REDIS_URL已设置。 - 连接失败时,Redis会自动回退到内存中。
- 使用
MCP_REDIS_TTL(默认3600秒)。
______________________________________________________________________
测试和CI
本地试运行
pytest -q覆盖
coverage run -m pytest -q
coverage report -m --fail-under=90CI管道处于
.github/workflows/ci.yml
- 针对Python 3.11/3.12/3.13的测试 - ruff check . - 覆盖+编解码器
______________________________________________________________________
故障排除
道路卫生
src/core/security.py 强制执行 MCP_WORKSPACE_ROOT 和 MCP_ALLOWED_DIRECTORIES如果你得到 SecurityError:
- 集
MCP_WORKSPACE_ROOT到您的repo根目录 - 通过添加允许的目录
MCP_ALLOWED_DIRECTORIES
不支持的格式
如果解析失败,格式不受支持,请检查扩展名+文件魔术,并仅使用标准格式。
LibreOffice失败
- 确保
soffice安装在PATH中(Dockerfile包括libreoffice-*包装) - 增加:
- export LIBREOFFICE_TIMEOUT_SEC=60 - export MCP_MAX_LIBREOFFICE_WORKERS=4
Redis缓存
- 如果没有配置Redis,该服务将使用内存缓存。
- 集
MCP_REDIS_ENABLED=true和MCP_REDIS_URL=redis://localhost:6379/0.
______________________________________________________________________
维护人员注意事项
- 此README由以下代码和支持的配置生成
src/和Docs/. - 对于扩展,请在中添加解析器类
src/parsers并注册@register(FileFormat.X). - 要公开新的MCP工具,请在中定义
src/tools并在中添加装饰功能src/app.py.
