chrometools-mcp 3.1.7 → 3.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +118 -0
- package/README.md +183 -117
- package/README.ru.md +352 -0
- package/chrome-extension.zip +0 -0
- package/docs/extension-developer-mode.png +0 -0
- package/docs/extension-installed.png +0 -0
- package/index.js +93 -90
- package/package.json +1 -1
- package/pom/apom-tree-converter.js +330 -46
- package/publish_output.txt +0 -0
- package/server/tool-definitions.js +24 -41
- package/server/tool-groups.js +0 -1
- package/server/tool-schemas.js +6 -11
- package/test-interactivity.html +178 -0
package/README.ru.md
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# chrometools-mcp
|
|
2
|
+
|
|
3
|
+
> 🌐 [English version](./README.md)
|
|
4
|
+
|
|
5
|
+
**Автоматизация Chrome через естественный язык для ИИ.** Забудьте о борьбе с CSS селекторами, XPath выражениями и хрупкими тестовыми скриптами. Просто скажите своему ИИ-помощнику, что вы хотите сделать на веб-странице, и ChromeTools MCP сделает это.
|
|
6
|
+
|
|
7
|
+
## Зачем нужен ChromeTools MCP?
|
|
8
|
+
|
|
9
|
+
**Для ИИ-агентов и разработчиков:**
|
|
10
|
+
- 🎯 **54 специализированных инструмента** для автоматизации браузера — от простых кликов до сравнения с Figma
|
|
11
|
+
- 🧠 **APOM (Agent Page Object Model)** — представление страницы для ИИ (~8-10k токенов против 15-25k для скриншотов)
|
|
12
|
+
- 🔄 **Постоянные сессии браузера** — страницы остаются открытыми между командами для итеративной работы
|
|
13
|
+
- ⚡ **Поддержка фреймворков** — автоматически обрабатывает события и состояние React, Vue, Angular
|
|
14
|
+
- 📸 **Визуальное тестирование** — попиксельное сравнение дизайна с макетами Figma
|
|
15
|
+
- 🎬 **Запись сценариев** — записывайте действия в браузере, воспроизводите их или экспортируйте в Playwright/Selenium
|
|
16
|
+
- 🌍 **Кросс-платформенность** — работает на Windows, WSL, Linux и macOS
|
|
17
|
+
|
|
18
|
+
**Идеально для:**
|
|
19
|
+
- 🤖 Создания ИИ-агентов, взаимодействующих с веб-приложениями
|
|
20
|
+
- 🧪 Автоматизированного тестирования без написания кода — пусть ИИ генерирует тесты из сценариев
|
|
21
|
+
- 🔍 Парсинга веб-страниц и извлечения данных с помощью естественного языка
|
|
22
|
+
- 🎨 Валидации дизайна — сравнение реализованного UI с дизайном в Figma
|
|
23
|
+
- 🚀 Быстрого прототипирования — тестирование пользовательских сценариев через их описание
|
|
24
|
+
- 📊 Мониторинга и проверки работоспособности веб-приложений
|
|
25
|
+
|
|
26
|
+
Перестаньте писать хрупкие скрипты автоматизации. Начните описывать желаемое на обычном языке.
|
|
27
|
+
|
|
28
|
+
## Установка
|
|
29
|
+
|
|
30
|
+
### Claude Code (CLI)
|
|
31
|
+
|
|
32
|
+
Самый простой способ установки для пользователей Claude Code:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
claude mcp add chrometools -- npx chrometools-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Эта команда автоматически настроит MCP сервер в настройках Claude Code.
|
|
39
|
+
|
|
40
|
+
### Claude Desktop
|
|
41
|
+
|
|
42
|
+
Добавьте в конфигурационный файл Claude Desktop:
|
|
43
|
+
|
|
44
|
+
**macOS/Linux:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
45
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"chrometools": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["chrometools-mcp"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Cursor
|
|
59
|
+
|
|
60
|
+
**Шаг 1:** Откройте настройки MCP в Cursor
|
|
61
|
+
- Нажмите на **Settings** (⚙️ иконка или `Cmd + ,` / `Ctrl + ,`)
|
|
62
|
+
- Перейдите в **Cursor Settings** → **MCP**
|
|
63
|
+
|
|
64
|
+
**Шаг 2:** Отредактируйте конфигурацию MCP
|
|
65
|
+
- Добавьте `chrometools` в объект `mcpServers`:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"chrometools": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["chrometools-mcp"]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Шаг 3:** Сохраните и перезапустите
|
|
79
|
+
- Сохраните конфигурационный файл
|
|
80
|
+
- Перезапустите Cursor для применения изменений
|
|
81
|
+
|
|
82
|
+
**Шаг 4:** Протестируйте установку
|
|
83
|
+
- Откройте Cursor Chat
|
|
84
|
+
- Выберите режим **Agent**
|
|
85
|
+
- Попробуйте команду: "Open browser and navigate to google.com"
|
|
86
|
+
|
|
87
|
+
### Ручная установка
|
|
88
|
+
|
|
89
|
+
Вы также можете запустить напрямую без конфигурации:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx chrometools-mcp
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Настройка расширения Chrome
|
|
96
|
+
|
|
97
|
+
Расширение Chrome **необходимо** для записи сценариев и других расширенных функций. Следуйте этим шагам для установки:
|
|
98
|
+
|
|
99
|
+
**Важно:** ChromeTools открывает Chrome с отдельным профилем пользователя, поэтому вы должны установить расширение **после** первого запуска Chrome через ChromeTools.
|
|
100
|
+
|
|
101
|
+
**Шаг 1:** Сначала запустите MCP сервер ChromeTools
|
|
102
|
+
- Убедитесь, что ChromeTools запущен через ваш MCP клиент (Claude Desktop, Cursor и т.д.)
|
|
103
|
+
- Или запустите вручную: `npx chrometools-mcp`
|
|
104
|
+
- Это запустит Chrome с изолированным профилем ChromeTools
|
|
105
|
+
|
|
106
|
+
**Шаг 2:** Включите режим разработчика в Chrome
|
|
107
|
+
- Откройте страницу расширений Chrome: `chrome://extensions`
|
|
108
|
+
- Переключите **Режим разработчика** (переключатель в правом верхнем углу)
|
|
109
|
+
|
|
110
|
+

|
|
111
|
+
|
|
112
|
+
**Шаг 3:** Скачайте и распакуйте расширение
|
|
113
|
+
|
|
114
|
+
**Вариант A - Скачать с GitHub (Рекомендуется):**
|
|
115
|
+
1. Скачайте архив расширения: [chrome-extension.zip](https://github.com/docentovich/chrometools-mcp/raw/main/chrome-extension.zip)
|
|
116
|
+
2. Распакуйте ZIP файл в папку на вашем компьютере
|
|
117
|
+
3. Запомните путь распаковки (он понадобится на следующем шаге)
|
|
118
|
+
|
|
119
|
+
**Вариант B - Использовать из node_modules (если знаете путь):**
|
|
120
|
+
- **После npx установки:** `~/.npm/_npx/.../node_modules/chrometools-mcp/extension`
|
|
121
|
+
- **После глобальной установки:** `<npm-global-path>/node_modules/chrometools-mcp/extension`
|
|
122
|
+
- **Из исходников:** `<repo-path>/extension`
|
|
123
|
+
|
|
124
|
+
**Шаг 4:** Загрузите расширение
|
|
125
|
+
- Нажмите кнопку **"Загрузить распакованное"** (Load unpacked)
|
|
126
|
+
- Перейдите к распакованной папке расширения (из Шага 3)
|
|
127
|
+
- Выберите папку и нажмите **"Выбрать папку"**
|
|
128
|
+
|
|
129
|
+
**Шаг 5:** Проверьте установку
|
|
130
|
+
- Вы должны увидеть расширение "ChromeTools MCP" в списке расширений с:
|
|
131
|
+
- **Название:** ChromeTools MCP
|
|
132
|
+
- **Версия:** (текущая версия)
|
|
133
|
+
- **Описание:** MCP server integration for Chrome automation
|
|
134
|
+
- **Статус:** Переключатель должен быть ВКЛЮЧЕН (синий)
|
|
135
|
+
- Найдите иконку ChromeTools (CT) в панели инструментов Chrome
|
|
136
|
+
- Расширение готово к использованию для записи сценариев
|
|
137
|
+
|
|
138
|
+

|
|
139
|
+
|
|
140
|
+
> **Примечание:** После установки карточка расширения появится на странице `chrome://extensions` вместе с другими установленными расширениями. Расширение должно отображаться как "Включено" с синим переключателем.
|
|
141
|
+
|
|
142
|
+
**Шаг 6:** Закрепите расширение (опционально, но рекомендуется)
|
|
143
|
+
- Нажмите на иконку пазла в панели инструментов Chrome
|
|
144
|
+
- Найдите "ChromeTools MCP" в списке
|
|
145
|
+
- Нажмите на иконку булавки, чтобы оставить его видимым в панели инструментов
|
|
146
|
+
|
|
147
|
+
**Устранение неполадок:**
|
|
148
|
+
- **Рекомендуется:** Используйте Вариант A (скачивание с GitHub), чтобы избежать поиска в node_modules
|
|
149
|
+
- Если используете Вариант B и не можете найти папку расширения после установки `npx`, выполните `npm list -g chrometools-mcp` чтобы найти путь установки
|
|
150
|
+
- Расширение работает только с экземплярами Chrome, запущенными через ChromeTools
|
|
151
|
+
- Если Chrome закрывается и открывается снова, расширение должно остаться загруженным (режим разработчика сохраняется)
|
|
152
|
+
- Когда ChromeTools впервые открывает Chrome, он автоматически показывает подсказку с путем к расширению в node_modules
|
|
153
|
+
|
|
154
|
+
## Оглавление
|
|
155
|
+
|
|
156
|
+
- [Установка](#установка)
|
|
157
|
+
- [Настройка расширения Chrome](#настройка-расширения-chrome)
|
|
158
|
+
- [Возможности оптимизации AI](#возможности-оптимизации-ai)
|
|
159
|
+
- [Записывающее устройство сценариев](#записывающее-устройство-сценариев)
|
|
160
|
+
- [Доступные инструменты](#доступные-инструменты) - **46+ инструментов всего**
|
|
161
|
+
- [AI-инструменты](#ai-инструменты)
|
|
162
|
+
- [Основные инструменты](#основные-инструменты)
|
|
163
|
+
- [Инструменты взаимодействия](#инструменты-взаимодействия)
|
|
164
|
+
- [Инструменты инспекции](#инструменты-инспекции)
|
|
165
|
+
- [Продвинутые инструменты](#продвинутые-инструменты)
|
|
166
|
+
- [Инструменты управления вкладками](#инструменты-управления-вкладками)
|
|
167
|
+
- [Инструменты записи](#инструменты-записи)
|
|
168
|
+
- [Типичный пример рабочего процесса](#типичный-пример-рабочего-процесса)
|
|
169
|
+
- [Советы по использованию инструментов](#советы-по-использованию-инструментов)
|
|
170
|
+
- [Конфигурация](#конфигурация)
|
|
171
|
+
- [Поддержка нескольких экземпляров](#поддержка-нескольких-экземпляров)
|
|
172
|
+
|
|
173
|
+
## Возможности оптимизации AI
|
|
174
|
+
|
|
175
|
+
Значительно сокращайте циклы запросов AI-агента с помощью интеллектуального поиска элементов и анализа страниц.
|
|
176
|
+
|
|
177
|
+
### Основные возможности:
|
|
178
|
+
|
|
179
|
+
- **analyzePage**: Возвращает структурированную модель страницы с уникальными ID элементов
|
|
180
|
+
- **smartFindElement**: Находит элементы по естественному языковому описанию
|
|
181
|
+
- **getElementDetails**: Получает детальную информацию о конкретном элементе
|
|
182
|
+
- **findElementsByText**: Находит элементы по видимому тексту
|
|
183
|
+
|
|
184
|
+
## Записывающее устройство сценариев
|
|
185
|
+
|
|
186
|
+
Визуальный UI-рекордер для создания переиспользуемых тестовых сценариев с автоматическим обнаружением секретов.
|
|
187
|
+
|
|
188
|
+
### Основные возможности:
|
|
189
|
+
|
|
190
|
+
- **Визуальный UI** - Используйте расширение Chrome для записи
|
|
191
|
+
- **Умная оптимизация** - Автоматически находит родительские элементы с обработчиками событий
|
|
192
|
+
- **Обнаружение секретов** - Автоматически определяет пароли, токены, ключи API
|
|
193
|
+
- **Умные ожидания** - 2 секунды минимум + обнаружение анимации/сети/изменений DOM
|
|
194
|
+
- **Генерация кода** - Экспортирует в Playwright/Selenium
|
|
195
|
+
|
|
196
|
+
## Доступные инструменты
|
|
197
|
+
|
|
198
|
+
### AI-инструменты
|
|
199
|
+
|
|
200
|
+
- `analyzePage` - Анализирует структуру страницы и возвращает модель с уникальными ID
|
|
201
|
+
- `smartFindElement` - Находит элементы по описанию на естественном языке
|
|
202
|
+
- `getElementDetails` - Получает детальную информацию о элементе
|
|
203
|
+
- `findElementsByText` - Находит элементы по видимому тексту
|
|
204
|
+
- `getAllInteractiveElements` - Получает все интерактивные элементы с селекторами
|
|
205
|
+
|
|
206
|
+
### Основные инструменты
|
|
207
|
+
|
|
208
|
+
- `ping` - Тестовая команда для проверки связи
|
|
209
|
+
- `openBrowser` - Открывает браузер и переходит по URL
|
|
210
|
+
|
|
211
|
+
### Инструменты взаимодействия
|
|
212
|
+
|
|
213
|
+
- `click` - Кликает по элементу
|
|
214
|
+
- `type` - Вводит текст в поле ввода
|
|
215
|
+
- `scrollTo` - Прокручивает к элементу
|
|
216
|
+
- `selectOption` - Выбирает опцию из выпадающего списка
|
|
217
|
+
- `selectFromGroup` - Выбирает из радио-кнопок или чекбоксов
|
|
218
|
+
- `drag` - Перетаскивает элемент мышью
|
|
219
|
+
- `scrollHorizontal` - Горизонтальная прокрутка элемента
|
|
220
|
+
|
|
221
|
+
### Инструменты инспекции
|
|
222
|
+
|
|
223
|
+
- `getComputedCss` - Получает вычисленные CSS стили
|
|
224
|
+
- `getBoxModel` - Получает box model элемента (размеры, отступы)
|
|
225
|
+
- `screenshot` - Делает скриншот элемента или страницы
|
|
226
|
+
- `saveScreenshot` - Сохраняет скриншот в файл
|
|
227
|
+
|
|
228
|
+
### Продвинутые инструменты
|
|
229
|
+
|
|
230
|
+
- `executeScript` - Выполняет JavaScript код
|
|
231
|
+
- `getConsoleLogs` - Получает логи консоли браузера
|
|
232
|
+
- `listNetworkRequests` - Список сетевых запросов
|
|
233
|
+
- `getNetworkRequest` - Детали конкретного запроса
|
|
234
|
+
- `filterNetworkRequests` - Фильтрует запросы по URL
|
|
235
|
+
- `hover` - Наводит курсор на элемент
|
|
236
|
+
- `setStyles` - Применяет inline CSS стили
|
|
237
|
+
- `setViewport` - Изменяет размер окна браузера
|
|
238
|
+
- `getViewport` - Получает размер окна браузера
|
|
239
|
+
- `navigateTo` - Переходит по новому URL
|
|
240
|
+
|
|
241
|
+
### Инструменты управления вкладками
|
|
242
|
+
|
|
243
|
+
- `listTabs` - Список всех открытых вкладок
|
|
244
|
+
- `switchTab` - Переключается на другую вкладку
|
|
245
|
+
|
|
246
|
+
### Инструменты записи
|
|
247
|
+
|
|
248
|
+
- `enableRecorder` - Проверяет статус рекордера
|
|
249
|
+
- `startRecording` - Начинает запись действий
|
|
250
|
+
- `stopRecording` - Останавливает запись
|
|
251
|
+
- `saveScenario` - Сохраняет записанный сценарий
|
|
252
|
+
- `executeScenario` - Выполняет сохраненный сценарий
|
|
253
|
+
- `listScenarios` - Список всех сценариев
|
|
254
|
+
- `searchScenarios` - Поиск сценариев
|
|
255
|
+
- `getScenarioInfo` - Детали сценария
|
|
256
|
+
- `deleteScenario` - Удаляет сценарий
|
|
257
|
+
- `exportScenarioAsCode` - Экспортирует сценарий в код теста
|
|
258
|
+
- `appendScenarioToFile` - Добавляет сценарий в существующий файл
|
|
259
|
+
- `generatePageObject` - Генерирует Page Object Model
|
|
260
|
+
|
|
261
|
+
## Типичный пример рабочего процесса
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
// 1. Открыть браузер
|
|
265
|
+
openBrowser({ url: "https://example.com" })
|
|
266
|
+
|
|
267
|
+
// 2. Проанализировать страницу
|
|
268
|
+
analyzePage()
|
|
269
|
+
// Возвращает структурированную модель с ID элементов
|
|
270
|
+
|
|
271
|
+
// 3. Взаимодействовать с элементами по ID
|
|
272
|
+
click({ id: "button_45" })
|
|
273
|
+
type({ id: "input_20", text: "Hello World" })
|
|
274
|
+
|
|
275
|
+
// 4. Обновить анализ после изменений
|
|
276
|
+
analyzePage({ refresh: true })
|
|
277
|
+
|
|
278
|
+
// 5. Получить детали конкретного элемента
|
|
279
|
+
getElementDetails({ id: "form_15" })
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Советы по использованию инструментов
|
|
283
|
+
|
|
284
|
+
1. **Используйте analyzePage часто** - Это самый эффективный способ понять состояние страницы
|
|
285
|
+
2. **Используйте ID элементов** - После analyzePage используйте ID (например, `button_45`) вместо CSS селекторов
|
|
286
|
+
3. **Обновляйте после изменений** - Используйте `analyzePage({ refresh: true })` после кликов/отправок форм
|
|
287
|
+
4. **Предпочитайте click/type вместо executeScript** - Они правильно работают с фреймворками
|
|
288
|
+
5. **Используйте saveScreenshot для Telegram** - Вместо screenshot для отправки изображений
|
|
289
|
+
|
|
290
|
+
## Конфигурация
|
|
291
|
+
|
|
292
|
+
### Переменные окружения
|
|
293
|
+
|
|
294
|
+
- `DEBUG_MODE=true` - Включает детальное логирование
|
|
295
|
+
- `CHROME_PATH=/path/to/chrome` - Путь к Chrome (опционально)
|
|
296
|
+
|
|
297
|
+
### Файл конфигурации
|
|
298
|
+
|
|
299
|
+
Создайте `.chrometools.json` в домашней директории:
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"debugMode": false,
|
|
304
|
+
"chromePath": null,
|
|
305
|
+
"userDataDir": null
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Поддержка нескольких экземпляров
|
|
310
|
+
|
|
311
|
+
Запускайте до 8 MCP серверов одновременно, подключайтесь/отключайтесь в любое время без координации.
|
|
312
|
+
|
|
313
|
+
### Возможности:
|
|
314
|
+
|
|
315
|
+
- **Динамическое выделение портов** (9223-9227)
|
|
316
|
+
- **Автоматическое обнаружение** расширением Chrome
|
|
317
|
+
- **Широковещательный паттерн** для параллельных AI клиентов
|
|
318
|
+
- **Плавная обработка** неожиданных завершений
|
|
319
|
+
|
|
320
|
+
### Использование:
|
|
321
|
+
|
|
322
|
+
Просто запустите несколько экземпляров:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
# Терминал 1
|
|
326
|
+
npx chrometools-mcp
|
|
327
|
+
|
|
328
|
+
# Терминал 2
|
|
329
|
+
npx chrometools-mcp
|
|
330
|
+
|
|
331
|
+
# Терминал 3
|
|
332
|
+
npx chrometools-mcp
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Каждый экземпляр автоматически найдет свободный порт и подключится к расширению Chrome.
|
|
336
|
+
|
|
337
|
+
## Особенности
|
|
338
|
+
|
|
339
|
+
- **Постоянные сессии браузера** - Вкладки остаются открытыми между запросами
|
|
340
|
+
- **Визуальный браузер (GUI режим)** - Видите автоматизацию в реальном времени
|
|
341
|
+
- **Кроссплатформенность** - Работает на Windows/WSL, Linux, macOS
|
|
342
|
+
- **Простая установка** - Одна команда с npx
|
|
343
|
+
- **Интеграция CDP** - Использует Chrome DevTools Protocol для точности
|
|
344
|
+
- **Дружелюбен к AI** - Детальные описания оптимизированы для AI агентов
|
|
345
|
+
|
|
346
|
+
## Лицензия
|
|
347
|
+
|
|
348
|
+
MIT
|
|
349
|
+
|
|
350
|
+
## Поддержка
|
|
351
|
+
|
|
352
|
+
Для вопросов и сообщений об ошибках создайте issue на GitHub.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.js
CHANGED
|
@@ -380,7 +380,21 @@ async function executeToolInternal(name, args) {
|
|
|
380
380
|
throw new Error(`Element not found: ${identifier}`);
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
|
|
383
|
+
// Try multiple click methods for better reliability
|
|
384
|
+
try {
|
|
385
|
+
// Method 1: Puppeteer click (most reliable for most cases)
|
|
386
|
+
await element.click();
|
|
387
|
+
} catch (clickError) {
|
|
388
|
+
// Method 2: Scroll into view and try again
|
|
389
|
+
try {
|
|
390
|
+
await element.evaluate(el => el.scrollIntoView({ behavior: 'instant', block: 'center' }));
|
|
391
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
392
|
+
await element.click();
|
|
393
|
+
} catch (scrollClickError) {
|
|
394
|
+
// Method 3: JavaScript click (works for hidden/overlapping elements)
|
|
395
|
+
await element.evaluate(el => el.click());
|
|
396
|
+
}
|
|
397
|
+
}
|
|
384
398
|
await new Promise(resolve => setTimeout(resolve, validatedArgs.waitAfter || 1500));
|
|
385
399
|
|
|
386
400
|
// Generate AI hints after click
|
|
@@ -437,7 +451,7 @@ async function executeToolInternal(name, args) {
|
|
|
437
451
|
// Use input model to handle the element appropriately
|
|
438
452
|
const model = await getInputModel(element, page);
|
|
439
453
|
const options = {
|
|
440
|
-
delay: validatedArgs.delay
|
|
454
|
+
delay: validatedArgs.delay !== undefined ? validatedArgs.delay : 30,
|
|
441
455
|
clearFirst: validatedArgs.clearFirst !== undefined ? validatedArgs.clearFirst : true,
|
|
442
456
|
};
|
|
443
457
|
|
|
@@ -451,32 +465,6 @@ async function executeToolInternal(name, args) {
|
|
|
451
465
|
};
|
|
452
466
|
}
|
|
453
467
|
|
|
454
|
-
if (name === "getElement") {
|
|
455
|
-
const validatedArgs = schemas.GetElementSchema.parse(args);
|
|
456
|
-
const page = await getLastOpenPage();
|
|
457
|
-
|
|
458
|
-
const client = await page.target().createCDPSession();
|
|
459
|
-
await client.send('DOM.enable');
|
|
460
|
-
|
|
461
|
-
const { root } = await client.send('DOM.getDocument');
|
|
462
|
-
const useSelector = (validatedArgs.selector && validatedArgs.selector.trim()) ? validatedArgs.selector : 'body';
|
|
463
|
-
|
|
464
|
-
const { nodeId } = await client.send('DOM.querySelector', {
|
|
465
|
-
selector: useSelector,
|
|
466
|
-
nodeId: root.nodeId
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
if (!nodeId) {
|
|
470
|
-
throw new Error(`Element not found: ${validatedArgs.selector}`);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const { outerHTML } = await client.send('DOM.getOuterHTML', { nodeId });
|
|
474
|
-
|
|
475
|
-
return {
|
|
476
|
-
content: [{ type: "text", text: outerHTML }],
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
|
|
480
468
|
if (name === "getComputedCss") {
|
|
481
469
|
const validatedArgs = schemas.GetComputedCssSchema.parse(args);
|
|
482
470
|
const page = await getLastOpenPage();
|
|
@@ -2115,16 +2103,21 @@ Start coding now.`;
|
|
|
2115
2103
|
};
|
|
2116
2104
|
}
|
|
2117
2105
|
|
|
2118
|
-
if (name === "
|
|
2119
|
-
const validatedArgs = schemas.
|
|
2106
|
+
if (name === "getElementDetails") {
|
|
2107
|
+
const validatedArgs = schemas.GetElementDetailsSchema.parse(args);
|
|
2120
2108
|
const page = await getLastOpenPage();
|
|
2121
2109
|
|
|
2122
|
-
const result = await page.evaluate((elementId, selectorResolverCode) => {
|
|
2110
|
+
const result = await page.evaluate((elementId, selectorResolverCode, apomTreeConverterCode, analyzeChildren, includeAll) => {
|
|
2123
2111
|
// Inject selector resolver if not loaded
|
|
2124
2112
|
if (typeof resolveSelector === 'undefined') {
|
|
2125
2113
|
eval(selectorResolverCode);
|
|
2126
2114
|
}
|
|
2127
2115
|
|
|
2116
|
+
// Inject APOM tree converter utilities
|
|
2117
|
+
if (typeof buildAPOMTree === 'undefined') {
|
|
2118
|
+
eval(apomTreeConverterCode);
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2128
2121
|
// Resolve APOM ID to selector
|
|
2129
2122
|
const resolved = resolveSelector(elementId);
|
|
2130
2123
|
|
|
@@ -2146,25 +2139,25 @@ Start coding now.`;
|
|
|
2146
2139
|
};
|
|
2147
2140
|
}
|
|
2148
2141
|
|
|
2149
|
-
// Get element details
|
|
2142
|
+
// Get element details with full information
|
|
2150
2143
|
const rect = element.getBoundingClientRect();
|
|
2151
2144
|
const computedStyle = window.getComputedStyle(element);
|
|
2152
2145
|
|
|
2153
|
-
|
|
2146
|
+
const details = {
|
|
2154
2147
|
success: true,
|
|
2155
2148
|
id: elementId,
|
|
2156
2149
|
selector: resolved.selector,
|
|
2157
2150
|
tag: element.tagName.toLowerCase(),
|
|
2158
2151
|
type: resolved.metadata.type || 'unknown',
|
|
2159
2152
|
bounds: {
|
|
2160
|
-
x: rect.x,
|
|
2161
|
-
y: rect.y,
|
|
2162
|
-
width: rect.width,
|
|
2163
|
-
height: rect.height,
|
|
2164
|
-
top: rect.top,
|
|
2165
|
-
right: rect.right,
|
|
2166
|
-
bottom: rect.bottom,
|
|
2167
|
-
left: rect.left
|
|
2153
|
+
x: Math.round(rect.x),
|
|
2154
|
+
y: Math.round(rect.y),
|
|
2155
|
+
width: Math.round(rect.width),
|
|
2156
|
+
height: Math.round(rect.height),
|
|
2157
|
+
top: Math.round(rect.top),
|
|
2158
|
+
right: Math.round(rect.right),
|
|
2159
|
+
bottom: Math.round(rect.bottom),
|
|
2160
|
+
left: Math.round(rect.left)
|
|
2168
2161
|
},
|
|
2169
2162
|
position: resolved.metadata.position || null,
|
|
2170
2163
|
visible: element.offsetWidth > 0 && element.offsetHeight > 0,
|
|
@@ -2179,70 +2172,80 @@ Start coding now.`;
|
|
|
2179
2172
|
required: element.hasAttribute('required'),
|
|
2180
2173
|
readonly: element.hasAttribute('readonly'),
|
|
2181
2174
|
href: element.getAttribute('href') || null,
|
|
2182
|
-
src: element.getAttribute('src') || null
|
|
2175
|
+
src: element.getAttribute('src') || null,
|
|
2176
|
+
type: element.getAttribute('type') || null,
|
|
2177
|
+
role: element.getAttribute('role') || null,
|
|
2178
|
+
ariaLabel: element.getAttribute('aria-label') || null
|
|
2183
2179
|
},
|
|
2184
2180
|
computed: {
|
|
2185
2181
|
display: computedStyle.display,
|
|
2186
2182
|
visibility: computedStyle.visibility,
|
|
2187
2183
|
opacity: computedStyle.opacity,
|
|
2188
2184
|
zIndex: computedStyle.zIndex,
|
|
2189
|
-
position: computedStyle.position
|
|
2190
|
-
|
|
2185
|
+
position: computedStyle.position,
|
|
2186
|
+
cursor: computedStyle.cursor,
|
|
2187
|
+
backgroundColor: computedStyle.backgroundColor,
|
|
2188
|
+
color: computedStyle.color,
|
|
2189
|
+
fontSize: computedStyle.fontSize,
|
|
2190
|
+
fontWeight: computedStyle.fontWeight
|
|
2191
|
+
},
|
|
2192
|
+
metadata: resolved.metadata || {}
|
|
2191
2193
|
};
|
|
2192
|
-
}, validatedArgs.id, selectorResolver);
|
|
2193
2194
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
if (!includeHidden && !isVisible) return;
|
|
2216
|
-
|
|
2217
|
-
const text = (el.textContent || el.value || el.getAttribute('aria-label') || el.placeholder || '').trim();
|
|
2195
|
+
// If analyzeChildren is true, add children tree structure
|
|
2196
|
+
if (analyzeChildren) {
|
|
2197
|
+
try {
|
|
2198
|
+
const pageId = `element_${elementId}_${Date.now()}`;
|
|
2199
|
+
|
|
2200
|
+
// Call buildAPOMTree with the element as root
|
|
2201
|
+
const fullAnalysis = buildAPOMTree(!includeAll, false);
|
|
2202
|
+
|
|
2203
|
+
// Find the node in the tree that matches our element ID
|
|
2204
|
+
function findNodeById(node, targetId) {
|
|
2205
|
+
if (!node) return null;
|
|
2206
|
+
if (node.id === targetId) return node;
|
|
2207
|
+
if (node.children) {
|
|
2208
|
+
for (const child of node.children) {
|
|
2209
|
+
const found = findNodeById(child, targetId);
|
|
2210
|
+
if (found) return found;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
return null;
|
|
2214
|
+
}
|
|
2218
2215
|
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2216
|
+
const targetNode = findNodeById(fullAnalysis.tree, elementId);
|
|
2217
|
+
|
|
2218
|
+
if (targetNode) {
|
|
2219
|
+
details.childrenTree = {
|
|
2220
|
+
pageId,
|
|
2221
|
+
url: window.location.href,
|
|
2222
|
+
title: document.title,
|
|
2223
|
+
timestamp: Date.now(),
|
|
2224
|
+
rootElementId: elementId,
|
|
2225
|
+
tree: targetNode,
|
|
2226
|
+
metadata: fullAnalysis.metadata
|
|
2227
|
+
};
|
|
2228
|
+
} else {
|
|
2229
|
+
details.childrenTree = {
|
|
2230
|
+
success: false,
|
|
2231
|
+
error: `Could not find element "${elementId}" in analysis tree`
|
|
2232
|
+
};
|
|
2229
2233
|
}
|
|
2230
|
-
})
|
|
2231
|
-
|
|
2234
|
+
} catch (err) {
|
|
2235
|
+
details.childrenTree = {
|
|
2236
|
+
success: false,
|
|
2237
|
+
error: `Failed to analyze children: ${err.message}`
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2232
2241
|
|
|
2233
|
-
return
|
|
2234
|
-
}, validatedArgs.
|
|
2242
|
+
return details;
|
|
2243
|
+
}, validatedArgs.id, selectorResolver, apomTreeConverter, validatedArgs.analyzeChildren || false, validatedArgs.includeAll || false);
|
|
2235
2244
|
|
|
2236
2245
|
return {
|
|
2237
2246
|
content: [{
|
|
2238
2247
|
type: 'text',
|
|
2239
|
-
text: JSON.stringify(
|
|
2240
|
-
count: elements.length,
|
|
2241
|
-
elements,
|
|
2242
|
-
hints: {
|
|
2243
|
-
suggestion: 'Use these selectors directly with click, type, or other tools'
|
|
2244
|
-
}
|
|
2245
|
-
}, null, 2)
|
|
2248
|
+
text: JSON.stringify(result, null, 2)
|
|
2246
2249
|
}]
|
|
2247
2250
|
};
|
|
2248
2251
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrometools-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.6",
|
|
4
4
|
"description": "MCP (Model Context Protocol) server for Chrome automation using Puppeteer. Persistent browser sessions, UI framework detection (MUI, Ant Design, etc.), Page Object support, visual testing, Figma comparison. Works seamlessly in WSL, Linux, macOS, and Windows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|