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.
- ascended_browser-0.1.0/.github/workflows/release.yml +55 -0
- ascended_browser-0.1.0/.gitignore +9 -0
- ascended_browser-0.1.0/LICENSE +21 -0
- ascended_browser-0.1.0/PKG-INFO +181 -0
- ascended_browser-0.1.0/README.md +154 -0
- ascended_browser-0.1.0/demo/cut.py +1168 -0
- ascended_browser-0.1.0/demo/record_demo.py +95 -0
- ascended_browser-0.1.0/npm/bin/ascended-browser.js +89 -0
- ascended_browser-0.1.0/npm/package.json +12 -0
- ascended_browser-0.1.0/pyproject.toml +48 -0
- ascended_browser-0.1.0/scripts/_closure.py +36 -0
- ascended_browser-0.1.0/scripts/sync_from_ascended.py +259 -0
- ascended_browser-0.1.0/src/ascended_browser/__init__.py +3 -0
- ascended_browser-0.1.0/src/ascended_browser/__main__.py +3 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/SOURCE.json +4 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/__init__.py +1 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_act.py +1252 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_action_receipts.py +390 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_action_settle.py +162 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_adblock.py +245 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_agent_cursor.py +239 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_audit.py +608 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_capture.py +372 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_capture_compare.py +202 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_challenge_widget.py +205 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_click_helpers.py +2623 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_deadline.py +94 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_design.py +576 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_diagnostics.py +881 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_element_query.py +198 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_evaluate_policy.py +48 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_execution.py +91 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_flow_variables.py +129 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_flows.py +430 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_form_runtime.py +85 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_inspect.py +419 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_live_verification.py +479 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_login_broker.py +904 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_navigation_hints.py +314 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_observation_delta.py +145 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_observation_outline.py +329 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_presented_tab.py +71 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_profile_coord.py +631 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_reliability.py +607 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_result_summary.py +22 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_safety.py +130 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_scroll.py +58 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_cache.py +128 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_controls.py +1669 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_semantic_target.py +274 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_sensitive_state.py +91 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_shadow_dom.py +196 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_snapshot_store.py +121 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_structured_extract.py +225 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_submit_gate.py +64 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_tab_events.py +284 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_upload.py +250 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_vendor/axe-core/axe.min.js +12 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_viewport_content.py +146 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_wait_conditions.py +129 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_wall.py +603 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/__init__.py +7 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/auth_state.py +476 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/backend.py +1775 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/clocks.py +27 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/engine.py +614 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/fingerprint.py +143 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/liveview.py +1369 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/manager.py +1430 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/manager_core.py +16776 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/memory_pressure.py +176 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/models.py +174 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/omnibox.py +329 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/browser_workspace/store.py +324 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/dispatch.py +1449 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/formatting.py +1565 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/settings_defaults.json +69 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/tool_schemas.json +845 -0
- ascended_browser-0.1.0/src/ascended_browser/_app/user_labels.py +112 -0
- ascended_browser-0.1.0/src/ascended_browser/cli.py +67 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/__init__.py +7 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/admission.py +66 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/agent_tools.py +11 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/constants.py +7 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/database.py +41 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/desktop.py +38 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/evidence.py +35 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/files.py +6 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/llm.py +15 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/noop.py +11 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/paths.py +21 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/permission.py +7 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/platform.py +46 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/runs.py +5 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/sandbox.py +27 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/settings.py +66 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/subagents.py +16 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/text.py +8 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/tool_execution.py +13 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/tool_registry.py +10 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/url_security.py +33 -0
- ascended_browser-0.1.0/src/ascended_browser/runtime/xwindow.py +63 -0
- ascended_browser-0.1.0/src/ascended_browser/server.py +225 -0
- ascended_browser-0.1.0/src/ascended_browser/window.py +273 -0
- ascended_browser-0.1.0/tests/agents/agent_tasks.py +214 -0
- ascended_browser-0.1.0/tests/smoke_mcp.py +130 -0
- 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,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.
|