Skip to main content
Glama
Pranavdmg20

pdf-extract-mcp

by Pranavdmg20

pdf-extract-mcp

CI Python License: MIT MCP

Сервер Model Context Protocol (MCP), который извлекает структурированные данные из неструктурированных PDF-документов детерминированно — извлечение обычного текста плюс сопоставление полей по регулярным выражениям/эвристикам, без вызовов LLM API во время извлечения.

Возможности

  • Настоящий MCP-сервер — построен на официальном MCP Python SDK (2.x), работает по протоколу через stdio, SSE или streamable HTTP. Проверен сквозным тестом, который запускает реальный сервер с официальным клиентом.

  • Извлечение на основе схем — укажите extract_fields на любую JSON Schema и получите структурированный JSON ровно для тех полей, которые вы запросили.

  • Детерминированность и прозрачность — сопоставление по регулярным выражениям/эвристикам, без вызовов LLM API, без скрытых затрат и чёрного ящика. Каждое извлечение воспроизводимо и проверяемо.

  • Понятные отчёты валидации — validate_against_schema объясняет по каждому полю, почему оно прошло проверку, не прошло или отсутствует.

  • Готовые схемы — invoice, resume и purchase_order поставляются готовыми к использованию, плюс синтетические образцы PDF, так что всё можно продемонстрировать сразу из коробки.

  • Корректная обработка ошибок — повреждённые PDF, отсутствующие файлы и неверные схемы возвращают структурированные ошибки, а не стек-трейсы.

Related MCP server: StructureAI MCP Server

Что такое MCP и зачем это нужно

Model Context Protocol — это открытый стандарт, который позволяет ИИ-ассистентам (Claude, Cursor и т.д.) вызывать внешние инструменты через постоянное двунаправленное соединение. Вместо того чтобы вставлять текст PDF в чат и просить модель «разобраться», ассистент может напрямую вызвать pdf-extract-mcp, получить структурированный JSON, соответствующий предоставленной вами схеме, и работать с ним. Поскольку извлечение здесь детерминированное (регулярные выражения + эвристики), а не вероятностный вызов модели, каждый результат можно проверить, воспроизвести, и это дёшево. Поэтому он идеально подходит для автоматизированных конвейеров обработки документов (счета — в бухгалтерию, резюме — в ATS, заказы на поставку — в отдел закупок), где нужно знать, почему поле было извлечено именно так.

Установка

cd pdf-extract-mcp
python3 -m venv .venv
source .venv/bin/activate
make install          # pip install -e ".[dev]"  (installs the console script too)

или, с обычным pip:

pip install -e ".[dev]"

Сервер использует официальный MCP Python SDK (mcp >= 2.x, текущая линия релизов, которая предоставляет API MCPServer). pdfplumber отвечает за извлечение текста, jsonschema — за валидацию, а reportlab генерирует образцы PDF.

При установке также появляется консольный скрипт pdf-extract-mcp, так что вы можете запускать сервер откуда угодно с помощью:

pdf-extract-mcp                     # stdio (default)
pdf-extract-mcp --transport streamable-http --host 127.0.0.1 --port 8000

Запуск

python server.py

Это запускает MCP через stdio (режим по умолчанию, который ожидают Claude Code / Claude Desktop). Вы также можете опубликовать его как сетевой сервис:

python server.py --transport streamable-http --host 127.0.0.1 --port 8000
python server.py --transport sse --host 127.0.0.1 --port 8001

Подключение к Claude Code / Claude Desktop

Claude Code — добавьте .mcp.json в корень вашего проекта:

{
  "mcpServers": {
    "pdf-extract": {
      "command": "python",
      "args": ["/absolute/path/to/pdf-extract-mcp/server.py"],
      "env": {}
    }
  }
}

Claude Desktop — добавьте тот же блок в конфигурацию Claude Desktop (claude_desktop_config.json, который находится в ~/Library/Application Support/Claude/ на macOS):

{
  "mcpServers": {
    "pdf-extract": {
      "command": "python",
      "args": ["/absolute/path/to/pdf-extract-mcp/server.py"]
    }
  }
}

Перезапустите клиент после сохранения. Вы должны увидеть три новых инструмента: extract_fields, validate_against_schema и list_supported_document_types.

Инструменты

Tool

Назначение

extract_fields(pdf_path, schema)

Извлекает структурированные поля из PDF по заданной JSON Schema -> {"ok": true, "data": {...}}

validate_against_schema(data, schema)

Проверяет извлечённые данные по схеме -> отчёт passed/failed/missing с понятными пояснениями

list_supported_document_types()

Выводит типы документов, для которых поставляются готовые схемы

Аргумент schema инструмента extract_fields принимает объект JSON Schema, имя встроенной схемы (например, "invoice") или путь к .json-файлу схемы. Встроенные схемы находятся в schemas/:

  • invoice — vendor_name, invoice_number, total_amount, due_date (обязательные) + issue_date, customer_name

  • resume — name, email (обязательные) + phone, skills

  • purchase_order — po_number, vendor_name, total_amount (обязательные) + issue_date, customer_name

Пример работы

Сначала сгенерируйте образцы PDF (они уже есть в репозитории; можно перегенерировать в любой момент с помощью):

python sample_pdfs/generate_samples.py

Теперь вызовите extract_fields для образца счёта, используя имя встроенной схемы invoice. В Claude Code можно просто сказать: «извлеки поля из sample_pdfs/invoice.pdf с помощью схемы invoice»; под капотом при этом выполняется вызов инструмента, эквивалентный:

{
  "name": "extract_fields",
  "arguments": {
    "pdf_path": "/absolute/path/to/pdf-extract-mcp/sample_pdfs/invoice.pdf",
    "schema": "invoice"
  }
}

Фактический ожидаемый результат:

{
  "ok": true,
  "data": {
    "vendor_name": "Acme Widgets Corp",
    "invoice_number": "INV-2024-0087",
    "total_amount": 1750.0,
    "due_date": "April 1, 2024",
    "issue_date": "March 1, 2024",
    "customer_name": "Globex Industries"
  },
  "text_length": 372
}

Передача данных в validate_against_schema с той же схемой:

{
  "ok": true,
  "valid": true,
  "passed": ["customer_name", "due_date", "invoice_number", "issue_date", "total_amount", "vendor_name"],
  "failed": [],
  "missing": [],
  "summary": "Valid: all 6 present field(s) conform to the schema.",
  "error": null
}

Запустите это напрямую из Python, чтобы увидеть вживую:

import json
from tools.extract import extract_fields
from tools.validate import validate_against_schema

schema = json.load(open("schemas/invoice.json"))
result = extract_fields("sample_pdfs/invoice.pdf", schema)
print(result["data"])
print(validate_against_schema(result["data"], schema))

Как работает регистрация инструментов MCP в server.py

Это сердце проекта, поэтому стоит точно понять, что SDK делает за вас.

1. Создайте объект сервера.

from mcp.server.mcpserver import MCPServer

mcp = MCPServer(
    "pdf-extract-mcp",
    title="PDF Extract MCP",
    description="Deterministic structured-data extraction from PDF documents",
    version="0.2.0",
)

MCPServer — это класс сервера из mcp SDK 2.x. Он реализует проводной протокол MCP: умеет отвечать на JSON-RPC-сообщения, которые клиент отправляет во время рукопожатия MCP (initialize, tools/list, tools/call и т.д.). Аргументы конструктора — это метаданные: имя сервера (обязательно для рукопожатия по протоколу), а также необязательные title/description/version, которые клиенты могут показывать пользователю.

2. Зарегистрируйте каждый инструмент с помощью декоратора.

@mcp.tool()
def extract_fields(pdf_path: str, schema: dict) -> dict:
    """Extract structured fields from an unstructured PDF ..."""
    return _extract_fields(pdf_path, schema)

Декоратор выполняет за вас три задачи:

  • Регистрация имени — имя функции extract_fields становится именем инструмента, которое клиент использует для его вызова. (Его можно переопределить с помощью @mcp.tool(name="...").)

  • Вывод схемы — SDK анализирует аннотации типов функции (pdf_path: str, schema: dict) и автоматически генерирует JSON-схему входных данных инструмента. Именно поэтому MCP-клиент ещё до вызова знает, что pdf_path — строка, а schema — объект. Это тот же подход, что использует FastAPI: типы и есть контракт.

  • Описание — docstring становится описанием инструмента; Claude читает его, чтобы решить, когда вызывать инструмент и с какими аргументами.

Итак, когда клиент спрашивает сервер «что ты умеешь?» (tools/list), SDK отвечает именем, описанием и выведенной входной схемой для каждой декорированной функции — никакой ручной таблицы регистрации, которую нужно синхронизировать.

3. Тело функции — это просто Python.

Когда клиент вызывает инструмент (tools/call с аргументами), SDK десериализует JSON-аргументы, вызывает вашу функцию с ними и сериализует возвращаемое значение обратно в протокол. Возвращаемое значение — это то, что видит клиент. Именно поэтому инструменты всегда возвращают обычные JSON-совместимые словари и никогда не выбрасывают исключений: исключение превратилось бы в непрозрачную ошибку протокола, а структурированный словарь {"ok": false, "error": "..."} — это то, что Claude может прочитать и на что может отреагировать. Сама логика извлечения/валидации находится в tools/extract.py и tools/validate.py, поэтому её можно покрывать юнит-тестами без MCP-клиента.

4. Запустите.

if __name__ == "__main__":
    main()   # argparse -> mcp.run(transport="stdio")

mcp.run(transport="stdio") запускает цикл протокола: читает запросы JSON-RPC, разделённые переводами строк, из stdin, направляет их зарегистрированным инструментам и записывает ответы в stdout. Это и есть весь сервер — ни HTTP-фреймворка, ни маршрутов, ни ручной обработки запросов. (Для streamable-http / sse тот же вызов run() запускает внутреннее ASGI-приложение.)

Ещё одна деталь, на которую стоит обратить внимание: extract_fields использует небольшой вспомогательный хелпер _load_schema, который принимает словарь схемы, имя встроенной схемы или путь к файлу, — так что один и тот же инструмент работает как с "invoice", так и с полным объектом схемы. Сама функция извлечения остаётся строгой (только dict), а удобные преобразования выполняет серверный слой.

Как работает извлечение (детерминированно и прозрачно)

  1. Извлечение текста — pdfplumber открывает PDF и извлекает обычный текст с каждой страницы.

  2. Сопоставление полей — для каждого свойства в вашей схеме перебирается упорядоченный список регулярных выражений; побеждает первое совпадение (tools/extract.py -> _FIELD_PATTERNS). Сначала идут наиболее специфичные шаблоны, а для неизвестных имён полей используется универсальное сопоставление «Field Name: value» плюс таблица синонимов (_FIELD_ALIASES).

  3. Приведение типов — сопоставленные строки приводятся к типу JSON Schema (например, "$1,750.00" -> 1750.0 для "type": "number"; разделение по запятой для массивов). При неудачном приведении используется исходная строка, чтобы не терять данные.

  4. Валидация — validate_against_schema повторно проверяет извлечённые данные с помощью пакета jsonschema и сообщает по каждому полю, прошло ли оно проверку, не прошло (с понятным пояснением) или отсутствует.

Поскольку каждый шаг — это обычный код, вы можете точно проследить, почему поле извлеклось или не извлеклось, — никакого чёрного ящика.

Обработка ошибок

Все три инструмента на любом пути возвращают структурированный JSON и никогда не выбрасывают стек-трейс за границу MCP:

  • Повреждённый/нечитаемый PDF -> {"ok": false, "error": "Could not read PDF ..."}

  • Отсутствующий файл -> {"ok": false, "error": "PDF not found: ..."}

  • PDF без извлекаемого текста -> {"ok": false, "error": "... contains no extractable text."}

  • Неверная схема (пустая, без свойств или некорректная JSON Schema) -> структурированный ключ ошибки

  • Отсутствующие обязательные поля -> перечисляются в "missing"; некорректные значения -> перечисляются в "failed" с пояснениями

Тесты

pytest tests/ -v

19 тестов, покрывающих:

  • Успешное извлечение для всех трёх типов документов (invoice, resume, purchase_order)

  • PDF с отсутствующими обязательными полями (негативное извлечение)

  • Проверка схемы, выявляющая неверный тип поля, отсутствующие обязательные поля, нарушения enum/pattern

  • Сценарии ошибок: повреждённый PDF, несуществующий файл, PDF без текста, неверная схема

  • Настоящий сквозной MCP-тест (tests/test_mcp_end_to_end.py), который запускает server.py как подпроцесс, подключается через stdio с официальным MCP-клиентом и вызывает все три инструмента по протоколу, — доказывая, что это настоящий MCP-сервер, а не библиотека, притворяющаяся им

Образцы PDF автоматически перегенерируются файлом tests/conftest.py, если они отсутствуют.

Структура репозитория

pdf-extract-mcp/
  server.py                    # MCP server: MCPServer + tool registration + transports
  tools/
    __init__.py
    extract.py                 # pdfplumber text extraction + regex field matching
    validate.py                # jsonschema validation with structured reports
  schemas/
    invoice.json               # pre-built schema: invoice
    resume.json                # pre-built schema: resume
    purchase_order.json        # pre-built schema: purchase_order
  sample_pdfs/
    generate_samples.py        # reportlab generator for the 4 sample PDFs
    invoice.pdf
    invoice_missing_fields.pdf
    resume.pdf
    purchase_order.pdf
  tests/
    conftest.py                # auto-generates sample PDFs if missing
    test_tools.py              # unit tests for extract/validate
    test_mcp_end_to_end.py     # end-to-end test over the real MCP stdio transport
  README.md
  requirements.txt

Устранение неполадок

  • ModuleNotFoundError: No module named 'mcp' — вы не в виртуальном окружении: source .venv/bin/activate (или используйте ./.venv/bin/python server.py).

  • Ошибки импорта FastMCP — server.py рассчитан на API mcp 2.x (MCPServer). Если в вашем окружении mcp 1.x, переустановите с помощью pip install -U "mcp>=2.0".

  • Инструменты не появляются в Claude — перезапустите клиент после изменения конфигурации и убедитесь, что "args" указывает на абсолютный путь к server.py, при необходимости используя python из виртуального окружения в качестве команды.

  • Извлечение пропускает поле — добавьте для него шаблон в _FIELD_PATTERNS в tools/extract.py (или используйте универсальное запасное правило «Field Name: value» и таблицу синонимов).

A
license - permissive license
A
quality
C
maintenance

Maintenance

UpdatingMaintainers
UpdatingResponse time
Release cycle
0Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI-powered extraction and analysis of PDF documents with 40+ specialized tools for text, tables, images, layout analysis, security assessment, and document intelligence. Supports both text-based and scanned PDFs with OCR capabilities.
    10
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Extracts structured JSON data from unstructured text using predefined schemas for receipts, invoices, resumes, and emails. It allows users to transform messy text into organized data through built-in or custom-defined fields.
    1
  • A
    license
    A
    quality
    D
    maintenance
    Enables RAG over messy PDFs — extract, chunk, embed, and search scanned, multi-column, and table-heavy documents.
    6
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Extracts text and tables from PDFs for AI agents via MCP, enabling structured data retrieval from invoices, reports, and statements.
    1
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Pranavdmg20/pdf-extract-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server