opera-browser-cli 0.1.27
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/LICENSE +21 -0
- package/README.md +316 -0
- package/SKILL.md +19 -0
- package/dist/bin/opera-browser-cli-bridge.d.ts +2 -0
- package/dist/bin/opera-browser-cli-bridge.js +7 -0
- package/dist/bin/opera-browser-cli-bridge.js.map +1 -0
- package/dist/bin/opera-browser-cli.d.ts +2 -0
- package/dist/bin/opera-browser-cli.js +4 -0
- package/dist/bin/opera-browser-cli.js.map +1 -0
- package/dist/bin/opera-cli-bridge.d.ts +2 -0
- package/dist/bin/opera-cli-bridge.js +7 -0
- package/dist/bin/opera-cli-bridge.js.map +1 -0
- package/dist/bin/opera-cli.d.ts +2 -0
- package/dist/bin/opera-cli.js +4 -0
- package/dist/bin/opera-cli.js.map +1 -0
- package/dist/src/bridge.d.ts +58 -0
- package/dist/src/bridge.js +379 -0
- package/dist/src/bridge.js.map +1 -0
- package/dist/src/cli.d.ts +74 -0
- package/dist/src/cli.js +2051 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/client.d.ts +48 -0
- package/dist/src/client.js +377 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/hooks.d.ts +45 -0
- package/dist/src/hooks.js +62 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/run.d.ts +35 -0
- package/dist/src/run.js +226 -0
- package/dist/src/run.js.map +1 -0
- package/dist/src/snapshot.d.ts +20 -0
- package/dist/src/snapshot.js +69 -0
- package/dist/src/snapshot.js.map +1 -0
- package/dist/src/suggestions.d.ts +6 -0
- package/dist/src/suggestions.js +51 -0
- package/dist/src/suggestions.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kun Chen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
<h1 align="center">opera-browser-cli</h1>
|
|
2
|
+
|
|
3
|
+
<h3 align="center">The most agent-ergonomic browser automation</h3>
|
|
4
|
+
|
|
5
|
+
`opera-browser-cli` is a fork of [chrome-devtools-axi](https://github.com/kunchenguid/chrome-devtools-axi).
|
|
6
|
+
It wraps [opera-devtools-mcp](https://github.com/operasoftware/opera-devtools-mcp) with an [AXI](https://axi.md)-compliant CLI.
|
|
7
|
+
|
|
8
|
+
- **Token-efficient** — TOON-encoded output cuts token usage ~40% vs raw JSON
|
|
9
|
+
- **Combined operations** — one command navigates, captures, and suggests next steps
|
|
10
|
+
- **Contextual suggestions** — every response includes actionable next-step hints
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
$ opera-browser-cli open https://example.com
|
|
16
|
+
page: {title: "Example Domain", url: "https://example.com", refs: 1}
|
|
17
|
+
snapshot:
|
|
18
|
+
RootWebArea "Example Domain"
|
|
19
|
+
heading "Example Domain"
|
|
20
|
+
paragraph "This domain is for use in illustrative examples..."
|
|
21
|
+
uid=1 link "More information..."
|
|
22
|
+
help[1]:
|
|
23
|
+
Run `opera-browser-cli click @1` to click the "More information..." link
|
|
24
|
+
|
|
25
|
+
$ opera-browser-cli click @1
|
|
26
|
+
page: {title: "IANA — IANA-Managed Reserved Domains", refs: 12}
|
|
27
|
+
snapshot:
|
|
28
|
+
...
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
Prerequisites: **Node.js >= 20**, **Opera** browser ([Opera Neon](https://www.operaneon.com) recommended for AI features), **[opera-devtools-mcp](https://github.com/operasoftware/opera-devtools-mcp)**.
|
|
34
|
+
|
|
35
|
+
### From source
|
|
36
|
+
|
|
37
|
+
**1. Build and link `opera-devtools-mcp`:**
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
git clone https://github.com/operasoftware/opera-devtools-mcp
|
|
41
|
+
cd opera-devtools-mcp
|
|
42
|
+
npm install && npm run build && npm link
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**2. Build and link `opera-browser-cli`:**
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
# in this repo
|
|
49
|
+
npm install && npm run build && npm link
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**3. Run first-time setup:**
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
opera-browser-cli setup
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This detects Opera installations, lets you pick one, saves configuration to `~/.opera-browser-cli/config`, and installs the Claude Code skill to `~/.claude/skills/opera-browser-cli/SKILL.md`.
|
|
59
|
+
|
|
60
|
+
Verify:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
opera-browser-cli --version
|
|
64
|
+
opera-browser-cli open https://example.com
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Usage examples
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
# Basic navigation
|
|
71
|
+
opera-browser-cli open https://example.com
|
|
72
|
+
|
|
73
|
+
# Use Opera as the browser
|
|
74
|
+
OPERA_CLI_EXECUTABLE_PATH="/Applications/Opera.app/Contents/MacOS/Opera" \
|
|
75
|
+
opera-browser-cli open https://example.com
|
|
76
|
+
|
|
77
|
+
# Headed mode (visible browser window)
|
|
78
|
+
OPERA_CLI_HEADED=1 opera-browser-cli open https://example.com
|
|
79
|
+
|
|
80
|
+
# Persistent profile (stay logged in across sessions)
|
|
81
|
+
OPERA_CLI_USER_DATA_DIR=~/.opera-profile opera-browser-cli open https://example.com
|
|
82
|
+
|
|
83
|
+
# Connect to already-running browser
|
|
84
|
+
OPERA_CLI_BROWSER_URL=http://127.0.0.1:9222 opera-browser-cli open https://example.com
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## How It Works
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
┌───────────────────────┐
|
|
91
|
+
│ opera-browser-cli │ CLI — parse args, format output
|
|
92
|
+
└──────────┬────────────┘
|
|
93
|
+
│ HTTP (localhost:9224)
|
|
94
|
+
▼
|
|
95
|
+
┌───────────────────────┐
|
|
96
|
+
│ Bridge Server │ Persistent process, manages MCP session
|
|
97
|
+
└──────────┬────────────┘
|
|
98
|
+
│ stdio
|
|
99
|
+
▼
|
|
100
|
+
┌───────────────────────┐
|
|
101
|
+
│ opera-devtools-mcp │ Headless Chrome via DevTools Protocol
|
|
102
|
+
└───────────────────────┘
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- **Persistent bridge** — a detached process keeps the MCP session alive across commands, so Chrome doesn't restart every invocation
|
|
106
|
+
- **Auto-lifecycle** — the bridge starts on first command and writes a PID file to `~/.opera-browser-cli/bridge.pid`
|
|
107
|
+
- **Snapshot parsing** — accessibility tree snapshots are extracted and analyzed for interactive elements (`uid=` refs)
|
|
108
|
+
- **TOON encoding** — structured metadata uses [TOON format](https://www.npmjs.com/package/@toon-format/toon) for compact, token-efficient output
|
|
109
|
+
|
|
110
|
+
## CLI Reference
|
|
111
|
+
|
|
112
|
+
### Navigation
|
|
113
|
+
|
|
114
|
+
| Command | Description |
|
|
115
|
+
| ----------------- | -------------------------------------------- |
|
|
116
|
+
| `open <url>` | Navigate to URL and snapshot |
|
|
117
|
+
| `snapshot` | Capture current page state |
|
|
118
|
+
| `screenshot <p>` | Save a screenshot to a file |
|
|
119
|
+
| `scroll <dir>` | Scroll: up, down, top, bottom |
|
|
120
|
+
| `back` | Navigate back |
|
|
121
|
+
| `wait <ms\|text>` | Wait for time or text to appear |
|
|
122
|
+
| `eval <js>` | Evaluate a JavaScript expression or function |
|
|
123
|
+
| `run` | Execute a multi-step script from stdin |
|
|
124
|
+
|
|
125
|
+
`eval` wraps plain input as `() => (<expr>)` before sending it to DevTools. For multi-statement logic, pass an arrow function, `function`, or IIFE yourself.
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
opera-browser-cli eval "document.title"
|
|
129
|
+
opera-browser-cli eval "(() => { const rows = [...document.querySelectorAll('tr')]; return rows.map((row) => row.textContent) })()"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Interaction
|
|
133
|
+
|
|
134
|
+
| Command | Description |
|
|
135
|
+
| -------------------------- | ------------------------------ |
|
|
136
|
+
| `click @<uid>` | Click an element by ref |
|
|
137
|
+
| `fill @<uid> <text>` | Fill a form field |
|
|
138
|
+
| `type <text>` | Type text at current focus |
|
|
139
|
+
| `press <key>` | Press a keyboard key |
|
|
140
|
+
| `hover @<uid>` | Hover over an element |
|
|
141
|
+
| `drag @<from> @<to>` | Drag an element onto another |
|
|
142
|
+
| `fillform @<uid>=<val>...` | Fill multiple form fields |
|
|
143
|
+
| `dialog <accept\|dismiss>` | Handle a browser dialog |
|
|
144
|
+
| `upload @<uid> <path>` | Upload a file through an input |
|
|
145
|
+
|
|
146
|
+
### Page Management
|
|
147
|
+
|
|
148
|
+
| Command | Description |
|
|
149
|
+
| ----------------- | --------------------------- |
|
|
150
|
+
| `pages` | List all open tabs |
|
|
151
|
+
| `newpage <url>` | Open a new tab |
|
|
152
|
+
| `selectpage <id>` | Switch to a tab by ID |
|
|
153
|
+
| `closepage <id>` | Close a tab by ID |
|
|
154
|
+
| `resize <w> <h>` | Resize the browser viewport |
|
|
155
|
+
|
|
156
|
+
### Emulation
|
|
157
|
+
|
|
158
|
+
| Command | Description |
|
|
159
|
+
| --------- | ------------------------------- |
|
|
160
|
+
| `emulate` | Emulate device/network/viewport |
|
|
161
|
+
|
|
162
|
+
### DevTools Debugging
|
|
163
|
+
|
|
164
|
+
| Command | Description |
|
|
165
|
+
| ------------------ | ------------------------------ |
|
|
166
|
+
| `console` | List console messages |
|
|
167
|
+
| `console-get <id>` | Get a specific console message |
|
|
168
|
+
| `network` | List network requests |
|
|
169
|
+
| `network-get [id]` | Get a specific network request |
|
|
170
|
+
|
|
171
|
+
### Performance
|
|
172
|
+
|
|
173
|
+
| Command | Description |
|
|
174
|
+
| --------------------------- | ----------------------------- |
|
|
175
|
+
| `lighthouse` | Run a Lighthouse audit |
|
|
176
|
+
| `perf-start` | Start a performance trace |
|
|
177
|
+
| `perf-stop` | Stop the performance trace |
|
|
178
|
+
| `perf-insight <set> <name>` | Analyze a performance insight |
|
|
179
|
+
| `heap <path>` | Capture a heap snapshot |
|
|
180
|
+
|
|
181
|
+
### Opera AI
|
|
182
|
+
|
|
183
|
+
Requires Opera Neon with an active Opera account.
|
|
184
|
+
|
|
185
|
+
| Command | Description |
|
|
186
|
+
| ------------------- | --------------------------------------------- |
|
|
187
|
+
| `chat <prompt>` | Send a chat message to Opera's built-in AI |
|
|
188
|
+
| `invoke-do <prompt>`| Ask the AI to perform a complex browsing task |
|
|
189
|
+
| `make <prompt>` | Ask the AI to build a webpage or app |
|
|
190
|
+
| `research <prompt>` | Ask the AI to research a topic in depth |
|
|
191
|
+
|
|
192
|
+
`research` accepts `--type local` (default), `--type one-minute`, or `--type deep`.
|
|
193
|
+
|
|
194
|
+
### Configuration
|
|
195
|
+
|
|
196
|
+
| Command | Description |
|
|
197
|
+
| -------- | ------------------------------------------------ |
|
|
198
|
+
| `setup` | Interactive first-time setup (browser path, etc) |
|
|
199
|
+
| `doctor` | Check configuration and environment |
|
|
200
|
+
| `logs` | Show bridge server logs |
|
|
201
|
+
|
|
202
|
+
### Bridge
|
|
203
|
+
|
|
204
|
+
| Command | Description |
|
|
205
|
+
| ------- | ----------------------- |
|
|
206
|
+
| `start` | Start the bridge server |
|
|
207
|
+
| `stop` | Stop the bridge server |
|
|
208
|
+
|
|
209
|
+
Running with no command shows the CLI home view. It prepends `bin` and
|
|
210
|
+
`description` metadata, then includes the current snapshot when a browser
|
|
211
|
+
session is active or the no-session status/help block when one is not.
|
|
212
|
+
|
|
213
|
+
### Flags
|
|
214
|
+
|
|
215
|
+
| Flag | Description |
|
|
216
|
+
| --------------------------- | ------------------------------------------- |
|
|
217
|
+
| `--help` | Show usage information |
|
|
218
|
+
| `-v`, `-V`, `--version` | Show the installed CLI version |
|
|
219
|
+
| `--full` | Show complete output without truncation |
|
|
220
|
+
| `--background` | Open new page in background (newpage) |
|
|
221
|
+
| `--uid @<uid>` | Target a specific element (screenshot) |
|
|
222
|
+
| `--full-page` | Capture entire scrollable page (screenshot) |
|
|
223
|
+
| `--format <fmt>` | Image format: png, jpeg, webp (screenshot) |
|
|
224
|
+
| `--viewport <spec>` | Viewport like "390x844x3,mobile" (emulate) |
|
|
225
|
+
| `--color-scheme <value>` | dark, light, or auto (emulate) |
|
|
226
|
+
| `--network <condition>` | Network throttle: Slow 3G, etc. (emulate) |
|
|
227
|
+
| `--cpu <rate>` | CPU throttling rate 1-20 (emulate) |
|
|
228
|
+
| `--geolocation <lat>x<lon>` | Set geolocation (emulate) |
|
|
229
|
+
| `--user-agent <string>` | Custom user agent (emulate) |
|
|
230
|
+
| `--type <type>` | Filter by type (console, network) |
|
|
231
|
+
| `--limit <n>` | Max items to return (console, network) |
|
|
232
|
+
| `--page <n>` | Pagination (console, network) |
|
|
233
|
+
| `--device <device>` | desktop or mobile (lighthouse) |
|
|
234
|
+
| `--mode <mode>` | navigation or snapshot (lighthouse) |
|
|
235
|
+
| `--output-dir <path>` | Directory for reports (lighthouse) |
|
|
236
|
+
| `--no-reload` | Skip page reload (perf-start) |
|
|
237
|
+
| `--no-auto-stop` | Disable auto-stop (perf-start) |
|
|
238
|
+
| `--file <path>` | Save trace data to file (perf-start/stop) |
|
|
239
|
+
| `--response-file <path>` | Save response body (network-get) |
|
|
240
|
+
| `--request-file <path>` | Save request body (network-get) |
|
|
241
|
+
|
|
242
|
+
## Configuration
|
|
243
|
+
|
|
244
|
+
| Variable | Default | Purpose |
|
|
245
|
+
| --- | --- | --- |
|
|
246
|
+
| `OPERA_CLI_PORT` | `9224` | Bridge server port |
|
|
247
|
+
| `OPERA_CLI_MCP_BIN` | `opera-devtools-mcp` | MCP server binary |
|
|
248
|
+
| `OPERA_CLI_EXECUTABLE_PATH` | _(system Chrome)_ | Custom browser binary |
|
|
249
|
+
| `OPERA_CLI_BROWSER_URL` | — | Connect to an existing browser instance instead of launching one |
|
|
250
|
+
| `OPERA_CLI_USER_DATA_DIR` | — | Persistent Chrome profile directory (skips isolated mode) |
|
|
251
|
+
| `OPERA_CLI_HEADED` | — | Set to `1` to run in headed (visible) mode |
|
|
252
|
+
| `OPERA_CLI_CHROME_ARGS` | — | Extra Chrome flags, space-separated |
|
|
253
|
+
| `OPERA_CLI_DISABLE_HOOKS` | — | Set to `1` to skip auto-installing session hooks |
|
|
254
|
+
|
|
255
|
+
State is stored in `~/.opera-browser-cli/`:
|
|
256
|
+
|
|
257
|
+
| File | Purpose |
|
|
258
|
+
| ------------ | ---------------------------------- |
|
|
259
|
+
| `bridge.pid` | PID and port of the running bridge |
|
|
260
|
+
|
|
261
|
+
### Session Hooks
|
|
262
|
+
|
|
263
|
+
On supported agents, the packaged CLI also installs a `SessionStart` hook in `~/.claude/settings.json` and `~/.codex/hooks.json`, and enables `codex_hooks` in `~/.codex/config.toml`.
|
|
264
|
+
|
|
265
|
+
Set `OPERA_CLI_DISABLE_HOOKS=1` to skip that auto-install behavior.
|
|
266
|
+
|
|
267
|
+
Development entrypoints such as `npm run dev` and `bin/opera-browser-cli.ts` do not modify those hook files.
|
|
268
|
+
|
|
269
|
+
## Local Setup (Full Stack)
|
|
270
|
+
|
|
271
|
+
Both `opera-devtools-mcp` and `opera-browser-cli` need to be built and linked so they're available in PATH.
|
|
272
|
+
|
|
273
|
+
**1. Build and link `opera-devtools-mcp`:**
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
# in the opera-devtools-mcp repo
|
|
277
|
+
npm install
|
|
278
|
+
npm run build
|
|
279
|
+
npm link
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**2. Build and link `opera-browser-cli`:**
|
|
283
|
+
|
|
284
|
+
```sh
|
|
285
|
+
# in this repo
|
|
286
|
+
npm install
|
|
287
|
+
npm run build
|
|
288
|
+
npm link
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**3. Set the browser executable path:**
|
|
292
|
+
|
|
293
|
+
```sh
|
|
294
|
+
export OPERA_CLI_EXECUTABLE_PATH="/Applications/Opera Neon Developer.app/Contents/MacOS/Opera"
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Tip:** Set `OPERA_CLI_MCP_BIN` to point to the locally linked `opera-devtools-mcp`:
|
|
298
|
+
|
|
299
|
+
```sh
|
|
300
|
+
export OPERA_CLI_MCP_BIN=opera-devtools-mcp
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Tip:** Set `OPERA_CLI_HEADED=1` to launch the browser in headed (visible) mode — useful during development to watch what's happening:
|
|
304
|
+
|
|
305
|
+
```sh
|
|
306
|
+
export OPERA_CLI_HEADED=1
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Development
|
|
310
|
+
|
|
311
|
+
```sh
|
|
312
|
+
npm run build # Compile TypeScript to dist/
|
|
313
|
+
npm run dev # Run CLI directly with tsx
|
|
314
|
+
npm test # Run tests with vitest
|
|
315
|
+
npm run test:watch # Run tests in watch mode
|
|
316
|
+
```
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opera-browser-cli
|
|
3
|
+
description: Browser automation and web interaction using the opera-browser-cli tool. Use for navigating pages, clicking elements, filling forms, taking screenshots, inspecting console/network, running performance audits, and Opera Neon AI features (chat, invoke-do, make, research) when Opera Neon is the active browser.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: opera-browser-cli Browser Automation
|
|
7
|
+
|
|
8
|
+
`opera-browser-cli` controls a Opera browser browser session.
|
|
9
|
+
|
|
10
|
+
- **Standard commands** (`open`, `click`, `fill`, `screenshot`, etc.) — work with any Opera browser session.
|
|
11
|
+
- **Opera AI commands** (`chat`, `invoke-do`, `make`, `research`) — require **Opera Neon** with an active sign-in.
|
|
12
|
+
|
|
13
|
+
Run `opera-browser-cli --help` for the full command list, or `opera-browser-cli <command> --help` for per-command flags and examples.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
opera-browser-cli open https://example.com # start here — navigate and snapshot the page
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If a user hits `Opera Neon: user is not signed in` or wants to use AI commands, suggest they run `opera-browser-cli setup` (interactive wizard) and sign in to Opera Neon. Run `opera-browser-cli doctor` to diagnose configuration issues.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { getErrorMessage, runBridge } from "../src/bridge.js";
|
|
3
|
+
runBridge().catch((error) => {
|
|
4
|
+
process.stderr.write(`[opera-browser-cli] Fatal: ${getErrorMessage(error)}\n`);
|
|
5
|
+
process.exit(1);
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=opera-browser-cli-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opera-browser-cli-bridge.js","sourceRoot":"","sources":["../../bin/opera-browser-cli-bridge.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE9D,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opera-browser-cli.js","sourceRoot":"","sources":["../../bin/opera-browser-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opera-cli-bridge.js","sourceRoot":"","sources":["../../bin/opera-cli-bridge.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE9D,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opera-cli.js","sourceRoot":"","sources":["../../bin/opera-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent MCP bridge server for opera-browser-cli.
|
|
3
|
+
*
|
|
4
|
+
* Spawns opera-devtools-mcp as a child process and maintains a single
|
|
5
|
+
* persistent MCP session. Exposes a simple HTTP API:
|
|
6
|
+
* POST /call { name, args } → { result }
|
|
7
|
+
* GET /tools → [{ name, description }]
|
|
8
|
+
* GET /health → { status: "ok" }
|
|
9
|
+
*
|
|
10
|
+
* Writes a PID file to ~/.opera-browser-cli/bridge.pid on startup.
|
|
11
|
+
*/
|
|
12
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
13
|
+
import type { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
14
|
+
import { type IncomingMessage, type Server, type ServerResponse } from "node:http";
|
|
15
|
+
export interface BridgeContentBlock {
|
|
16
|
+
type: string;
|
|
17
|
+
text?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BridgeCallPayload {
|
|
20
|
+
name: string;
|
|
21
|
+
args: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
interface BridgeToolDescription {
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface BridgeClient {
|
|
28
|
+
listTools(): Promise<{
|
|
29
|
+
tools: BridgeToolDescription[];
|
|
30
|
+
}>;
|
|
31
|
+
callTool(request: {
|
|
32
|
+
name: string;
|
|
33
|
+
arguments: Record<string, unknown>;
|
|
34
|
+
}, resultSchema?: unknown, options?: RequestOptions): Promise<unknown>;
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function isBridgeClientConnected(client: BridgeClient): Promise<boolean>;
|
|
38
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
39
|
+
export declare function extractToolText(content: BridgeContentBlock[]): string;
|
|
40
|
+
export declare function parseBridgeCallPayload(body: string): BridgeCallPayload;
|
|
41
|
+
export declare function resolveBridgeScript(importMetaDir: string): string;
|
|
42
|
+
export declare function handleBridgeRequest(client: BridgeClient, req: IncomingMessage, res: ServerResponse, captureNextId?: () => Promise<string>): Promise<void>;
|
|
43
|
+
export declare function createBridgeServer(client: BridgeClient, captureNextId?: () => Promise<string>): Server;
|
|
44
|
+
export declare function buildTransportArgs(): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Wraps transport.send to intercept outgoing JSON-RPC request IDs so each
|
|
47
|
+
* streaming callTool call can register its own log writer before the first
|
|
48
|
+
* notification arrives.
|
|
49
|
+
*
|
|
50
|
+
* INVARIANT: The MCP SDK's Client.request() calls transport.send() synchronously
|
|
51
|
+
* inside its Promise constructor (see @modelcontextprotocol/sdk shared/protocol.js).
|
|
52
|
+
* This means callTool() triggers transport.send before yielding, allowing us to
|
|
53
|
+
* capture the ID before any concurrent handler can interleave.
|
|
54
|
+
* Verify this invariant when upgrading @modelcontextprotocol/sdk.
|
|
55
|
+
*/
|
|
56
|
+
export declare function wrapTransportForIdCapture(transport: StdioClientTransport): () => Promise<string>;
|
|
57
|
+
export declare function runBridge(port?: number): Promise<void>;
|
|
58
|
+
export {};
|