browsercontrol 0.1.2__tar.gz → 0.1.4__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 (40) hide show
  1. browsercontrol-0.1.4/.claude/settings.local.json +10 -0
  2. browsercontrol-0.1.4/.github/workflows/ci.yml +135 -0
  3. browsercontrol-0.1.4/.github/workflows/dependency-review.yml +39 -0
  4. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/.gitignore +3 -6
  5. browsercontrol-0.1.4/.pre-commit-config.yaml +48 -0
  6. browsercontrol-0.1.4/CLAUDE.md +114 -0
  7. browsercontrol-0.1.4/CODE_QUALITY.md +81 -0
  8. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/CONTRIBUTING.md +25 -2
  9. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/PKG-INFO +291 -102
  10. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/README.md +290 -101
  11. browsercontrol-0.1.4/assets/logo-main.png +0 -0
  12. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/__init__.py +1 -1
  13. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/__main__.py +1 -1
  14. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/browser.py +273 -227
  15. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/config.py +18 -22
  16. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/server.py +5 -12
  17. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/content.py +36 -38
  18. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/devtools.py +124 -142
  19. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/forms.py +51 -33
  20. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/interaction.py +74 -45
  21. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/navigation.py +37 -31
  22. browsercontrol-0.1.4/browsercontrol/tools/recording.py +166 -0
  23. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/tabs.py +14 -14
  24. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/pyproject.toml +50 -1
  25. browsercontrol-0.1.4/tests/__init__.py +0 -0
  26. browsercontrol-0.1.4/tests/conftest.py +127 -0
  27. browsercontrol-0.1.4/tests/test_browser.py +367 -0
  28. browsercontrol-0.1.4/tests/test_content.py +135 -0
  29. browsercontrol-0.1.4/tests/test_devtools.py +205 -0
  30. browsercontrol-0.1.4/tests/test_forms.py +151 -0
  31. browsercontrol-0.1.4/tests/test_interaction.py +235 -0
  32. browsercontrol-0.1.4/tests/test_navigation.py +167 -0
  33. browsercontrol-0.1.4/tests/test_recording.py +168 -0
  34. browsercontrol-0.1.4/tests/test_tabs.py +109 -0
  35. browsercontrol-0.1.4/uv.lock +2085 -0
  36. browsercontrol-0.1.2/assets/logo.png +0 -0
  37. browsercontrol-0.1.2/browsercontrol/tools/recording.py +0 -220
  38. browsercontrol-0.1.2/uv.lock +0 -1896
  39. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/LICENSE +0 -0
  40. {browsercontrol-0.1.2 → browsercontrol-0.1.4}/browsercontrol/tools/__init__.py +3 -3
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(uv run *)",
5
+ "Bash(xargs cat -n)",
6
+ "Bash(git show-ref *)"
7
+ ]
8
+ },
9
+ "prefersReducedMotion": false
10
+ }
@@ -0,0 +1,135 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v4
15
+ with:
16
+ fetch-depth: 0
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v3
20
+ with:
21
+ version: "latest"
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --all-extras
25
+
26
+ - name: Run pre-commit hooks
27
+ run: uv run pre-commit run --all-files
28
+
29
+ - name: Run ruff check
30
+ run: uv run ruff check .
31
+
32
+ - name: Run ruff format check
33
+ run: uv run ruff format --check .
34
+
35
+ test:
36
+ runs-on: ubuntu-latest
37
+ needs: lint
38
+ steps:
39
+ - name: Checkout
40
+ uses: actions/checkout@v4
41
+
42
+ - name: Install uv
43
+ uses: astral-sh/setup-uv@v3
44
+ with:
45
+ version: "latest"
46
+
47
+ - name: Install dependencies
48
+ run: uv sync --all-extras
49
+
50
+ - name: Install Playwright browsers
51
+ run: uv run playwright install chromium --with-deps
52
+
53
+ - name: Run tests
54
+ run: uv run pytest -v
55
+
56
+ # Test on Windows and macOS as well
57
+ test-windows:
58
+ runs-on: windows-latest
59
+ needs: lint
60
+ steps:
61
+ - name: Checkout
62
+ uses: actions/checkout@v4
63
+
64
+ - name: Install uv
65
+ uses: astral-sh/setup-uv@v3
66
+ with:
67
+ version: "latest"
68
+
69
+ - name: Install dependencies
70
+ run: uv sync --all-extras
71
+
72
+ - name: Install Playwright browsers
73
+ run: uv run playwright install chromium
74
+
75
+ - name: Run tests
76
+ run: uv run pytest -v
77
+
78
+ test-macos:
79
+ runs-on: macos-latest
80
+ needs: lint
81
+ steps:
82
+ - name: Checkout
83
+ uses: actions/checkout@v4
84
+
85
+ - name: Install uv
86
+ uses: astral-sh/setup-uv@v3
87
+ with:
88
+ version: "latest"
89
+
90
+ - name: Install dependencies
91
+ run: uv sync --all-extras
92
+
93
+ - name: Install Playwright browsers
94
+ run: uv run playwright install chromium
95
+
96
+ - name: Run tests
97
+ run: uv run pytest -v
98
+
99
+ security:
100
+ runs-on: ubuntu-latest
101
+ needs: lint
102
+ steps:
103
+ - name: Checkout
104
+ uses: actions/checkout@v4
105
+ with:
106
+ fetch-depth: 0
107
+
108
+ - name: Install uv
109
+ uses: astral-sh/setup-uv@v3
110
+ with:
111
+ version: "latest"
112
+
113
+ - name: Install dependencies
114
+ run: uv sync --all-extras
115
+
116
+ - name: Run bandit security checks
117
+ run: uv run bandit -c pyproject.toml -r . --exclude ./tests,./.venv
118
+
119
+ type-check:
120
+ runs-on: ubuntu-latest
121
+ needs: lint
122
+ steps:
123
+ - name: Checkout
124
+ uses: actions/checkout@v4
125
+
126
+ - name: Install uv
127
+ uses: astral-sh/setup-uv@v3
128
+ with:
129
+ version: "latest"
130
+
131
+ - name: Install dependencies
132
+ run: uv sync --all-extras
133
+
134
+ - name: Run mypy (if type hints are used)
135
+ run: uv run mypy browsercontrol/ || echo "No mypy configuration found"
@@ -0,0 +1,39 @@
1
+ # Dependency Review Action
2
+ #
3
+ # This Action will scan dependency manifest files that change as part of a Pull Request,
4
+ # surfacing known-vulnerable versions of the packages declared or updated in the PR.
5
+ # Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable
6
+ # packages will be blocked from merging.
7
+ #
8
+ # Source repository: https://github.com/actions/dependency-review-action
9
+ # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
10
+ name: "Dependency review"
11
+ on:
12
+ pull_request:
13
+ branches: ["main"]
14
+
15
+ # If using a dependency submission action in this workflow this permission will need to be set to:
16
+ #
17
+ # permissions:
18
+ # contents: write
19
+ #
20
+ # https://docs.github.com/en/enterprise-cloud@latest/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api
21
+ permissions:
22
+ contents: read
23
+ # Write permissions for pull-requests are required for using the `comment-summary-in-pr` option, comment out if you aren't using this option
24
+ pull-requests: write
25
+
26
+ jobs:
27
+ dependency-review:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: "Checkout repository"
31
+ uses: actions/checkout@v4
32
+ - name: "Dependency Review"
33
+ uses: actions/dependency-review-action@v4
34
+ # Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options.
35
+ with:
36
+ comment-summary-in-pr: always
37
+ # fail-on-severity: moderate
38
+ # deny-licenses: GPL-1.0-or-later, LGPL-2.0-or-later
39
+ # retry-on-snapshot-warnings: true
@@ -6,13 +6,10 @@
6
6
  # Python
7
7
  */__pycache__/*
8
8
  *.py[cod]
9
- *$py.class
10
- *.so
11
- .Python
12
- *.egg-info/
13
9
  dist/
14
- build/
10
+ .pytest_cache/
15
11
 
16
12
  # Virtual environments
17
13
  .venv/
18
-
14
+ .ruff_cache/
15
+ .pytest_cache/
@@ -0,0 +1,48 @@
1
+ repos:
2
+ # Ruff - Fast Python linter and formatter
3
+ - repo: https://github.com/astral-sh/ruff-pre-commit
4
+ rev: v0.8.4
5
+ hooks:
6
+ # Run the linter
7
+ - id: ruff
8
+ args: [--fix]
9
+ # Run the formatter
10
+ - id: ruff-format
11
+
12
+ # General file checks
13
+ - repo: https://github.com/pre-commit/pre-commit-hooks
14
+ rev: v5.0.0
15
+ hooks:
16
+ - id: trailing-whitespace
17
+ - id: end-of-file-fixer
18
+ - id: check-yaml
19
+ - id: check-toml
20
+ - id: check-json
21
+ - id: check-added-large-files
22
+ args: [--maxkb=1000]
23
+ - id: check-merge-conflict
24
+ - id: check-case-conflict
25
+ - id: mixed-line-ending
26
+ args: [--fix=lf]
27
+
28
+ # Python security checks
29
+ - repo: https://github.com/PyCQA/bandit
30
+ rev: 1.8.0
31
+ hooks:
32
+ - id: bandit
33
+ args: [-c, pyproject.toml]
34
+ additional_dependencies: ["bandit[toml]"]
35
+ exclude: ^tests/
36
+
37
+ # CI configuration
38
+ ci:
39
+ autofix_commit_msg: |
40
+ [pre-commit.ci] auto fixes from pre-commit hooks
41
+
42
+ for more information, see https://pre-commit.ci
43
+ autofix_prs: true
44
+ autoupdate_branch: ""
45
+ autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
46
+ autoupdate_schedule: weekly
47
+ skip: []
48
+ submodules: false
@@ -0,0 +1,114 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Overview
6
+
7
+ BrowserControl is an MCP (Model Context Protocol) server that gives AI agents
8
+ vision-first browser automation via Playwright. Its defining idea is **Set of
9
+ Marks (SoM)**: every action returns an annotated screenshot where interactive
10
+ elements are overlaid with numbered red boxes, so the agent acts by referring to
11
+ an element's number (`click(7)`) instead of CSS selectors or XPath.
12
+
13
+ ## Commands
14
+
15
+ This project uses `uv` for all dependency and task management.
16
+
17
+ ```bash
18
+ uv sync # Install deps (use --all-extras in CI to include dev group)
19
+ uv run playwright install chromium # One-time: install the browser engine
20
+
21
+ uv run pytest # Run all tests
22
+ uv run pytest tests/test_navigation.py # Run a single test file
23
+ uv run pytest tests/test_navigation.py::TestScroll::test_scroll_down_medium # Single test
24
+ uv run pytest --cov=browsercontrol # With coverage
25
+
26
+ uv run ruff check . # Lint
27
+ uv run ruff check . --fix # Lint + autofix
28
+ uv run ruff format . # Format (line length 100, double quotes)
29
+ uv run mypy browsercontrol/ # Type-check (strict mode)
30
+ uv run bandit -c pyproject.toml -r . --exclude ./tests,./.venv # Security scan
31
+ uv run pre-commit run --all-files # Run every hook (mirrors the CI lint job)
32
+
33
+ uv run fastmcp dev browsercontrol/server.py # Run the server in dev mode with inspector
34
+ browsercontrol # Run the installed server (also: python -m browsercontrol)
35
+ ```
36
+
37
+ CI (`.github/workflows/ci.yml`) gates on the lint job first, then runs tests on
38
+ Linux/Windows/macOS plus bandit and mypy. Run `ruff check`, `ruff format`, and
39
+ `pytest` locally before pushing.
40
+
41
+ ## Architecture
42
+
43
+ The flow is: agent calls an MCP tool → tool drives the Playwright page → a fresh
44
+ annotated screenshot + element map is captured → both are returned to the agent.
45
+
46
+ **`browser.py` — the heart of the system.** Exposes a single module-global
47
+ `browser = BrowserManager()` instance and a module-global `element_map` dict.
48
+ Key behaviors to understand before touching anything:
49
+
50
+ - `screenshot_with_som()` is called at the end of nearly every tool. It takes a
51
+ screenshot, runs `get_interactive_elements()` (injected JS that collects
52
+ visible, on-screen interactive elements and their bounding boxes), draws the
53
+ numbered boxes, and **overwrites the global `element_map`** with 1-indexed IDs.
54
+ - **Element IDs are ephemeral.** They are only valid against the most recent
55
+ screenshot. Any navigation, click, scroll, or screenshot regenerates the map
56
+ and renumbers everything. Tools look up the target via `get_element_map()` and
57
+ return an error listing valid IDs when the ID is missing.
58
+ - The browser uses `launch_persistent_context` against a profile directory
59
+ (`~/.browsercontrol/user_data` by default), so cookies, localStorage, and login
60
+ state persist across server restarts. Launch args include localhost proxy
61
+ bypass to avoid `ERR_CONNECTION_REFUSED`.
62
+ - DevTools data (console logs, network requests, page errors) is captured by
63
+ event listeners attached in `_setup_page_listeners`, auto-wired to every new
64
+ page/popup, and stored in capped in-memory ring buffers on the manager.
65
+
66
+ **`server.py` — composition root.** Creates the `FastMCP` instance, attaches a
67
+ `lifespan` context manager that starts/stops the browser, and calls each
68
+ `register_*_tools(mcp)`. The server-level `instructions` string is the prompt the
69
+ agent sees describing available tools — keep it in sync when adding tools.
70
+
71
+ **`tools/` — one module per category** (navigation, interaction, forms, content,
72
+ devtools, recording, tabs). Each exports a single `register_<category>_tools(mcp)`
73
+ function that defines inner `async` functions decorated with `@mcp.tool()`.
74
+ Conventions every tool follows:
75
+
76
+ - Signature returns `tuple[str, Image]`: a human-readable status string plus the
77
+ annotated screenshot.
78
+ - Starts with `await browser.ensure_started()` (lazily boots the browser if the
79
+ lifespan hasn't, e.g. in some test paths).
80
+ - Ends by building the result via a local `_get_screenshot_with_summary()`
81
+ helper. **This helper is duplicated verbatim in several tool modules** — if you
82
+ change the summary format, update every copy.
83
+
84
+ **`config.py`** — a `Config` dataclass loaded once at import via
85
+ `Config.from_env()` into a global `config`. All settings come from `BROWSER_*`
86
+ and `LOG_LEVEL` env vars (see README for the full table). Because it is read at
87
+ import time, env changes require a server restart.
88
+
89
+ ## Testing conventions
90
+
91
+ Tests **do not launch a real browser** — everything is mocked. The pattern:
92
+
93
+ - `tests/conftest.py` provides `mock_browser_manager` (a fully stubbed
94
+ `BrowserManager`), `mock_page`, `mock_context`, and `sample_element_map`.
95
+ - A test registers the tools onto a throwaway `FastMCP("test")`, then patches the
96
+ module-level `browser` symbol **in that specific tool module** (e.g.
97
+ `patch("browsercontrol.tools.navigation.browser", mock_browser_manager)`) —
98
+ because each tool module does `from browsercontrol.browser import browser`, it
99
+ holds its own reference that must be patched independently.
100
+ - The tool callable is reached through FastMCP internals:
101
+ `mcp_server._tool_manager._tools["navigate_to"].fn(...)`.
102
+ - `asyncio_mode = "auto"` is set, so `async def test_*` runs without an explicit
103
+ marker (though existing tests also add `@pytest.mark.asyncio`).
104
+
105
+ When adding a tool, add a test covering both the happy path and graceful error
106
+ handling, following the existing per-module test files.
107
+
108
+ ## Conventions
109
+
110
+ - Python 3.11+. Type hints are required and checked by mypy in **strict** mode
111
+ (`disallow_untyped_defs`, etc.) — annotate fully.
112
+ - Commits follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`).
113
+ - Pre-commit hooks (ruff, prettier for md/yaml/json, bandit) run on commit;
114
+ `git commit --no-verify` bypasses them but CI will still enforce them.
@@ -0,0 +1,81 @@
1
+ # Code Formatting and Quality
2
+
3
+ This project uses automated code formatting and linting tools to maintain code quality.
4
+
5
+ ## Tools
6
+
7
+ - **[Ruff](https://github.com/astral-sh/ruff)** - Fast Python linter and formatter
8
+ - **[Pre-commit](https://pre-commit.com/)** - Git hooks for automated checks
9
+ - **[Prettier](https://prettier.io/)** - Markdown/YAML/JSON formatting
10
+ - **[Bandit](https://bandit.readthedocs.io/)** - Security vulnerability scanner
11
+
12
+ ## Setup
13
+
14
+ The tools are already configured. To install the pre-commit hooks:
15
+
16
+ ```bash
17
+ uv sync
18
+ uv run pre-commit install
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Manual Formatting
24
+
25
+ ```bash
26
+ # Check for linting issues
27
+ uv run ruff check .
28
+
29
+ # Auto-fix linting issues
30
+ uv run ruff check . --fix
31
+
32
+ # Format code
33
+ uv run ruff format .
34
+
35
+ # Run all pre-commit hooks manually
36
+ uv run pre-commit run --all-files
37
+ ```
38
+
39
+ ### Automatic Formatting
40
+
41
+ Pre-commit hooks run automatically on `git commit`. They will:
42
+
43
+ 1. Run ruff linter and formatter
44
+ 2. Trim trailing whitespace
45
+ 3. Fix end-of-file issues
46
+ 4. Format markdown/YAML/JSON with prettier
47
+ 5. Check for security issues with bandit
48
+
49
+ If any hook fails, the commit will be aborted and files will be auto-fixed. Review the changes and commit again.
50
+
51
+ ## Configuration
52
+
53
+ ### Ruff
54
+
55
+ Configuration in `pyproject.toml`:
56
+
57
+ - **Line length**: 100 characters
58
+ - **Target Python**: 3.11+
59
+ - **Enabled rules**: pycodestyle, pyflakes, isort, pep8-naming, pyupgrade, bugbear, comprehensions, simplify, type-checking, Ruff-specific
60
+ - **Ignored rules**: E501 (line too long), B008 (function call in defaults), N805 (first arg naming), SIM117 (nested with), B904 (exception chaining)
61
+
62
+ ### Pre-commit
63
+
64
+ Configuration in `.pre-commit-config.yaml`:
65
+
66
+ - Ruff linter and formatter
67
+ - General file checks (trailing whitespace, EOF, YAML/TOML/JSON validation, large files, merge conflicts)
68
+ - Prettier for markdown formatting
69
+ - Bandit for security checks (excludes tests, allows subprocess for Playwright)
70
+
71
+ ## Bypassing Hooks
72
+
73
+ If you need to bypass pre-commit hooks (not recommended):
74
+
75
+ ```bash
76
+ git commit --no-verify
77
+ ```
78
+
79
+ ## CI Integration
80
+
81
+ Pre-commit.ci is configured to run automatically on pull requests and can auto-fix issues.
@@ -23,7 +23,11 @@ We love your input! We want to make contributing to BrowserControl as easy and t
23
23
  ```bash
24
24
  uv run playwright install chromium
25
25
  ```
26
- 5. **Run the server in dev mode**:
26
+ 5. **Install pre-commit hooks**:
27
+ ```bash
28
+ uv run pre-commit install
29
+ ```
30
+ 6. **Run the server in dev mode**:
27
31
  ```bash
28
32
  uv run fastmcp dev browsercontrol/server.py
29
33
  ```
@@ -33,11 +37,13 @@ We love your input! We want to make contributing to BrowserControl as easy and t
33
37
  We use [uv](https://github.com/astral-sh/uv) for dependency management and packaging. It's fast and reliable.
34
38
 
35
39
  ### Project Structure
40
+
36
41
  - `browsercontrol/server.py`: Main MCP server definition
37
42
  - `browsercontrol/browser.py`: Core logic (Playwright + Set of Marks)
38
43
  - `browsercontrol/tools/`: Tool implementations split by category
39
44
 
40
45
  ### Making Changes
46
+
41
47
  1. Create a branch for your feature: `git checkout -b feature/amazing-feature`
42
48
  2. Implement your changes
43
49
  3. Run tests (see below)
@@ -48,17 +54,33 @@ We use [uv](https://github.com/astral-sh/uv) for dependency management and packa
48
54
 
49
55
  ## 🧪 Testing
50
56
 
51
- We use `pytest`. Please ensure all tests pass before submitting a PR.
57
+ We use `pytest` for testing and `ruff` for code quality. Please ensure all checks pass before submitting a PR.
52
58
 
53
59
  ```bash
54
60
  # Run all tests
55
61
  uv run pytest
56
62
 
63
+ # Run tests with coverage
64
+ uv run pytest --cov=browsercontrol
65
+
66
+ # Check code formatting and linting
67
+ uv run ruff check .
68
+ uv run ruff format .
69
+
70
+ # Run all pre-commit hooks
71
+ uv run pre-commit run --all-files
72
+ ```
73
+
74
+ See [CODE_QUALITY.md](CODE_QUALITY.md) for more details on code formatting and quality tools.
75
+
57
76
  # Run specific test file
77
+
58
78
  uv run pytest tests/test_navigation.py
79
+
59
80
  ```
60
81
 
61
82
  If you add a new tool or feature, please add a corresponding test case covering:
83
+
62
84
  - Happy path (it works)
63
85
  - Error handling (it fails gracefully)
64
86
 
@@ -82,3 +104,4 @@ Bugs are tracked as GitHub issues. When filing an issue, please explain the prob
82
104
  ## 📄 License
83
105
 
84
106
  By contributing, you agree that your contributions will be licensed under its MIT License.
107
+ ```