Skip to main content
Glama

🛠️ DevTools MCP Server

Легковесный сервер Model Context Protocol (MCP), который предоставляет любому MCP-совместимому LLM-клиенту (Claude Desktop, Claude Code, Cursor и т.д.) набор инструментов разработчика: веб-скрапинг, просмотр журналов, живой веб-поиск и выполнение SQL-запросов только для чтения к SQLite или Postgres/Supabase — всё через один сервер.

MCP Python Tests License

🔗 Живая песочница: Glama MCP Link — попробуйте инструменты прямо в браузере после публикации (см. Развёртывание).


📖 Обзор

DevTools MCP предоставляет четыре инструмента через MCP, чтобы LLM-ассистент мог:

  • Извлекать чистый читаемый текст с любой веб-страницы

  • Просматривать последние строки локальных файлов журналов для отладки ошибок

  • Искать в живом вебе актуальную документацию перед написанием кода

  • Выполнять запросы SELECT только для чтения к локальному файлу SQLite или живой базе данных Postgres/Supabase

Каждый инструмент — это простая тестируемая Python-функция; здесь ничто не зависит от платных API, кроме вашего собственного необязательного проекта Supabase.


Related MCP server: MCP Server Toolkit

✨ Возможности

Инструмент

Описание

🌐 fetch_markdown(url)

Загружает веб-страницу, удаляет script/style/nav/footer и возвращает чистый текст (не более 8 000 символов).

📄 read_log(file_path, lines)

Читает последние N строк локального файла — показывает недавние стектрейсы или вывод ошибок.

🔍 search_web(query, max_results)

Ищет в живом вебе через DuckDuckGo (ddgs, без API-ключа) актуальную документацию или решения.

🗄️ query_database(db_path_or_url, sql_query, limit)

Выполняет только для чтения SELECT к локальному файлу SQLite или строке подключения Postgres/Supabase, с ограничением limit строк.


🏗️ Архитектура

┌──────────────────────┐
│    MCP Client         │   (Claude Desktop / Claude Code / Cursor / etc.)
└──────────┬────────────┘
           │ MCP protocol (stdio)
┌──────────▼────────────┐
│  DevTools MCP Server   │   FastMCP("DevTools")   — server.py
│                        │
│  ┌──────────────────┐  │
│  │ fetch_markdown    │  │──▶ requests + BeautifulSoup ──▶ any URL
│  ├──────────────────┤  │
│  │ read_log          │  │──▶ local filesystem
│  ├──────────────────┤  │
│  │ search_web        │  │──▶ DDGS (DuckDuckGo, key-free)
│  ├──────────────────┤  │
│  │ query_database     │  │──▶ _is_safe_select()  (SQL safety gate)
│  │                    │  │      │
│  │                    │  │      ├──▶ _query_sqlite()   ──▶ local .db file
│  │                    │  │      └──▶ _query_postgres() ──▶ Postgres / Supabase
│  └──────────────────┘  │
└────────────────────────┘

Как query_database решает, куда отправить запрос

query_database(db_path_or_url, sql_query, limit)
        │
        ▼
  _is_safe_select(sql_query)?
        │
   ┌────┴────┐
   NO         YES
   │           │
 reject   does db_path_or_url start with
 query    "postgres://" or "postgresql://" ?
              │
        ┌─────┴─────┐
        YES           NO
        │             │
 _query_postgres()  _query_sqlite()

_is_safe_select — это жёсткий шлюз, который разрешает только одиночные простые операторы SELECT — никаких INSERT/UPDATE/DELETE/DROP/ALTER/и т.д., а также никаких составных запросов, склеенных через ;. Это важно, потому что SQL-текст генерируется LLM, а не вводится вручную — шлюз нужен, чтобы галлюцинированный или подделанный запрос не мог изменить или уничтожить ваши данные.

Стек:

  • fastmcp — MCP-серверный фреймворк; превращает Python-функции в MCP-инструменты через @mcp.tool

  • requests + beautifulsoup4 — веб-скрапинг

  • ddgs — веб-поиск без ключа (ранее duckduckgo-search)

  • sqlite3 — встроен в Python, используется для локальных запросов к БД

  • psycopg2 — клиент Postgres/Supabase, импортируется лениво, только когда используется Postgres URL

  • python-dotenv — загружает локальные переменные .env

  • pytest + pytest-mock — набор тестов


📂 Структура проекта

.
├── venv/                # Local virtual environment (not committed)
├── .env                 # Local secrets — real keys/paths, never committed
├── .gitignore
├── README.md
├── requirements.txt      # Runtime + dev/test dependencies
├── server.py             # Main MCP server — all 4 tools live here
├── test_server.py        # Pytest suite covering all 4 tools
├── Dockerfile             # Optional — only needed for Glama's hosted deployment
├── glama.json             # Optional — repo attribution for Glama's listing
└── smithery.yaml         # Optional — only relevant if also listing on Smithery

🚀 Начало работы

1. Клонируйте репозиторий

git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO

2. Создайте виртуальное окружение и установите зависимости

python -m venv venv
source venv/bin/activate   # On Windows: venv\Scripts\activate

pip install -r requirements.txt

3. Настройте переменные окружения (необязательно)

server.py вызывает load_dotenv() при запуске, поэтому все переменные из локального файла .env подхватываются автоматически. Ни один из текущих инструментов не требует переменных окружения — query_database принимает информацию о подключении как прямой параметр, — но вы всё равно можете создать .env для локального удобства:

# Only needed if you want a default connection string handy locally.
# Real credentials should live here and nowhere else.
SUPABASE_DB_URL=postgresql://postgres:your-password@db.xxxxxxxx.supabase.co:5432/postgres

⚠️ Никогда не коммитьте файл .env. Он уже исключён через .gitignore.

Примечание: это не то же самое, что SUPABASE_URL / SUPABASE_KEY проекта Supabase (используется REST/JS-клиентом). query_database общается с Postgres напрямую через psycopg2, поэтому ему нужна строка подключения Postgres из панели Supabase в разделе Настройки → База данных → Строка подключения, а не пара API URL/ключ.

4. Запустите сервер локально

python server.py

Это запускает MCP-сервер через stdio, готовый к подключению к любому MCP-клиенту.


🔌 Подключение к Claude Desktop / Claude Code

Добавьте сервер в конфигурацию MCP-клиента (например, claude_desktop_config.json):

{
  "mcpServers": {
    "devtools": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

Перезапустите клиент — четыре инструмента (fetch_markdown, read_log, search_web, query_database) появятся как функции, которые ассистент может вызывать.


🧰 Справочник инструментов

fetch_markdown(url: str) -> str

Загружает веб-страницу, удаляет теги <script>, <style>, <nav> и <footer> и возвращает очищенный обычный текст (не более 8 000 символов).

fetch_markdown("https://docs.python.org/3/library/asyncio.html")

read_log(file_path: str, lines: int = 50) -> str

Читает последние lines строк локального текстового/журнального файла.

read_log("/var/log/app/error.log", lines=100)

search_web(query: str, max_results: int = 3) -> str

Выполняет поиск в DuckDuckGo по заданному запросу и возвращает заголовок, ссылку и фрагмент для каждого результата.

search_web("fastapi background tasks example")

query_database(db_path_or_url: str, sql_query: str, limit: int = 50) -> str

Выполняет SELECT только для чтения для:

  • локального файла SQLite (укажите путь к файлу), или

  • базы данных Postgres/Supabase (передайте строку подключения, начинающуюся с postgres:// или postgresql://)

Результаты возвращаются в виде списка словарей {column: value}, ограниченного limit строками.

query_database("app.db", "SELECT * FROM users WHERE status = 'active'", limit=5)
query_database("postgresql://user:pass@host:5432/db", "SELECT id, email FROM users", limit=10)

Гарантии безопасности:

  • Разрешены только запросы, начинающиеся с SELECT

  • Запросы, содержащие INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, GRANT, REVOKE, CREATE или ATTACH в любом месте, отклоняются

  • Составные запросы (SELECT ...; DROP TABLE ...) отклоняются

  • Известное ограничение: проверка основана на поиске подстроки, а не на полноценном SQL-парсере — безобидный запрос вроде SELECT * FROM updates_log также будет отклонён, поскольку содержит подстроку update. Это намеренный компромисс в пользу ложных срабатываний, а не пропуска опасных запросов.


🧪 Тестирование

В проект входит набор из 27 тестов pytest, покрывающий все четыре инструмента. Набор полностью запускается офлайн благодаря замоканным сетевым вызовам и одноразовым фикстурам tmp_path — ничего не касается реальных файлов, баз данных или веб-сайтов.

pip install -r requirements.txt
pytest test_server.py -v

Что покрыто:

  • _is_safe_select — более 10 сценариев: корректные SELECT, каждое запрещённое ключевое слово, составные запросы и известное поведение с ложными срабатываниями

  • query_database (SQLite) — простой SELECT, limit, фильтрация по WHERE, блокировка небезопасных запросов, отсутствующий файл, отсутствующая таблица, пустой результат и маршрутизация Postgres URL (замокано)

  • read_log — чтение хвоста, отсутствующий файл, количество строк по умолчанию

  • fetch_markdown — удаление HTML и обработка ошибок (сеть замокана)

  • search_web — форматирование результатов, пустые результаты, обработка ошибок (сеть замокана)

Сам _query_postgres не проверяется в этом наборе против живой базы данных — только логика маршрутизации, которая решает, нужно ли его вызывать. Живое тестирование требует реальной строки подключения Postgres/Supabase, которую никогда нельзя жёстко прописывать в тестовых файлах или коммитить в репозиторий.


🌐 Развёртывание

Вариант A — Glama (бесплатная публикация в каталоге + браузерный инспектор)

Отправьте GitHub URL этого репозитория на glama.ai/mcp — Glama индексирует ваши инструменты прямо из исходного кода, без сборки или манифеста. Посетители получают браузерный инспектор, чтобы попробовать fetch_markdown, read_log, search_web и query_database, без установки чего-либо локально.

Необязательно: добавьте glama.json (уже включён), чтобы подтвердить/привязать публикацию к вашему GitHub-аккаунту.

Вариант B — размещение на Glama (Glama запускает сервер за вас, 24/7)

Подключите Glama GitHub App к этому репозиторию, и он соберёт включённый Dockerfile в работающий экземпляр за шлюзом Glama (управляемый TLS, аутентификация, логирование). Перед выбором этого пути ознакомьтесь с актуальными тарифами на glama.ai/mcp/hosting.

Вариант C — Smithery

⚠️ По состоянию на начало 2026 года Smithery больше не принимает новые бесплатные размещённые развёртывания через GitHub — теперь для этого требуется платный тариф. Бесплатный путь на Smithery — регистрация этого сервера как внешнего сервера (то есть вы размещаете его самостоятельно — например, через вариант размещения Glama выше — и просто указываете этот URL в публикации Smithery). smithery.yaml по-прежнему включён в этот репозиторий на случай, если вы выберете этот путь; актуальные подробности смотрите на smithery.ai, так как их модель размещения активно меняется.


🔐 Переменные окружения

Переменная

Обязательность

Используется

SUPABASE_DB_URL (или любой Postgres URL)

❌ Необязательно

Не читается автоматически — query_database принимает строку подключения как прямой аргумент. Полезна только как личная ссылка/удобство в .env.

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


🗺️ Дорожная карта

  • Добавить настоящий интеграционный тест с одноразовым экземпляром Postgres/Supabase (только в CI, учётные данные никогда не коммитятся)

  • Заменить проверку ключевых слов SQL по подстрокам на полноценный SQL-парсер (например, sqlparse), чтобы устранить ложные срабатывания

  • Добавить кэширование для search_web и fetch_markdown

  • Добавить слой аутентификации для размещённых развёртываний Smithery


🤝 Вклад в проект

Приветствуются вклады, вопросы и запросы новых функций — не стесняйтесь открывать PR или issue.


📄 Лицензия

Этот проект распространяется под лицензией MIT.

Related MCP Connectors

Related MCP Servers