{ lib, pkgs, config, inputs, ... }: let pkgsRepositories = pkgs.nix-vscode-extensions.forVSCodeVersion config.programs.vscode.package.version; pkgsRepository = pkgsRepositories.open-vsx; mcp-nixos = inputs.mcp-nixos.packages.${pkgs.stdenv.hostPlatform.system}.default; anyProfileHasMcpNixos = lib.any ( profile: profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.nixos.enable ) (lib.attrValues config.programs.vscode.profiles); anyProfileHasMcpEslint = lib.any ( profile: profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.eslint.enable ) (lib.attrValues config.programs.vscode.profiles); anyProfileHasMcpVitest = lib.any ( profile: profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.vitest.enable ) (lib.attrValues config.programs.vscode.profiles); anyProfileHasMcpSleep = lib.any ( profile: profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.sleep.enable ) (lib.attrValues config.programs.vscode.profiles); anyProfileHasMcp = anyProfileHasMcpNixos || anyProfileHasMcpEslint || anyProfileHasMcpVitest || anyProfileHasMcpSleep; getMcpTimeout = serverName: lib.findFirst (timeout: timeout != null) null (map ( profile: if profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.${serverName}.enable then profile.extraExtensions.claudeDev.mcp.${serverName}.timeout else null ) (lib.attrValues config.programs.vscode.profiles)); getMcpAutoApprove = serverName: lib.foldl' ( acc: profile: if profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.${serverName}.enable then acc // profile.extraExtensions.claudeDev.mcp.${serverName}.autoApprove else acc ) {} (lib.attrValues config.programs.vscode.profiles); getMcpPackage = serverName: lib.findFirst (package: package != null) null (map ( profile: if profile.extraExtensions.claudeDev.enable && profile.extraExtensions.claudeDev.mcp.${serverName}.enable then profile.extraExtensions.claudeDev.mcp.${serverName}.package else null ) (lib.attrValues config.programs.vscode.profiles)); in { options.programs.vscode.profiles = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule ({config, ...}: { options = { extraExtensions.claudeDev = { enable = lib.mkEnableOption "should the claude-dev extension for vscode be enabled"; extension = lib.mkPackageOption pkgsRepository "claude-dev" { default = ["saoudrizwan" "claude-dev"]; }; mcp = { nixos = { enable = lib.mkEnableOption "enable NixOS MCP server for Claude Dev"; }; eslint = { enable = lib.mkEnableOption "enable ESLint MCP server for Claude Dev"; package = lib.mkOption { type = lib.types.str; default = "@eslint/mcp@latest"; description = "NPM package to use for ESLint MCP server"; }; timeout = lib.mkOption { type = lib.types.nullOr lib.types.int; default = null; description = "Timeout in seconds for ESLint MCP server operations"; }; autoApprove = { lint-files = lib.mkEnableOption "Should the lint-files tool be auto approved for ESLint MCP server"; }; }; vitest = { enable = lib.mkEnableOption "enable Vitest MCP server for Claude Dev"; package = lib.mkOption { type = lib.types.str; default = "@djankies/vitest-mcp"; description = "NPM package to use for Vitest MCP server"; }; timeout = lib.mkOption { type = lib.types.nullOr lib.types.int; default = null; description = "Timeout in seconds for Vitest MCP server operations"; }; autoApprove = { list_tests = lib.mkEnableOption "Should the list_tests tool be auto approved for Vitest MCP server"; run_tests = lib.mkEnableOption "Should the run_tests tool be auto approved for Vitest MCP server"; analyze_coverage = lib.mkEnableOption "Should the analyze_coverage tool be auto approved for Vitest MCP server"; }; }; sleep = { enable = lib.mkEnableOption "enable Sleep MCP server for Claude Dev"; package = lib.mkOption { type = lib.types.str; default = "sleep-mcp"; description = "NPM package to use for Sleep MCP server"; }; timeout = lib.mkOption { type = lib.types.nullOr lib.types.int; default = null; description = "Timeout in seconds for Sleep MCP server operations"; }; autoApprove = { sleep = lib.mkEnableOption "Should the sleep tool be auto approved for Sleep MCP server"; }; }; }; }; }; config = lib.mkIf config.extraExtensions.claudeDev.enable { extensions = [ config.extraExtensions.claudeDev.extension ]; }; })); }; config = lib.mkMerge [ (lib.mkIf anyProfileHasMcpNixos { home.packages = [ mcp-nixos ]; }) (lib.mkIf anyProfileHasMcp { home.file."${config.xdg.configHome}/VSCodium/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json" = { text = builtins.toJSON { mcpServers = (lib.optionalAttrs anyProfileHasMcpNixos { nixos = { command = "${mcp-nixos}/bin/mcp-nixos"; }; }) // (lib.optionalAttrs anyProfileHasMcpEslint { eslint = { command = "${pkgs.nodejs}/bin/npx"; args = ["-y" (getMcpPackage "eslint")]; } // (lib.optionalAttrs ((getMcpTimeout "eslint") != null) { timeout = getMcpTimeout "eslint"; }) // (lib.optionalAttrs ((getMcpAutoApprove "eslint") != {}) { autoApprove = builtins.attrNames (lib.filterAttrs (_: v: v) (getMcpAutoApprove "eslint")); }); }) // (lib.optionalAttrs anyProfileHasMcpVitest { vitest = { command = "${pkgs.nodejs}/bin/npx"; args = ["-y" (getMcpPackage "vitest")]; } // (lib.optionalAttrs ((getMcpTimeout "vitest") != null) { timeout = getMcpTimeout "vitest"; }) // (lib.optionalAttrs ((getMcpAutoApprove "vitest") != {}) { autoApprove = builtins.attrNames (lib.filterAttrs (_: v: v) (getMcpAutoApprove "vitest")); }); }) // (lib.optionalAttrs anyProfileHasMcpSleep { sleep-mcp = { command = "${pkgs.nodejs}/bin/npx"; args = ["-y" (getMcpPackage "sleep")]; } // (lib.optionalAttrs ((getMcpTimeout "sleep") != null) { timeout = getMcpTimeout "sleep"; }) // (lib.optionalAttrs ((getMcpAutoApprove "sleep") != {}) { autoApprove = builtins.attrNames (lib.filterAttrs (_: v: v) (getMcpAutoApprove "sleep")); }); }); }; force = true; }; }) ]; }