chrometools-mcp 3.1.6 → 3.2.4
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 +97 -3
- package/README.md +157 -108
- package/README.ru.md +331 -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 +95 -44
- package/package.json +1 -1
- package/pom/apom-tree-converter.js +302 -39
- package/server/tool-definitions.js +23 -30
- package/server/tool-schemas.js +5 -6
- package/test-interactivity.html +178 -0
package/README.ru.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# chrometools-mcp
|
|
2
|
+
|
|
3
|
+
MCP сервер для автоматизации Chrome с использованием Puppeteer и постоянными сессиями браузера.
|
|
4
|
+
|
|
5
|
+
[English version](README.md)
|
|
6
|
+
|
|
7
|
+
## Установка
|
|
8
|
+
|
|
9
|
+
### Claude Code (CLI)
|
|
10
|
+
|
|
11
|
+
Самый простой способ установки для пользователей Claude Code:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
claude mcp add chrometools -- npx chrometools-mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Эта команда автоматически настроит MCP сервер в настройках Claude Code.
|
|
18
|
+
|
|
19
|
+
### Claude Desktop
|
|
20
|
+
|
|
21
|
+
Добавьте в конфигурационный файл Claude Desktop:
|
|
22
|
+
|
|
23
|
+
**macOS/Linux:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
24
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"chrometools": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["chrometools-mcp"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Cursor
|
|
38
|
+
|
|
39
|
+
**Шаг 1:** Откройте настройки MCP в Cursor
|
|
40
|
+
- Нажмите на **Settings** (⚙️ иконка или `Cmd + ,` / `Ctrl + ,`)
|
|
41
|
+
- Перейдите в **Cursor Settings** → **MCP**
|
|
42
|
+
|
|
43
|
+
**Шаг 2:** Отредактируйте конфигурацию MCP
|
|
44
|
+
- Добавьте `chrometools` в объект `mcpServers`:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"chrometools": {
|
|
50
|
+
"command": "npx",
|
|
51
|
+
"args": ["chrometools-mcp"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Шаг 3:** Сохраните и перезапустите
|
|
58
|
+
- Сохраните конфигурационный файл
|
|
59
|
+
- Перезапустите Cursor для применения изменений
|
|
60
|
+
|
|
61
|
+
**Шаг 4:** Протестируйте установку
|
|
62
|
+
- Откройте Cursor Chat
|
|
63
|
+
- Выберите режим **Agent**
|
|
64
|
+
- Попробуйте команду: "Open browser and navigate to google.com"
|
|
65
|
+
|
|
66
|
+
### Ручная установка
|
|
67
|
+
|
|
68
|
+
Вы также можете запустить напрямую без конфигурации:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npx chrometools-mcp
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Настройка расширения Chrome
|
|
75
|
+
|
|
76
|
+
Расширение Chrome **необходимо** для записи сценариев и других расширенных функций. Следуйте этим шагам для установки:
|
|
77
|
+
|
|
78
|
+
**Важно:** ChromeTools открывает Chrome с отдельным профилем пользователя, поэтому вы должны установить расширение **после** первого запуска Chrome через ChromeTools.
|
|
79
|
+
|
|
80
|
+
**Шаг 1:** Сначала запустите MCP сервер ChromeTools
|
|
81
|
+
- Убедитесь, что ChromeTools запущен через ваш MCP клиент (Claude Desktop, Cursor и т.д.)
|
|
82
|
+
- Или запустите вручную: `npx chrometools-mcp`
|
|
83
|
+
- Это запустит Chrome с изолированным профилем ChromeTools
|
|
84
|
+
|
|
85
|
+
**Шаг 2:** Включите режим разработчика в Chrome
|
|
86
|
+
- Откройте страницу расширений Chrome: `chrome://extensions`
|
|
87
|
+
- Переключите **Режим разработчика** (переключатель в правом верхнем углу)
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
**Шаг 3:** Скачайте и распакуйте расширение
|
|
92
|
+
|
|
93
|
+
**Вариант A - Скачать с GitHub (Рекомендуется):**
|
|
94
|
+
1. Скачайте архив расширения: [chrome-extension.zip](https://github.com/modelcontextprotocol/servers/raw/main/src/chrometools/chrome-extension.zip)
|
|
95
|
+
2. Распакуйте ZIP файл в папку на вашем компьютере
|
|
96
|
+
3. Запомните путь распаковки (он понадобится на следующем шаге)
|
|
97
|
+
|
|
98
|
+
**Вариант B - Использовать из node_modules (если знаете путь):**
|
|
99
|
+
- **После npx установки:** `~/.npm/_npx/.../node_modules/chrometools-mcp/extension`
|
|
100
|
+
- **После глобальной установки:** `<npm-global-path>/node_modules/chrometools-mcp/extension`
|
|
101
|
+
- **Из исходников:** `<repo-path>/extension`
|
|
102
|
+
|
|
103
|
+
**Шаг 4:** Загрузите расширение
|
|
104
|
+
- Нажмите кнопку **"Загрузить распакованное"** (Load unpacked)
|
|
105
|
+
- Перейдите к распакованной папке расширения (из Шага 3)
|
|
106
|
+
- Выберите папку и нажмите **"Выбрать папку"**
|
|
107
|
+
|
|
108
|
+
**Шаг 5:** Проверьте установку
|
|
109
|
+
- Вы должны увидеть расширение "ChromeTools MCP" в списке расширений с:
|
|
110
|
+
- **Название:** ChromeTools MCP
|
|
111
|
+
- **Версия:** (текущая версия)
|
|
112
|
+
- **Описание:** MCP server integration for Chrome automation
|
|
113
|
+
- **Статус:** Переключатель должен быть ВКЛЮЧЕН (синий)
|
|
114
|
+
- Найдите иконку ChromeTools (CT) в панели инструментов Chrome
|
|
115
|
+
- Расширение готово к использованию для записи сценариев
|
|
116
|
+
|
|
117
|
+

|
|
118
|
+
|
|
119
|
+
> **Примечание:** После установки карточка расширения появится на странице `chrome://extensions` вместе с другими установленными расширениями. Расширение должно отображаться как "Включено" с синим переключателем.
|
|
120
|
+
|
|
121
|
+
**Шаг 6:** Закрепите расширение (опционально, но рекомендуется)
|
|
122
|
+
- Нажмите на иконку пазла в панели инструментов Chrome
|
|
123
|
+
- Найдите "ChromeTools MCP" в списке
|
|
124
|
+
- Нажмите на иконку булавки, чтобы оставить его видимым в панели инструментов
|
|
125
|
+
|
|
126
|
+
**Устранение неполадок:**
|
|
127
|
+
- **Рекомендуется:** Используйте Вариант A (скачивание с GitHub), чтобы избежать поиска в node_modules
|
|
128
|
+
- Если используете Вариант B и не можете найти папку расширения после установки `npx`, выполните `npm list -g chrometools-mcp` чтобы найти путь установки
|
|
129
|
+
- Расширение работает только с экземплярами Chrome, запущенными через ChromeTools
|
|
130
|
+
- Если Chrome закрывается и открывается снова, расширение должно остаться загруженным (режим разработчика сохраняется)
|
|
131
|
+
- Когда ChromeTools впервые открывает Chrome, он автоматически показывает подсказку с путем к расширению в node_modules
|
|
132
|
+
|
|
133
|
+
## Оглавление
|
|
134
|
+
|
|
135
|
+
- [Установка](#установка)
|
|
136
|
+
- [Настройка расширения Chrome](#настройка-расширения-chrome)
|
|
137
|
+
- [Возможности оптимизации AI](#возможности-оптимизации-ai)
|
|
138
|
+
- [Записывающее устройство сценариев](#записывающее-устройство-сценариев)
|
|
139
|
+
- [Доступные инструменты](#доступные-инструменты) - **46+ инструментов всего**
|
|
140
|
+
- [AI-инструменты](#ai-инструменты)
|
|
141
|
+
- [Основные инструменты](#основные-инструменты)
|
|
142
|
+
- [Инструменты взаимодействия](#инструменты-взаимодействия)
|
|
143
|
+
- [Инструменты инспекции](#инструменты-инспекции)
|
|
144
|
+
- [Продвинутые инструменты](#продвинутые-инструменты)
|
|
145
|
+
- [Инструменты управления вкладками](#инструменты-управления-вкладками)
|
|
146
|
+
- [Инструменты записи](#инструменты-записи)
|
|
147
|
+
- [Типичный пример рабочего процесса](#типичный-пример-рабочего-процесса)
|
|
148
|
+
- [Советы по использованию инструментов](#советы-по-использованию-инструментов)
|
|
149
|
+
- [Конфигурация](#конфигурация)
|
|
150
|
+
- [Поддержка нескольких экземпляров](#поддержка-нескольких-экземпляров)
|
|
151
|
+
|
|
152
|
+
## Возможности оптимизации AI
|
|
153
|
+
|
|
154
|
+
Значительно сокращайте циклы запросов AI-агента с помощью интеллектуального поиска элементов и анализа страниц.
|
|
155
|
+
|
|
156
|
+
### Основные возможности:
|
|
157
|
+
|
|
158
|
+
- **analyzePage**: Возвращает структурированную модель страницы с уникальными ID элементов
|
|
159
|
+
- **smartFindElement**: Находит элементы по естественному языковому описанию
|
|
160
|
+
- **getElementDetails**: Получает детальную информацию о конкретном элементе
|
|
161
|
+
- **findElementsByText**: Находит элементы по видимому тексту
|
|
162
|
+
|
|
163
|
+
## Записывающее устройство сценариев
|
|
164
|
+
|
|
165
|
+
Визуальный UI-рекордер для создания переиспользуемых тестовых сценариев с автоматическим обнаружением секретов.
|
|
166
|
+
|
|
167
|
+
### Основные возможности:
|
|
168
|
+
|
|
169
|
+
- **Визуальный UI** - Используйте расширение Chrome для записи
|
|
170
|
+
- **Умная оптимизация** - Автоматически находит родительские элементы с обработчиками событий
|
|
171
|
+
- **Обнаружение секретов** - Автоматически определяет пароли, токены, ключи API
|
|
172
|
+
- **Умные ожидания** - 2 секунды минимум + обнаружение анимации/сети/изменений DOM
|
|
173
|
+
- **Генерация кода** - Экспортирует в Playwright/Selenium
|
|
174
|
+
|
|
175
|
+
## Доступные инструменты
|
|
176
|
+
|
|
177
|
+
### AI-инструменты
|
|
178
|
+
|
|
179
|
+
- `analyzePage` - Анализирует структуру страницы и возвращает модель с уникальными ID
|
|
180
|
+
- `smartFindElement` - Находит элементы по описанию на естественном языке
|
|
181
|
+
- `getElementDetails` - Получает детальную информацию о элементе
|
|
182
|
+
- `findElementsByText` - Находит элементы по видимому тексту
|
|
183
|
+
- `getAllInteractiveElements` - Получает все интерактивные элементы с селекторами
|
|
184
|
+
|
|
185
|
+
### Основные инструменты
|
|
186
|
+
|
|
187
|
+
- `ping` - Тестовая команда для проверки связи
|
|
188
|
+
- `openBrowser` - Открывает браузер и переходит по URL
|
|
189
|
+
|
|
190
|
+
### Инструменты взаимодействия
|
|
191
|
+
|
|
192
|
+
- `click` - Кликает по элементу
|
|
193
|
+
- `type` - Вводит текст в поле ввода
|
|
194
|
+
- `scrollTo` - Прокручивает к элементу
|
|
195
|
+
- `selectOption` - Выбирает опцию из выпадающего списка
|
|
196
|
+
- `selectFromGroup` - Выбирает из радио-кнопок или чекбоксов
|
|
197
|
+
- `drag` - Перетаскивает элемент мышью
|
|
198
|
+
- `scrollHorizontal` - Горизонтальная прокрутка элемента
|
|
199
|
+
|
|
200
|
+
### Инструменты инспекции
|
|
201
|
+
|
|
202
|
+
- `getComputedCss` - Получает вычисленные CSS стили
|
|
203
|
+
- `getBoxModel` - Получает box model элемента (размеры, отступы)
|
|
204
|
+
- `screenshot` - Делает скриншот элемента или страницы
|
|
205
|
+
- `saveScreenshot` - Сохраняет скриншот в файл
|
|
206
|
+
|
|
207
|
+
### Продвинутые инструменты
|
|
208
|
+
|
|
209
|
+
- `executeScript` - Выполняет JavaScript код
|
|
210
|
+
- `getConsoleLogs` - Получает логи консоли браузера
|
|
211
|
+
- `listNetworkRequests` - Список сетевых запросов
|
|
212
|
+
- `getNetworkRequest` - Детали конкретного запроса
|
|
213
|
+
- `filterNetworkRequests` - Фильтрует запросы по URL
|
|
214
|
+
- `hover` - Наводит курсор на элемент
|
|
215
|
+
- `setStyles` - Применяет inline CSS стили
|
|
216
|
+
- `setViewport` - Изменяет размер окна браузера
|
|
217
|
+
- `getViewport` - Получает размер окна браузера
|
|
218
|
+
- `navigateTo` - Переходит по новому URL
|
|
219
|
+
|
|
220
|
+
### Инструменты управления вкладками
|
|
221
|
+
|
|
222
|
+
- `listTabs` - Список всех открытых вкладок
|
|
223
|
+
- `switchTab` - Переключается на другую вкладку
|
|
224
|
+
|
|
225
|
+
### Инструменты записи
|
|
226
|
+
|
|
227
|
+
- `enableRecorder` - Проверяет статус рекордера
|
|
228
|
+
- `startRecording` - Начинает запись действий
|
|
229
|
+
- `stopRecording` - Останавливает запись
|
|
230
|
+
- `saveScenario` - Сохраняет записанный сценарий
|
|
231
|
+
- `executeScenario` - Выполняет сохраненный сценарий
|
|
232
|
+
- `listScenarios` - Список всех сценариев
|
|
233
|
+
- `searchScenarios` - Поиск сценариев
|
|
234
|
+
- `getScenarioInfo` - Детали сценария
|
|
235
|
+
- `deleteScenario` - Удаляет сценарий
|
|
236
|
+
- `exportScenarioAsCode` - Экспортирует сценарий в код теста
|
|
237
|
+
- `appendScenarioToFile` - Добавляет сценарий в существующий файл
|
|
238
|
+
- `generatePageObject` - Генерирует Page Object Model
|
|
239
|
+
|
|
240
|
+
## Типичный пример рабочего процесса
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// 1. Открыть браузер
|
|
244
|
+
openBrowser({ url: "https://example.com" })
|
|
245
|
+
|
|
246
|
+
// 2. Проанализировать страницу
|
|
247
|
+
analyzePage()
|
|
248
|
+
// Возвращает структурированную модель с ID элементов
|
|
249
|
+
|
|
250
|
+
// 3. Взаимодействовать с элементами по ID
|
|
251
|
+
click({ id: "button_45" })
|
|
252
|
+
type({ id: "input_20", text: "Hello World" })
|
|
253
|
+
|
|
254
|
+
// 4. Обновить анализ после изменений
|
|
255
|
+
analyzePage({ refresh: true })
|
|
256
|
+
|
|
257
|
+
// 5. Получить детали конкретного элемента
|
|
258
|
+
getElementDetails({ id: "form_15" })
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Советы по использованию инструментов
|
|
262
|
+
|
|
263
|
+
1. **Используйте analyzePage часто** - Это самый эффективный способ понять состояние страницы
|
|
264
|
+
2. **Используйте ID элементов** - После analyzePage используйте ID (например, `button_45`) вместо CSS селекторов
|
|
265
|
+
3. **Обновляйте после изменений** - Используйте `analyzePage({ refresh: true })` после кликов/отправок форм
|
|
266
|
+
4. **Предпочитайте click/type вместо executeScript** - Они правильно работают с фреймворками
|
|
267
|
+
5. **Используйте saveScreenshot для Telegram** - Вместо screenshot для отправки изображений
|
|
268
|
+
|
|
269
|
+
## Конфигурация
|
|
270
|
+
|
|
271
|
+
### Переменные окружения
|
|
272
|
+
|
|
273
|
+
- `DEBUG_MODE=true` - Включает детальное логирование
|
|
274
|
+
- `CHROME_PATH=/path/to/chrome` - Путь к Chrome (опционально)
|
|
275
|
+
|
|
276
|
+
### Файл конфигурации
|
|
277
|
+
|
|
278
|
+
Создайте `.chrometools.json` в домашней директории:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"debugMode": false,
|
|
283
|
+
"chromePath": null,
|
|
284
|
+
"userDataDir": null
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Поддержка нескольких экземпляров
|
|
289
|
+
|
|
290
|
+
Запускайте до 8 MCP серверов одновременно, подключайтесь/отключайтесь в любое время без координации.
|
|
291
|
+
|
|
292
|
+
### Возможности:
|
|
293
|
+
|
|
294
|
+
- **Динамическое выделение портов** (9223-9227)
|
|
295
|
+
- **Автоматическое обнаружение** расширением Chrome
|
|
296
|
+
- **Широковещательный паттерн** для параллельных AI клиентов
|
|
297
|
+
- **Плавная обработка** неожиданных завершений
|
|
298
|
+
|
|
299
|
+
### Использование:
|
|
300
|
+
|
|
301
|
+
Просто запустите несколько экземпляров:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Терминал 1
|
|
305
|
+
npx chrometools-mcp
|
|
306
|
+
|
|
307
|
+
# Терминал 2
|
|
308
|
+
npx chrometools-mcp
|
|
309
|
+
|
|
310
|
+
# Терминал 3
|
|
311
|
+
npx chrometools-mcp
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Каждый экземпляр автоматически найдет свободный порт и подключится к расширению Chrome.
|
|
315
|
+
|
|
316
|
+
## Особенности
|
|
317
|
+
|
|
318
|
+
- **Постоянные сессии браузера** - Вкладки остаются открытыми между запросами
|
|
319
|
+
- **Визуальный браузер (GUI режим)** - Видите автоматизацию в реальном времени
|
|
320
|
+
- **Кроссплатформенность** - Работает на Windows/WSL, Linux, macOS
|
|
321
|
+
- **Простая установка** - Одна команда с npx
|
|
322
|
+
- **Интеграция CDP** - Использует Chrome DevTools Protocol для точности
|
|
323
|
+
- **Дружелюбен к AI** - Детальные описания оптимизированы для AI агентов
|
|
324
|
+
|
|
325
|
+
## Лицензия
|
|
326
|
+
|
|
327
|
+
MIT
|
|
328
|
+
|
|
329
|
+
## Поддержка
|
|
330
|
+
|
|
331
|
+
Для вопросов и сообщений об ошибках создайте 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
|
|
@@ -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,17 +2172,75 @@ 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
|
-
|
|
2194
|
+
|
|
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
|
+
}
|
|
2215
|
+
|
|
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
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
} catch (err) {
|
|
2235
|
+
details.childrenTree = {
|
|
2236
|
+
success: false,
|
|
2237
|
+
error: `Failed to analyze children: ${err.message}`
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
return details;
|
|
2243
|
+
}, validatedArgs.id, selectorResolver, apomTreeConverter, validatedArgs.analyzeChildren || false, validatedArgs.includeAll || false);
|
|
2193
2244
|
|
|
2194
2245
|
return {
|
|
2195
2246
|
content: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrometools-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.4",
|
|
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",
|