Repository: co-browser/browser-use-mcp-server
Pull request #36: fix: enhance project configuration with dynamic versioning and update CI workflow for artifact handling
Author: login: hashkode
Labels: name: bug
description: Something isn't working
name: enhancement
description: New feature or request
name: released
Created: 2025-04-10T16:24:08Z | Merged: 2025-04-15T18:15:42Z

This pull request includes updates to the GitHub Actions workflow for publishing a Python package and modifications to the `pyproject.toml` file to integrate dynamic versioning.

Changes to GitHub Actions workflow:

* [`.github/workflows/python-publish.yml`](diffhunk://#diff-87c8be2ac3b248aef84cc474af838d7cc461b7f8fb7f5444ac75f4d8fc02e377L24-R24): Updated `fetch-depth` to `0` in the checkout step to fetch all history. Simplified the build process by combining the build steps and renaming artifact upload step. [[1]](diffhunk://#diff-87c8be2ac3b248aef84cc474af838d7cc461b7f8fb7f5444ac75f4d8fc02e377L24-R24) [[2]](diffhunk://#diff-87c8be2ac3b248aef84cc474af838d7cc461b7f8fb7f5444ac75f4d8fc02e377L33-R40)
* [`.github/workflows/python-publish.yml`](diffhunk://#diff-87c8be2ac3b248aef84cc474af838d7cc461b7f8fb7f5444ac75f4d8fc02e377R72): Added a blank line for better readability in the `pypi-publish` job.

Changes to `pyproject.toml`:

* [`pyproject.toml`](diffhunk://#diff-50c86b7ed8ac2cf95bd48334961bf0530cdc77b5a56f852c5c61b89d735fd711L2-R7): Added `uv-dynamic-versioning` to the build requirements and set the project version to be dynamically generated.
* [`pyproject.toml`](diffhunk://#diff-50c86b7ed8ac2cf95bd48334961bf0530cdc77b5a56f852c5c61b89d735fd711R81-R88): Configured `uv-dynamic-versioning` to use Git for version control with PEP 440 style and enabled automatic version bumping.

## Description

To avoid manual labor an commits during releasing, uv dynamic versioning is introduced.

Fixes #35 

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

N/A, Action runs after merge

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes (if applicable)


Linked issue #35: [FEATURE] Fix PyPi package release versioning
## Is your feature request related to a problem? Please describe.

Currently, the PyPi package publish does not work. This is largely caused by missing automation to assume the version number defined by the Action in release.yaml.

## Describe the solution you'd like

The PiPy package should assume the versioning from the tag, which is assigned to the merge commits to the main branch.

## Describe alternatives you've considered

N/A, currently broken

## Additional context

N/A

Linked issue comments: user: login: michiosw
created_at: 2025-04-15T18:16:47Z
body: :tada: This issue has been resolved in version 1.0.1 :tada:

The release is available on [GitHub release](https://github.com/co-browser/browser-use-mcp-server/releases/tag/v1.0.1)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: CONTRIBUTOR

Diff:
diff --git a/.bandit.yml b/.bandit.yml
new file mode 100644
index 0000000..9085791
--- /dev/null
+++ b/.bandit.yml
@@ -0,0 +1,9 @@
+---
+# Bandit configuration file
+
+# Skip specific test IDs
+skips: [B104, B404, B603]
+
+# Plugin configs
+any_other_function_with_shell_equals_true:
+  no_shell: [subprocess.Popen] 
\ No newline at end of file
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..8991ac9
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,6 @@
+[flake8]
+max-line-length = 88
+extend-ignore = E501
+per-file-ignores =
+    server/server.py:E501
+    src/browser_use_mcp_server/cli.py:E501 
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 00fc465..104995a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,9 +41,6 @@ jobs:
       - name: "Python lint"
         run: uvx ruff check .
 
-      - name: "Validate project metadata"
-        run: uvx --from 'validate-pyproject[all,store]' validate-pyproject  pyproject.toml
-
   build-and-publish:
     runs-on: ubuntu-latest
 
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
index d77bb7b..52943f9 100644
--- a/.github/workflows/python-publish.yml
+++ b/.github/workflows/python-publish.yml
@@ -21,7 +21,7 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          fetch-depth: 1
+          fetch-depth: 0
 
       - name: Set up uv and Python
         uses: astral-sh/setup-uv@v5
@@ -30,18 +30,14 @@ jobs:
           python-version: "3.13"
           cache-dependency-glob: "pyproject.toml"
 
-      - name: Install python packages
-        run: |
-          uv sync
-      - name: Build a binary wheel and a source tarball
-        run: |
-          uv build --sdist --wheel --out-dir dist
+      - name: Build
+        run: uv build
 
-      - name: Publish build artifacts
+      - name: Upload build artifacts
         uses: actions/upload-artifact@v4
         with:
           name: pypi-dists
-          path: "./dist"
+          path: dist/
 
   pypi-publish:
     runs-on: ubuntu-latest
@@ -73,6 +69,7 @@ jobs:
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           packages-dir: dist/
+
   github-release:
     name: >-
       Sign the Python 🐍 distribution 📦 with Sigstore and upload them to GitHub
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..bafe386
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,59 @@
+[MASTER]
+# Python version
+py-version = 3.11
+
+# Disable specific messages
+disable=
+    C0301, # Line too long
+    R0402, # Use 'from mcp import types' instead
+    W1203, # Use lazy % formatting in logging functions
+    R0913, # Too many arguments
+    R0917, # Too many positional arguments
+    R0914, # Too many local variables
+    W0718, # Catching too general exception Exception
+    R0915, # Too many statements
+    W0613, # Unused argument
+    R1705, # Unnecessary "elif" after "return"
+    R0912, # Too many branches
+    W0621, # Redefining name from outer scope
+    W0404, # Reimport
+    C0415, # Import outside toplevel
+    W0212, # Access to a protected member
+    W0107, # Unnecessary pass statement
+    R0801, # Similar lines in files
+    import-error,
+    no-value-for-parameter,
+    logging-fstring-interpolation,
+    protected-access,
+    redefined-outer-name,
+    reimported
+
+# Add files or directories to the blacklist
+ignore=.git,__pycache__,.venv,dist,build
+
+# Use multiple processes to speed up Pylint
+jobs=4
+
+[FORMAT]
+# Maximum number of characters on a single line
+max-line-length=120
+
+# Maximum number of lines in a module
+max-module-lines=300
+
+[MESSAGES CONTROL]
+# Only show warnings with the listed confidence levels
+confidence=HIGH,CONTROL_FLOW
+
+[DESIGN]
+# Maximum number of arguments for function / method
+max-args=10
+
+# Maximum number of locals for function / method
+max-locals=30
+
+# Maximum number of statements in function / method body
+max-statements=60
+
+# Maximum number of branch for function / method body
+max-branches=15 
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 9adab69..a96f139 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,7 +7,7 @@ ENV UV_COMPILE_BYTECODE=1 \
 
 # Install build dependencies and clean up in the same layer
 RUN apt-get update -y && \
-    apt-get install --no-install-recommends -y clang && \
+    apt-get install --no-install-recommends -y clang git && \
     rm -rf /var/lib/apt/lists/*
 
 # Install Python before the project for caching
@@ -57,7 +57,8 @@ COPY --from=builder /app /app
 # Set proper permissions
 RUN chmod -R 755 /python /app
 
-ENV PATH="/app/.venv/bin:$PATH" \
+ENV ANONYMIZED_TELEMETRY=false \
+    PATH="/app/.venv/bin:$PATH" \
     DISPLAY=:0 \
     CHROME_BIN=/usr/bin/chromium \
     CHROMIUM_FLAGS="--no-sandbox --headless --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage"
diff --git a/pyproject.toml b/pyproject.toml
index 38c1cfb..bf9aa1e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,13 +1,10 @@
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-
 [project]
 name = "browser-use-mcp-server"
-version = "0.1.3"
+dynamic = ["version"]
 description = "MCP browser-use server library"
 readme = "README.md"
 requires-python = ">=3.11,<4.0"
+license = {text = "MIT"}
 authors = [
     {name = "Cobrowser Team"}
 ]
@@ -32,17 +29,19 @@ dependencies = [
 ]
 
 [project.optional-dependencies]
-dev = [
+# Dependencies for running tests
+test = [
     "pytest>=7.0.0",
     "pytest-asyncio>=0.21.0",
+    "pytest-cov>=4.1.0",
+]
+# Dependencies for development (includes test dependencies)
+dev = [
+    "browser-use-mcp-server[test]",
     "black>=23.0.0",
     "isort>=5.12.0",
     "mypy>=1.0.0",
-]
-test = [
-    "pytest>=7.0.0",
-    "pytest-asyncio>=0.21.0",
-    "pytest-cov>=4.1.0",
+    "ruff>=0.5.5",
 ]
 
 [project.urls]
@@ -53,6 +52,7 @@ test = [
 testpaths = ["tests"]
 python_files = "test_*.py"
 asyncio_mode = "auto"
+asyncio_default_fixture_loop_scope = "function"
 
 [tool.black]
 line-length = 88
@@ -72,9 +72,39 @@ disallow_incomplete_defs = true
 [project.scripts]
 browser-use-mcp-server = "browser_use_mcp_server.cli:cli"
 
+[build-system]
+requires = ["hatchling", "uv-dynamic-versioning"]
+build-backend = "hatchling.build"
+
 [tool.hatch.build]
-packages = ["src", "server"]
-include = ["server"]
+include = ["src/browser_use_mcp_server", "server"]
 
 [tool.hatch.build.targets.wheel]
 packages = ["src/browser_use_mcp_server", "server"]
+
+[tool.hatch.version]
+source = "uv-dynamic-versioning"
+
+[tool.uv-dynamic-versioning]
+vcs = "git"
+style = "pep440"
+bump = true
+
+[tool.ruff]
+line-length = 88
+target-version = "py311"
+
+[tool.ruff.lint]
+# Enable common Pyflakes, pycodestyle, and isort rules
+select = ["E", "F", "W", "I"]
+# Ignore line length violations in comments, docstrings, and string literals
+extend-ignore = ["E501"]
+
+# Exclude string literals and comments from line length checks
+[tool.ruff.lint.per-file-ignores]
+"server/server.py" = ["E501"]
+"src/browser_use_mcp_server/cli.py" = ["E501"]
+
+[tool.ruff.format]
+# Use black-compatible formatting
+quote-style = "double"
diff --git a/pyrightconfig.json b/pyrightconfig.json
new file mode 100644
index 0000000..1d23be8
--- /dev/null
+++ b/pyrightconfig.json
@@ -0,0 +1,8 @@
+{
+    "reportMissingImports": false,
+    "reportMissingModuleSource": false,
+    "reportOptionalMemberAccess": false,
+    "reportAttributeAccessIssue": false,
+    "reportCallIssue": false,
+    "reportFunctionMemberAccess": false
+}
\ No newline at end of file
diff --git a/server/__init__.py b/server/__init__.py
index cfa8a22..d6cba9a 100644
--- a/server/__init__.py
+++ b/server/__init__.py
@@ -1,3 +1,29 @@
-from .server import main
+"""
+Browser-Use MCP Server core implementation.
 
-__all__ = ["main"]
+This package provides the core implementation of the MCP server for browser automation.
+"""
+
+from .server import (
+    CONFIG,
+    Server,
+    cleanup_old_tasks,
+    create_browser_context_for_task,
+    create_mcp_server,
+    init_configuration,
+    main,
+    run_browser_task_async,
+    task_store,
+)
+
+__all__ = [
+    "Server",
+    "main",
+    "create_browser_context_for_task",
+    "run_browser_task_async",
+    "cleanup_old_tasks",
+    "create_mcp_server",
+    "init_configuration",
+    "CONFIG",
+    "task_store",
+]
diff --git a/server/server.py b/server/server.py
index 52eff2c..5ef695c 100644
--- a/server/server.py
+++ b/server/server.py
@@ -10,34 +10,41 @@
 """
 
 # Standard library imports
-import os
 import asyncio
 import json
 import logging
+import os
+import sys
+
+# Set up SSE transport
+import threading
+import time
 import traceback
 import uuid
 from datetime import datetime
 from typing import Any, Dict, Optional, Tuple, Union
-import time
-import sys
 
 # Third-party imports
 import click
-from dotenv import load_dotenv
-from pythonjsonlogger import jsonlogger
+import mcp.types as types
+import uvicorn
 
 # Browser-use library imports
 from browser_use import Agent
 from browser_use.browser.browser import Browser, BrowserConfig
 from browser_use.browser.context import BrowserContext, BrowserContextConfig
-
-# MCP server components
-from mcp.server import Server
-import mcp.types as types
+from dotenv import load_dotenv
+from langchain_core.language_models import BaseLanguageModel
 
 # LLM provider
 from langchain_openai import ChatOpenAI
-from langchain_core.language_models import BaseLanguageModel
+
+# MCP server components
+from mcp.server import Server
+from mcp.server.sse import SseServerTransport
+from pythonjsonlogger import jsonlogger
+from starlette.applications import Starlette
+from starlette.routing import Mount, Route
 
 # Configure logging
 logger = logging.getLogger()
@@ -805,14 +812,6 @@ def main(
         locale=locale,
     )
 
-    # Set up SSE transport
-    from mcp.server.sse import SseServerTransport
-    from starlette.applications import Starlette
-    from starlette.routing import Mount, Route
-    import uvicorn
-    import asyncio
-    import threading
-
     sse = SseServerTransport("/messages/")
 
     # Create the Starlette app for SSE
@@ -891,7 +890,7 @@ def run_uvicorn():
 
         uvicorn.run(
             starlette_app,
-            host="0.0.0.0",
+            host="0.0.0.0",  # nosec
             port=port,
             log_config=log_config,
             log_level="info",
@@ -899,7 +898,7 @@ def run_uvicorn():
 
     # If proxy mode is enabled, run both the SSE server and mcp-proxy
     if stdio:
-        import subprocess
+        import subprocess  # nosec
 
         # Start the SSE server in a separate thread
         sse_thread = threading.Thread(target=run_uvicorn)
@@ -924,7 +923,8 @@ def run_uvicorn():
         )
 
         try:
-            with subprocess.Popen(proxy_cmd) as proxy_process:
+            # Using trusted command arguments from CLI parameters
+            with subprocess.Popen(proxy_cmd) as proxy_process:  # nosec
                 proxy_process.wait()
         except Exception as e:
             logger.error(f"Error starting mcp-proxy: {str(e)}")
diff --git a/src/browser_use_mcp_server/__init__.py b/src/browser_use_mcp_server/__init__.py
index 853878c..6b4973f 100644
--- a/src/browser_use_mcp_server/__init__.py
+++ b/src/browser_use_mcp_server/__init__.py
@@ -4,5 +4,3 @@
 This package provides a Model-Control-Protocol (MCP) server for browser automation
 using the browser_use library.
 """
-
-__version__ = "0.1.3"
diff --git a/src/browser_use_mcp_server/cli.py b/src/browser_use_mcp_server/cli.py
index da15747..94f8f2e 100644
--- a/src/browser_use_mcp_server/cli.py
+++ b/src/browser_use_mcp_server/cli.py
@@ -5,14 +5,17 @@
 It wraps the existing server functionality with a CLI.
 """
 
-import os
-import sys
 import json
 import logging
+import sys
+from typing import Optional
+
 import click
-import importlib.util
 from pythonjsonlogger import jsonlogger
 
+# Import directly from our package
+from browser_use_mcp_server.server import main as server_main
+
 # Configure logging for CLI
 logger = logging.getLogger()
 logger.handlers = []  # Remove any existing handlers
@@ -25,50 +28,15 @@
 logger.setLevel(logging.INFO)
 
 
-def log_error(message: str, error: Exception = None):
+def log_error(message: str, error: Optional[Exception] = None):
     """Log error in JSON format to stderr"""
     error_data = {"error": message, "traceback": str(error) if error else None}
     print(json.dumps(error_data), file=sys.stderr)
 
 
-def import_server_module():
-    """
-    Import the server module from the server directory.
-    This allows us to reuse the existing server code.
-    """
-    # Add the root directory to the Python path to find server module
-    root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
-    sys.path.insert(0, root_dir)
-
-    try:
-        # Try to import the server module
-        import server.server
-
-        return server.server
-    except ImportError:
-        # If running as an installed package, the server module might be elsewhere
-        try:
-            # Look in common locations
-            if os.path.exists(os.path.join(root_dir, "server", "server.py")):
-                spec = importlib.util.spec_from_file_location(
-                    "server.server", os.path.join(root_dir, "server", "server.py")
-                )
-                server_module = importlib.util.module_from_spec(spec)
-                spec.loader.exec_module(server_module)
-                return server_module
-        except Exception as e:
-            log_error("Could not import server module", e)
-            raise ImportError(f"Could not import server module: {e}")
-
-        raise ImportError(
-            "Could not find server module. Make sure it's installed correctly."
-        )
-
-
 @click.group()
 def cli():
     """Browser-use MCP server command line interface."""
-    pass
 
 
 @cli.command()
@@ -112,9 +80,6 @@ def run(
         sys.exit(1)
 
     try:
-        # Import the server module
-        server_module = import_server_module()
-
         # We need to construct the command line arguments to pass to the server's Click command
         old_argv = sys.argv.copy()
 
@@ -144,7 +109,7 @@ def run(
 
         # Run the server's command directly
         try:
-            return server_module.main()
+            return server_main()
         finally:
             # Restore original sys.argv
             sys.argv = old_argv
diff --git a/src/browser_use_mcp_server/server.py b/src/browser_use_mcp_server/server.py
index a101b80..4679aad 100644
--- a/src/browser_use_mcp_server/server.py
+++ b/src/browser_use_mcp_server/server.py
@@ -4,24 +4,18 @@
 This provides a clean import path for the CLI and other code.
 """
 
-import os
-import sys
 from server.server import (
+    CONFIG,
     Server,
-    main,
-    create_browser_context_for_task,
-    run_browser_task_async,
     cleanup_old_tasks,
+    create_browser_context_for_task,
     create_mcp_server,
     init_configuration,
-    CONFIG,
+    main,
+    run_browser_task_async,
     task_store,
 )
 
-# Add the root directory to the Python path to find server module
-root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
-sys.path.insert(0, root_dir)
-
 # Re-export everything we imported
 __all__ = [
     "Server",


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**.github/workflows/python-publish.yml:34**
* Verify that the 'uv build' command generates both the wheel and sdist artifacts as expected. If it does not, adjust the command to explicitly build both distributions to ensure consistency with downstream steps.
```
run: uv build
```
**pyproject.toml:88**
* [nitpick] Ensure that automatic version bumping with 'bump = true' aligns with your release process, as it might lead to unintended version increments if not managed carefully.
```
bump = true
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T16:24:32Z
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 9 out of 13 changed files in this pull request and generated 1 comment.

<details>
<summary>Files not reviewed (4)</summary>

* **.flake8**: Language not supported
* **.pylintrc**: Language not supported
* **Dockerfile**: Language not supported
* **pyrightconfig.json**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/browser_use_mcp_server/__init__.py:8**
* The static version '__version__ = "0.0.0"' may cause confusion when using dynamic versioning. Consider removing it or adding a comment to clarify that the version is dynamically replaced during build.
```
__version__ = "0.0.0"
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T22:06:11Z
user: login: maceip
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T18:02:56Z
user: login: maceip
body: lgtm
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T18:03:24Z
user: login: michiosw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T18:27:53Z
user: login: hashkode
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T20:52:32Z
user: login: hashkode
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T20:53:10Z
user: login: hashkode
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T22:08:18Z

Review comments:
diff_hunk: @@ -806,12 +806,13 @@ def main(
     )
 
     # Set up SSE transport
+    import asyncio
path: server/server.py
user: login: Copilot
body: [nitpick] The module 'asyncio' is already imported at the top of the file; consider removing this duplicate import to improve code clarity.
```suggestion

```
created_at: 2025-04-10T22:06:10Z
author_association: NONE
diff_hunk: @@ -1,13 +1,10 @@
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-
 [project]
 name = "browser-use-mcp-server"
-version = "0.1.3"
+dynamic = ["version"]
path: pyproject.toml
user: login: maceip
body: thank god
created_at: 2025-04-11T18:02:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,4 +5,4 @@
 using the browser_use library.
 """
 
-__version__ = "0.1.3"
+__version__ = "0.0.0"
path: src/browser_use_mcp_server/__init__.py
user: login: michiosw
body: Is this versioning linked to our auto versioning?
created_at: 2025-04-11T18:26:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,13 +1,10 @@
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-
 [project]
 name = "browser-use-mcp-server"
-version = "0.1.3"
+dynamic = ["version"]
path: pyproject.toml
user: login: hashkode
body: yeah it's pretty great, good stuff by the uv gang
created_at: 2025-04-11T20:52:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,4 +5,4 @@
 using the browser_use library.
 """
 
-__version__ = "0.1.3"
+__version__ = "0.0.0"
path: src/browser_use_mcp_server/__init__.py
user: login: hashkode
body: not exactly, but it's somewhat helpful to keep tools calm. removal is a bit difficult I think, could be investigated, though.
created_at: 2025-04-11T20:53:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,4 +5,4 @@
 using the browser_use library.
 """
 
-__version__ = "0.1.3"
+__version__ = "0.0.0"
path: src/browser_use_mcp_server/__init__.py
user: login: hashkode
body: removed, somehow the quirky complaints disappeared. i think it was part of the linter stage (was incompatible with uv dynamic versioning as a whole), which i removed. so not required anymore.
created_at: 2025-04-11T22:08:17Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-10T16:27:12Z
body: ## [🦙 MegaLinter](https://megalinter.io/8.3.0) status: ⚠️ [WARNING](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260)

| Descriptor  |                                  Linter                                   |Files|Fixed|                                      Errors                                       |Elapsed time|
|-------------|---------------------------------------------------------------------------|-----|----:|-----------------------------------------------------------------------------------|------------|
|✅ ACTION    |[actionlint](https://megalinter.io/8.3.0/descriptors/action_actionlint)    |    2|     |                                                                                  0|0.02s       |
|⚠️ COPYPASTE |[jscpd](https://megalinter.io/8.3.0/descriptors/copypaste_jscpd)           |yes  |     |[2](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260) |1.39s       |
|⚠️ DOCKERFILE|[hadolint](https://megalinter.io/8.3.0/descriptors/dockerfile_hadolint)    |    1|     |[1](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260) |0.18s       |
|✅ JSON      |[jsonlint](https://megalinter.io/8.3.0/descriptors/json_jsonlint)          |    1|     |                                                                                  0|0.2s        |
|✅ JSON      |[prettier](https://megalinter.io/8.3.0/descriptors/json_prettier)          |    1|    1|                                                                                  0|0.39s       |
|✅ JSON      |[v8r](https://megalinter.io/8.3.0/descriptors/json_v8r)                    |    1|     |                                                                                  0|3.15s       |
|✅ PYTHON    |[bandit](https://megalinter.io/8.3.0/descriptors/python_bandit)            |    5|     |                                                                                  0|0.76s       |
|✅ PYTHON    |[black](https://megalinter.io/8.3.0/descriptors/python_black)              |    5|    0|                                                                                  0|0.71s       |
|✅ PYTHON    |[flake8](https://megalinter.io/8.3.0/descriptors/python_flake8)            |    5|     |                                                                                  0|0.4s        |
|✅ PYTHON    |[isort](https://megalinter.io/8.3.0/descriptors/python_isort)              |    5|    1|                                                                                  0|0.17s       |
|✅ PYTHON    |[mypy](https://megalinter.io/8.3.0/descriptors/python_mypy)                |    5|     |                                                                                  0|2.96s       |
|✅ PYTHON    |[pylint](https://megalinter.io/8.3.0/descriptors/python_pylint)            |    5|     |                                                                                  0|5.76s       |
|✅ PYTHON    |[pyright](https://megalinter.io/8.3.0/descriptors/python_pyright)          |    5|     |                                                                                  0|4.93s       |
|✅ PYTHON    |[ruff](https://megalinter.io/8.3.0/descriptors/python_ruff)                |    5|    1|                                                                                  0|0.02s       |
|⚠️ REPOSITORY|[checkov](https://megalinter.io/8.3.0/descriptors/repository_checkov)      |yes  |     |[3](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260) |10.91s      |
|⚠️ REPOSITORY|[devskim](https://megalinter.io/8.3.0/descriptors/repository_devskim)      |yes  |     |[2](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260) |1.17s       |
|✅ REPOSITORY|[dustilock](https://megalinter.io/8.3.0/descriptors/repository_dustilock)  |yes  |     |no                                                                                 |0.01s       |
|✅ REPOSITORY|[gitleaks](https://megalinter.io/8.3.0/descriptors/repository_gitleaks)    |yes  |     |no                                                                                 |0.27s       |
|✅ REPOSITORY|[git_diff](https://megalinter.io/8.3.0/descriptors/repository_git_diff)    |yes  |     |no                                                                                 |0.01s       |
|✅ REPOSITORY|[grype](https://megalinter.io/8.3.0/descriptors/repository_grype)          |yes  |     |no                                                                                 |11.14s      |
|⚠️ REPOSITORY|[kics](https://megalinter.io/8.3.0/descriptors/repository_kics)            |yes  |     |[31](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260)|1.97s       |
|✅ REPOSITORY|[secretlint](https://megalinter.io/8.3.0/descriptors/repository_secretlint)|yes  |     |no                                                                                 |0.67s       |
|✅ REPOSITORY|[syft](https://megalinter.io/8.3.0/descriptors/repository_syft)            |yes  |     |no                                                                                 |1.05s       |
|⚠️ REPOSITORY|[trivy](https://megalinter.io/8.3.0/descriptors/repository_trivy)          |yes  |     |[1](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260) |5.85s       |
|✅ REPOSITORY|[trivy-sbom](https://megalinter.io/8.3.0/descriptors/repository_trivy_sbom)|yes  |     |no                                                                                 |0.07s       |
|✅ REPOSITORY|[trufflehog](https://megalinter.io/8.3.0/descriptors/repository_trufflehog)|yes  |     |no                                                                                 |2.94s       |
|✅ YAML      |[prettier](https://megalinter.io/8.3.0/descriptors/yaml_prettier)          |    3|    1|                                                                                  0|0.55s       |
|✅ YAML      |[v8r](https://megalinter.io/8.3.0/descriptors/yaml_v8r)                    |    3|     |                                                                                  0|3.75s       |
|✅ YAML      |[yamllint](https://megalinter.io/8.3.0/descriptors/yaml_yamllint)          |    3|     |                                                                                  0|0.39s       |

See detailed report in [MegaLinter reports](https://github.com/co-browser/browser-use-mcp-server/actions/runs/14412827260)
_Set `VALIDATE_ALL_CODEBASE: true` in mega-linter.yml to validate all sources, not only the diff_

_MegaLinter is graciously provided by [![OX Security](https://www.ox.security/wp-content/uploads/2022/06/logo.svg?ref=megalinter_comment)](https://www.ox.security/?ref=megalinter)_

<!-- megalinter: github-comment-reporter workflow='MegaLinter' jobid='megalinter' -->

author_association: NONE
user: login: michiosw
created_at: 2025-04-15T18:16:44Z
body: :tada: This PR is included in version 1.0.1 :tada:

The release is available on [GitHub release](https://github.com/co-browser/browser-use-mcp-server/releases/tag/v1.0.1)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: CONTRIBUTOR