Skip to main content
Glama
jorgell23-sys

mdcx

mdcx

PyPI License DOI

Преобразуйте коллекцию документов в проверенный Markdown, упакуйте её в один зашифрованный файл и сделайте её доступной для запросов агентов через Model Context Protocol.

Проблема

У агента, отвечающего на вопросы о коллекции документов, есть два варианта. Он может получить документы в своём контекстном окне — это дорого и ограничено размером окна. Либо он может обратиться к компоненту, который уже знает, где находится каждый элемент.

Измерение одного конкретного запроса — где указан минимальный диаметр трубы, который необходимо моделировать в 3D — по реальной коллекции из 99 документов и 180 МБ, с использованием токенизатора cl100k_base:

Токены модели

Локальные токены

Чтение оригиналов

2 265 488

2 265 327

Запрос к пакету

435

2 688 861

435 состоят из 20 на вопрос, 274 на извлечённый фрагмент и 141 на ответ.

Первая строка стоит всей коллекции по конкретной причине: PDF нельзя искать, это бинарный файл, и без предварительного преобразования невозможно узнать, какой из 99 документов содержит ответ. Их все приходится извлекать и читать.

Это одно измерение, а не среднее значение: экономия зависит от того, сколько текста требует ответ. Неизменна лишь форма изменения. Работа не исчезает, она перемещается из контекстного окна — которое тарифицируется и конечно — в CPU, который не тарифицируется. Именно поэтому локальный столбец растёт, а не падает.

Related MCP server: md-mcp

Три этапа

Преобразование. Каждый документ преобразуется в Markdown и проверяется по тексту, который оригинал фактически предоставляет, считываемому библиотекой, независимой от движка, выполнившего преобразование. Содержимое, пропущенное структурированным движком, добавляется дословно, а не сообщается как утраченное.

По коллекции, использовавшейся при разработке — 99 документов, 1 144 553 эталонных слова — 594 слова не были восстановлены, что составляет глобальное покрытие 99,948%. Из 184 документов, предоставляющих текст, 116 вышли ровно на 100%, и ни один не ниже 99,5%. Оставшиеся четыре — это сканированные чертежи, не содержащие в файле никакого текста: они были прочитаны с помощью оптического распознавания символов и помечены как непроверяемые, поскольку не существует текстового оригинала, с которым их можно было бы сверить.

Упаковка. Корпус, его поисковый индекс и происхождение каждого фрагмента помещаются в один файл .mdcx, зашифрованный с помощью AES-256-GCM, заголовок которого можно прочитать без ключа. С 8,8 МБ Markdown до 3,9 МБ в одном файле.

Поиск. Запрос возвращает фрагменты, отвечающие на него, с указанием их точного источника. По 20 реальным запросам, использовавшимся для настройки, правильный документ появляется в пятёрке лучших результатов в 19 случаях и в десятке лучших во всех 20.

Установка

Пакет разделяет запросы и преобразование, поскольку у них очень разные требования.

Команда

Устанавливает

Размер

pip install mdcx

запросы и чтение пакетов .mdcx

~10 МБ

pip install "mdcx[mcp]"

предыдущее плюс MCP-сервер

~50 МБ

pip install "mdcx[convert]"

преобразование документов (Docling, PyTorch)

~1,4 ГБ

pip install "mdcx[all]"

всё, включая OCR

~1,5 ГБ

Именно преобразование притягивает тяжёлые зависимости. Тот, кто получает файл .mdcx и нуждается только в запросах к нему, не устанавливает ни Docling, ни PyTorch.

Преобразование коллекции

pip install "mdcx[convert]"
mdcx-convert --input ./Documents --output ./Documents_md

Результат повторяет структуру каталогов на входе, добавляет глобальный индекс и для каждого файла фиксирует достигнутое покрытие относительно его оригинала.

Упаковка и запросы

mdcx pack --output ./Documents_md --target corpus.mdcx --key "..."
mdcx info corpus.mdcx
mdcx search corpus.mdcx "where is the minimum diameter stated" --key "..."
mdcx export corpus.mdcx --target ./restored --key "..."

info читает заголовок без ключа, поэтому эмитента и целостность файла можно проверить до его открытия. export восстанавливает исходную папку: формат, из которого нельзя выйти, — это ловушка, какими бы благими ни были намерения.

Использование в качестве MCP-сервера

Серверу требуются Python и этот пакет. Ему не нужен стек преобразования, поэтому занимаемый объём составляет около 50 МБ.

{
  "mcpServers": {
    "mdcx": {
      "command": "python",
      "args": ["-m", "mdcx.mcp_server"],
      "env": {
        "MDCX_FILE": "/path/to/corpus.mdcx",
        "MDCX_KEY": "package-key"
      }
    }
  }
}

В качестве альтернативы, с помощью uv сервер запускается без предварительной установки, что является обычной схемой для Python MCP-серверов:

{
  "mcpServers": {
    "mdcx": {
      "command": "uvx",
      "args": ["--from", "mdcx[mcp]", "python", "-m", "mdcx.mcp_server"],
      "env": {
        "MDCX_FILE": "/path/to/corpus.mdcx",
        "MDCX_KEY": "package-key"
      }
    }
  }
}

Предоставляются три инструмента. search возвращает фрагменты, отвечающие на вопрос, каждый со своим исходным документом и переносимым путём. info описывает корпус и точность его преобразования. document возвращает полный документ, когда фрагментов недостаточно.

Сервер проверяет пакет до начала прослушивания, поэтому неверный путь или ключ сообщаются немедленно, а не при первом запросе.

Тесты

pip install pytest
python -m pytest tests/ -v

Набор покрывает враждебные входные данные: пустые и повреждённые файлы, имена на других алфавитах, некорректные запросы, включая попытки SQL-инъекций, усечённые и подделанные пакеты, а также уплотнение против потери содержимого.

Пути

Ни один вывод не содержит абсолютных путей. Каждый документ идентифицируется псевдопутём, начинающимся с @/, разрешаемым относительно папки или пакета, содержащего его, поэтому корпус остаётся действительным, где бы он ни хранился: на локальном диске, в сетевой папке или в облаке.

Подпись

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

mdcx keygen
mdcx pack --output ./Documents_md --target corpus.mdcx --key "..." \
          --issuer "Acme Ltd" --signing-key <private-key>
mdcx verify corpus.mdcx --public-key <public-key>

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

Поле эмитента само по себе — это произвольный текст, и оно ничего не доказывает. Только подпись доказывает.

Шифрование

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

Ключ выводится с помощью scrypt, что замедляет подбор: около 8 попыток в секунду, каждая требует 32 МБ памяти, что предотвращает распараллеливание на GPU. Тем не менее, реальная стойкость — в парольной фразе: словарный пароль взламывается за день.

Авторство

Замысел и руководство — Хорхе Эльена Г., программирование при содействии Claude (Anthropic).

Каждое решение в этом пакете принималось на основе измерений, а не условностей: какой движок преобразования использовать, какая лицензия что разрешает, как ранжировать поиск, какие оптимизации принять, а какие отбросить. Некоторые были отброшены именно потому, что были измерены — сокращение пула кандидатов для поиска казалось в десять раз быстрее и на самом деле снизило точность с 19 до 17 из 20 — и эти измерения зафиксированы вместе с решениями, которые они обосновывают.

Цитирование

Архивировано на Zenodo с постоянным идентификатором. Концептуальный DOI всегда разрешается в последнюю версию:

https://doi.org/10.5281/zenodo.22015991

Лицензия

Apache 2.0. Программное обеспечение может использоваться, изменяться и продаваться при условии сохранения уведомления об авторских правах.

PyMuPDF был намеренно исключён: его лицензия AGPL потребовала бы от любого, кто использует это программное обеспечение, публиковать своё под AGPL, включая тех, кто предлагает его только как сетевой сервис.

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
33Releases (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

View all related MCP servers

Related MCP Connectors

  • Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.

  • Securely search and manage workspace context files for AI agents and teams.

  • Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.

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/jorgell23-sys/mdcx'

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