shop-mcp
shop-mcp — Read-Only SQLite MCP Server
MCP-сервер на Python, предоставляющий AI-агенту (например, Pi) безопасный read-only доступ к базе данных SQLite shop.db через stdio.
Агент самостоятельно исследует схему БД, пишет SQL-запросы и решает аналитические задачи. Сервер не содержит готовых ответов — только инструменты для исследования и выполнения read-only запросов.
AI Agent (Pi)
│ stdio
▼
┌────────────────────┐
│ MCP Server │ list_tables / describe_table / read_query
└─────────┬──────────┘
▼
SQL validation ← только один SELECT / WITH ... SELECT
▼
read-only guard ← connection authorizer
▼
SQLite (mode=ro) ← файл физически невозможно изменить1. Requirements
Python 3.13+
Файл базы данных
shop.db(уже находится в корне проекта)
2. Installation
uv syncuv создаст виртуальное окружение и установит зависимости. Вручную создавать venv не нужно.
3. Database configuration
Путь к базе не захардкожен и настраивается через переменную окружения.
Вариант A — переменная окружения (абсолютный путь):
export SHOP_DB_PATH=/absolute/path/to/shop.db
export MAX_RESULT_ROWS=1000 # опционально, default 1000Вариант B — без настройки (fallback): если SHOP_DB_PATH не задана, сервер использует shop.db из корня проекта.
Допустимо также скопировать .env.example в .env и указать значения там (сервер читает .env из корня проекта; переменные окружения имеют приоритет):
cp .env.example .env4. Run MCP locally
uv run python -m shop_mcp.serverСервер работает через stdio и ожидает MCP-протокол на stdin/stdout — отдельно его запускать не нужно, его запускает сам клиент (Pi). Ручной запуск выше полезен только для отладки.
Некорректная конфигурация (например, отсутствует файл БД) завершает процесс с понятным сообщением в stderr.
5. Connect MCP to Pi
Pi подключает MCP-серверы через пакет pi-mcp-adapter и читает конфигурацию из .mcp.json в корне проекта. Такой файл уже входит в репозиторий:
{
"mcpServers": {
"shop": {
"command": "uv",
"args": ["run", "python", "-m", "shop_mcp.server"],
"cwd": "/Users/stalexsm/projects/shop-mcp"
}
}
}Для другой машины поправьте cwd на абсолютный путь к каталогу проекта (или замените на env с переменной SHOP_DB_PATH):
{
"mcpServers": {
"shop": {
"command": "uv",
"args": ["run", "python", "-m", "shop_mcp.server"],
"cwd": "/absolute/path/to/shop-mcp",
"env": {
"SHOP_DB_PATH": "/absolute/path/to/shop.db",
"MAX_RESULT_ROWS": "1000"
}
}
}
}Запускать отдельный HTTP-сервер или вручную держать python server.py в терминале не требуется: Pi сам стартует процесс по stdio (лениво, при первом обращении к инструментам).
Если адаптер ещё не установлен:
pi install npm:pi-mcp-adapterЗатем перезапустите Pi в каталоге проекта. Инструменты сервера появятся в панели /mcp.
6. Available tools
list_tables
Список таблиц БД с кратким описанием и количеством строк. Отправная точка исследования схемы. SQL не требуется.
describe_table
Структура одной таблицы: колонки (name, type, nullable, primary_key, default) и foreign keys в виде orders.customer_id -> customers.id. Несуществующая таблица даёт понятную ошибку со списком доступных таблиц.
read_query
Выполнение одного read-only SQL-запроса (SELECT или WITH ... SELECT).
Параметры:
sql(обязательный) — текст запроса;max_rows(опциональный) — запрошенный лимит строк; серверный hard limitMAX_RESULT_ROWS(по умолчанию 1000) не может быть превышен.
Поддерживается обычная аналитика SQLite: JOIN, LEFT JOIN, GROUP BY, HAVING, ORDER BY, LIMIT/OFFSET, COUNT/SUM/AVG/MIN/MAX, DISTINCT, CASE, CTE.
Результат — структурированный JSON:
{
"columns": ["name", "revenue"],
"rows": [["Ноутбук UltraBook 15", 6569270.0]],
"row_count": 1,
"truncated": false,
"execution_time_ms": 0.716
}truncated: true означает, что из-за лимита возвращена только часть строк — уточните запрос (LIMIT, WHERE, агрегация), не считая данные полными.
7. Security model
Три независимых уровня защиты:
SQL validation — разрешён ровно один statement, начинающийся с
SELECT/WITH. ЗапрещеныINSERT,UPDATE,DELETE,REPLACE INTO,DROP,ALTER,CREATE,ATTACH,DETACH,VACUUM,REINDEX,PRAGMAи другие изменяющие операции. Multi-statement запросы (SELECT ...; DELETE ...) отклоняются целиком. Валидатор понимает строковые литералы, комментарии и закавыченные идентификаторы, поэтому'DELETE'внутри строки не считается нарушением.Connection authorizer — всё, что не является чтением (SELECT / чтение таблицы / вызов функции), отклоняется на этапе подготовки запроса.
mode=ro— файл SQLite открывается в read-only режиме; даже при обходе первых двух уровней физическая запись невозможна.
Ошибки возвращаются агенту в понятном виде (Database query failed: no such column: foo) — без traceback, путей файловой системы и деталей реализации.
shop.db — read-only source of truth: сервер не изменяет ни содержимое, ни структуру файла. Это зафиксировано тестом целостности (checksum + счётчики строк до/после всех попыток разрушающих операций).
8. Example questions
Задайте эти вопросы агенту Pi — он сам вызовет list_tables, describe_table и read_query:
Show me all available tables and explain what information each table contains.
Who is the customer who spent the most money?
What are the top 5 best-selling products?
What are the top 3 product categories by revenue?
How much revenue did we generate in 2025?
Which customer placed the most orders?
Справка по бизнес-логике (агент выводит это из описаний инструментов, сервер ответов не кодирует):
revenue по товарам/категориям считается как
SUM(order_items.quantity * order_items.unit_price);заказы со статусом
cancelledне учитываются;revenue по годам считается по
orders.order_date; если заказов нет — корректный ответ0.
Вопрос про страны
How many customers are from Germany? — на этот вопрос нельзя достоверно ответить: в таблице customers нет поля country (только first_name, last_name, email, phone, created_at). Сервер отдаёт агенту достоверную информацию о схеме, а агент обязан сообщить, что требуемых данных в БД нет, вместо того чтобы выводить страну из email/телефона или гадать.
9. Testing
uv run pytestНабор тестов (66):
tests/test_database.py— read-only подключение, discovery схемы, foreign keys, закрытие соединений;tests/test_security.py— все запрещённые операции (раздел 24 спецификации), multi-statement, integrity-тест БД;tests/test_tools.py— интеграционные тесты MCP-инструментов через реальную клиентскую сессию (in-memory transport), включая обработку ошибок;tests/test_analytics.py— аналитические сценарии (раздел 27) со сверкой против независимого SQLite-источника, лимиты размера результата.
Тесты не изменяют shop.db (integrity-тест сверяет checksum файла).
10. Troubleshooting
Симптом | Причина и решение |
|
|
Инструменты не видны в Pi | Убедитесь, что |
| В одном вызове |
| Запрос начинается не с |
Результат неполный ( | Сработал лимит строк. Добавьте |
Хочу другой лимит строк | Задайте |
Project layout
shop-mcp/
├── README.md
├── pyproject.toml
├── uv.lock
├── .env.example
├── .gitignore
├── .mcp.json # конфигурация MCP для Pi
├── shop.db # read-only source of truth
├── scripts/
│ └── smoke_stdio.py # ручной smoke-тест через реальный stdio
├── src/shop_mcp/
│ ├── __init__.py
│ ├── server.py # MCP-инструменты (stdio)
│ ├── database.py # read-only слой доступа к SQLite
│ ├── security.py # SQL validation + single-statement guard
│ ├── models.py # структуры результатов
│ └── config.py # SHOP_DB_PATH / MAX_RESULT_ROWS
└── tests/
├── test_database.py
├── test_security.py
├── test_tools.py
└── test_analytics.pyLatest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/stalexsm/shop-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server