ascended-browser 0.1.0__tar.gz

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.
Files changed (107) hide show
  1. ascended_browser-0.1.0/.github/workflows/release.yml +55 -0
  2. ascended_browser-0.1.0/.gitignore +9 -0
  3. ascended_browser-0.1.0/LICENSE +21 -0
  4. ascended_browser-0.1.0/PKG-INFO +181 -0
  5. ascended_browser-0.1.0/README.md +154 -0
  6. ascended_browser-0.1.0/demo/cut.py +1168 -0
  7. ascended_browser-0.1.0/demo/record_demo.py +95 -0
  8. ascended_browser-0.1.0/npm/bin/ascended-browser.js +89 -0
  9. ascended_browser-0.1.0/npm/package.json +12 -0
  10. ascended_browser-0.1.0/pyproject.toml +48 -0
  11. ascended_browser-0.1.0/scripts/_closure.py +36 -0
  12. ascended_browser-0.1.0/scripts/sync_from_ascended.py +259 -0
  13. ascended_browser-0.1.0/src/ascended_browser/__init__.py +3 -0
  14. ascended_browser-0.1.0/src/ascended_browser/__main__.py +3 -0
  15. ascended_browser-0.1.0/src/ascended_browser/_app/SOURCE.json +4 -0
  16. ascended_browser-0.1.0/src/ascended_browser/_app/__init__.py +1 -0
  17. ascended_browser-0.1.0/src/ascended_browser/_app/browser_act.py +1252 -0
  18. ascended_browser-0.1.0/src/ascended_browser/_app/browser_action_receipts.py +390 -0
  19. ascended_browser-0.1.0/src/ascended_browser/_app/browser_action_settle.py +162 -0
  20. ascended_browser-0.1.0/src/ascended_browser/_app/browser_adblock.py +245 -0
  21. ascended_browser-0.1.0/src/ascended_browser/_app/browser_agent_cursor.py +239 -0
  22. ascended_browser-0.1.0/src/ascended_browser/_app/browser_audit.py +608 -0
  23. ascended_browser-0.1.0/src/ascended_browser/_app/browser_capture.py +372 -0
  24. ascended_browser-0.1.0/src/ascended_browser/_app/browser_capture_compare.py +202 -0
  25. ascended_browser-0.1.0/src/ascended_browser/_app/browser_challenge_widget.py +205 -0
  26. ascended_browser-0.1.0/src/ascended_browser/_app/browser_click_helpers.py +2623 -0
  27. ascended_browser-0.1.0/src/ascended_browser/_app/browser_deadline.py +94 -0
  28. ascended_browser-0.1.0/src/ascended_browser/_app/browser_design.py +576 -0
  29. ascended_browser-0.1.0/src/ascended_browser/_app/browser_diagnostics.py +881 -0
  30. ascended_browser-0.1.0/src/ascended_browser/_app/browser_element_query.py +198 -0
  31. ascended_browser-0.1.0/src/ascended_browser/_app/browser_evaluate_policy.py +48 -0
  32. ascended_browser-0.1.0/src/ascended_browser/_app/browser_execution.py +91 -0
  33. ascended_browser-0.1.0/src/ascended_browser/_app/browser_flow_variables.py +129 -0
  34. ascended_browser-0.1.0/src/ascended_browser/_app/browser_flows.py +430 -0
  35. ascended_browser-0.1.0/src/ascended_browser/_app/browser_form_runtime.py +85 -0
  36. ascended_browser-0.1.0/src/ascended_browser/_app/browser_inspect.py +419 -0
  37. ascended_browser-0.1.0/src/ascended_browser/_app/browser_live_verification.py +479 -0
  38. ascended_browser-0.1.0/src/ascended_browser/_app/browser_login_broker.py +904 -0
  39. ascended_browser-0.1.0/src/ascended_browser/_app/browser_navigation_hints.py +314 -0
  40. ascended_browser-0.1.0/src/ascended_browser/_app/browser_observation_delta.py +145 -0
  41. ascended_browser-0.1.0/src/ascended_browser/_app/browser_observation_outline.py +329 -0
  42. ascended_browser-0.1.0/src/ascended_browser/_app/browser_presented_tab.py +71 -0
  43. ascended_browser-0.1.0/src/ascended_browser/_app/browser_profile_coord.py +631 -0
  44. ascended_browser-0.1.0/src/ascended_browser/_app/browser_reliability.py +607 -0
  45. ascended_browser-0.1.0/src/ascended_browser/_app/browser_result_summary.py +22 -0
  46. ascended_browser-0.1.0/src/ascended_browser/_app/browser_safety.py +130 -0
  47. ascended_browser-0.1.0/src/ascended_browser/_app/browser_scroll.py +58 -0
  48. ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_cache.py +128 -0
  49. ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_controls.py +1669 -0
  50. ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_target.py +274 -0
  51. ascended_browser-0.1.0/src/ascended_browser/_app/browser_sensitive_state.py +91 -0
  52. ascended_browser-0.1.0/src/ascended_browser/_app/browser_shadow_dom.py +196 -0
  53. ascended_browser-0.1.0/src/ascended_browser/_app/browser_snapshot_store.py +121 -0
  54. ascended_browser-0.1.0/src/ascended_browser/_app/browser_structured_extract.py +225 -0
  55. ascended_browser-0.1.0/src/ascended_browser/_app/browser_submit_gate.py +64 -0
  56. ascended_browser-0.1.0/src/ascended_browser/_app/browser_tab_events.py +284 -0
  57. ascended_browser-0.1.0/src/ascended_browser/_app/browser_upload.py +250 -0
  58. ascended_browser-0.1.0/src/ascended_browser/_app/browser_vendor/axe-core/axe.min.js +12 -0
  59. ascended_browser-0.1.0/src/ascended_browser/_app/browser_viewport_content.py +146 -0
  60. ascended_browser-0.1.0/src/ascended_browser/_app/browser_wait_conditions.py +129 -0
  61. ascended_browser-0.1.0/src/ascended_browser/_app/browser_wall.py +603 -0
  62. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/__init__.py +7 -0
  63. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/auth_state.py +476 -0
  64. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/backend.py +1775 -0
  65. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/clocks.py +27 -0
  66. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/engine.py +614 -0
  67. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/fingerprint.py +143 -0
  68. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/liveview.py +1369 -0
  69. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/manager.py +1430 -0
  70. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/manager_core.py +16776 -0
  71. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/memory_pressure.py +176 -0
  72. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/models.py +174 -0
  73. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/omnibox.py +329 -0
  74. ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/store.py +324 -0
  75. ascended_browser-0.1.0/src/ascended_browser/_app/dispatch.py +1449 -0
  76. ascended_browser-0.1.0/src/ascended_browser/_app/formatting.py +1565 -0
  77. ascended_browser-0.1.0/src/ascended_browser/_app/settings_defaults.json +69 -0
  78. ascended_browser-0.1.0/src/ascended_browser/_app/tool_schemas.json +845 -0
  79. ascended_browser-0.1.0/src/ascended_browser/_app/user_labels.py +112 -0
  80. ascended_browser-0.1.0/src/ascended_browser/cli.py +67 -0
  81. ascended_browser-0.1.0/src/ascended_browser/runtime/__init__.py +7 -0
  82. ascended_browser-0.1.0/src/ascended_browser/runtime/admission.py +66 -0
  83. ascended_browser-0.1.0/src/ascended_browser/runtime/agent_tools.py +11 -0
  84. ascended_browser-0.1.0/src/ascended_browser/runtime/constants.py +7 -0
  85. ascended_browser-0.1.0/src/ascended_browser/runtime/database.py +41 -0
  86. ascended_browser-0.1.0/src/ascended_browser/runtime/desktop.py +38 -0
  87. ascended_browser-0.1.0/src/ascended_browser/runtime/evidence.py +35 -0
  88. ascended_browser-0.1.0/src/ascended_browser/runtime/files.py +6 -0
  89. ascended_browser-0.1.0/src/ascended_browser/runtime/llm.py +15 -0
  90. ascended_browser-0.1.0/src/ascended_browser/runtime/noop.py +11 -0
  91. ascended_browser-0.1.0/src/ascended_browser/runtime/paths.py +21 -0
  92. ascended_browser-0.1.0/src/ascended_browser/runtime/permission.py +7 -0
  93. ascended_browser-0.1.0/src/ascended_browser/runtime/platform.py +46 -0
  94. ascended_browser-0.1.0/src/ascended_browser/runtime/runs.py +5 -0
  95. ascended_browser-0.1.0/src/ascended_browser/runtime/sandbox.py +27 -0
  96. ascended_browser-0.1.0/src/ascended_browser/runtime/settings.py +66 -0
  97. ascended_browser-0.1.0/src/ascended_browser/runtime/subagents.py +16 -0
  98. ascended_browser-0.1.0/src/ascended_browser/runtime/text.py +8 -0
  99. ascended_browser-0.1.0/src/ascended_browser/runtime/tool_execution.py +13 -0
  100. ascended_browser-0.1.0/src/ascended_browser/runtime/tool_registry.py +10 -0
  101. ascended_browser-0.1.0/src/ascended_browser/runtime/url_security.py +33 -0
  102. ascended_browser-0.1.0/src/ascended_browser/runtime/xwindow.py +63 -0
  103. ascended_browser-0.1.0/src/ascended_browser/server.py +225 -0
  104. ascended_browser-0.1.0/src/ascended_browser/window.py +273 -0
  105. ascended_browser-0.1.0/tests/agents/agent_tasks.py +214 -0
  106. ascended_browser-0.1.0/tests/smoke_mcp.py +130 -0
  107. ascended_browser-0.1.0/tests/stress/run_ascended_stress.py +113 -0
@@ -0,0 +1,55 @@
1
+ # Publishes to PyPI and npm when a GitHub release is published.
2
+ # Both use trusted publishing (no token stored anywhere): the PyPI project and
3
+ # the npm package each trust this repository's `release.yml` workflow.
4
+ name: release
5
+
6
+ on:
7
+ release:
8
+ types: [published]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v6
16
+ - run: uv build
17
+ - name: The tag matches both package versions
18
+ run: |
19
+ version=$(grep -m1 '^version' pyproject.toml | cut -d'"' -f2)
20
+ test "v${version}" = "${GITHUB_REF_NAME}"
21
+ test "$(node -p 'require("./npm/package.json").version')" = "${version}"
22
+ - uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist/
26
+
27
+ publish:
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment: pypi
31
+ permissions:
32
+ id-token: write
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+ - uses: pypa/gh-action-pypi-publish@release/v1
39
+
40
+ npm:
41
+ # After PyPI, so the launcher never points at a version that is not there yet.
42
+ needs: publish
43
+ runs-on: ubuntu-latest
44
+ permissions:
45
+ id-token: write
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: actions/setup-node@v4
49
+ with:
50
+ node-version: 24
51
+ registry-url: https://registry.npmjs.org
52
+ - run: npm install -g npm@latest # trusted publishing needs npm 11.5.1+
53
+ - run: cp README.md LICENSE npm/
54
+ - run: npm publish --access public --provenance
55
+ working-directory: npm
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ /runs/
8
+ /videos/raw/
9
+ runs/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohamed Elshoubky
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.
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.5
2
+ Name: ascended-browser
3
+ Version: 0.1.0
4
+ Summary: A real, hardened browser for AI agents: verified actions, page reading, dev tools. An MCP server.
5
+ Author: Mohamed Elshoubky
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: agent,automation,browser,camoufox,claude,codex,mcp
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
12
+ Requires-Python: >=3.11
13
+ Requires-Dist: cloverlabs-camoufox==0.6.0
14
+ Requires-Dist: curl-cffi>=0.7
15
+ Requires-Dist: httpx>=0.27
16
+ Requires-Dist: mcp<2,>=1.10
17
+ Requires-Dist: pillow>=10
18
+ Requires-Dist: playwright==1.58.0
19
+ Requires-Dist: pyotp>=2.9
20
+ Requires-Dist: python-xlib>=0.33; sys_platform == 'linux'
21
+ Requires-Dist: sqlalchemy>=2
22
+ Requires-Dist: tldextract>=5
23
+ Requires-Dist: websockets>=12
24
+ Provides-Extra: cloudscraper
25
+ Requires-Dist: cloudscraper; extra == 'cloudscraper'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # ascended-browser
29
+
30
+ A real browser for AI agents, as an MCP server. Your agent opens pages, reads
31
+ them, and acts on them through **verified actions**: it fills a whole form in
32
+ one call, picks "Mrs." from a custom React dropdown by name, and is told what
33
+ the page did in response, instead of clicking coordinates and hoping.
34
+
35
+ It is the browser from Ascended, packaged on its own:
36
+ [Camoufox](https://camoufox.com) (a hardened Firefox that looks like a
37
+ person's browser to the sites it visits) behind the same tool dispatcher, page
38
+ reading and result formatting Ascended's own agent uses.
39
+
40
+ ## See it work
41
+
42
+ Three real runs of Claude Code with only this server attached, on live sites.
43
+ The panel on the side is Claude Code's own transcript: every tool call it made
44
+ and what came back, errors included, with the real elapsed time. Waiting is
45
+ cut and tool time plays faster; the pointer, device frames, devtools panels
46
+ and outlines are drawn afterwards from the server's event log
47
+ (`demo/record_demo.py`), so they sit on what the agent really touched and read.
48
+ The full unedited screen recordings are in [`videos/unedited/`](videos/unedited/)
49
+ (the browser is driven through Playwright, so no OS pointer appears in them).
50
+
51
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/dev-react.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/dev-react.gif" alt="Front-end QA. react.dev on a phone and a tablet, dark/light, before/after screenshots, an audit outlining the real offending elements, console and network." width="760"></a>
52
+
53
+ **Front-end QA.** react.dev on a phone and a tablet, dark/light, before/after screenshots, an audit outlining the real offending elements, console and network.
54
+
55
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/browse.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/browse.gif" alt="Browsing. Types into Wikipedia's search, finds a fact in the article, then searches YouTube and plays the first video." width="760"></a>
56
+
57
+ **Browsing.** Types into Wikipedia's search, finds a fact in the article, then searches YouTube and plays the first video.
58
+
59
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/booking.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/booking.gif" alt="Real forms. booking.com: popup, destination autocomplete, date picker, search, sort by price." width="760"></a>
60
+
61
+ **Real forms.** booking.com: popup, destination autocomplete, date picker, search, sort by price.
62
+
63
+ Click any clip for the full-quality MP4.
64
+
65
+ ## Install
66
+
67
+ From Python (3.11 or newer) or from npm; both run the same server.
68
+
69
+ ```bash
70
+ uvx ascended-browser doctor # checks the machine; downloads nothing
71
+ uvx ascended-browser fetch # downloads the Camoufox browser (otherwise on first use)
72
+
73
+ npx -y ascended-browser doctor # the same, from npm
74
+ ```
75
+
76
+ The npm package is a small launcher: it runs the Python package with `uvx`
77
+ when [uv](https://docs.astral.sh/uv/) is installed (uv brings its own Python),
78
+ else `pipx`, else a private venv made with your Python 3.11+. Use whichever
79
+ command you prefer in the configs below (`npx -y ascended-browser` in place of
80
+ `uvx ascended-browser`).
81
+
82
+ Linux: install `xvfb` to keep the browser on a virtual display (closest to a
83
+ real screen); without it the browser runs headless. On a display,
84
+ `browser_viewport` resizes the real window, so phone and tablet checks reflow
85
+ the page at true breakpoints.
86
+
87
+ ## Add it to your agent
88
+
89
+ **Claude Code**
90
+
91
+ ```bash
92
+ claude mcp add ascended-browser -- uvx ascended-browser
93
+ # or: claude mcp add ascended-browser -- npx -y ascended-browser
94
+ ```
95
+
96
+ **Codex**
97
+
98
+ ```bash
99
+ codex mcp add ascended-browser -- uvx ascended-browser
100
+ ```
101
+
102
+ Codex asks for approval before browser actions; approve them when it asks.
103
+ For `codex exec` (which cannot ask, so every call would fail), add
104
+ `default_tools_approval_mode = "approve"` under `[mcp_servers.ascended-browser]`
105
+ in `~/.codex/config.toml`.
106
+
107
+ **opencode** (`opencode.json`)
108
+
109
+ ```json
110
+ {
111
+ "mcp": {
112
+ "ascended-browser": { "type": "local", "command": ["uvx", "ascended-browser"], "enabled": true }
113
+ }
114
+ }
115
+ ```
116
+
117
+ **Cursor, Windsurf, Claude Desktop and other clients:** a stdio server with
118
+ command `uvx` and args `["ascended-browser"]`, or command `npx` and args
119
+ `["-y", "ascended-browser"]`.
120
+
121
+ ## Tools
122
+
123
+ | Tool | What it does |
124
+ |---|---|
125
+ | `browser_open` | Open a URL (or several at once) and return what is on the page, each control with a ref |
126
+ | `browser_observe` | Look at the page again, or narrow to a region, a query or a filter |
127
+ | `browser_act` | `navigate`, `click`, `fill`, `fill_form`, `select`, `check`, `date`, `press`, `upload`, `scroll`, `wait`, `sequence`: each verified, each answered with what changed |
128
+ | `browser_extract` | Read the page's text and field state, query by CSS selector, pull repeated items into a JSON shape, or `read=console`, `read=network`, `read=inspect` to debug a page |
129
+ | `browser_screenshot` | A picture, when an observation cannot describe it: canvas, charts, visual layout; `compare_with` diffs against an earlier picture or another tab |
130
+ | `browser_viewport` | Resize to phone/tablet/desktop (Linux), emulate dark mode, reduced motion, forced colors or offline |
131
+ | `browser_evaluate` | Read-only JavaScript, policy-checked |
132
+ | `browser_tabs` | List, close or sleep tabs |
133
+ | `browser_flow` | Record a task once, replay it on the next page with new values |
134
+ | `wait_for_bot_wall` | Wait out a "checking your browser" page; press a Turnstile/reCAPTCHA checkbox if one blocks a form |
135
+
136
+ Long results come back clipped, with an `evidence_ref` that
137
+ `browser_extract` pages through, so a huge page cannot flood the agent's
138
+ context.
139
+
140
+ ## Settings
141
+
142
+ | Variable | Default | |
143
+ |---|---|---|
144
+ | `ASCENDED_BROWSER_WINDOW` | hidden | `show` opens a visible window |
145
+ | `ASCENDED_DATA_DIR` | `~/.local/share/ascended/browser` | Browser profile (sign-ins persist), session files |
146
+ | `ASCENDED_RESULT_MAX_CHARS` | `24000` | Longer results are clipped with an `evidence_ref` |
147
+ | `ASCENDED_SETTING_<KEY>` | | Any browser setting, e.g. `ASCENDED_SETTING_BROWSER_WORKSPACE_OBSERVE_FORMAT=outline` |
148
+ | `ASCENDED_LOG_LEVEL` | `WARNING` | Logs go to stderr |
149
+
150
+ ## Limits (0.1)
151
+
152
+ - **Resizing the window** (phone/tablet presets, multi-size screenshot
153
+ grids) runs through Ascended's live view, which this package does not
154
+ ship yet. Emulation (dark mode and the rest) works.
155
+ - **Saved logins** (`browser_login`) and **schema extraction backed by a
156
+ model** need the Ascended app.
157
+ - One server process is one browser session: tabs and refs last until your
158
+ client disconnects; the profile (cookies, sign-ins) lasts across sessions.
159
+
160
+ ## How it is built
161
+
162
+ `src/ascended_browser/_app` is generated from Ascended by
163
+ `scripts/sync_from_ascended.py`: the browser modules copied as they are, the
164
+ browser tool dispatcher and result formatter extracted by reachability, and
165
+ every import of the rest of the app rewritten to `runtime/` (small standalone
166
+ stand-ins). The sync refuses any app import it cannot map.
167
+
168
+ Tested with Ascended's own stress harnesses run against this package
169
+ (`tests/stress/`), a client-side MCP smoke test (`tests/smoke_mcp.py`), and
170
+ live-website tasks given to real agents (`tests/agents/`).
171
+
172
+ What has been verified so far: Linux (Python 3.11, 3.12 and 3.14), with Claude
173
+ Code and Codex (0.160) on live-site tasks, opencode on a navigation task, and
174
+ the npm launcher through uvx and through its own venv. macOS and Windows should
175
+ work headless or with a visible window, but are untested, and window resizing
176
+ for phone/tablet checks is Linux-only for now.
177
+
178
+ ## License
179
+
180
+ MIT. The bundled axe-core (`_app/browser_vendor/axe-core`) is MPL-2.0 and keeps
181
+ its notice in the file.
@@ -0,0 +1,154 @@
1
+ # ascended-browser
2
+
3
+ A real browser for AI agents, as an MCP server. Your agent opens pages, reads
4
+ them, and acts on them through **verified actions**: it fills a whole form in
5
+ one call, picks "Mrs." from a custom React dropdown by name, and is told what
6
+ the page did in response, instead of clicking coordinates and hoping.
7
+
8
+ It is the browser from Ascended, packaged on its own:
9
+ [Camoufox](https://camoufox.com) (a hardened Firefox that looks like a
10
+ person's browser to the sites it visits) behind the same tool dispatcher, page
11
+ reading and result formatting Ascended's own agent uses.
12
+
13
+ ## See it work
14
+
15
+ Three real runs of Claude Code with only this server attached, on live sites.
16
+ The panel on the side is Claude Code's own transcript: every tool call it made
17
+ and what came back, errors included, with the real elapsed time. Waiting is
18
+ cut and tool time plays faster; the pointer, device frames, devtools panels
19
+ and outlines are drawn afterwards from the server's event log
20
+ (`demo/record_demo.py`), so they sit on what the agent really touched and read.
21
+ The full unedited screen recordings are in [`videos/unedited/`](videos/unedited/)
22
+ (the browser is driven through Playwright, so no OS pointer appears in them).
23
+
24
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/dev-react.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/dev-react.gif" alt="Front-end QA. react.dev on a phone and a tablet, dark/light, before/after screenshots, an audit outlining the real offending elements, console and network." width="760"></a>
25
+
26
+ **Front-end QA.** react.dev on a phone and a tablet, dark/light, before/after screenshots, an audit outlining the real offending elements, console and network.
27
+
28
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/browse.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/browse.gif" alt="Browsing. Types into Wikipedia's search, finds a fact in the article, then searches YouTube and plays the first video." width="760"></a>
29
+
30
+ **Browsing.** Types into Wikipedia's search, finds a fact in the article, then searches YouTube and plays the first video.
31
+
32
+ <a href="https://github.com/AceAtDev/ascended-browser/blob/main/videos/booking.mp4"><img src="https://github.com/AceAtDev/ascended-browser/raw/main/videos/booking.gif" alt="Real forms. booking.com: popup, destination autocomplete, date picker, search, sort by price." width="760"></a>
33
+
34
+ **Real forms.** booking.com: popup, destination autocomplete, date picker, search, sort by price.
35
+
36
+ Click any clip for the full-quality MP4.
37
+
38
+ ## Install
39
+
40
+ From Python (3.11 or newer) or from npm; both run the same server.
41
+
42
+ ```bash
43
+ uvx ascended-browser doctor # checks the machine; downloads nothing
44
+ uvx ascended-browser fetch # downloads the Camoufox browser (otherwise on first use)
45
+
46
+ npx -y ascended-browser doctor # the same, from npm
47
+ ```
48
+
49
+ The npm package is a small launcher: it runs the Python package with `uvx`
50
+ when [uv](https://docs.astral.sh/uv/) is installed (uv brings its own Python),
51
+ else `pipx`, else a private venv made with your Python 3.11+. Use whichever
52
+ command you prefer in the configs below (`npx -y ascended-browser` in place of
53
+ `uvx ascended-browser`).
54
+
55
+ Linux: install `xvfb` to keep the browser on a virtual display (closest to a
56
+ real screen); without it the browser runs headless. On a display,
57
+ `browser_viewport` resizes the real window, so phone and tablet checks reflow
58
+ the page at true breakpoints.
59
+
60
+ ## Add it to your agent
61
+
62
+ **Claude Code**
63
+
64
+ ```bash
65
+ claude mcp add ascended-browser -- uvx ascended-browser
66
+ # or: claude mcp add ascended-browser -- npx -y ascended-browser
67
+ ```
68
+
69
+ **Codex**
70
+
71
+ ```bash
72
+ codex mcp add ascended-browser -- uvx ascended-browser
73
+ ```
74
+
75
+ Codex asks for approval before browser actions; approve them when it asks.
76
+ For `codex exec` (which cannot ask, so every call would fail), add
77
+ `default_tools_approval_mode = "approve"` under `[mcp_servers.ascended-browser]`
78
+ in `~/.codex/config.toml`.
79
+
80
+ **opencode** (`opencode.json`)
81
+
82
+ ```json
83
+ {
84
+ "mcp": {
85
+ "ascended-browser": { "type": "local", "command": ["uvx", "ascended-browser"], "enabled": true }
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Cursor, Windsurf, Claude Desktop and other clients:** a stdio server with
91
+ command `uvx` and args `["ascended-browser"]`, or command `npx` and args
92
+ `["-y", "ascended-browser"]`.
93
+
94
+ ## Tools
95
+
96
+ | Tool | What it does |
97
+ |---|---|
98
+ | `browser_open` | Open a URL (or several at once) and return what is on the page, each control with a ref |
99
+ | `browser_observe` | Look at the page again, or narrow to a region, a query or a filter |
100
+ | `browser_act` | `navigate`, `click`, `fill`, `fill_form`, `select`, `check`, `date`, `press`, `upload`, `scroll`, `wait`, `sequence`: each verified, each answered with what changed |
101
+ | `browser_extract` | Read the page's text and field state, query by CSS selector, pull repeated items into a JSON shape, or `read=console`, `read=network`, `read=inspect` to debug a page |
102
+ | `browser_screenshot` | A picture, when an observation cannot describe it: canvas, charts, visual layout; `compare_with` diffs against an earlier picture or another tab |
103
+ | `browser_viewport` | Resize to phone/tablet/desktop (Linux), emulate dark mode, reduced motion, forced colors or offline |
104
+ | `browser_evaluate` | Read-only JavaScript, policy-checked |
105
+ | `browser_tabs` | List, close or sleep tabs |
106
+ | `browser_flow` | Record a task once, replay it on the next page with new values |
107
+ | `wait_for_bot_wall` | Wait out a "checking your browser" page; press a Turnstile/reCAPTCHA checkbox if one blocks a form |
108
+
109
+ Long results come back clipped, with an `evidence_ref` that
110
+ `browser_extract` pages through, so a huge page cannot flood the agent's
111
+ context.
112
+
113
+ ## Settings
114
+
115
+ | Variable | Default | |
116
+ |---|---|---|
117
+ | `ASCENDED_BROWSER_WINDOW` | hidden | `show` opens a visible window |
118
+ | `ASCENDED_DATA_DIR` | `~/.local/share/ascended/browser` | Browser profile (sign-ins persist), session files |
119
+ | `ASCENDED_RESULT_MAX_CHARS` | `24000` | Longer results are clipped with an `evidence_ref` |
120
+ | `ASCENDED_SETTING_<KEY>` | | Any browser setting, e.g. `ASCENDED_SETTING_BROWSER_WORKSPACE_OBSERVE_FORMAT=outline` |
121
+ | `ASCENDED_LOG_LEVEL` | `WARNING` | Logs go to stderr |
122
+
123
+ ## Limits (0.1)
124
+
125
+ - **Resizing the window** (phone/tablet presets, multi-size screenshot
126
+ grids) runs through Ascended's live view, which this package does not
127
+ ship yet. Emulation (dark mode and the rest) works.
128
+ - **Saved logins** (`browser_login`) and **schema extraction backed by a
129
+ model** need the Ascended app.
130
+ - One server process is one browser session: tabs and refs last until your
131
+ client disconnects; the profile (cookies, sign-ins) lasts across sessions.
132
+
133
+ ## How it is built
134
+
135
+ `src/ascended_browser/_app` is generated from Ascended by
136
+ `scripts/sync_from_ascended.py`: the browser modules copied as they are, the
137
+ browser tool dispatcher and result formatter extracted by reachability, and
138
+ every import of the rest of the app rewritten to `runtime/` (small standalone
139
+ stand-ins). The sync refuses any app import it cannot map.
140
+
141
+ Tested with Ascended's own stress harnesses run against this package
142
+ (`tests/stress/`), a client-side MCP smoke test (`tests/smoke_mcp.py`), and
143
+ live-website tasks given to real agents (`tests/agents/`).
144
+
145
+ What has been verified so far: Linux (Python 3.11, 3.12 and 3.14), with Claude
146
+ Code and Codex (0.160) on live-site tasks, opencode on a navigation task, and
147
+ the npm launcher through uvx and through its own venv. macOS and Windows should
148
+ work headless or with a visible window, but are untested, and window resizing
149
+ for phone/tablet checks is Linux-only for now.
150
+
151
+ ## License
152
+
153
+ MIT. The bundled axe-core (`_app/browser_vendor/axe-core`) is MPL-2.0 and keeps
154
+ its notice in the file.