Skip to content

Commit df11584

Browse files
authored
Merge pull request #36 from co-browser/35-feature-fix-pypi-package-release-versioning
fix: enhance project configuration with dynamic versioning and update CI workflow for artifact handling
2 parents 6f5ccda + 0b0d41a commit df11584

File tree

13 files changed

+195
-105
lines changed

13 files changed

+195
-105
lines changed

.bandit.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
# Bandit configuration file
3+
4+
# Skip specific test IDs
5+
skips: [B104, B404, B603]
6+
7+
# Plugin configs
8+
any_other_function_with_shell_equals_true:
9+
no_shell: [subprocess.Popen]

.flake8

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[flake8]
2+
max-line-length = 88
3+
extend-ignore = E501
4+
per-file-ignores =
5+
server/server.py:E501
6+
src/browser_use_mcp_server/cli.py:E501

.github/workflows/ci.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ jobs:
4141
- name: "Python lint"
4242
run: uvx ruff check .
4343

44-
- name: "Validate project metadata"
45-
run: uvx --from 'validate-pyproject[all,store]' validate-pyproject pyproject.toml
46-
4744
build-and-publish:
4845
runs-on: ubuntu-latest
4946

.github/workflows/python-publish.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
steps:
2222
- uses: actions/checkout@v4
2323
with:
24-
fetch-depth: 1
24+
fetch-depth: 0
2525

2626
- name: Set up uv and Python
2727
uses: astral-sh/setup-uv@v5
@@ -30,18 +30,14 @@ jobs:
3030
python-version: "3.13"
3131
cache-dependency-glob: "pyproject.toml"
3232

33-
- name: Install python packages
34-
run: |
35-
uv sync
36-
- name: Build a binary wheel and a source tarball
37-
run: |
38-
uv build --sdist --wheel --out-dir dist
33+
- name: Build
34+
run: uv build
3935

40-
- name: Publish build artifacts
36+
- name: Upload build artifacts
4137
uses: actions/upload-artifact@v4
4238
with:
4339
name: pypi-dists
44-
path: "./dist"
40+
path: dist/
4541

4642
pypi-publish:
4743
runs-on: ubuntu-latest
@@ -73,6 +69,7 @@ jobs:
7369
uses: pypa/gh-action-pypi-publish@release/v1
7470
with:
7571
packages-dir: dist/
72+
7673
github-release:
7774
name: >-
7875
Sign the Python 🐍 distribution 📦 with Sigstore and upload them to GitHub

.pylintrc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
[MASTER]
2+
# Python version
3+
py-version = 3.11
4+
5+
# Disable specific messages
6+
disable=
7+
C0301, # Line too long
8+
R0402, # Use 'from mcp import types' instead
9+
W1203, # Use lazy % formatting in logging functions
10+
R0913, # Too many arguments
11+
R0917, # Too many positional arguments
12+
R0914, # Too many local variables
13+
W0718, # Catching too general exception Exception
14+
R0915, # Too many statements
15+
W0613, # Unused argument
16+
R1705, # Unnecessary "elif" after "return"
17+
R0912, # Too many branches
18+
W0621, # Redefining name from outer scope
19+
W0404, # Reimport
20+
C0415, # Import outside toplevel
21+
W0212, # Access to a protected member
22+
W0107, # Unnecessary pass statement
23+
R0801, # Similar lines in files
24+
import-error,
25+
no-value-for-parameter,
26+
logging-fstring-interpolation,
27+
protected-access,
28+
redefined-outer-name,
29+
reimported
30+
31+
# Add files or directories to the blacklist
32+
ignore=.git,__pycache__,.venv,dist,build
33+
34+
# Use multiple processes to speed up Pylint
35+
jobs=4
36+
37+
[FORMAT]
38+
# Maximum number of characters on a single line
39+
max-line-length=120
40+
41+
# Maximum number of lines in a module
42+
max-module-lines=300
43+
44+
[MESSAGES CONTROL]
45+
# Only show warnings with the listed confidence levels
46+
confidence=HIGH,CONTROL_FLOW
47+
48+
[DESIGN]
49+
# Maximum number of arguments for function / method
50+
max-args=10
51+
52+
# Maximum number of locals for function / method
53+
max-locals=30
54+
55+
# Maximum number of statements in function / method body
56+
max-statements=60
57+
58+
# Maximum number of branch for function / method body
59+
max-branches=15

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ENV UV_COMPILE_BYTECODE=1 \
77

88
# Install build dependencies and clean up in the same layer
99
RUN apt-get update -y && \
10-
apt-get install --no-install-recommends -y clang && \
10+
apt-get install --no-install-recommends -y clang git && \
1111
rm -rf /var/lib/apt/lists/*
1212

1313
# Install Python before the project for caching
@@ -57,7 +57,8 @@ COPY --from=builder /app /app
5757
# Set proper permissions
5858
RUN chmod -R 755 /python /app
5959

60-
ENV PATH="/app/.venv/bin:$PATH" \
60+
ENV ANONYMIZED_TELEMETRY=false \
61+
PATH="/app/.venv/bin:$PATH" \
6162
DISPLAY=:0 \
6263
CHROME_BIN=/usr/bin/chromium \
6364
CHROMIUM_FLAGS="--no-sandbox --headless --disable-gpu --disable-software-rasterizer --disable-dev-shm-usage"

pyproject.toml

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
[build-system]
2-
requires = ["hatchling"]
3-
build-backend = "hatchling.build"
4-
51
[project]
62
name = "browser-use-mcp-server"
7-
version = "0.1.3"
3+
dynamic = ["version"]
84
description = "MCP browser-use server library"
95
readme = "README.md"
106
requires-python = ">=3.11,<4.0"
7+
license = {text = "MIT"}
118
authors = [
129
{name = "Cobrowser Team"}
1310
]
@@ -32,17 +29,19 @@ dependencies = [
3229
]
3330

3431
[project.optional-dependencies]
35-
dev = [
32+
# Dependencies for running tests
33+
test = [
3634
"pytest>=7.0.0",
3735
"pytest-asyncio>=0.21.0",
36+
"pytest-cov>=4.1.0",
37+
]
38+
# Dependencies for development (includes test dependencies)
39+
dev = [
40+
"browser-use-mcp-server[test]",
3841
"black>=23.0.0",
3942
"isort>=5.12.0",
4043
"mypy>=1.0.0",
41-
]
42-
test = [
43-
"pytest>=7.0.0",
44-
"pytest-asyncio>=0.21.0",
45-
"pytest-cov>=4.1.0",
44+
"ruff>=0.5.5",
4645
]
4746

4847
[project.urls]
@@ -53,6 +52,7 @@ test = [
5352
testpaths = ["tests"]
5453
python_files = "test_*.py"
5554
asyncio_mode = "auto"
55+
asyncio_default_fixture_loop_scope = "function"
5656

5757
[tool.black]
5858
line-length = 88
@@ -72,9 +72,39 @@ disallow_incomplete_defs = true
7272
[project.scripts]
7373
browser-use-mcp-server = "browser_use_mcp_server.cli:cli"
7474

75+
[build-system]
76+
requires = ["hatchling", "uv-dynamic-versioning"]
77+
build-backend = "hatchling.build"
78+
7579
[tool.hatch.build]
76-
packages = ["src", "server"]
77-
include = ["server"]
80+
include = ["src/browser_use_mcp_server", "server"]
7881

7982
[tool.hatch.build.targets.wheel]
8083
packages = ["src/browser_use_mcp_server", "server"]
84+
85+
[tool.hatch.version]
86+
source = "uv-dynamic-versioning"
87+
88+
[tool.uv-dynamic-versioning]
89+
vcs = "git"
90+
style = "pep440"
91+
bump = true
92+
93+
[tool.ruff]
94+
line-length = 88
95+
target-version = "py311"
96+
97+
[tool.ruff.lint]
98+
# Enable common Pyflakes, pycodestyle, and isort rules
99+
select = ["E", "F", "W", "I"]
100+
# Ignore line length violations in comments, docstrings, and string literals
101+
extend-ignore = ["E501"]
102+
103+
# Exclude string literals and comments from line length checks
104+
[tool.ruff.lint.per-file-ignores]
105+
"server/server.py" = ["E501"]
106+
"src/browser_use_mcp_server/cli.py" = ["E501"]
107+
108+
[tool.ruff.format]
109+
# Use black-compatible formatting
110+
quote-style = "double"

pyrightconfig.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"reportMissingImports": false,
3+
"reportMissingModuleSource": false,
4+
"reportOptionalMemberAccess": false,
5+
"reportAttributeAccessIssue": false,
6+
"reportCallIssue": false,
7+
"reportFunctionMemberAccess": false
8+
}

server/__init__.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1-
from .server import main
1+
"""
2+
Browser-Use MCP Server core implementation.
23
3-
__all__ = ["main"]
4+
This package provides the core implementation of the MCP server for browser automation.
5+
"""
6+
7+
from .server import (
8+
CONFIG,
9+
Server,
10+
cleanup_old_tasks,
11+
create_browser_context_for_task,
12+
create_mcp_server,
13+
init_configuration,
14+
main,
15+
run_browser_task_async,
16+
task_store,
17+
)
18+
19+
__all__ = [
20+
"Server",
21+
"main",
22+
"create_browser_context_for_task",
23+
"run_browser_task_async",
24+
"cleanup_old_tasks",
25+
"create_mcp_server",
26+
"init_configuration",
27+
"CONFIG",
28+
"task_store",
29+
]

server/server.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,41 @@
1010
"""
1111

1212
# Standard library imports
13-
import os
1413
import asyncio
1514
import json
1615
import logging
16+
import os
17+
import sys
18+
19+
# Set up SSE transport
20+
import threading
21+
import time
1722
import traceback
1823
import uuid
1924
from datetime import datetime
2025
from typing import Any, Dict, Optional, Tuple, Union
21-
import time
22-
import sys
2326

2427
# Third-party imports
2528
import click
26-
from dotenv import load_dotenv
27-
from pythonjsonlogger import jsonlogger
29+
import mcp.types as types
30+
import uvicorn
2831

2932
# Browser-use library imports
3033
from browser_use import Agent
3134
from browser_use.browser.browser import Browser, BrowserConfig
3235
from browser_use.browser.context import BrowserContext, BrowserContextConfig
33-
34-
# MCP server components
35-
from mcp.server import Server
36-
import mcp.types as types
36+
from dotenv import load_dotenv
37+
from langchain_core.language_models import BaseLanguageModel
3738

3839
# LLM provider
3940
from langchain_openai import ChatOpenAI
40-
from langchain_core.language_models import BaseLanguageModel
41+
42+
# MCP server components
43+
from mcp.server import Server
44+
from mcp.server.sse import SseServerTransport
45+
from pythonjsonlogger import jsonlogger
46+
from starlette.applications import Starlette
47+
from starlette.routing import Mount, Route
4148

4249
# Configure logging
4350
logger = logging.getLogger()
@@ -805,14 +812,6 @@ def main(
805812
locale=locale,
806813
)
807814

808-
# Set up SSE transport
809-
from mcp.server.sse import SseServerTransport
810-
from starlette.applications import Starlette
811-
from starlette.routing import Mount, Route
812-
import uvicorn
813-
import asyncio
814-
import threading
815-
816815
sse = SseServerTransport("/messages/")
817816

818817
# Create the Starlette app for SSE
@@ -891,15 +890,15 @@ def run_uvicorn():
891890

892891
uvicorn.run(
893892
starlette_app,
894-
host="0.0.0.0",
893+
host="0.0.0.0", # nosec
895894
port=port,
896895
log_config=log_config,
897896
log_level="info",
898897
)
899898

900899
# If proxy mode is enabled, run both the SSE server and mcp-proxy
901900
if stdio:
902-
import subprocess
901+
import subprocess # nosec
903902

904903
# Start the SSE server in a separate thread
905904
sse_thread = threading.Thread(target=run_uvicorn)
@@ -924,7 +923,8 @@ def run_uvicorn():
924923
)
925924

926925
try:
927-
with subprocess.Popen(proxy_cmd) as proxy_process:
926+
# Using trusted command arguments from CLI parameters
927+
with subprocess.Popen(proxy_cmd) as proxy_process: # nosec
928928
proxy_process.wait()
929929
except Exception as e:
930930
logger.error(f"Error starting mcp-proxy: {str(e)}")

src/browser_use_mcp_server/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,3 @@
44
This package provides a Model-Control-Protocol (MCP) server for browser automation
55
using the browser_use library.
66
"""
7-
8-
__version__ = "0.1.3"

0 commit comments

Comments
 (0)