Shop MCP Server
Локальный MCP-сервер для аналитики SQLite-базы интернет-магазина. AI-агент вызывает MCP-инструмент, сервер преобразует запрос в безопасный SQL SELECT, напрямую читает shop.db и возвращает структурированный результат.
Host-приложение
├── AI-агент / LLM
└── MCP-клиент
│ JSON-RPC / stdio
▼
Shop MCP Server
│ read-only SQLite
▼
data/shop.db
Возможности
- прямое подключение к SQLite без HTTP и отдельного DB-сервера;
- MCP-транспорт
stdio; - обнаружение
query_shopиinspect_databaseчерезtools/list; - восемь примеров задания в описании и JSON Schema инструмента;
- обычный текст, JSON intent или готовый безопасный
SELECT; - исключение заказов
cancelledиз всей аналитики; - пагинация и ограничение результата;
- многоуровневая read-only защита.
Установка
Требуется Python 3.11 или новее.
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
Подготовленная база уже находится в data/shop.db. В ней 150 клиентов, поле customers.country заполнено у всех клиентов, а 45 клиентов относятся к Germany.
Повторная подготовка базы
Исходная база не изменяется. Команда создаёт новую рабочую копию и добавляет country TEXT NOT NULL с воспроизводимыми синтетическими значениями:
.venv/bin/shop-prepare-db /path/to/original/shop.db ./data/shop.db
Распределение зависит только от customers.id, поэтому повторная подготовка даёт те же значения. Страны являются тестовыми данными и не описывают реальное местонахождение клиентов.
Настройка пути
Путь определяется в таком порядке:
SHOP_DB_PATH;- JSON-файл из
SHOP_MCP_CONFIGилиconfig/shop_mcp.json; data/shop.dbотносительно рабочей директории.
Пример переменной окружения находится в .env.example, а конфигурация MCP-клиента — в config/mcp.example.json. Замените /absolute/path/to/MCPDeveloper на абсолютный путь к проекту.
Запуск
Обычно сервер запускает MCP-клиент из своей конфигурации. Для ручного запуска процесса:
SHOP_DB_PATH=./data/shop.db .venv/bin/python -m shop_mcp.server
stdout зарезервирован для MCP JSON-RPC. Диагностика не выводится в протокольный поток.
Инструменты
inspect_database
Аргументы:
{"action": "list_tables"}
или:
{"action": "describe_table", "table": "customers"}
query_shop
Аргументы:
{
"request": "Сколько клиентов из Германии?",
"limit": 100,
"offset": 0
}
Примеры, объявляемые через tools/list:
- Какие таблицы есть в базе и какие в них поля?
- Сколько клиентов из Германии?
- В какой стране больше всего клиентов?
- Какой клиент потратил больше всего? Верни имя, email и общую сумму.
- Покажи топ-5 товаров по проданному количеству и выручке.
- Покажи топ-3 категории по выручке.
- Какая выручка была в 2025 году?
- Какой клиент сделал больше всего заказов?
Можно передать структурированный intent:
{
"request": "{\"intent\": \"revenue_by_year\", \"year\": 2025}"
}
Или готовый запрос:
{
"request": "SELECT name, category FROM products ORDER BY name"
}
Бизнес-правила
orders.status = 'cancelled'не участвует в метриках.- Расходы клиентов и годовая выручка считаются по
orders.total_amount. - Выручка товаров и категорий считается как
quantity * unit_price. - Интервал года полуоткрытый: от 1 января включительно до 1 января следующего года исключительно.
- В поставленной базе все заказы относятся к 2026 году, поэтому выручка за 2025 год равна
0.
Безопасность
Сервер открывает SQLite через mode=ro, включает query_only, устанавливает SQLite authorizer, запрещает несколько выражений, DML, DDL, ATTACH, изменяющие PRAGMA, загрузку расширений и ограничивает время выполнения.
Любая попытка выполнить операцию, отличную от SELECT, возвращает точный ответ:
Не доступный вариант запроса
Внутренние ошибки SQLite, stack trace и локальные пути клиенту не возвращаются.
Проверка
.venv/bin/pytest
.venv/bin/ruff check .
.venv/bin/ruff format --check .
Тесты включают реальный запуск MCP-сервера как subprocess, подключение ClientSession через stdio, tools/list, вызов обоих инструментов, аналитические сценарии и попытки изменения базы.
Полная утверждённая спецификация находится в docs/specification.md.