Skip to main content
Glama
awesome0w

mcp-ready-data-discovery-tool

by awesome0w
README.md
# MCP-ready Data Discovery Tool

Локальный MVP-инструмент для поиска и обнаружения данных. Проект индексирует метаданные, схемы, примеры строк, примеры значений и Markdown-документацию из нескольких локальных источников, сохраняет каталог в SQLite и отдаёт результаты через Web UI, REST API и MCP-ready функции.

Это инструмент обнаружения данных, а не система Text-to-SQL.

## Что делает проект

- Подключает локальные источники данных: SQLite-базу, папку с CSV-файлами и Markdown-документацию.
- Показывает доступные источники, таблицы/файлы, колонки и документы.
- Собирает метаданные: количество строк, типы данных, примеры строк, примеры значений и время последней индексации.
- Индексирует данные во внутренний каталог `storage/catalog.db`.
- Использует SQLite FTS5 для поиска по ключевым словам.
- Использует локальный семантический слой на основе TF-IDF и косинусного сходства. поверх Markdown-документации, описаний, `metadata`, примеров значений и `preview`.
- Возвращает ранжированные результаты с происхождением данных: `source`, `sourceType`, `table`, `column`, `path`, `matchedBy`, `keywordScore`, `semanticScore`.
- Возвращает фрагменты Markdown-документов, а для таблиц и колонок — примеры строк и примеры значений.
- Предоставляет MCP-ready инструменты: `listSources`, `indexSource`, `search`, `getSchema`.

## Что проект НЕ делает

- Не является Text-to-SQL системой.
- Не генерирует SQL из пользовательского текста.
- Не выполняет LLM query planning.
- Не реализует ETL/ELT-пайплайн.
- Не реализует CDC.
- Не является production RBAC системой.
- Не использует внешние платные API.
- Не отправляет данные во внешние сервисы по умолчанию.

## Быстрый запуск

```bash
make install
make seed
make index
make run
```

После запуска откройте:

```text
http://localhost:8000
```

## Ручной запуск без `make`

```bash
python -m pip install -e ".[dev]"
python scripts/generate_seed_data.py
python scripts/index_all.py
python -m uvicorn app.main:app --reload
```

## Тестовые данные

Команда:

```bash
make seed
```

создаёт воспроизводимые локальные данные:

- `data/shop.db`
  - `users`
  - `orders`
  - `payments`
  - `products`
- `data/csv/events.csv`
- `data/csv/support_tickets.csv`
- `data/csv/marketing_campaigns.csv`
- `data/docs/users.md`
- `data/docs/orders.md`
- `data/docs/payments.md`

Генератор использует фиксированное зерно `42`, поэтому данные одинаково воспроизводятся при повторных запусках.

## Индексирование

Команда:

```bash
make index
```

индексирует все настроенные источники и записывает результат во внутреннюю SQLite-базу каталога:

```text
storage/catalog.db
```

В каталоге сохраняются:

- источники;
- элементы каталога;
- история запусков индексирования;
- поисковый индекс FTS5.

Индексируются не все строки целиком, а представления, полезные для поиска данных: схемы, названия, описания, примеры строк, примеры значений и документация.

## UI

Минимальный Web UI реализован через FastAPI и Jinja2-шаблоны.

- `/`
  Главная страница со списком источников и строкой поиска.

- `/search?q=customer+email`
  Страница с ранжированными результатами поиска.

- `/schema?sourceId=sqlite_shop&path=sqlite_shop.users`
  Страница просмотра схемы: колонки, `metadata` и примеры строк.

UI остаётся тонким слоем и использует ту же бизнес-логику, что REST API и MCP-инструменты.

## REST API

Примеры:

```bash
curl http://localhost:8000/api/sources
```

```bash
curl -X POST http://localhost:8000/api/sources/sqlite_shop/index
```

```bash
curl "http://localhost:8000/api/search?q=payment%20method"
```

```bash
curl "http://localhost:8000/api/search?q=email&sourceId=csv_folder&type=column"
```

```bash
curl "http://localhost:8000/api/schema?sourceId=sqlite_shop&path=sqlite_shop.users"
```

`/api/search` возвращает объекты такого формата:

```json
{
  "type": "column",
  "score": 0.91,
  "sourceId": "sqlite_shop",
  "path": "sqlite_shop.users.email",
  "metadata": {
    "sourceId": "sqlite_shop",
    "path": "sqlite_shop.users.email",
    "sourceType": "sqlite",
    "resultType": "column",
    "matchedBy": "hybrid",
    "keywordScore": 1.34,
    "semanticScore": 0.11,
    "parentTable": "users",
    "table": "users",
    "column": "email"
  },
  "preview": ["user001@example.com", "user002@example.com"]
}
```

## Поиск

Поиск реализован как локальный гибридный механизм:

1. **SQLite FTS5 для поиска по ключевым словам**
   Ищет по именам источников, таблиц и колонок, тексту документации, `metadata` и примерам значений.

2. **Локальный семантический поиск на основе TF-IDF**
   Использует `TfidfVectorizer` и Cosine Similarity по вспомогательному тексту:
   - Markdown-документации;
   - именам элементов;
   - путям;
   - описаниям;
   - `metadata`;
   - примерам значений;
   - фрагментам в `preview`.

3. **Гибридное ранжирование результатов**
   Результаты FTS5 и TF-IDF объединяются по `(sourceId, path)`. В `metadata` сохраняются:
   - `keywordScore`;
   - `semanticScore`;
   - `matchedBy`.

   Итоговый `score` примерно объединяет `keywordScore` и `semanticScore` с весами `0.65 / 0.35`.

4. **Происхождение результатов и поле `preview`**
   Каждый результат содержит сведения о происхождении: источник, таблицу, колонку или документ. Документы возвращают фрагмент Markdown-текста, таблицы — примеры строк, колонки — примеры значений.

Важно: под семантическим поиском здесь понимается локальный механизм на TF-IDF, а не LLM- или embedding-based поиск.

## MCP-инструменты

MCP-ready слой находится в:

```text
app/mcp_server/server.py
app/mcp_server/manifest.json
```

Доступные инструменты:

- `listSources()`
- `indexSource({sourceId})`
- `search({query, filters?})`
- `getSchema({sourceId, path})`

Локальная демонстрация:

```bash
make mcp-demo
```

Она напрямую вызывает локальные функции-инструменты и проверяет тот же контракт, который мог бы использовать AI-агент, совместимый с MCP. Реальный AI-агент для демонстрации не требуется.

Если установлен MCP Python SDK, `app/mcp_server/server.py` может зарегистрировать эти инструменты через `FastMCP`. Если SDK не установлен, локальные функции всё равно работают.

## Тесты

```bash
make test
```

Тесты покрывают ключевые сценарии:

- SQLite-коннектор;
- CSV-коннектор;
- индексирование;
- фильтры поиска;
- `metadata` для гибридного поиска и происхождения результатов;
- фрагменты документов;
- маршруты REST/UI;
- MCP-инструменты;
- получение схемы.

## Оценка качества поиска

```bash
make evaluate
```

Оценка считает:

- Precision@5;
- Recall@5;
- задержку поиска;
- количество проиндексированных объектов;
- результаты запросов для проверки семантического поиска;
- распределение `matchedBy`.

Результаты также записываются в:

```text
storage/evaluation_results.json
```

## Docker Compose

```bash
docker compose up
```

Контейнер устанавливает зависимости, генерирует тестовые данные, индексирует источники и запускает приложение на порту `8000`.

## Принятые архитектурные компромиссы

- SQLite FTS5 выбран вместо Elasticsearch, потому что MVP должен быть локальным, лёгким и воспроизводимым.
- TF-IDF выбран вместо embedding-моделей на базе transformer, чтобы получить локальный семантический слой без внешних API и тяжёлой инфраструктуры.
- SQLite + CSV выбраны вместо PostgreSQL/warehouse, потому что задача связана с обнаружением данных, а не с production-платформой для работы с данными.
- Jinja2 выбран вместо React, потому что нужен минимальный рабочий UI.
- Примеры строк и примеры значений индексируются вместо полной индексации на уровне отдельных строк, чтобы не превращать проект в ETL или индексатор для data lake.
- MCP SDK остаётся необязательным: проект можно демонстрировать через локальные функции-инструменты.

## Ограничения текущей реализации

- Это MVP, а не enterprise-каталог данных.
- Конфигурация источников статическая.
- TF-IDF не понимает смысл так же глубоко, как embedding-модели на базе transformer.
- `semanticScore` может не доминировать над `keywordScore`.
- Для больших каталогов TF-IDF-матрицу лучше кешировать или вынести в отдельный локальный индекс.
- RBAC, audit, multi-tenant isolation и усиление безопасности и надёжности для production-эксплуатации не реализованы.

## Возможные направления дальнейшего развития

- Добавить конфигурационный файл для источников.
- Кешировать TF-IDF-матрицу между запросами.
- Добавить инкрементальную индексацию по времени изменения файлов.
- Улучшить словари синонимов и подсказок для бизнес-терминов.
- Рассмотреть локальные embedding-модели на базе transformer и лёгкое векторное хранилище.
- Добавить полноценную инструкцию регистрации MCP server в реальном клиенте, совместимом с MCP.