diff --git a/hosts/glyph/services/default.nix b/hosts/glyph/services/default.nix index 931b3e86..2c5344c2 100644 --- a/hosts/glyph/services/default.nix +++ b/hosts/glyph/services/default.nix @@ -59,4 +59,6 @@ enable = true; extraUpFlags = ["--ssh"]; }; + + services.mcpjungle.enable = true; } diff --git a/modules/home/development.nix b/modules/home/development.nix index 63ec24ac..d5f87ee8 100644 --- a/modules/home/development.nix +++ b/modules/home/development.nix @@ -56,6 +56,7 @@ in { "Bash(git show *)" "Bash(git add *)" "Bash(git branch *)" + "Bash(gh api:*)" "Bash(mkdir *)" "Bash(* --version)" "Bash(* --help *)" diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 29e27779..dedc1b46 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -1,6 +1,7 @@ # NixOS-specific configuration modules { imports = [ + ./llm ./web ./filebrowser-quantum.nix ./users.nix diff --git a/modules/nixos/llm/default.nix b/modules/nixos/llm/default.nix new file mode 100644 index 00000000..f31ba072 --- /dev/null +++ b/modules/nixos/llm/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./mcpjungle.nix + ]; +} diff --git a/modules/nixos/llm/mcpjungle.nix b/modules/nixos/llm/mcpjungle.nix new file mode 100644 index 00000000..9800a600 --- /dev/null +++ b/modules/nixos/llm/mcpjungle.nix @@ -0,0 +1,60 @@ +{ + config, + pkgs, + lib, + ... +}: let + cfg = config.services.mcpjungle; +in { + options.services.mcpjungle = { + enable = lib.mkEnableOption "MCPJungle MCP Gateway"; + + package = lib.mkPackageOption pkgs "mcpjungle" {}; + + port = lib.mkOption { + type = lib.types.port; + default = 8090; + description = "Port for the HTTP server to listen on."; + }; + + openFirewall = lib.mkEnableOption "opening firewall ports for MCPJungle"; + }; + + config = lib.mkIf cfg.enable { + users.users.mcpjungle = { + isSystemUser = true; + group = "mcpjungle"; + }; + users.groups.mcpjungle = {}; + + systemd.services.mcpjungle = { + description = "MCPJungle MCP Gateway"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} start --port ${toString cfg.port}"; + User = "mcpjungle"; + Group = "mcpjungle"; + WorkingDirectory = "/var/lib/mcpjungle"; + StateDirectory = "mcpjungle"; + Restart = "on-failure"; + RestartSec = 5; + + # Hardening + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectHome = true; + ProtectSystem = "strict"; + ReadWritePaths = ["/var/lib/mcpjungle"]; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + RestrictSUIDSGID = true; + }; + }; + + networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [cfg.port]; + }; +} diff --git a/overlays/custom-packages.nix b/overlays/custom-packages.nix index c8694841..9e7515bc 100644 --- a/overlays/custom-packages.nix +++ b/overlays/custom-packages.nix @@ -13,6 +13,9 @@ self: super: { # FileBrowser quantum fork filebrowser-quantum = super.callPackage ./../packages/filebrowser-quantum/package.nix {}; + # MCP Gateway + mcpjungle = super.callPackage ./../packages/mcpjungle/package.nix {}; + # Mochi spaced repetition software mochi = super.callPackage ./../packages/mochi/package.nix {}; diff --git a/packages/mcpjungle/package.nix b/packages/mcpjungle/package.nix new file mode 100644 index 00000000..03218a35 --- /dev/null +++ b/packages/mcpjungle/package.nix @@ -0,0 +1,36 @@ +{ + lib, + fetchFromGitHub, + buildGoModule, +}: +buildGoModule rec { + pname = "mcpjungle"; + version = "0.3.5"; + + src = fetchFromGitHub { + owner = "mcpjungle"; + repo = "mcpjungle"; + rev = version; + hash = "sha256-Q/ASyI6DygmYa284wk2pmYgVtPKRummnyh60v+Ri7bU="; + }; + + vendorHash = "sha256-pvCDf7Y+LiIOiZ0O/bJMzkf75o7HQbYpF01yFY4J9Yg="; + + # Tests require HOME to exist (tilde expansion); skip in sandbox + doCheck = false; + + env.CGO_ENABLED = 0; + + ldflags = [ + "-s" + "-w" + "-X github.com/mcpjungle/mcpjungle/pkg/version.Version=${version}" + ]; + + meta = with lib; { + description = "Self-hosted MCP Gateway"; + homepage = "https://github.com/mcpjungle/mcpjungle"; + license = licenses.mit; + mainProgram = "mcpjungle"; + }; +}