Skip to main content
Glama
lampmaster

shop-sql-mcp

by lampmaster

shop-sql-mcp

Небольшой MCP-сервер, который даёт ИИ-агенту только чтение аналитический доступ к базе SQLite shop.db через stdio.

Сервер делает три вещи и больше ничего: перечисляет таблицы, описывает их схему и выполняет один запрос (только чтение) за вызов с принудительной пагинацией на стороне сервера. Все рассуждения — какие соединения выполнять, как агрегировать, когда смотреть схему — остаются за агентом.

AI Agent
    |
    |  MCP over stdio
    v
shop-sql-mcp
    |
    +-- list_tables
    +-- describe_table
    +-- query_database
    |
    v
read-only SQLite connection
    |
    v
shop.db

Требования

  • Node.js 22.5 или новее (рекомендуется 24+). Сервер использует встроенный модуль node:sqlite, поэтому не нужно собирать нативное расширение SQLite.

  • Других требований к окружению нет.

Related MCP server: mcpserve-py

Установка

npm install

Настройка

Настройка необязательна. По умолчанию сервер открывает shop.db в корне проекта.

Переменная

Значение по умолчанию

Описание

DATABASE_PATH

<project>/shop.db

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

Скопируйте .env.example в .env, если хотите оставить локальные изменения. Сам сервер читает обычные переменные окружения; ANTHROPIC_API_KEY, EVAL_MODEL и EVAL_MAX_STEPS из .env.example используются только при запуске npm run eval.

Сборка

npm run build

Компилирует src/ в dist/.

Запуск

npm start              # runs the built server (dist/index.js)
npm run dev            # runs src/index.ts directly, no build step

Сервер общается по MCP на stdin/stdout и пишет на stderr только диагностику, поэтому в терминале запуск будет выглядеть как зависший — это нормально. Его должен запускать MCP-хост.

Подключение к MCP-агенту

Добавьте это в конфигурацию MCP-хоста (claude_desktop_config.json для Claude Desktop, .mcp.json для Claude Code или эквивалентный файл своего хоста), используя абсолютный путь к проекту:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"]
    }
  }
}

Чтобы запустить из исходников без сборки, укажите вместо этого точку входа TypeScript — Node выполнит её напрямую:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/src/index.ts"]
    }
  }
}

Чтобы читать базу в другом месте:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"],
      "env": { "DATABASE_PATH": "/absolute/path/to/other.db" }
    }
  }
}

Для Claude Code можно также зарегистрировать сервер из командной строки:

claude mcp add shop-sql -- node /absolute/path/to/shop-sql-mcp/dist/index.js

Инструменты

list_tables

Без аргументов. Возвращает пользовательские таблицы; внутренние таблицы sqlite_* скрыты.

{
  "tables": [
    { "name": "customers" },
    { "name": "order_items" },
    { "name": "orders" },
    { "name": "products" }
  ]
}

describe_table

{ table: string }

Читает схему напрямую из SQLite — ничего не зашито в код — и возвращает колонки, типы, допустимость NULL, первичные и внешние ключи:

{
  "table": "order_items",
  "columns": [
    { "name": "id", "type": "INTEGER", "nullable": false, "primaryKey": true },
    { "name": "order_id", "type": "INTEGER", "nullable": false, "primaryKey": false }
  ],
  "foreignKeys": [
    { "column": "order_id", "referencesTable": "orders", "referencesColumn": "id" },
    { "column": "product_id", "referencesTable": "products", "referencesColumn": "id" }
  ]
}

Неизвестное имя — это обрабатываемая ошибка, а не падение:

{ "error": { "code": "TABLE_NOT_FOUND", "message": "TABLE_NOT_FOUND: Table \"foo\" does not exist." } }

Примечание: колонка, которая является INTEGER PRIMARY KEY, возвращается как nullable: false. Функция SQLite table_info говорит иначе, но такая колонка — псевдоним rowid и никогда не может содержать NULL.

query_database

{ sql: string; limit?: number; offset?: number }

Выполняет один запрос только на чтение — SELECT ... или WITH ... SELECT ... — с поддержкой JOIN, WHERE, GROUP BY, HAVING, ORDER BY, подзапросов, агрегатов и фильтрации по датам.

{
  "columns": ["category", "revenue"],
  "rows": [["Electronics", 1234567.89]],
  "returnedRows": 1,
  "limit": 100,
  "offset": 0,
  "hasMore": false
}

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

Ошибки возвращаются обычным результатом инструмента с флагом isError и понятным коротким сообщение, чтобы агент мог исправить SQL и повторить:

{ "error": { "code": "SQL_ERROR", "message": "no such column: total" } }

Коды ошибок: SQL_ERROR, READ_ONLY_VIOLATION, MULTIPLE_STATEMENTS, TABLE_NOT_FOUND, INVALID_ARGUMENT, DATABASE_UNAVAILABLE. Стек-трейсы никогда не возвращаются.

Пагинация

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

  • limit по умолчанию — 100, максимум — 500; offset по умолчанию — 0.

  • Запрос агента оборачивается как SELECT * FROM (<ваш sql>) LIMIT ? OFFSET ?, так что даже запрос с собственным LIMIT 100000 не сможет вернуть больше строк, чем limit.

  • Сервер внутри загружает limit + 1 строк, чтобы определить hasMore, без повторного запроса счётчика, и возвращает не более limit строк.

  • Один вызов никогда не вернёт более 500 строк — благодаря этому широкий SELECT * не переполняет контекст модели.

Для листания результатов оставьте SQL без изменений (с детерминированным ORDER BY) и увеличивайте offset на limit, пока hasMore равно true.

Безопасность только для чтения

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

1. Валидация SQL(src/sqlSafety.ts). Небольшой лексический анализ пропускает комментарии, строковые литералы и идентификаторы в кавычках, после чего требует, чтобы:

  • выражение начиналось с SELECT или WITH — наивный startsWith("SELECT") отклонил бы смелые read-only CTE;

  • там был ровно один оператор (любой лишний ; отклоняется, при этом ; внутри литерала или комментария это не разделитель);

  • нигде не встретилось запрещённого ключевого слова, включая содержимое CTE: INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, REPLACE, ATTACH, DETACH, VACUUM, REINDEX, PRAGMA, ANALYZE, BEGIN, COMMIT, ROLLBACK, SAVEPOINT, load_extension, writable_schema.

Запрещённый SQL всегда отклоняется явной ошибкой — никогда не игнорируется молча и никогда не выполняется частично. При этом REPLACE(a, b, c) разрешён как скалярная функция, потому что записывающим является только оператор REPLACE INTO.

Само подключение SQLite. shop.db открывается через new DatabaseSync(path, { readOnly: true }). Даже если запись просочилась мимо валидации, SQLite откажется с ошибкой "attempt to write a readonly database". Набор тестов проверяет это напрямую, выполняя запросы записи в обход валидатора.

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

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

npm test

Выполняет детерминированный набор тестов — без сети, без ключей API, без LLM. Встроенный тестовый раннер Node выполняет исходники TypeScript напрямую. Покрытие включает: list_tables, describe_table (колонки, типы, допустимость NULL, первичные ключи, внешние ключи, неизвестные таблицы), простые выборки, фильтрацию, агрегацию, joins, GROUP BY, read-only CTE, фильтрацию по дате, пагинацию (лимит по умолчанию, максимальный лимит, offset, границы hasMore), неверный SQL, неизвестные колонки и таблицы, отказ INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/REPLACE/ATTACH/DETACH/VACUUM/REINDEX/PRAGMA и нескольких запросов, подтверждение того, что база побайтово не меняется после каждого отклонённого запроса на запись, а также полные вызовы MCP через stdio, которые подтверждают, что сервер остаётся рабочим после ошибок.

Запуск оценки вручную

export ANTHROPIC_API_KEY=sk-...
npm run eval

Запускайте это вручную. Целевая фраза исключена из npm test, потому что этап вызывает реальную LLM против реального MCP-сервера через stdio и требует платных API-вызовов.

Она запускает сервер, предоставляет модели три MCP-инструмента и инструмент submit_answer, JSON-схема которого зафиксирована для каждой задачи, и сравнивает структурированный ответ с эталонным значением, которое вычислено напрямую из SQLite — не с анализом естественного языка. Задачи охватывают обнаружение таблиц, определение схемы, фильтрацию, агрегирование, joins, затраты клиентов, количество заказов клиентов, продажи товара и выручку категорий; выручку за 2025 год и деструктивный запрос, который должен быть отклонён (проверяется также, что база после этого не изменилась).

Необязательно: EVAL_MODEL (по умолчанию claude-sonnet-5) и EVAL_MAX_STEPS (по умолчанию 12). Ненулевой кодзультата, если хотя бы одна задача провалится.

Структура

src/
  index.ts       MCP server: tool registration, stdio wiring, error shaping
  db.ts          read-only connection, path resolution, row/value normalisation
  tools.ts       the three tools: list_tables, describe_table, query_database
  sqlSafety.ts   single-statement read-only SQL validation
tests/
  sqlSafety.test.ts   validator, allowed and forbidden SQL
  tools.test.ts       tools against the real shop.db
  mcp.test.ts         end-to-end over stdio with a real MCP client
eval/
  tasks.ts       eval tasks and their SQLite reference values
  run.ts         LLM + MCP eval runner (manual)
shop.db

Зависимости

Package

Назначение

@modelcontextprotocol/server

Официальный MCP TypeScript SDK (v2). Предоставляет McpServer и stdio-транспорт, поэтому протокол не реализуется вручную.

zod

Требуется SDK для схем входа/выхода инструментов; именно он предоставляет машиночитаемые типы аргументов агенту.

typescript, @types/node

Только для разработки: сборка и проверка типов.

@modelcontextprotocol/client

Только для разработки: официальный MCP-клиент для сквозных тестов stdio и тестирования.

SQLite — это встроенный node:sqlite; тесты — встроенный раннер Node; HTTP для оценки это обычный fetch — без драйверов, ORM, query builder’ов, веб-фреймворков, логирования, тестовой среды, разборки SQL или LLM SDK.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (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
    Exposes SQLite database query tools and markdown document resources over JSON-RPC 2.0 stdio transport, enabling AI assistants to read and search documents and execute read-only SQL queries.
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets AI agents query local SQLite database files read-only using Node's built-in sqlite module, providing tools for listing tables, describing schemas, and running SQL queries.
    3
    15
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes any SQLite database as read-only MCP tools for AI assistants, enabling listing tables, describing schemas, and running SELECT queries with filtering, ordering, and pagination.

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/lampmaster/shop-sql-mcp'

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