This repository has no description
3.4 kB
97 lines
1{ ... }:
2{
3 perSystem =
4 {
5 pkgs,
6 lib,
7 self',
8 ...
9 }:
10 let
11 python = pkgs.python3.withPackages (ps: [ ps.mcp ]);
12 extensionId = "browser-mcp@lassul.us";
13 pinentry =
14 if pkgs.stdenv.hostPlatform.isDarwin then
15 "${pkgs.pinentry_mac}/${pkgs.pinentry_mac.binaryPath}"
16 else
17 "${self'.packages.pinentry-rofi}/bin/pinentry-rofi";
18 in
19 {
20 # stdio MCP server (bin/browser-mcp) plus the native messaging host
21 # Firefox spawns for the extension (bin/browser-mcp-host, manifest in
22 # lib/mozilla/native-messaging-hosts).
23 packages.browser-mcp = pkgs.stdenv.mkDerivation {
24 pname = "browser-mcp";
25 version = (lib.importJSON ./extension/manifest.json).version;
26 src = ./.;
27 nativeBuildInputs = [
28 pkgs.makeWrapper
29 pkgs.ruff
30 python.pkgs.mypy
31 ];
32 doCheck = true;
33 checkPhase = ''
34 runHook preCheck
35 ruff check browser_mcp.py
36 ruff format --check browser_mcp.py
37 ${python}/bin/python -m mypy --strict browser_mcp.py
38 runHook postCheck
39 '';
40 installPhase = ''
41 runHook preInstall
42 install -Dm755 browser_mcp.py $out/libexec/browser_mcp.py
43 makeWrapper ${python}/bin/python $out/bin/browser-mcp \
44 --add-flags $out/libexec/browser_mcp.py
45 makeWrapper ${python}/bin/python $out/bin/browser-mcp-host \
46 --add-flags "$out/libexec/browser_mcp.py host"
47
48 mkdir -p $out/lib/mozilla/native-messaging-hosts
49 cat > $out/lib/mozilla/native-messaging-hosts/browser_mcp.json <<EOF
50 {
51 "name": "browser_mcp",
52 "description": "Relay between the Browser MCP extension and browser-mcp",
53 "path": "$out/bin/browser-mcp-host",
54 "type": "stdio",
55 "allowed_extensions": ["${extensionId}"]
56 }
57 EOF
58 runHook postInstall
59 '';
60 meta.mainProgram = "browser-mcp";
61 };
62
63 # Signs the extension as unlisted on addons.mozilla.org so release
64 # Firefox installs it. Bump the version in extension/manifest.json
65 # first: AMO signs every version only once. Credentials come from the
66 # jwt_issuer/jwt_secret fields of the rbw entry accounts.firefox.com.
67 packages.browser-mcp-sign = pkgs.writeShellApplication {
68 name = "browser-mcp-sign";
69 runtimeInputs = [
70 pkgs.web-ext
71 pkgs.rbw
72 ];
73 text = ''
74 out=''${1:-.}
75 if [ -z "''${WEB_EXT_API_KEY:-}" ] || [ -z "''${WEB_EXT_API_SECRET:-}" ]; then
76 if ! rbw unlocked 2>/dev/null; then
77 rbw config set pinentry ${pinentry}
78 rbw unlock
79 fi
80 WEB_EXT_API_KEY=$(rbw get --field jwt_issuer accounts.firefox.com)
81 WEB_EXT_API_SECRET=$(rbw get --field jwt_secret accounts.firefox.com)
82 export WEB_EXT_API_KEY WEB_EXT_API_SECRET
83 fi
84 # web-ext writes .amo-upload-uuid into the source dir, so sign a
85 # writable copy of the extension.
86 src=$(mktemp -d)
87 trap 'rm -rf "$src"' EXIT
88 cp -r ${./extension}/. "$src"
89 chmod -R u+w "$src"
90 web-ext sign \
91 --channel unlisted \
92 --source-dir "$src" \
93 --artifacts-dir "$out"
94 '';
95 };
96 };
97}