looking-glass-mcp 2.2.0 → 3.0.0
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/README.md +337 -219
- package/build/index.js +5723 -2536
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -2,47 +2,73 @@
|
|
|
2
2
|
<img src=".github/assets/looking-glass-logo.png" alt="Looking Glass" width="600" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<h1 align="center">Looking Glass</h1>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>The AI-native browser for agents.</strong><br/>
|
|
9
|
+
72 MCP tools. Self-healing interactions. Semantic change detection. Structured extraction. Credential vault. Enterprise-grade security. Deploy anywhere.
|
|
10
|
+
</p>
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="#quickstart">Quickstart</a> |
|
|
14
|
+
<a href="#intelligence-layer">Intelligence</a> |
|
|
15
|
+
<a href="#tools">Tools</a> |
|
|
16
|
+
<a href="#deploy-to-azure">Deploy to Azure</a> |
|
|
17
|
+
<a href="#security">Security</a> |
|
|
18
|
+
<a href="#configuration">Configuration</a>
|
|
19
|
+
</p>
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://portal.azure.com/#create/Microsoft.Template"><img src="https://aka.ms/deploytoazurebutton" alt="Deploy to Azure" /></a>
|
|
23
|
+
</p>
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
---
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
## What's New in v3.0
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
You: "Does the checkout flow work on staging?"
|
|
29
|
+
Looking Glass v3.0 transforms from a browser automation tool into an **AI-native intelligence platform**. The browser now thinks alongside the agent.
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
- **Semantic change detection** -- after every action, the browser tells you *what changed* (modal opened, form validation failed, content added), not just the raw page state
|
|
32
|
+
- **Self-healing interactions** -- every `browser_click`, `browser_type`, and `browser_hover` now has the test runner's self-healing: CSS selector fails? Automatic fallback to semantic resolution with confidence scoring
|
|
33
|
+
- **Structured data extraction** -- `browser_extract` takes a schema and returns structured JSON from tables, repeated elements, or single-entity pages
|
|
34
|
+
- **Intent-based navigation** -- `browser_go "settings page"` figures out how to get there
|
|
35
|
+
- **Semantic waiting** -- `browser_wait_for "search results loaded"` instead of guessing CSS selectors
|
|
36
|
+
- **Workflow tracking** -- every response includes page type, form progress, breadcrumbs, modal state, and step indicators
|
|
37
|
+
- **Credential vault** -- AES-256-GCM encrypted credentials with PBKDF2 key derivation and blind injection (the agent never sees passwords)
|
|
38
|
+
- **HTTP transport** -- deploy as a cloud service with `StreamableHTTPServerTransport`
|
|
39
|
+
- **Docker + Terraform** -- one-command Azure deployment with Key Vault, managed identity, and hardened security
|
|
40
|
+
- **Enterprise security** -- timing-safe auth, rate limiting, auth lockout, deep audit logging, non-root containers
|
|
28
41
|
|
|
29
42
|
---
|
|
30
43
|
|
|
31
|
-
##
|
|
44
|
+
## Quickstart
|
|
32
45
|
|
|
33
|
-
**
|
|
46
|
+
**Claude Code:**
|
|
34
47
|
|
|
35
48
|
```bash
|
|
36
49
|
claude mcp add looking-glass -- npx looking-glass-mcp
|
|
37
50
|
```
|
|
38
51
|
|
|
39
|
-
**
|
|
52
|
+
**GitHub Copilot / VS Code:**
|
|
40
53
|
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
Add to `.vscode/mcp.json`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"servers": {
|
|
59
|
+
"looking-glass": {
|
|
60
|
+
"command": "npx",
|
|
61
|
+
"args": ["looking-glass-mcp"],
|
|
62
|
+
"env": {
|
|
63
|
+
"BROWSER_HEADLESS": "false",
|
|
64
|
+
"BROWSER_SECURITY_PROFILE": "local-dev"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
43
69
|
```
|
|
44
70
|
|
|
45
|
-
**
|
|
71
|
+
**Any MCP client** via `.mcp.json`:
|
|
46
72
|
|
|
47
73
|
```json
|
|
48
74
|
{
|
|
@@ -51,292 +77,384 @@ npm install -g looking-glass-mcp
|
|
|
51
77
|
"command": "npx",
|
|
52
78
|
"args": ["looking-glass-mcp"],
|
|
53
79
|
"env": {
|
|
54
|
-
"BROWSER_HEADLESS": "false"
|
|
80
|
+
"BROWSER_HEADLESS": "false",
|
|
81
|
+
"BROWSER_SECURITY_PROFILE": "local-dev"
|
|
55
82
|
}
|
|
56
83
|
}
|
|
57
84
|
}
|
|
58
85
|
}
|
|
59
86
|
```
|
|
60
87
|
|
|
61
|
-
|
|
88
|
+
**Global install:**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install -g looking-glass-mcp
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Once connected, the agent can:
|
|
62
95
|
|
|
63
96
|
```
|
|
64
97
|
"Open localhost:3000 and tell me what you see"
|
|
98
|
+
"Extract all products from this page as JSON with name, price, and rating"
|
|
99
|
+
"Go to the settings page"
|
|
100
|
+
"Wait for the search results to load, then extract the table"
|
|
65
101
|
"Run an accessibility audit on the landing page"
|
|
66
|
-
"
|
|
67
|
-
"Explore the entire site and map all the pages"
|
|
102
|
+
"Log in with vault profile staging-admin"
|
|
68
103
|
```
|
|
69
104
|
|
|
70
105
|
---
|
|
71
106
|
|
|
72
|
-
##
|
|
107
|
+
## Intelligence Layer
|
|
73
108
|
|
|
74
|
-
|
|
109
|
+
These capabilities run **automatically** on every interaction -- no extra tool calls needed.
|
|
75
110
|
|
|
76
|
-
###
|
|
111
|
+
### Semantic Change Detection
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| `browser_go_back` / `browser_go_forward` | History navigation |
|
|
90
|
-
| `browser_tab_new` / `browser_tab_list` / `browser_tab_select` / `browser_close` | Multi-tab management |
|
|
91
|
-
|
|
92
|
-
### AI-Native Intelligence
|
|
93
|
-
|
|
94
|
-
These tools exist because an AI is the operator — they would be useless to a human.
|
|
95
|
-
|
|
96
|
-
| Tool | What it does |
|
|
97
|
-
|------|-------------|
|
|
98
|
-
| `browser_analyze_page` | Returns structured page analysis: type (login, dashboard, form, error), available actions, forms, navigation links, data elements, and page state |
|
|
99
|
-
| `browser_resolve_element` | Finds elements by natural language ("the email input", "third navigation link") with confidence scores, **visibility, enabled state, bounding box, and viewport position** |
|
|
100
|
-
| `browser_smart_click` | Click elements described in plain English instead of fragile CSS selectors. Returns page state envelope with screenshot. |
|
|
101
|
-
| `browser_suggest_actions` | Examines the page and suggests what the agent should do next, with pre-filled tool parameters (returns structured JSON) |
|
|
102
|
-
| `browser_explore` | Autonomously crawls the site within domain boundaries, classifies every page, and returns a complete site map (returns structured JSON) |
|
|
103
|
-
| `browser_wait_until_stable` | Waits for true page readiness using multiple signals: network idle, DOM settled, spinners gone, images loaded |
|
|
104
|
-
| `browser_login` | **Composite action**: navigates to login URL, auto-detects fields, fills credentials, submits, verifies redirect, reports cookies set — all in one call |
|
|
105
|
-
| `browser_fill_and_submit` | **Composite action**: fills form fields by selector or label, submits, returns before/after state with screenshot |
|
|
106
|
-
|
|
107
|
-
### Observation & Debugging
|
|
108
|
-
|
|
109
|
-
| Tool | What it does |
|
|
110
|
-
|------|-------------|
|
|
111
|
-
| `browser_screenshot` | Capture viewport or full-page screenshot (returned inline) |
|
|
112
|
-
| `browser_snapshot` | Get the full accessibility tree as structured text |
|
|
113
|
-
| `browser_evaluate` | Execute arbitrary JavaScript in page context |
|
|
114
|
-
| `browser_console_messages` | Read console logs, warnings, errors |
|
|
115
|
-
| `browser_network_requests` | Monitor all HTTP requests and responses |
|
|
116
|
-
| `browser_diagnose` | One-shot diagnostic bundle: console errors + failed requests + DOM context + screenshot |
|
|
117
|
-
| `browser_error_report` | Catalog of all uncaught JS exceptions and failed resource loads |
|
|
118
|
-
| `browser_snapshot_state` / `browser_diff_state` | Take a before/after snapshot and see exactly what changed on the page |
|
|
119
|
-
| `browser_action_history` | Full journal of every action taken: tool, args, URL before/after, new errors, duration (returns structured JSON) |
|
|
120
|
-
| `browser_clear_history` | Reset the action journal |
|
|
121
|
-
|
|
122
|
-
### Storage & State Inspection
|
|
123
|
-
|
|
124
|
-
| Tool | What it does |
|
|
125
|
-
|------|-------------|
|
|
126
|
-
| `browser_get_cookies` / `browser_set_cookie` | Read and write browser cookies |
|
|
127
|
-
| `browser_get_localstorage` / `browser_set_localstorage` | Read and write localStorage entries |
|
|
128
|
-
| `browser_clear_storage` | Clear cookies, localStorage, sessionStorage, or all at once |
|
|
129
|
-
| `browser_clean_slate` | Nuclear option: wipe cookies, localStorage, sessionStorage, IndexedDB, and Cache API |
|
|
113
|
+
After every click, type, or navigation, the response includes a `Changes Detected` section:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
--- Changes Detected ---
|
|
117
|
+
* Modal appeared: "Confirm Order"
|
|
118
|
+
* 3 table rows added
|
|
119
|
+
* Form validation: Please enter a valid email
|
|
120
|
+
* Loading completed
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The browser captures a page snapshot before and after each action, then categorizes the differences into 11 semantic change types: `url_changed`, `title_changed`, `modal_opened`, `modal_closed`, `alert_appeared`, `form_validation`, `content_added`, `content_removed`, `loading_started`, `loading_finished`, `toast_notification`.
|
|
130
124
|
|
|
131
|
-
###
|
|
125
|
+
### Self-Healing Interactions
|
|
132
126
|
|
|
133
|
-
|
|
127
|
+
Every interaction tool (`browser_click`, `browser_type`, `browser_hover`, `browser_select_option`) now uses the same resolution chain as the test runner:
|
|
128
|
+
|
|
129
|
+
1. Try the CSS selector (fast path, 2s timeout)
|
|
130
|
+
2. If it fails, resolve semantically via the accessibility tree (role, text, label, placeholder matching)
|
|
131
|
+
3. Report which strategy worked and the confidence score
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Clicked: "Submit Order" (resolved via getByRole('button', {name: 'Submit Order'}), confidence: 0.92)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
If the CSS selector failed and semantic resolution succeeded:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
Self-healed: selector "#old-btn" failed -> resolved via getByText('Submit') (confidence: 0.85)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Workflow Context
|
|
144
|
+
|
|
145
|
+
Every response includes workflow intelligence:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
--- Workflow ---
|
|
149
|
+
Page: form (populated) | Step: Payment (3/5) | Form: 2/6 filled | Required: phone, address
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Detects: page type (login, dashboard, form, listing, article, error), breadcrumbs, step indicators (wizard/stepper), form progress (filled/remaining/validation errors), active modals, and toast notifications.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Tools
|
|
157
|
+
|
|
158
|
+
Looking Glass ships with **72 tools** across 10 categories.
|
|
159
|
+
|
|
160
|
+
### Browser Control (11 tools)
|
|
161
|
+
|
|
162
|
+
| Tool | Description |
|
|
163
|
+
|------|-------------|
|
|
164
|
+
| `browser_navigate` | Navigate to a URL |
|
|
165
|
+
| `browser_click` | Click by CSS selector or text (self-healing) |
|
|
166
|
+
| `browser_type` | Fill an input field (self-healing) |
|
|
167
|
+
| `browser_hover` | Hover over an element (self-healing) |
|
|
168
|
+
| `browser_drag` | Drag and drop between elements |
|
|
169
|
+
| `browser_select_option` | Select a dropdown option (self-healing) |
|
|
170
|
+
| `browser_press_key` | Send keyboard input |
|
|
171
|
+
| `browser_scroll` | Scroll the page or to a specific element |
|
|
172
|
+
| `browser_go_back` / `browser_go_forward` | Navigate browser history |
|
|
173
|
+
| `browser_tab_*` | Multi-tab management (new, list, select, close) |
|
|
174
|
+
|
|
175
|
+
### AI Intelligence (13 tools)
|
|
176
|
+
|
|
177
|
+
| Tool | Description |
|
|
134
178
|
|------|-------------|
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
179
|
+
| `browser_analyze_page` | Structured page analysis: type, forms, navigation, actions, data elements |
|
|
180
|
+
| `browser_resolve_element` | Semantic element lookup with confidence scoring |
|
|
181
|
+
| `browser_smart_click` | Click by natural language description |
|
|
182
|
+
| `browser_suggest_actions` | Context-aware action recommendations |
|
|
183
|
+
| `browser_explore` | Autonomous site crawl with page classification |
|
|
184
|
+
| `browser_wait_until_stable` | Multi-signal page readiness detection |
|
|
185
|
+
| `browser_login` | Composite login flow with auto-detection |
|
|
186
|
+
| `browser_fill_and_submit` | Composite form fill and submit |
|
|
187
|
+
| `browser_extract` | **NEW** Schema-driven structured data extraction |
|
|
188
|
+
| `browser_go` | **NEW** Intent-based navigation ("go to settings") |
|
|
189
|
+
| `browser_wait_for` | **NEW** Semantic condition waiting ("results loaded") |
|
|
190
|
+
| `browser_workflow` | **NEW** On-demand workflow context |
|
|
191
|
+
|
|
192
|
+
### Credential Vault (5 tools)
|
|
193
|
+
|
|
194
|
+
| Tool | Description |
|
|
149
195
|
|------|-------------|
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
196
|
+
| `vault_store` | Store encrypted credential profile (AES-256-GCM + PBKDF2) |
|
|
197
|
+
| `vault_list` | List profile names and timestamps (no values) |
|
|
198
|
+
| `vault_delete` | Delete a credential profile |
|
|
199
|
+
| `vault_login` | Login using a vault profile (blind injection) |
|
|
200
|
+
| `vault_inject` | Fill form fields from vault without submitting |
|
|
153
201
|
|
|
154
|
-
###
|
|
202
|
+
### Observation & Debugging (10 tools)
|
|
155
203
|
|
|
156
|
-
|
|
157
|
-
|------|-------------|
|
|
158
|
-
| `browser_mock_route` | Intercept requests matching a URL pattern and return mock responses |
|
|
159
|
-
| `browser_list_mocks` / `browser_clear_mocks` | Manage active mock routes |
|
|
204
|
+
`browser_screenshot`, `browser_snapshot`, `browser_evaluate`, `browser_console_messages`, `browser_network_requests`, `browser_diagnose`, `browser_error_report`, `browser_snapshot_state` / `browser_diff_state`, `browser_action_history`
|
|
160
205
|
|
|
161
|
-
###
|
|
206
|
+
### Storage & State (6 tools)
|
|
162
207
|
|
|
163
|
-
|
|
164
|
-
|------|-------------|
|
|
165
|
-
| `browser_health_check` | Verify the browser is responsive |
|
|
166
|
-
| `browser_recover` | Auto-recover from crashes by relaunching and restoring the last URL |
|
|
208
|
+
`browser_get_cookies` / `browser_set_cookie`, `browser_get_localstorage` / `browser_set_localstorage`, `browser_clear_storage`, `browser_clean_slate`
|
|
167
209
|
|
|
168
|
-
|
|
210
|
+
### Test Automation (12 tools)
|
|
169
211
|
|
|
170
|
-
|
|
212
|
+
`test_scenario_run`, `test_scenario_status`, `test_assert`, `test_fill_form`, `test_auth_flow`, `test_watch_events` / `test_stop_watch`, `test_accessibility_audit`, `browser_performance_audit`, `test_generate_assertions`, `test_chaos` / `test_chaos_clear`
|
|
171
213
|
|
|
172
|
-
|
|
214
|
+
### Session & Visual (5 tools)
|
|
173
215
|
|
|
174
|
-
|
|
216
|
+
`session_start` / `session_end` / `session_list`, `session_export_playwright`, `visual_baseline` / `visual_compare`
|
|
175
217
|
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
"name": "Login Flow",
|
|
179
|
-
"steps": [
|
|
180
|
-
{ "name": "Navigate", "action": "navigate", "url": "http://localhost:3000/login" },
|
|
181
|
-
{ "name": "Enter email", "action": "type", "selector": "input[type='email']", "value": "user@test.com" },
|
|
182
|
-
{ "name": "Enter password", "action": "type", "selector": "input[type='password']", "value": "secret" },
|
|
183
|
-
{ "name": "Submit", "action": "click", "selector": "button[type='submit']" },
|
|
184
|
-
{ "name": "Verify redirect", "action": "assert", "type": "urlContains", "expected": "/dashboard" },
|
|
185
|
-
{ "name": "Capture result", "action": "screenshot", "screenshotName": "post-login" }
|
|
186
|
-
]
|
|
187
|
-
}
|
|
188
|
-
```
|
|
218
|
+
### Request Mocking (3 tools)
|
|
189
219
|
|
|
190
|
-
|
|
220
|
+
`browser_mock_route`, `browser_list_mocks`, `browser_clear_mocks`
|
|
191
221
|
|
|
192
|
-
|
|
193
|
-
{
|
|
194
|
-
"name": "Login Flow (smart)",
|
|
195
|
-
"steps": [
|
|
196
|
-
{ "name": "Navigate", "action": "navigate", "url": "http://localhost:3000/login" },
|
|
197
|
-
{ "name": "Enter email", "action": "type", "query": "email input", "value": "user@test.com" },
|
|
198
|
-
{ "name": "Enter password", "action": "type", "query": "password field", "value": "secret" },
|
|
199
|
-
{ "name": "Submit", "action": "click", "query": "sign in button" },
|
|
200
|
-
{ "name": "Verify redirect", "action": "assert", "type": "urlContains", "expected": "/dashboard" }
|
|
201
|
-
]
|
|
202
|
-
}
|
|
203
|
-
```
|
|
222
|
+
### Reliability (2 tools)
|
|
204
223
|
|
|
205
|
-
|
|
224
|
+
`browser_health_check`, `browser_recover`
|
|
206
225
|
|
|
207
|
-
|
|
226
|
+
---
|
|
208
227
|
|
|
209
|
-
|
|
210
|
-
{ "name": "Submit", "action": "click", "selector": "button.btn-login", "query": "the login button" }
|
|
211
|
-
```
|
|
228
|
+
## Deploy to Azure
|
|
212
229
|
|
|
213
|
-
|
|
230
|
+
Looking Glass can be deployed as a cloud service on Azure Container Apps with persistent sessions, encrypted credential storage, and enterprise security.
|
|
214
231
|
|
|
215
|
-
|
|
232
|
+
### Prerequisites
|
|
216
233
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
234
|
+
- [Terraform](https://terraform.io) >= 1.5
|
|
235
|
+
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/) authenticated
|
|
236
|
+
- [Docker](https://docker.com)
|
|
220
237
|
|
|
221
|
-
|
|
222
|
-
{ "name": "Fill signup", "action": "fill_form", "fields": { "Email": "test@co.com", "Name": "Jane" }, "selector": "button.submit" }
|
|
223
|
-
```
|
|
238
|
+
### Quick Deploy
|
|
224
239
|
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
|
|
240
|
+
```bash
|
|
241
|
+
# 1. Build and push the Docker image
|
|
242
|
+
cd deploy/azure
|
|
243
|
+
cp terraform.tfvars.example terraform.tfvars
|
|
244
|
+
# Edit terraform.tfvars with your API key (32+ chars required)
|
|
228
245
|
|
|
229
|
-
|
|
246
|
+
terraform init
|
|
247
|
+
terraform apply
|
|
230
248
|
|
|
231
|
-
|
|
249
|
+
# 2. Build and push the image to ACR
|
|
250
|
+
bash build-and-push.sh
|
|
232
251
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
"name": "Login with {{role}} user",
|
|
236
|
-
"steps": [
|
|
237
|
-
{ "name": "Enter email", "action": "type", "query": "email input", "value": "{{username}}" },
|
|
238
|
-
{ "name": "Enter password", "action": "type", "query": "password field", "value": "{{password}}" },
|
|
239
|
-
{ "name": "Submit", "action": "click", "query": "sign in button" },
|
|
240
|
-
{ "name": "Verify", "action": "assert", "type": "urlContains", "expected": "{{expectedUrl}}" }
|
|
241
|
-
],
|
|
242
|
-
"dataSets": [
|
|
243
|
-
{ "label": "admin", "variables": { "role": "admin", "username": "admin@co.com", "password": "Admin1!", "expectedUrl": "/dashboard" } },
|
|
244
|
-
{ "label": "viewer", "variables": { "role": "viewer", "username": "view@co.com", "password": "View1!", "expectedUrl": "/readonly" } },
|
|
245
|
-
{ "label": "invalid", "variables": { "role": "invalid", "username": "bad@co.com", "password": "wrong", "expectedUrl": "/login" } }
|
|
246
|
-
]
|
|
247
|
-
}
|
|
252
|
+
# 3. Access your instance
|
|
253
|
+
terraform output container_app_url
|
|
248
254
|
```
|
|
249
255
|
|
|
250
|
-
###
|
|
256
|
+
### What Gets Deployed
|
|
251
257
|
|
|
252
|
-
|
|
258
|
+
| Resource | Purpose |
|
|
259
|
+
|----------|---------|
|
|
260
|
+
| Azure Container Registry | Docker image storage |
|
|
261
|
+
| Azure Container Apps | Runs Looking Glass (scale-to-zero) |
|
|
262
|
+
| Azure Key Vault | Stores API key and vault encryption key |
|
|
263
|
+
| Azure Files | Persistent session data and credentials |
|
|
264
|
+
| Log Analytics | Container logs (90-day retention) |
|
|
265
|
+
| Managed Identity | Secure auth between services (no passwords) |
|
|
253
266
|
|
|
254
|
-
|
|
267
|
+
### Security Features
|
|
255
268
|
|
|
256
|
-
**
|
|
269
|
+
- **HTTPS** -- Azure Container Apps provides automatic TLS termination
|
|
270
|
+
- **API key required** -- 32+ character key, stored in Key Vault
|
|
271
|
+
- **Managed Identity** -- ACR pull and Key Vault access without stored credentials
|
|
272
|
+
- **Non-root container** -- Runs as unprivileged `lglass` user
|
|
273
|
+
- **Rate limiting** -- 120 req/min per IP, auth lockout after 5 failures
|
|
274
|
+
- **Audit logging** -- Every tool call, auth event, and session lifecycle logged
|
|
257
275
|
|
|
258
|
-
|
|
276
|
+
### Docker (standalone)
|
|
259
277
|
|
|
260
|
-
|
|
278
|
+
```bash
|
|
279
|
+
docker build -t looking-glass .
|
|
280
|
+
docker run -p 8080:8080 \
|
|
281
|
+
-e MCP_API_KEY=your-secret-key-at-least-32-chars \
|
|
282
|
+
-v looking-glass-data:/data \
|
|
283
|
+
looking-glass
|
|
284
|
+
```
|
|
261
285
|
|
|
262
|
-
|
|
286
|
+
---
|
|
263
287
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
| `BROWSER_ENGINE` | `chromium` | Browser engine: `chromium`, `firefox`, or `webkit` |
|
|
268
|
-
| `BROWSER_VIEWPORT_WIDTH` | `1280` | Viewport width in pixels |
|
|
269
|
-
| `BROWSER_VIEWPORT_HEIGHT` | `720` | Viewport height in pixels |
|
|
270
|
-
| `BROWSER_TIMEOUT` | `30000` | Default operation timeout (ms) |
|
|
271
|
-
| `BROWSER_SESSIONS_DIR` | `.browser-sessions` | Where screenshots, sessions, and audit logs are stored |
|
|
272
|
-
| `BROWSER_SECURITY_PROFILE` | `local-dev` | Security profile (see below) |
|
|
273
|
-
| `BROWSER_CHANNEL` | — | Specific browser channel (`chrome`, `msedge`) |
|
|
274
|
-
| `BROWSER_PROXY_URL` | — | HTTP/HTTPS/SOCKS5 proxy for corporate environments |
|
|
275
|
-
| `BROWSER_CA_CERT_PATH` | — | Path to custom CA certificate |
|
|
288
|
+
## Security
|
|
289
|
+
|
|
290
|
+
See [SECURITY.md](SECURITY.md) for the full security model.
|
|
276
291
|
|
|
277
292
|
### Security Profiles
|
|
278
293
|
|
|
279
294
|
| Profile | URL Access | JS Execution | Tool Access | Rate Limit |
|
|
280
295
|
|---------|-----------|--------------|-------------|------------|
|
|
296
|
+
| `restricted` (default) | localhost only | Blocked | Observation only | 30/min |
|
|
281
297
|
| `local-dev` | All HTTP/HTTPS | Allowed | All tools | 60/min |
|
|
282
|
-
| `restricted` | localhost only | Blocked | Observation only | 30/min |
|
|
283
298
|
| `open` | Everything | Allowed | All tools | 120/min |
|
|
299
|
+
| `sandbox` | Blocked | Blocked | Observation only | 10/min |
|
|
300
|
+
|
|
301
|
+
### HTTP Transport Security
|
|
302
|
+
|
|
303
|
+
- API key **required** in HTTP mode (server exits if unset)
|
|
304
|
+
- Timing-safe key comparison (no side-channel leakage)
|
|
305
|
+
- Per-IP rate limiting with auth failure lockout (5 failures = 60s ban)
|
|
306
|
+
- Session IDs via cryptographic `randomUUID()`
|
|
307
|
+
|
|
308
|
+
### Credential Vault
|
|
309
|
+
|
|
310
|
+
- AES-256-GCM encryption with PBKDF2 key derivation (100k iterations, SHA-512)
|
|
311
|
+
- Field names and values encrypted together (no metadata leakage)
|
|
312
|
+
- Vault file permissions restricted to owner (`0600`)
|
|
313
|
+
- Agent never sees plaintext credentials -- blind injection only
|
|
314
|
+
- `createdAt` and `lastUsedAt` tracking per profile
|
|
284
315
|
|
|
285
|
-
|
|
316
|
+
### Audit Trail
|
|
317
|
+
|
|
318
|
+
Every operation is logged to `audit/audit-YYYY-MM-DD.jsonl`:
|
|
319
|
+
- Tool calls with deep-redacted arguments
|
|
320
|
+
- Auth successes and failures (with client IP)
|
|
321
|
+
- Session start/end events
|
|
322
|
+
- Policy violations
|
|
323
|
+
- 20+ sensitive field patterns redacted recursively
|
|
286
324
|
|
|
287
325
|
---
|
|
288
326
|
|
|
289
|
-
##
|
|
327
|
+
## Configuration
|
|
290
328
|
|
|
291
|
-
|
|
292
|
-
graph TD
|
|
293
|
-
A[Claude Code] -->|MCP stdio| B[Looking Glass]
|
|
294
|
-
B -->|Playwright API| C[Browser Engine]
|
|
295
|
-
C -->|Screenshots + DOM| B
|
|
296
|
-
B -->|Inline images + text| A
|
|
329
|
+
All configuration is through environment variables.
|
|
297
330
|
|
|
298
|
-
|
|
299
|
-
D --> E[Audit Logger]
|
|
300
|
-
D --> F[RBAC Policy]
|
|
331
|
+
### Browser
|
|
301
332
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
333
|
+
| Variable | Default | Description |
|
|
334
|
+
|----------|---------|-------------|
|
|
335
|
+
| `BROWSER_HEADLESS` | `true` | Set to `false` to display the browser window |
|
|
336
|
+
| `BROWSER_ENGINE` | `chromium` | `chromium`, `firefox`, or `webkit` |
|
|
337
|
+
| `BROWSER_VIEWPORT_WIDTH` | `1280` | Viewport width in pixels |
|
|
338
|
+
| `BROWSER_VIEWPORT_HEIGHT` | `720` | Viewport height in pixels |
|
|
339
|
+
| `BROWSER_TIMEOUT` | `30000` | Default operation timeout (ms) |
|
|
340
|
+
| `BROWSER_SESSIONS_DIR` | `.browser-sessions` | Directory for data storage |
|
|
341
|
+
| `BROWSER_SECURITY_PROFILE` | `restricted` | Security profile |
|
|
342
|
+
| `BROWSER_CHANNEL` | | Browser channel (`chrome`, `msedge`) |
|
|
343
|
+
| `BROWSER_ENGINE` | `chromium` | Browser engine |
|
|
344
|
+
| `BROWSER_PROXY_URL` | | HTTP/HTTPS/SOCKS5 proxy |
|
|
345
|
+
| `BROWSER_VISUAL_THRESHOLD` | `0.1` | Pixel comparison threshold (increase for Firefox/WebKit) |
|
|
346
|
+
| `BROWSER_PERSISTENT_CONTEXT` | `false` | Persist cookies/localStorage across restarts |
|
|
347
|
+
| `BROWSER_USER_DATA_DIR` | `.browser-data` | User data directory for persistent context |
|
|
348
|
+
|
|
349
|
+
### Transport
|
|
350
|
+
|
|
351
|
+
| Variable | Default | Description |
|
|
352
|
+
|----------|---------|-------------|
|
|
353
|
+
| `MCP_TRANSPORT` | `stdio` | `stdio` (local) or `http` (cloud) |
|
|
354
|
+
| `MCP_HTTP_PORT` | `8080` | HTTP server port |
|
|
355
|
+
| `MCP_API_KEY` | | **Required in HTTP mode.** Minimum 32 characters. |
|
|
305
356
|
|
|
306
|
-
|
|
357
|
+
### Vault
|
|
358
|
+
|
|
359
|
+
| Variable | Default | Description |
|
|
360
|
+
|----------|---------|-------------|
|
|
361
|
+
| `VAULT_ENCRYPTION_KEY` | | Passphrase for credential encryption (32+ chars). Key derived via PBKDF2. |
|
|
307
362
|
|
|
308
363
|
---
|
|
309
364
|
|
|
310
|
-
##
|
|
365
|
+
## Test Scenarios
|
|
366
|
+
|
|
367
|
+
`test_scenario_run` executes multi-step test flows defined in JSON with three targeting strategies:
|
|
311
368
|
|
|
312
|
-
|
|
369
|
+
- **`selector`** -- CSS selectors (fast, exact)
|
|
370
|
+
- **`query`** -- natural language resolution via accessibility tree (resilient to DOM changes)
|
|
371
|
+
- **Both** -- self-healing: selector tried first, query as fallback
|
|
313
372
|
|
|
314
|
-
|
|
373
|
+
### Example: Self-Healing Login
|
|
315
374
|
|
|
375
|
+
```json
|
|
376
|
+
{
|
|
377
|
+
"name": "Login Flow",
|
|
378
|
+
"steps": [
|
|
379
|
+
{ "name": "Navigate", "action": "navigate", "url": "http://localhost:3000/login" },
|
|
380
|
+
{ "name": "Email", "action": "type", "selector": "input[type='email']", "query": "email input", "value": "user@test.com" },
|
|
381
|
+
{ "name": "Password", "action": "type", "selector": "input[type='password']", "query": "password field", "value": "secret" },
|
|
382
|
+
{ "name": "Submit", "action": "click", "selector": "button[type='submit']", "query": "sign in button" },
|
|
383
|
+
{ "name": "Verify", "action": "assert", "type": "urlContains", "expected": "/dashboard" }
|
|
384
|
+
]
|
|
385
|
+
}
|
|
316
386
|
```
|
|
317
|
-
|
|
387
|
+
|
|
388
|
+
### Data-Driven Testing
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"name": "Login as {{role}}",
|
|
393
|
+
"steps": [
|
|
394
|
+
{ "name": "Email", "action": "type", "query": "email input", "value": "{{username}}" },
|
|
395
|
+
{ "name": "Password", "action": "type", "query": "password field", "value": "{{password}}" },
|
|
396
|
+
{ "name": "Submit", "action": "click", "query": "sign in button" },
|
|
397
|
+
{ "name": "Verify", "action": "assert", "type": "urlContains", "expected": "{{expectedUrl}}" }
|
|
398
|
+
],
|
|
399
|
+
"dataSets": [
|
|
400
|
+
{ "label": "admin", "variables": { "role": "admin", "username": "admin@co.com", "password": "Admin1!", "expectedUrl": "/dashboard" } },
|
|
401
|
+
{ "label": "viewer", "variables": { "role": "viewer", "username": "view@co.com", "password": "View1!", "expectedUrl": "/readonly" } }
|
|
402
|
+
]
|
|
403
|
+
}
|
|
318
404
|
```
|
|
319
405
|
|
|
320
|
-
|
|
406
|
+
**18 step actions:** `navigate`, `click`, `type`, `select`, `hover`, `scroll`, `press`, `waitForSelector`, `waitForText`, `waitForNavigation`, `waitForNetworkIdle`, `assert`, `screenshot`, `evaluate`, `sleep`, `login`, `fill_form`, `wait_stable`
|
|
321
407
|
|
|
322
|
-
|
|
408
|
+
**12 assertion types:** `exists`, `notExists`, `textContains`, `textEquals`, `hasAttribute`, `hasClass`, `isVisible`, `isEnabled`, `urlContains`, `urlEquals`, `countEquals`, `consoleNoErrors`
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Architecture
|
|
323
413
|
|
|
324
414
|
```
|
|
325
|
-
|
|
415
|
+
MCP Client (Claude, Copilot, etc.)
|
|
416
|
+
|
|
|
417
|
+
| stdio or HTTP (StreamableHTTP)
|
|
418
|
+
v
|
|
419
|
+
+-------------------------------------------+
|
|
420
|
+
| Looking Glass v3.0 |
|
|
421
|
+
| |
|
|
422
|
+
| Middleware Layer (automatic) |
|
|
423
|
+
| - Change Detection (pre/post snapshot) |
|
|
424
|
+
| - Workflow Tracking (page state machine) |
|
|
425
|
+
| - Self-Healing Resolution |
|
|
426
|
+
| - Audit Logging (deep redaction) |
|
|
427
|
+
| - RBAC Policy Enforcement |
|
|
428
|
+
| |
|
|
429
|
+
| 72 Tools |
|
|
430
|
+
| - Intelligence (extract, go, wait_for) |
|
|
431
|
+
| - Interaction (click, type, hover) |
|
|
432
|
+
| - Observation (screenshot, snapshot) |
|
|
433
|
+
| - Testing (scenarios, assertions) |
|
|
434
|
+
| - Vault (store, inject, login) |
|
|
435
|
+
| |
|
|
436
|
+
| Browser Manager |
|
|
437
|
+
| - Playwright (Chromium/Firefox/WebKit) |
|
|
438
|
+
| - Persistent context (optional) |
|
|
439
|
+
| - Console/network tracking |
|
|
440
|
+
+-------------------------------------------+
|
|
441
|
+
|
|
|
442
|
+
| Playwright API
|
|
443
|
+
v
|
|
444
|
+
Browser Engine
|
|
326
445
|
```
|
|
327
446
|
|
|
328
|
-
It will navigate, screenshot, discover pages, run assertions, check for JS errors, audit accessibility, and generate a pass/fail report.
|
|
329
|
-
|
|
330
447
|
---
|
|
331
448
|
|
|
332
449
|
## Development
|
|
333
450
|
|
|
334
451
|
```bash
|
|
335
|
-
git clone
|
|
336
|
-
cd
|
|
452
|
+
git clone https://github.com/Sahib-Sawhney-WH/LookingGlass.git
|
|
453
|
+
cd LookingGlass
|
|
337
454
|
npm install
|
|
338
455
|
npx playwright install chromium
|
|
339
456
|
npm run build
|
|
457
|
+
npm test
|
|
340
458
|
npm start
|
|
341
459
|
```
|
|
342
460
|
|