Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion hosts/glyph/services/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,12 @@
extraUpFlags = ["--ssh"];
};

services.mcpjungle.enable = true;
services.basic-memory.enable = true;
services.mcpjungle = {
enable = true;
servers.basic-memory = {
url = "http://127.0.0.1:8091/mcp";
description = "Knowledge management with markdown files";
};
};
}
76 changes: 76 additions & 0 deletions modules/nixos/llm/basic-memory.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
config,
pkgs,
lib,
...
}: let
cfg = config.services.basic-memory;
dataDir = "/var/lib/basic-memory";
in {
options.services.basic-memory = {
enable = lib.mkEnableOption "Basic Memory MCP server";

port = lib.mkOption {
type = lib.types.port;
default = 8091;
description = "Port for the streamable HTTP transport.";
};

host = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "Address to bind the HTTP server to.";
};

openFirewall = lib.mkEnableOption "opening firewall ports for Basic Memory";
};

config = lib.mkIf cfg.enable {
users.users.basic-memory = {
isSystemUser = true;
group = "basic-memory";
home = dataDir;
};
users.groups.basic-memory = {};

systemd.services.basic-memory = {
description = "Basic Memory MCP Server";
after = ["network-online.target"];
wants = ["network-online.target"];
wantedBy = ["multi-user.target"];

environment = {
HOME = dataDir;
BASIC_MEMORY_CONFIG_DIR = dataDir;
UV_CACHE_DIR = "${dataDir}/.cache/uv";
};

serviceConfig = {
ExecStart = "${lib.getExe pkgs.uv} tool run basic-memory mcp --transport streamable-http --port ${toString cfg.port} --host ${cfg.host}";
User = "basic-memory";
Group = "basic-memory";
WorkingDirectory = dataDir;
StateDirectory = "basic-memory";
Restart = "on-failure";
RestartSec = 5;

# Hardening
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProtectHome = "tmpfs";
BindPaths = ["${dataDir}"];
ProtectSystem = "strict";
ReadWritePaths = [dataDir];
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictSUIDSGID = true;
};
};

programs.nix-ld.enable = true;

networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [cfg.port];
};
}
1 change: 1 addition & 0 deletions modules/nixos/llm/default.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
imports = [
./basic-memory.nix
./mcpjungle.nix
];
}
41 changes: 41 additions & 0 deletions modules/nixos/llm/mcpjungle.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ in {
};

openFirewall = lib.mkEnableOption "opening firewall ports for MCPJungle";

servers = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule {
options = {
url = lib.mkOption {
type = lib.types.str;
description = "Streamable HTTP URL of the MCP server.";
};
description = lib.mkOption {
type = lib.types.str;
default = "";
description = "Description of the MCP server.";
};
};
});
default = {};
description = "MCP servers to register with the gateway.";
};
};

config = lib.mkIf cfg.enable {
Expand Down Expand Up @@ -55,6 +73,29 @@ in {
};
};

systemd.services.mcpjungle-register = lib.mkIf (cfg.servers != {}) {
description = "Register MCP servers with MCPJungle";
after = ["mcpjungle.service"];
requires = ["mcpjungle.service"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = let
registry = "http://127.0.0.1:${toString cfg.port}";
bin = lib.getExe cfg.package;
registrations = lib.concatStringsSep "\n" (lib.mapAttrsToList (name: server: ''
if ! ${bin} list servers --registry ${registry} 2>/dev/null | grep -q '${name}'; then
${bin} register --name '${name}' --description '${server.description}' --url '${server.url}' --registry ${registry}
fi
'')
cfg.servers);
in ''
${registrations}
'';
};

networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [cfg.port];
};
}