SQL-MCP-101
SQL-MCP-101
Новичок в MCP? Начните с интерактивного учебника — пошагового обзора инструментов, ресурсов и промптов, а также того, как решить, какой из них использовать для функции.
Небольшой, обильно комментированный MCP-сервер для MySQL, который демонстрирует все три примитива Model Context Protocol (tools, resources и prompts) примерно в 1100 строках Python, плюс браузерный интерфейс для его изучения.
Этот репозиторий существует для того, чтобы его читали, а не только запускали. Если вы встречали упоминания MCP и хотите понять, что на самом деле нужно для создания сервера, — это полный работающий пример, достаточно маленький, чтобы прочитать его за один присест: по одному примитиву на файл, комментарии, которые объясняют почему, а не что, и демонстрационная база с намеренными недостатками, чтобы примеры находили реальные проблемы, а не игрушечные.
mcp_server/
├── database.py read-only introspection; the only file not about MCP
├── execution.py running queries and writes, plus every safety control
├── tools.py 6 TOOLS inspect structure, cannot read or change a row
├── data_tools.py 6 TOOLS read rows, and insert / update / delete / alter
├── resources.py 4 RESOURCES content the APPLICATION attaches (+2 templates)
├── prompts.py 6 PROMPTS workflows the USER invokes
└── server.py wires them together, about 10 meaningful linesСервер поддерживает чтение и запись: он отвечает на вопросы о данных, выполняя настоящие запросы, и может изменять данные и схему. Он ограничен одной одноразовой демонстрационной базой данных, а механизмы, которые делают это безопасным, находятся в execution.py и описаны ниже. Сам этот дизайн — часть урока.
Главная мысль, которую стоит вынести
Большинство учебников по MCP рассказывают только об инструментах, из-за чего складывается впечатление, что MCP — это и есть инструменты. На самом деле примитивов три, и различаются они тем, кто управляет:
Примитив | Кто решает | Когда происходит | Аналогия |
Инструмент | модель | в ходе диалога, автономно | функция, которую модель может вызвать |
Ресурс | приложение | заранее, выбирает человек | файл, который вы прикрепляете |
Промпт | пользователь | явно, из меню | сохранённый вопрос эксперта |
Одни и те же данные могут выступать сразу в нескольких ролях. В этом репозитории get_table_ddl — это инструмент, и schema://table/{name}/ddl — это ресурс. Одни и те же байты, доступные двумя разными способами, потому что «модель получает их, когда сама решает, что они нужны» и «человек прикрепляет их до начала работы» — это действительно разные потребности.
Related MCP server: mysql-mcp-server
Быстрый старт
git clone https://github.com/Khushboo-Mishra/SQL-MCP-101.git
cd SQL-MCP-101
bash scripts/setup.shsetup.sh проверяет предусловия, создаёт виртуальное окружение, устанавливает две зависимости, создаёт демонстрационную базу данных и проверяет сервер по полному циклу. При первом же отсутствующем компоненте он останавливается с конкретным сообщением.
Затем посмотрите все три примитива за один раз:
bash scripts/run_explorer.shТребования
Python 3.10+
MySQL 8.x, работающая локально (
brew services start mysql)Node.js: необязательно, только для MCP Inspector
Ollama: необязательно, только для панели Chat в интерфейсе
По умолчанию используется root на 127.0.0.1:3306 без пароля — это стандарт Homebrew, так что большинству менять ничего не нужно. В противном случае задайте переменные окружения MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT.
Что в итоге создано
12 инструментов, 4 ресурса + 2 URI-шаблона и 6 промптов поверх демонстрационной базы из шести таблиц.
Инструменты: их вызывает модель
Разнесены по двум файлам по радиусу поражения, а не по подсистемам. Это осознанное архитектурное решение, которое стоит повторить: оно сохраняет рискованную поверхность небольшой и очевидной для любого, кто проверяет сервер или пишет для его базы GRANT.
tools.py: изучение структуры. Не может прочитать ни одной строки и ничего изменить.
Инструмент | Назначение |
| все таблицы и представления с оценкой числа строк |
| колонки, типы, ключи, индексы, внешние ключи |
| точный |
| все объявленные внешние ключи |
| колонки, чьё название намекает на PII или секреты |
| найти колонку, если забыли, в какой она таблице |
data_tools.py: чтение строк и изменение данных. Это половина, у которой есть последствия.
Инструмент | Назначение |
| выполняет SELECT и возвращает строки; именно это отвечает на вопросы о данных |
| INSERT / UPDATE / DELETE / CREATE / ALTER / DROP / TRUNCATE |
| структурированная вставка; значения передаются как связанные параметры |
| структурированное обновление; |
| структурированное удаление; |
| каждый оператор, который выполнил сервер |
Зачем и общий execute_statement, и структурированные обёртки? Структурированные инструменты безопаснее: аргументы типизированы, значения связаны, поэтому модель никогда не пишет текст SQL и не может создать что-то некорректное. Но они делают только то, что вы предусмотрели. Общий вход в SQL покрывает длинный хвост: оконные функции, непредвиденный ALTER. Именно поэтому большинство реальных серверов в итоге поставляют оба варианта.
Ресурсы: их прикрепляет приложение
URI | Тип | Содержимое |
| JSON | опись таблиц |
| SQL | DDL всей схемы |
| JSON | все внешние ключи |
| Markdown | человекочитаемая сводка |
| JSON | одна таблица (шаблонный ресурс) |
| SQL | DDL одной таблицы (шаблонный ресурс) |
Статический ресурс имеет фиксированный URI и присутствует в resources/list, поэтому клиент может показать его в селекторе. Шаблонный ресурс, наоборот, содержит {placeholders} и присутствует в resources/templates/list. Готового списка для показа нет, так что клиент заполняет пропуск.
Промпты: их вызывает пользователь
Промпт | Аргументы | Что делает |
| нет | пятишаговая проверка здоровья: ключи, связи, PII, именование |
|
| объясняет одну таблицу простым языком |
|
| пишет запрос, выполняет его и отвечает простым языком |
|
| предпросмотр → подтверждение → применение → проверка для изменений |
| нет | генерирует справочную документацию |
|
| направленный первый взгляд, адаптированный под роль |
Выбор: инструмент, ресурс или промпт?
Вопрос, на котором люди застревают. Проходите по нему в таком порядке.
1. Совершает ли оно действие или получает то, что выбирает модель? → Инструмент. Всё, что модель должна иметь возможность решить сделать самостоятельно.
2. Это документ, который человек разумно прикрепил бы перед началом работы? → Ресурс. Справочный материал, контекст всей схемы, всё стабильное.
3. Это повторяемая задача, где способ вопроса и есть экспертиза? → Промпт. Поставляйте хороший вопрос, а не рассчитывайте, что его переоткроют.
Две эвристики, которые снимают большинство оставшихся сомнений:
Кто инициирует? Модель → инструмент. Приложение → ресурс. Пользователь → промпт.
Хотели бы вы видеть это в меню? Если да — это промпт. Меню созданы для людей, и только промпты показываются людям как команды.
Разобранные примеры из этого репозитория
Возможность | Выбор | Почему |
Получить структуру одной таблицы | инструмент | модель нуждается в ней в процессе рассуждения, непредсказуемо |
DDL всей схемы | оба | инструмент для модели; ресурс для человека, чтобы прикрепить заранее |
Аудит схемы | промпт | повторяемая задача, где ценность — в знании что спросить |
Поиск колонки | инструмент | принимает аргумент, который модель выбирает в момент вызова |
Обзор в Markdown | ресурс | пассивный справочник, не требует решения |
Где люди ошибаются
Всё делать инструментами. Работает, но модель тратит вызовы на получение контекста, который человек мог прикрепить один раз, и у пользователей не появляется обнаруживаемых точек входа.
Ресурсы для того, что требует аргументов, которые выбирает модель. Если параметр выбирает модель — это инструмент.
Промпты, которые выполняют работу. Промпт возвращает текст. Если вы ловите себя на том, что внутри промпта обращаетесь к базе, вам нужен инструмент.
Демонстрационная база данных
mcp_demo — шесть таблиц, намеренно неидеальных, чтобы примеры находили реальные проблемы:
Таблица | Намеренный недостаток |
|
|
|
|
| (чистая, эталонный пример) |
|
|
| вообще нет первичного ключа |
|
|
Запустите audit_schema для неё — и каждый из этих недостатков должен всплыть. В этом суть демо: инструменты находят настоящие проблемы, а не игрушечные.
Запуск
Обозреватель: все примитивы за один раз
bash scripts/run_explorer.shВыводит рукопожатие initialize, затем перечисляет и задействует инструменты, ресурсы (статические и шаблонные) и промпты. Запустите его первым: он подтверждает, что установка работает, и показывает всю поверхность протокола на одном экране.
Веб-интерфейс: все три примитива в браузере
bash scripts/run_ui.sh # http://127.0.0.1:8000
PORT=9000 bash scripts/run_ui.shЧетыре панели, по одной на каждое, что стоит показать:
Панель | Что она демонстрирует |
Chat | вопросы на простом английском; каждый выбранный моделью инструмент указан непосредственно над ответом |
Tools | все 12, сгруппированы по радиусу поражения, каждый можно вызвать из формы |
Resources | статические и шаблонные, читаются прямо на месте |
Prompts | разверните, чтобы увидеть текст, или отправьте сразу в чат |
Живая полоса Activity внизу показывает реальный JSON-RPC под капотом: tools/call, resources/read, prompts/get, так что протокол виден всё время.
Страница — сама MCP-клиент: у неё нет собственного доступа к MySQL. Всё, что на экране, пришло через тот же протокол, который использует Claude Desktop.
Для Chat нужна локальная LLM через Ollama — бесплатно, без API-ключа, и ничего не покидает машину:
brew install ollama && ollama serve
ollama pull qwen2.5:7bЗадайте вместо этого ANTHROPIC_API_KEY — и интерфейс автоматически переключится на Claude API. Панели Tools, Resources и Prompts работают вообще без LLM.
MCP Inspector: собственный клиент Anthropic
bash scripts/run_inspector.shОткройте напечатанный URL http://localhost:6274?..., требуется токен. В нём есть отдельные вкладки Tools, Resources и Prompts, что является самым убедительным способом показать все три: ни одна из них не является нашим кодом, поэтому если Inspector управляет сервером, сервер действительно соответствует спецификации.
Предлагаемый маршрут: Tools → describe_table с ORDERS; Resources → schema://overview; Prompts → audit_schema.
Claude Desktop / Claude Code
bash scripts/add_to_claude_desktop.sh # Claude Desktop, run from Terminal.app
bash scripts/install_claude.sh # Claude Code, safe to run anywhereadd_to_claude_desktop.sh создаёт резервную копию вашей конфигурации, сохраняет уже зарегистрированные серверы, проверяет JSON, дымовым тестом проверяет точную команду запуска и перезапускает приложение. По завершении он выводит предлагаемый демонстрационный сценарий.
Затем спросите: «Проверьте эту базу данных», или используйте промпт audit_schema из меню — именно там промпты наконец становятся видимыми.
--desktopнеобходимо запускать из Terminal.app, а не изнутри Claude Desktop. Claude Desktop хранит свою конфигурацию в памяти и перезаписывает файл из этой копии, поэтому изменение, сделанное во время его работы, молча отбрасывается. Скрипт завершает приложение, вносит изменения и перезапускает его, что убьёт сессию, из которой вы его запустили.
Чтение кода
Примерно час от начала до конца. Этот порядок выстраивается без прямых ссылок вперёд:
1. mcp_server/server.py: начните здесь. Десять значимых строк, и вся архитектура умещается на одном экране: создайте сервер, зарегистрируйте три примитива, запустите. Всё остальное — детали.
2. mcp_server/database.py: обычный код MySQL, в котором вообще нет MCP. Его стоит прочитать рано, потому что он показывает, насколько тонким на самом деле является слой MCP: если у вас уже есть слой доступа к данным, вы уже почти у цели.
Внимательно посмотрите на safe_identifier. MySQL не позволяет передавать имя таблицы как параметр (SHOW CREATE TABLE %s — недопустимый SQL), поэтому идентификаторы приходится интерполировать в строку. Это реальный риск инъекций, и именно эта небольшая функция делает его безопасным.
3. mcp_server/tools.py: декоратор @mcp.tool() и идея, которая делает больше всего работы во всём проекте: docstring — это и есть промпт. Это единственное, что модель читает, решая, вызывать ли инструмент, поэтому он написан для модели, а не для человека, читающего исходный код.
4. mcp_server/resources.py: статические URI против шаблонных, и почему get_table_ddl существует и как инструмент, и как ресурс. Это дублирование намеренно и является самой наглядной иллюстрацией идеи «кто чем управляет».
5. mcp_server/prompts.py: промпты возвращают текст, а не данные. Текст — это инструкция, которая обычно говорит модели, какие инструменты использовать. Короткий файл, и его большинство людей никогда не видели.
6. mcp_server/execution.py: прочитайте это, когда захотите узнать, как можно сделать безопасным доступ на запись. Пять механизмов контроля, каждый с комментарием, объясняющим, что он предотвращает.
7. examples/explore_server.py: другая сторона протокола. Минимальный клиент, который перечисляет и вызывает всё, чтобы вы могли увидеть, что на самом деле передаётся по сети.
Дальнейшее развитие
Этот сервер ограничен одной базой данных, чтобы примеры были короткими. Чтобы развить его дальше:
Несколько схем: принимайте
schemaкак аргумент инструмента, а не читайтеMYSQL_DEMO_SCHEMA. Добавьте белый список, чтобы агент не мог добраться до продакшена.Выполнение запросов: инструмент
run_query. Это возможно, но полностью меняет историю безопасности: тогда серверу нужны учётные данные, которые читают ваши таблицы, а результаты попадают в контекст модели. Ограничьте толькоSELECT, добавьтеLIMITи используйте пользователя базы данных с доступом только на чтение.Удалённый транспорт:
mcp.run(transport="streamable-http"). Те же инструменты, тот же код, другой канал. Добавьте аутентификацию перед тем, как открыть доступ.Кэширование:
describe_tableобращается к базе данных при каждом вызове. Небольшой кэш с TTL стоит того, как только модель начинает вызывать его в цикле.
Замечания по безопасности
Этот сервер может изменять ваши данные. Это намеренно: «может ли агент писать в мою базу данных?» — вопрос, который задаёт каждая команда, и рабочий пример того, как делать это безопасно, полезнее, чем тот, который избегает этой темы. Но это означает, что механизмы контроля имеют значение.
Пять механизмов контроля, все в execution.py
Контроль | Что он предотвращает |
Блокировка схемы | каждый оператор выполняется на соединении, привязанном к демонстрационной базе данных; ссылка на любую другую базу данных отклоняется |
Один оператор за вызов | второй оператор не может «проехать зайцем» вместе с легитимным |
Раздельные двери чтения/записи |
|
Ограничение строк | широкий |
Журнал аудита | каждый оператор записывается и доступен для чтения через |
Чёрный список также отклоняет операторы, которые могли бы обойти блокировку схемы, обратиться к файловой системе или изменить состояние всего сервера, изменения привилегий, управление пользователями, импорт/экспорт файлов и операции уровня базы данных.
Одна тонкость, потому что это легко повторяемая ошибка: блокировка схемы не может работать только по шаблону. В SQL a.b — это обычно alias.column (SELECT c.NAME FROM CUSTOMERS c), а не schema.table, поэтому отклонение любого имени с точкой ломает обычные JOIN — именно такой баг был в первой версии. Теперь она сравнивает каждый квалификатор с фактическим списком баз данных на сервере: реальное имя базы данных отклоняется, а алиас таблицы проходит без изменений.
Направьте его на ограниченного пользователя
Описанные выше механизмы контроля — это эшелонированная защита, а не сама защита. В любом случае, кроме демо, подключайтесь как пользователь MySQL, чьи права покрывают только ту схему, которую вы собираетесь открыть. Если учётные данные не могут добраться до продакшена, то и инъекция в промпт, и ошибка модели тоже не смогут.
Ещё две вещи, которые стоит сказать прямо:
Имена таблиц не могут быть связанными параметрами.
SHOW CREATE TABLE %s— недопустимый SQL, поэтому идентификаторы должны интерполироваться, что является настоящей точкой инъекций. Именноdatabase.safe_identifierделает это безопасным, и это самая важная функция в проекте.Подключающийся пользователь MySQL — это настоящая граница. Выдайте ему
GRANTтолько на чтение, ограниченный схемами, которые вы собираетесь открыть. Доступ только на чтение в коде — это эшелонированная защита, а не сама защита.
Лицензия
MIT, см. LICENSE.
This server cannot be installed
Maintenance
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
- AlicenseNot gradedqualityDmaintenanceEnables interaction with MySQL databases through MCP, supporting query execution, table operations (insert, update, delete), and schema inspection for natural language database management.121MIT
- AlicenseNot gradedqualityDmaintenanceEnables MySQL database operations through MCP, including executing SQL queries, listing databases and tables, and describing table structures.4545MIT
- AlicenseNot gradedqualityDmaintenanceEnables natural language interaction with MySQL databases through MCP, supporting SQL execution, schema exploration, and database management via tools, resources, and prompts.5MIT
- AlicenseNot gradedqualityCmaintenanceEnables natural language interaction with MySQL databases through MCP tools for querying, executing DDL/DML, listing databases/tables, and describing table schemas, with parameterized queries and read-only mode.454MIT
Related MCP Connectors
GibsonAI MCP server: manage your databases with natural language
Connect to PlanetScale databases, branches, schema, query insights, and execute SQL
MCP server for managing Prisma Postgres.
Latest 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/Khushboo-Mishra/SQL-MCP-101'
If you have feedback or need assistance with the MCP directory API, please join our Discord server