Bug 2018245 - Give firefox-devtools-mcp better defaults r=ai4dev-reviewers,padenot
Differential Revision: https://phabricator.services.mozilla.com/D294087
This commit is contained in:
committed by
jdescottes@mozilla.com
parent
d0b8a022bc
commit
73620ff460
+1
-1
@@ -3,4 +3,4 @@ url = "https://mcp-dev.moz.tools/mcp"
|
||||
|
||||
[mcp_servers.firefox-devtools]
|
||||
command = "./mach"
|
||||
args = ["npx", "@mozilla/firefox-devtools-mcp-moz", "--pref", "browser.ml.enable=true", "--enable-scripting", "--enable-privileged-context"]
|
||||
args = ["npx", "@mozilla/firefox-devtools-mcp-moz", "--pref", "browser.ml.enable=true", "--enable-script", "--enable-privileged-context"]
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
"command": "./mach",
|
||||
"args": [
|
||||
"--quiet",
|
||||
"npx",
|
||||
"@mozilla/firefox-devtools-mcp-moz",
|
||||
"devtools-mcp",
|
||||
"--pref",
|
||||
"browser.ml.enable=true",
|
||||
"--enable-scripting",
|
||||
"--enable-privileged-context"
|
||||
"remote.prefs.recommended=false",
|
||||
"--pref",
|
||||
"browser.smartwindow.enabled=true",
|
||||
"--enable-privileged-context",
|
||||
"--enable-script"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ MACH_COMMANDS = {
|
||||
"data-review": MachCommandReference(
|
||||
"toolkit/components/glean/build_scripts/mach_commands.py"
|
||||
),
|
||||
"devtools-mcp": MachCommandReference("tools/mach_commands.py"),
|
||||
"devtools-node-test": MachCommandReference("devtools/mach_commands.py"),
|
||||
"doc": MachCommandReference("tools/moztreedocs/mach_commands.py"),
|
||||
"doctor": MachCommandReference("python/mozbuild/mozbuild/mach_commands.py"),
|
||||
|
||||
@@ -91,6 +91,8 @@ subsuite = "mozbuild"
|
||||
|
||||
["test_containers.py"]
|
||||
|
||||
["test_devtools_mcp.py"]
|
||||
|
||||
["test_dotproperties.py"]
|
||||
|
||||
["test_expression.py"]
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import buildconfig
|
||||
from mach.registrar import Registrar
|
||||
from mozunit import main
|
||||
|
||||
sys.path.insert(0, os.path.join(buildconfig.topsrcdir, "tools"))
|
||||
|
||||
|
||||
class TestDevtoolsMcp(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.remove_cats = []
|
||||
for cat in ("build", "post-build", "misc", "testing", "devenv"):
|
||||
if cat in Registrar.categories:
|
||||
continue
|
||||
Registrar.register_category(cat, cat, cat)
|
||||
self.remove_cats.append(cat)
|
||||
|
||||
def tearDown(self):
|
||||
for cat in self.remove_cats:
|
||||
del Registrar.categories[cat]
|
||||
del Registrar.commands_by_category[cat]
|
||||
|
||||
def _mock_context(self, topobjdir="/obj", binary_path="/obj/dist/bin/firefox"):
|
||||
ctx = MagicMock()
|
||||
ctx.topobjdir = topobjdir
|
||||
ctx.get_binary_path.return_value = binary_path
|
||||
return ctx
|
||||
|
||||
@patch("os.path.exists", return_value=True)
|
||||
@patch("mach_commands.npx")
|
||||
def test_delegates_to_npx_with_build_args(self, mock_npx, mock_exists):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
mock_context = self._mock_context()
|
||||
mock_npx.return_value = 0
|
||||
|
||||
devtools_mcp(mock_context, args=["--pref", "x=1"])
|
||||
|
||||
mock_context.get_binary_path.assert_called_once_with(validate_exists=True)
|
||||
mock_npx.assert_called_once_with(
|
||||
mock_context,
|
||||
[
|
||||
"@mozilla/firefox-devtools-mcp-moz",
|
||||
"--firefox-path",
|
||||
"/obj/dist/bin/firefox",
|
||||
"--profile-path",
|
||||
"/obj/tmp/profile-default",
|
||||
"--pref",
|
||||
"x=1",
|
||||
],
|
||||
)
|
||||
|
||||
@patch("mach_commands.npx")
|
||||
def test_starts_without_binary_when_no_build(self, mock_npx):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
from mozbuild.base import BinaryNotFoundException
|
||||
|
||||
mock_context = self._mock_context()
|
||||
mock_context.get_binary_path.side_effect = BinaryNotFoundException(
|
||||
"/obj/dist/bin/firefox"
|
||||
)
|
||||
mock_npx.return_value = 0
|
||||
|
||||
result = devtools_mcp(mock_context, args=[])
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
mock_npx.assert_called_once_with(
|
||||
mock_context,
|
||||
["@mozilla/firefox-devtools-mcp-moz"],
|
||||
)
|
||||
|
||||
@patch("mach_commands.npx")
|
||||
def test_starts_without_binary_when_no_build_environment(self, mock_npx):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
from mozbuild.base import BuildEnvironmentNotFoundException
|
||||
|
||||
mock_context = self._mock_context()
|
||||
mock_context.get_binary_path.side_effect = BuildEnvironmentNotFoundException(
|
||||
"no build environment"
|
||||
)
|
||||
mock_npx.return_value = 0
|
||||
|
||||
result = devtools_mcp(mock_context, args=[])
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
mock_npx.assert_called_once_with(
|
||||
mock_context,
|
||||
["@mozilla/firefox-devtools-mcp-moz"],
|
||||
)
|
||||
|
||||
@patch("os.path.exists", return_value=True)
|
||||
@patch("mach_commands.npx")
|
||||
def test_works_with_no_extra_args(self, mock_npx, mock_exists):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
mock_context = self._mock_context()
|
||||
mock_npx.return_value = 0
|
||||
|
||||
devtools_mcp(mock_context, args=[])
|
||||
|
||||
mock_npx.assert_called_once_with(
|
||||
mock_context,
|
||||
[
|
||||
"@mozilla/firefox-devtools-mcp-moz",
|
||||
"--firefox-path",
|
||||
"/obj/dist/bin/firefox",
|
||||
"--profile-path",
|
||||
"/obj/tmp/profile-default",
|
||||
],
|
||||
)
|
||||
|
||||
@patch("os.path.exists", return_value=True)
|
||||
@patch("mach_commands.npx")
|
||||
def test_profile_path_derives_from_topobjdir(self, mock_npx, mock_exists):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
mock_context = self._mock_context(
|
||||
topobjdir="/builds/objdir",
|
||||
binary_path="/somewhere/else/dist/bin/firefox",
|
||||
)
|
||||
mock_npx.return_value = 0
|
||||
|
||||
devtools_mcp(mock_context, args=[])
|
||||
|
||||
call_args = mock_npx.call_args[0][1]
|
||||
profile_idx = call_args.index("--profile-path")
|
||||
self.assertEqual(
|
||||
call_args[profile_idx + 1], "/builds/objdir/tmp/profile-default"
|
||||
)
|
||||
|
||||
@patch("os.path.exists", return_value=True)
|
||||
@patch("mach_commands.npx")
|
||||
def test_skips_binary_detection_when_firefox_path_provided(
|
||||
self, mock_npx, mock_exists
|
||||
):
|
||||
from mach_commands import devtools_mcp
|
||||
|
||||
mock_context = self._mock_context()
|
||||
mock_npx.return_value = 0
|
||||
|
||||
devtools_mcp(mock_context, args=["--firefox-path", "/custom/firefox"])
|
||||
|
||||
mock_context.get_binary_path.assert_not_called()
|
||||
mock_npx.assert_called_once_with(
|
||||
mock_context,
|
||||
["@mozilla/firefox-devtools-mcp-moz", "--firefox-path", "/custom/firefox"],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -310,6 +310,41 @@ def npx(command_context, args):
|
||||
)
|
||||
|
||||
|
||||
@Command(
|
||||
"devtools-mcp",
|
||||
category="devenv",
|
||||
description="Run the firefox-devtools-mcp server with the local build.",
|
||||
)
|
||||
@CommandArgument("args", nargs=argparse.REMAINDER)
|
||||
def devtools_mcp(command_context, args):
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from mozbuild.base import BinaryNotFoundException, BuildEnvironmentNotFoundException
|
||||
|
||||
extra_args = []
|
||||
|
||||
if "--firefox-path" not in args and "--firefoxPath" not in args:
|
||||
binary_path = None
|
||||
try:
|
||||
binary_path = command_context.get_binary_path(validate_exists=True)
|
||||
except (BuildEnvironmentNotFoundException, BinaryNotFoundException) as e:
|
||||
print(f"Warning: Local build not found: {e}")
|
||||
|
||||
if binary_path and os.path.exists(binary_path):
|
||||
extra_args += ["--firefox-path", binary_path]
|
||||
if "--profile-path" not in args and "--profilePath" not in args:
|
||||
profile_path = (
|
||||
Path(command_context.topobjdir) / "tmp" / "profile-default"
|
||||
).as_posix()
|
||||
extra_args += ["--profile-path", profile_path]
|
||||
|
||||
return npx(
|
||||
command_context,
|
||||
["@mozilla/firefox-devtools-mcp-moz"] + extra_args + args,
|
||||
)
|
||||
|
||||
|
||||
def logspam_create_parser(subcommand):
|
||||
# Create the logspam command line parser.
|
||||
# if logspam is not installed, or not up to date, it will
|
||||
|
||||
Reference in New Issue
Block a user