bump
This commit is contained in:
@@ -1034,6 +1034,300 @@ web_clear_storage_cremotemcp:
|
||||
timeout: 5
|
||||
```
|
||||
|
||||
### 34. `web_drag_and_drop_cremotemcp` *(New in Phase 6)*
|
||||
Perform drag and drop operation from source element to target element.
|
||||
|
||||
**Parameters:**
|
||||
- `source` (required): CSS selector for the source element to drag
|
||||
- `target` (required): CSS selector for the target element to drop on
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Drag item to drop zone
|
||||
web_drag_and_drop_cremotemcp:
|
||||
source: ".draggable-item"
|
||||
target: ".drop-zone"
|
||||
timeout: 10
|
||||
|
||||
# Drag file to upload area
|
||||
web_drag_and_drop_cremotemcp:
|
||||
source: "#file-item"
|
||||
target: "#upload-area"
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 35. `web_drag_and_drop_coordinates_cremotemcp` *(New in Phase 6)*
|
||||
Perform drag and drop operation from source element to specific coordinates.
|
||||
|
||||
**Parameters:**
|
||||
- `source` (required): CSS selector for the source element to drag
|
||||
- `x` (required): Target X coordinate
|
||||
- `y` (required): Target Y coordinate
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Drag item to specific coordinates
|
||||
web_drag_and_drop_coordinates_cremotemcp:
|
||||
source: ".draggable-item"
|
||||
x: 300
|
||||
y: 200
|
||||
timeout: 10
|
||||
|
||||
# Drag widget to precise position
|
||||
web_drag_and_drop_coordinates_cremotemcp:
|
||||
source: "#dashboard-widget"
|
||||
x: 150
|
||||
y: 400
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 36. `web_drag_and_drop_offset_cremotemcp` *(New in Phase 6)*
|
||||
Perform drag and drop operation from source element by relative offset.
|
||||
|
||||
**Parameters:**
|
||||
- `source` (required): CSS selector for the source element to drag
|
||||
- `offset_x` (required): Horizontal offset in pixels
|
||||
- `offset_y` (required): Vertical offset in pixels
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Drag item by relative offset
|
||||
web_drag_and_drop_offset_cremotemcp:
|
||||
source: ".draggable-item"
|
||||
offset_x: 100
|
||||
offset_y: 50
|
||||
timeout: 10
|
||||
|
||||
# Move element slightly to the right and down
|
||||
web_drag_and_drop_offset_cremotemcp:
|
||||
source: "#moveable-element"
|
||||
offset_x: 25
|
||||
offset_y: 25
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 37. `web_right_click_cremotemcp` *(New in Phase 7)*
|
||||
Right-click on an element to open context menus.
|
||||
|
||||
**Parameters:**
|
||||
- `selector` (required): CSS selector for the element to right-click
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Right-click to open context menu
|
||||
web_right_click_cremotemcp:
|
||||
selector: ".file-item"
|
||||
timeout: 10
|
||||
|
||||
# Right-click on specific element
|
||||
web_right_click_cremotemcp:
|
||||
selector: "#document-title"
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 38. `web_double_click_cremotemcp` *(New in Phase 7)*
|
||||
Double-click on an element for file operations or text selection.
|
||||
|
||||
**Parameters:**
|
||||
- `selector` (required): CSS selector for the element to double-click
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Double-click to open file
|
||||
web_double_click_cremotemcp:
|
||||
selector: ".file-icon"
|
||||
timeout: 10
|
||||
|
||||
# Double-click to select text
|
||||
web_double_click_cremotemcp:
|
||||
selector: ".text-content"
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 39. `web_hover_cremotemcp` *(New in Phase 7)*
|
||||
Hover over an element to trigger tooltips or dropdowns.
|
||||
|
||||
**Parameters:**
|
||||
- `selector` (required): CSS selector for the element to hover over
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Hover to show tooltip
|
||||
web_hover_cremotemcp:
|
||||
selector: ".tooltip-trigger"
|
||||
timeout: 10
|
||||
|
||||
# Hover to open dropdown menu
|
||||
web_hover_cremotemcp:
|
||||
selector: ".nav-item"
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 40. `web_middle_click_cremotemcp` *(New in Phase 7)*
|
||||
Middle-click on an element (typically opens links in new tabs).
|
||||
|
||||
**Parameters:**
|
||||
- `selector` (required): CSS selector for the element to middle-click
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Middle-click to open link in new tab
|
||||
web_middle_click_cremotemcp:
|
||||
selector: "a[href='/dashboard']"
|
||||
timeout: 10
|
||||
|
||||
# Middle-click on navigation link
|
||||
web_middle_click_cremotemcp:
|
||||
selector: ".nav-link"
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 41. `web_mouse_move_cremotemcp` *(New in Phase 7)*
|
||||
Move mouse to specific coordinates without clicking.
|
||||
|
||||
**Parameters:**
|
||||
- `x` (required): X coordinate to move mouse to
|
||||
- `y` (required): Y coordinate to move mouse to
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Move mouse to specific position
|
||||
web_mouse_move_cremotemcp:
|
||||
x: 400
|
||||
y: 300
|
||||
timeout: 5
|
||||
|
||||
# Position mouse for subsequent action
|
||||
web_mouse_move_cremotemcp:
|
||||
x: 150
|
||||
y: 200
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 42. `web_scroll_wheel_cremotemcp` *(New in Phase 7)*
|
||||
Scroll with mouse wheel at specific coordinates.
|
||||
|
||||
**Parameters:**
|
||||
- `x` (required): X coordinate for scroll wheel
|
||||
- `y` (required): Y coordinate for scroll wheel
|
||||
- `delta_y` (required): Vertical scroll delta (negative = up, positive = down)
|
||||
- `delta_x` (optional): Horizontal scroll delta (negative = left, positive = right, default: 0)
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Scroll up at specific location
|
||||
web_scroll_wheel_cremotemcp:
|
||||
x: 400
|
||||
y: 300
|
||||
delta_y: -120
|
||||
timeout: 5
|
||||
|
||||
# Scroll down with horizontal component
|
||||
web_scroll_wheel_cremotemcp:
|
||||
x: 500
|
||||
y: 400
|
||||
delta_x: 50
|
||||
delta_y: 120
|
||||
tab: "tab-123"
|
||||
```
|
||||
|
||||
### 43. `web_key_combination_cremotemcp` *(New in Phase 7)*
|
||||
Send key combinations like Ctrl+C, Alt+Tab, Shift+Enter.
|
||||
|
||||
**Parameters:**
|
||||
- `keys` (required): Key combination to send (e.g., 'Ctrl+C', 'Alt+Tab', 'Shift+Enter', 'Ctrl+Shift+T')
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Copy selected text
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+C"
|
||||
timeout: 5
|
||||
|
||||
# Open new tab
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+T"
|
||||
tab: "tab-123"
|
||||
|
||||
# Select all text
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+A"
|
||||
```
|
||||
|
||||
### 44. `web_special_key_cremotemcp` *(New in Phase 7)*
|
||||
Send special keys like Enter, Escape, Tab, F1-F12, Arrow keys.
|
||||
|
||||
**Parameters:**
|
||||
- `key` (required): Special key to send (e.g., 'Enter', 'Escape', 'Tab', 'F1', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'Delete', 'Backspace')
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Press Enter key
|
||||
web_special_key_cremotemcp:
|
||||
key: "Enter"
|
||||
timeout: 5
|
||||
|
||||
# Navigate with arrow keys
|
||||
web_special_key_cremotemcp:
|
||||
key: "ArrowDown"
|
||||
tab: "tab-123"
|
||||
|
||||
# Press Escape to close dialog
|
||||
web_special_key_cremotemcp:
|
||||
key: "Escape"
|
||||
```
|
||||
|
||||
### 45. `web_modifier_click_cremotemcp` *(New in Phase 7)*
|
||||
Click on an element with modifier keys (Ctrl+click, Shift+click).
|
||||
|
||||
**Parameters:**
|
||||
- `selector` (required): CSS selector for the element to click
|
||||
- `modifiers` (required): Modifier keys to hold while clicking (e.g., 'Ctrl', 'Shift', 'Alt', 'Ctrl+Shift', 'Ctrl+Alt')
|
||||
- `tab` (optional): Tab ID (uses current tab if not specified)
|
||||
- `timeout` (optional): Timeout in seconds (default: 5)
|
||||
|
||||
**Example Usage:**
|
||||
```
|
||||
# Ctrl+click for multi-selection
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".selectable-item"
|
||||
modifiers: "Ctrl"
|
||||
timeout: 10
|
||||
|
||||
# Shift+click for range selection
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".list-item:nth-child(5)"
|
||||
modifiers: "Shift"
|
||||
tab: "tab-123"
|
||||
|
||||
# Ctrl+Shift+click for extended selection
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".table-row"
|
||||
modifiers: "Ctrl+Shift"
|
||||
```
|
||||
|
||||
## Common Usage Patterns
|
||||
|
||||
### 1. Basic Web Navigation
|
||||
@@ -1737,10 +2031,110 @@ get_partial_accessibility_tree_cremotemcp:
|
||||
- Test screen reader compatibility by analyzing semantic structure
|
||||
- Build more robust automation using ARIA roles and accessible names
|
||||
|
||||
### Advanced Input Operation Testing *(Phase 7 Patterns)*
|
||||
```
|
||||
# Test context menu workflows
|
||||
web_right_click_cremotemcp:
|
||||
selector: ".file-item"
|
||||
timeout: 5
|
||||
web_interact_cremotemcp:
|
||||
action: "click"
|
||||
selector: ".context-menu .delete"
|
||||
timeout: 5
|
||||
|
||||
# Test hover-triggered dropdowns
|
||||
web_hover_cremotemcp:
|
||||
selector: ".nav-item"
|
||||
timeout: 5
|
||||
web_interact_cremotemcp:
|
||||
action: "click"
|
||||
selector: ".dropdown-item"
|
||||
timeout: 5
|
||||
|
||||
# Test keyboard navigation accessibility
|
||||
web_special_key_cremotemcp:
|
||||
key: "Tab"
|
||||
timeout: 5
|
||||
web_special_key_cremotemcp:
|
||||
key: "Enter"
|
||||
timeout: 5
|
||||
|
||||
# Test copy/paste workflows
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+A"
|
||||
timeout: 5
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+C"
|
||||
timeout: 5
|
||||
web_interact_cremotemcp:
|
||||
action: "click"
|
||||
selector: "#target-input"
|
||||
timeout: 5
|
||||
web_key_combination_cremotemcp:
|
||||
keys: "Ctrl+V"
|
||||
timeout: 5
|
||||
|
||||
# Test multi-selection with modifier clicks
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".item:nth-child(1)"
|
||||
modifiers: "Ctrl"
|
||||
timeout: 5
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".item:nth-child(3)"
|
||||
modifiers: "Ctrl"
|
||||
timeout: 5
|
||||
web_modifier_click_cremotemcp:
|
||||
selector: ".item:nth-child(5)"
|
||||
modifiers: "Ctrl"
|
||||
timeout: 5
|
||||
|
||||
# Test precise mouse wheel scrolling
|
||||
web_scroll_wheel_cremotemcp:
|
||||
x: 400
|
||||
y: 300
|
||||
delta_y: -240 # Scroll up 2 notches
|
||||
timeout: 5
|
||||
|
||||
# Test middle-click for new tabs
|
||||
web_middle_click_cremotemcp:
|
||||
selector: "a[href='/dashboard']"
|
||||
timeout: 5
|
||||
|
||||
# Test double-click for text selection
|
||||
web_double_click_cremotemcp:
|
||||
selector: ".editable-text"
|
||||
timeout: 5
|
||||
```
|
||||
|
||||
### Advanced Drag & Drop Testing *(Phase 6 Patterns)*
|
||||
```
|
||||
# Test sortable list reordering
|
||||
web_drag_and_drop_cremotemcp:
|
||||
source: ".list-item:first-child"
|
||||
target: ".list-item:last-child"
|
||||
timeout: 10
|
||||
|
||||
# Test file upload via drag and drop
|
||||
web_drag_and_drop_coordinates_cremotemcp:
|
||||
source: ".file-item"
|
||||
x: 400
|
||||
y: 300 # Drop zone coordinates
|
||||
timeout: 15
|
||||
|
||||
# Test dashboard widget repositioning
|
||||
web_drag_and_drop_offset_cremotemcp:
|
||||
source: ".widget"
|
||||
offset_x: 200
|
||||
offset_y: 100
|
||||
timeout: 10
|
||||
```
|
||||
|
||||
## 🎉 Production Ready
|
||||
|
||||
This comprehensive web automation platform provides **31 tools** across 6 enhancement phases, optimized specifically for LLM agents and production workflows. All tools include proper error handling, timeout management, and structured responses for reliable automation.
|
||||
This comprehensive web automation platform provides **45 tools** across 7 enhancement phases, optimized specifically for LLM agents and production workflows. All tools include proper error handling, timeout management, and structured responses for reliable automation.
|
||||
|
||||
**Latest Enhancement - Phase 7**: Advanced input operations including right-click context menus, hover interactions, keyboard combinations, modifier clicks, precise mouse control, and mouse wheel scrolling for comprehensive testing of modern interactive web applications.
|
||||
|
||||
---
|
||||
|
||||
**Ready for Production**: Complete web automation platform with 31 tools, designed for maximum efficiency and reliability in LLM-driven workflows.
|
||||
**Ready for Production**: Complete web automation platform with 45 tools, designed for maximum efficiency and reliability in LLM-driven workflows.
|
||||
|
||||
201
mcp/README.md
201
mcp/README.md
@@ -611,9 +611,187 @@ Clear web storage (localStorage, sessionStorage, IndexedDB, etc.) for a tab.
|
||||
}
|
||||
```
|
||||
|
||||
#### 34. `web_drag_and_drop_cremotemcp`
|
||||
Perform drag and drop operation from source element to target element.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_drag_and_drop_cremotemcp",
|
||||
"arguments": {
|
||||
"source": ".draggable-item",
|
||||
"target": ".drop-zone",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 35. `web_drag_and_drop_coordinates_cremotemcp`
|
||||
Perform drag and drop operation from source element to specific coordinates.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_drag_and_drop_coordinates_cremotemcp",
|
||||
"arguments": {
|
||||
"source": ".draggable-item",
|
||||
"x": 300,
|
||||
"y": 200,
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 36. `web_drag_and_drop_offset_cremotemcp`
|
||||
Perform drag and drop operation from source element by relative offset.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_drag_and_drop_offset_cremotemcp",
|
||||
"arguments": {
|
||||
"source": ".draggable-item",
|
||||
"offset_x": 100,
|
||||
"offset_y": 50,
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 37. `web_right_click_cremotemcp`
|
||||
Right-click on an element to open context menus.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_right_click_cremotemcp",
|
||||
"arguments": {
|
||||
"selector": ".file-item",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 38. `web_double_click_cremotemcp`
|
||||
Double-click on an element for file operations or text selection.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_double_click_cremotemcp",
|
||||
"arguments": {
|
||||
"selector": ".file-icon",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 39. `web_hover_cremotemcp`
|
||||
Hover over an element to trigger tooltips or dropdowns.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_hover_cremotemcp",
|
||||
"arguments": {
|
||||
"selector": ".tooltip-trigger",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 40. `web_middle_click_cremotemcp`
|
||||
Middle-click on an element (typically opens links in new tabs).
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_middle_click_cremotemcp",
|
||||
"arguments": {
|
||||
"selector": "a[href='/dashboard']",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 41. `web_mouse_move_cremotemcp`
|
||||
Move mouse to specific coordinates without clicking.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_mouse_move_cremotemcp",
|
||||
"arguments": {
|
||||
"x": 400,
|
||||
"y": 300,
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 42. `web_scroll_wheel_cremotemcp`
|
||||
Scroll with mouse wheel at specific coordinates.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_scroll_wheel_cremotemcp",
|
||||
"arguments": {
|
||||
"x": 400,
|
||||
"y": 300,
|
||||
"delta_x": 0,
|
||||
"delta_y": -120,
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 43. `web_key_combination_cremotemcp`
|
||||
Send key combinations like Ctrl+C, Alt+Tab, Shift+Enter.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_key_combination_cremotemcp",
|
||||
"arguments": {
|
||||
"keys": "Ctrl+C",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 44. `web_special_key_cremotemcp`
|
||||
Send special keys like Enter, Escape, Tab, F1-F12, Arrow keys.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_special_key_cremotemcp",
|
||||
"arguments": {
|
||||
"key": "Enter",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 45. `web_modifier_click_cremotemcp`
|
||||
Click on an element with modifier keys (Ctrl+click, Shift+click).
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "web_modifier_click_cremotemcp",
|
||||
"arguments": {
|
||||
"selector": ".selectable-item",
|
||||
"modifiers": "Ctrl",
|
||||
"tab": "tab-123",
|
||||
"timeout": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎉 Complete Enhancement Summary
|
||||
|
||||
All 6 phases of the MCP enhancement plan have been successfully implemented, delivering a comprehensive web automation platform with **33 tools** organized across the following capabilities:
|
||||
All phases of the MCP enhancement plan have been successfully implemented, delivering a comprehensive web automation platform with **45 tools** organized across the following capabilities:
|
||||
|
||||
### ✅ Phase 1: Element State and Checking (2 tools)
|
||||
**Enables conditional logic without timing issues**
|
||||
@@ -657,16 +835,31 @@ All 6 phases of the MCP enhancement plan have been successfully implemented, del
|
||||
|
||||
**Benefits**: Better debugging with targeted screenshots, improved file handling workflows, automatic resource management, enhanced visual debugging capabilities.
|
||||
|
||||
### ✅ Phase 6: Browser Cache and Site Data Management (6 tools)
|
||||
**Enables comprehensive cache and site data control for testing and privacy**
|
||||
### ✅ Phase 6: Browser Cache, Site Data Management, and Drag & Drop (9 tools)
|
||||
**Enables comprehensive cache/site data control and advanced drag & drop interactions**
|
||||
- `web_disable_cache_cremotemcp`: Disable browser cache for a tab
|
||||
- `web_enable_cache_cremotemcp`: Enable browser cache for a tab
|
||||
- `web_clear_cache_cremotemcp`: Clear browser cache for a tab
|
||||
- `web_clear_all_site_data_cremotemcp`: Clear all site data (cookies, storage, cache, etc.)
|
||||
- `web_clear_cookies_cremotemcp`: Clear cookies for a tab
|
||||
- `web_clear_storage_cremotemcp`: Clear web storage (localStorage, sessionStorage, IndexedDB, etc.)
|
||||
- `web_drag_and_drop_cremotemcp`: Drag and drop between elements
|
||||
- `web_drag_and_drop_coordinates_cremotemcp`: Drag and drop to specific coordinates
|
||||
- `web_drag_and_drop_offset_cremotemcp`: Drag and drop by relative offset
|
||||
|
||||
**Benefits**: Essential for testing scenarios requiring fresh page loads, performance testing without cached resources, debugging cache-related issues, ensuring consistent test environments, privacy testing, authentication testing, and complete site data cleanup.
|
||||
### ✅ Phase 7: Advanced Input Operations (9 tools)
|
||||
**Enables sophisticated mouse and keyboard interactions for comprehensive testing**
|
||||
- `web_right_click_cremotemcp`: Right-click for context menus
|
||||
- `web_double_click_cremotemcp`: Double-click for file operations and text selection
|
||||
- `web_hover_cremotemcp`: Hover for tooltips and dropdown triggers
|
||||
- `web_middle_click_cremotemcp`: Middle-click for opening links in new tabs
|
||||
- `web_mouse_move_cremotemcp`: Precise mouse positioning without clicking
|
||||
- `web_scroll_wheel_cremotemcp`: Mouse wheel scrolling with pixel-perfect control
|
||||
- `web_key_combination_cremotemcp`: Key combinations (Ctrl+C, Alt+Tab, Shift+Enter, etc.)
|
||||
- `web_special_key_cremotemcp`: Special keys (Enter, Escape, Tab, F1-F12, Arrow keys, etc.)
|
||||
- `web_modifier_click_cremotemcp`: Modifier clicks (Ctrl+click, Shift+click for multi-selection)
|
||||
|
||||
**Benefits**: Essential for testing scenarios requiring fresh page loads, performance testing without cached resources, debugging cache-related issues, ensuring consistent test environments, privacy testing, authentication testing, complete site data cleanup, **plus advanced drag & drop testing for sortable lists, file uploads, kanban boards, dashboard widgets, and interactive UI components**. **Advanced input operations enable context menu testing, keyboard navigation accessibility testing, tooltip/dropdown interactions, multi-selection workflows, copy/paste operations, and sophisticated user interaction patterns**.
|
||||
|
||||
## Key Benefits for LLM Agents
|
||||
|
||||
|
||||
863
mcp/main.go
863
mcp/main.go
@@ -2440,6 +2440,869 @@ func main() {
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Drag and drop tools
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_drag_and_drop_cremotemcp",
|
||||
Description: "Perform drag and drop operation from source element to target element",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"source": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the source element to drag",
|
||||
},
|
||||
"target": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the target element to drop on",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"source", "target"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
// Convert arguments to map
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
source := getStringParam(params, "source", "")
|
||||
target := getStringParam(params, "target", "")
|
||||
tab := getStringParam(params, "tab", "")
|
||||
timeout := getIntParam(params, "timeout", 5)
|
||||
|
||||
if source == "" {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Error: source parameter is required"),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if target == "" {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Error: target parameter is required"),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := cremoteServer.client.DragAndDrop(tab, source, target, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Drag and drop completed successfully from %s to %s", source, target)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_drag_and_drop_coordinates_cremotemcp",
|
||||
Description: "Perform drag and drop operation from source element to specific coordinates",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"source": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the source element to drag",
|
||||
},
|
||||
"x": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Target X coordinate",
|
||||
},
|
||||
"y": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Target Y coordinate",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"source", "x", "y"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
// Convert arguments to map
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
source := getStringParam(params, "source", "")
|
||||
x := getIntParam(params, "x", 0)
|
||||
y := getIntParam(params, "y", 0)
|
||||
tab := getStringParam(params, "tab", "")
|
||||
timeout := getIntParam(params, "timeout", 5)
|
||||
|
||||
if source == "" {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Error: source parameter is required"),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := cremoteServer.client.DragAndDropToCoordinates(tab, source, x, y, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop to coordinates: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Drag and drop to coordinates (%d, %d) completed successfully from %s", x, y, source)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_drag_and_drop_offset_cremotemcp",
|
||||
Description: "Perform drag and drop operation from source element by relative offset",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"source": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the source element to drag",
|
||||
},
|
||||
"offset_x": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Horizontal offset in pixels",
|
||||
},
|
||||
"offset_y": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Vertical offset in pixels",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"source", "offset_x", "offset_y"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
// Convert arguments to map
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
source := getStringParam(params, "source", "")
|
||||
offsetX := getIntParam(params, "offset_x", 0)
|
||||
offsetY := getIntParam(params, "offset_y", 0)
|
||||
tab := getStringParam(params, "tab", "")
|
||||
timeout := getIntParam(params, "timeout", 5)
|
||||
|
||||
if source == "" {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Error: source parameter is required"),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
err := cremoteServer.client.DragAndDropByOffset(tab, source, offsetX, offsetY, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Error performing drag and drop by offset: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Drag and drop by offset (%d, %d) completed successfully from %s", offsetX, offsetY, source)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_right_click tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_right_click_cremotemcp",
|
||||
Description: "Right-click on an element",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"selector": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the element to right-click",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"selector"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
selector, ok := params["selector"].(string)
|
||||
if !ok || selector == "" {
|
||||
return nil, fmt.Errorf("selector is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.RightClick(tab, selector, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to right-click: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Right-click completed successfully"),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_double_click tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_double_click_cremotemcp",
|
||||
Description: "Double-click on an element",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"selector": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the element to double-click",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"selector"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
selector, ok := params["selector"].(string)
|
||||
if !ok || selector == "" {
|
||||
return nil, fmt.Errorf("selector is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.DoubleClick(tab, selector, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to double-click: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Double-click completed successfully"),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_hover tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_hover_cremotemcp",
|
||||
Description: "Hover over an element",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"selector": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the element to hover over",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"selector"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
selector, ok := params["selector"].(string)
|
||||
if !ok || selector == "" {
|
||||
return nil, fmt.Errorf("selector is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.Hover(tab, selector, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to hover: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Hover completed successfully"),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_middle_click tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_middle_click_cremotemcp",
|
||||
Description: "Middle-click on an element (typically opens links in new tabs)",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"selector": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the element to middle-click",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"selector"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
selector, ok := params["selector"].(string)
|
||||
if !ok || selector == "" {
|
||||
return nil, fmt.Errorf("selector is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.MiddleClick(tab, selector, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to middle-click: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent("Middle-click completed successfully"),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_mouse_move tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_mouse_move_cremotemcp",
|
||||
Description: "Move mouse to specific coordinates without clicking",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"x": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "X coordinate to move mouse to",
|
||||
},
|
||||
"y": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Y coordinate to move mouse to",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"x", "y"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
xFloat, ok := params["x"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("x coordinate is required")
|
||||
}
|
||||
x := int(xFloat)
|
||||
|
||||
yFloat, ok := params["y"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("y coordinate is required")
|
||||
}
|
||||
y := int(yFloat)
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.MouseMove(tab, x, y, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to move mouse: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Mouse moved to coordinates (%d, %d) successfully", x, y)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_scroll_wheel tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_scroll_wheel_cremotemcp",
|
||||
Description: "Scroll with mouse wheel at specific coordinates",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"x": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "X coordinate for scroll wheel",
|
||||
},
|
||||
"y": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Y coordinate for scroll wheel",
|
||||
},
|
||||
"delta_x": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Horizontal scroll delta (negative = left, positive = right)",
|
||||
"default": 0,
|
||||
},
|
||||
"delta_y": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Vertical scroll delta (negative = up, positive = down)",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"x", "y", "delta_y"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
xFloat, ok := params["x"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("x coordinate is required")
|
||||
}
|
||||
x := int(xFloat)
|
||||
|
||||
yFloat, ok := params["y"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("y coordinate is required")
|
||||
}
|
||||
y := int(yFloat)
|
||||
|
||||
deltaXFloat := float64(0)
|
||||
if deltaXParam, exists := params["delta_x"]; exists {
|
||||
if deltaXVal, ok := deltaXParam.(float64); ok {
|
||||
deltaXFloat = deltaXVal
|
||||
}
|
||||
}
|
||||
deltaX := int(deltaXFloat)
|
||||
|
||||
deltaYFloat, ok := params["delta_y"].(float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("delta_y is required")
|
||||
}
|
||||
deltaY := int(deltaYFloat)
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.ScrollWheel(tab, x, y, deltaX, deltaY, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to scroll with mouse wheel: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Mouse wheel scroll at (%d, %d) with delta (%d, %d) completed successfully", x, y, deltaX, deltaY)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_key_combination tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_key_combination_cremotemcp",
|
||||
Description: "Send key combinations like Ctrl+C, Alt+Tab, Shift+Enter, etc.",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"keys": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Key combination to send (e.g., 'Ctrl+C', 'Alt+Tab', 'Shift+Enter', 'Ctrl+Shift+T')",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"keys"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
keys, ok := params["keys"].(string)
|
||||
if !ok || keys == "" {
|
||||
return nil, fmt.Errorf("keys parameter is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.KeyCombination(tab, keys, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to send key combination: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Key combination '%s' sent successfully", keys)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_special_key tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_special_key_cremotemcp",
|
||||
Description: "Send special keys like Enter, Escape, Tab, F1-F12, Arrow keys, etc.",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"key": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Special key to send (e.g., 'Enter', 'Escape', 'Tab', 'F1', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'Delete', 'Backspace')",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"key"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
key, ok := params["key"].(string)
|
||||
if !ok || key == "" {
|
||||
return nil, fmt.Errorf("key parameter is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.SpecialKey(tab, key, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to send special key: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Special key '%s' sent successfully", key)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Register web_modifier_click tool
|
||||
mcpServer.AddTool(mcp.Tool{
|
||||
Name: "web_modifier_click_cremotemcp",
|
||||
Description: "Click on an element with modifier keys (Ctrl+click, Shift+click, Alt+click, etc.)",
|
||||
InputSchema: mcp.ToolInputSchema{
|
||||
Type: "object",
|
||||
Properties: map[string]any{
|
||||
"selector": map[string]any{
|
||||
"type": "string",
|
||||
"description": "CSS selector for the element to click",
|
||||
},
|
||||
"modifiers": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Modifier keys to hold while clicking (e.g., 'Ctrl', 'Shift', 'Alt', 'Ctrl+Shift', 'Ctrl+Alt')",
|
||||
},
|
||||
"tab": map[string]any{
|
||||
"type": "string",
|
||||
"description": "Tab ID (optional, uses current tab)",
|
||||
},
|
||||
"timeout": map[string]any{
|
||||
"type": "integer",
|
||||
"description": "Timeout in seconds (default: 5)",
|
||||
"default": 5,
|
||||
},
|
||||
},
|
||||
Required: []string{"selector", "modifiers"},
|
||||
},
|
||||
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
params, ok := request.Params.Arguments.(map[string]any)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid arguments format")
|
||||
}
|
||||
|
||||
selector, ok := params["selector"].(string)
|
||||
if !ok || selector == "" {
|
||||
return nil, fmt.Errorf("selector is required")
|
||||
}
|
||||
|
||||
modifiers, ok := params["modifiers"].(string)
|
||||
if !ok || modifiers == "" {
|
||||
return nil, fmt.Errorf("modifiers parameter is required")
|
||||
}
|
||||
|
||||
tab := ""
|
||||
if tabParam, exists := params["tab"]; exists {
|
||||
if tabStr, ok := tabParam.(string); ok {
|
||||
tab = tabStr
|
||||
}
|
||||
}
|
||||
|
||||
timeout := 5
|
||||
if timeoutParam, exists := params["timeout"]; exists {
|
||||
if timeoutFloat, ok := timeoutParam.(float64); ok {
|
||||
timeout = int(timeoutFloat)
|
||||
}
|
||||
}
|
||||
|
||||
err := cremoteServer.client.ModifierClick(tab, selector, modifiers, timeout)
|
||||
if err != nil {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Failed to perform modifier click: %v", err)),
|
||||
},
|
||||
IsError: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
mcp.NewTextContent(fmt.Sprintf("Modifier click with '%s' on %s completed successfully", modifiers, selector)),
|
||||
},
|
||||
IsError: false,
|
||||
}, nil
|
||||
})
|
||||
|
||||
// Start the server
|
||||
log.Printf("Cremote MCP server ready")
|
||||
if err := server.ServeStdio(mcpServer); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user