From 47112b87947d93577f8ab8ebb15259f70843daf1 Mon Sep 17 00:00:00 2001 From: servius Date: Wed, 17 Jun 2026 03:30:03 +0530 Subject: [PATCH] feat: Added sops token for slack --- home/programs/goose.nix | 87 ++++++++++++++++++++++++++++++++++++++--- secrets/secrets.yaml | 8 ++-- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/home/programs/goose.nix b/home/programs/goose.nix index c652e4e..aa45068 100644 --- a/home/programs/goose.nix +++ b/home/programs/goose.nix @@ -5,8 +5,24 @@ device, ... }: let + secretsFile = builtins.readFile ../../secrets/secrets.yaml; + hasSlackMcpXoxpToken = lib.hasInfix "mcp-xoxp-token:" secretsFile; + hasSlackMcpXoxcToken = lib.hasInfix "mcp-xoxc-token:" secretsFile; + hasSlackMcpXoxdToken = lib.hasInfix "mcp-xoxd-token:" secretsFile; homeAssistantUrl = "https://home.darksailor.dev"; homeAssistantTokenFile = config.sops.secrets."homeassistant/cli-token".path; + slackXoxpTokenFile = + if hasSlackMcpXoxpToken + then config.sops.secrets."slack/mcp-xoxp-token".path + else "${device.home}/.config/goose/slack-mcp/xoxp-token"; + slackXoxcTokenFile = + if hasSlackMcpXoxcToken + then config.sops.secrets."slack/mcp-xoxc-token".path + else "${device.home}/.config/goose/slack-mcp/xoxc-token"; + slackXoxdTokenFile = + if hasSlackMcpXoxdToken + then config.sops.secrets."slack/mcp-xoxd-token".path + else "${device.home}/.config/goose/slack-mcp/xoxd-token"; gooseShell = "${pkgs.bash}/bin/bash"; goosePath = lib.concatStringsSep ":" [ "${device.home}/.nix-profile/bin" @@ -44,6 +60,39 @@ exec ${pkgs.nodejs}/bin/npx --yes --loglevel=silent ha-mcp "$@" ''; + slackMcp = pkgs.writeShellScriptBin "goose-slack-mcp" '' + set -euo pipefail + + cache_root="''${XDG_CACHE_HOME:-${device.home}/.cache}/goose/slack-mcp" + xoxp_token_file=${lib.escapeShellArg (toString slackXoxpTokenFile)} + xoxc_token_file=${lib.escapeShellArg (toString slackXoxcTokenFile)} + xoxd_token_file=${lib.escapeShellArg (toString slackXoxdTokenFile)} + mkdir -p "$cache_root" + + if [ -s "$xoxc_token_file" ] && [ -s "$xoxd_token_file" ]; then + export SLACK_MCP_XOXC_TOKEN="$(cat "$xoxc_token_file")" + export SLACK_MCP_XOXD_TOKEN="$(cat "$xoxd_token_file")" + elif [ -s "$xoxp_token_file" ]; then + export SLACK_MCP_XOXP_TOKEN="$(cat "$xoxp_token_file")" + else + echo "Slack MCP token missing: add SOPS secrets slack/mcp-xoxc-token and slack/mcp-xoxd-token, or slack/mcp-xoxp-token." >&2 + exit 1 + fi + + export SLACK_MCP_USERS_CACHE="$cache_root/users.json" + export SLACK_MCP_CHANNELS_CACHE="$cache_root/channels.json" + export SLACK_MCP_ENABLED_TOOLS=conversations_history,conversations_replies,conversations_search_messages,conversations_unreads,channels_list,channels_me,users_search,usergroups_list,saved_list + export SLACK_MCP_LOG_LEVEL=error + + # Keep the stdio server startup free of npm chatter before JSON-RPC begins. + export PATH=${lib.escapeShellArg (lib.makeBinPath [pkgs.nodejs pkgs.bash pkgs.coreutils])} + export NPM_CONFIG_LOGLEVEL=silent + export NPM_CONFIG_UPDATE_NOTIFIER=false + export NPM_CONFIG_FUND=false + export NPM_CONFIG_AUDIT=false + + exec ${pkgs.nodejs}/bin/npx --yes --loglevel=silent slack-mcp-server@latest --transport stdio "$@" + ''; gooseHomeAssistantExtension = { enabled = true; type = "stdio"; @@ -56,8 +105,23 @@ bundled = false; available_tools = []; }; - gooseHomeAssistantExtensionFile = (pkgs.formats.yaml {}).generate "goose-homeassistant-extension.yaml" { - extensions.homeassistant = gooseHomeAssistantExtension; + gooseSlackExtension = { + enabled = true; + type = "stdio"; + name = "slack"; + display_name = "Slack"; + description = "Read Slack channels, threads, DMs, users, and unread messages via slack-mcp-server."; + cmd = "${slackMcp}/bin/goose-slack-mcp"; + args = []; + timeout = 300; + bundled = false; + available_tools = []; + }; + gooseExtensionFile = (pkgs.formats.yaml {}).generate "goose-extensions.yaml" { + extensions = { + homeassistant = gooseHomeAssistantExtension; + slack = gooseSlackExtension; + }; }; gooseDesktopExternalBackendConfigFile = config.sops.templates."goose-desktop-external-goosed.json".path; goosedMacosScript = pkgs.writeShellScriptBin "goosed-shiro" '' @@ -92,14 +156,27 @@ in [ pkgs.goose-ai homeAssistantMcp + slackMcp ] ++ lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-linux") [pkgs.goose-desktop]; - sops.secrets."homeassistant/cli-token" = {}; + sops.secrets = + { + "homeassistant/cli-token" = {}; + } + // lib.optionalAttrs hasSlackMcpXoxpToken { + "slack/mcp-xoxp-token" = {}; + } + // lib.optionalAttrs hasSlackMcpXoxcToken { + "slack/mcp-xoxc-token" = {}; + } + // lib.optionalAttrs hasSlackMcpXoxdToken { + "slack/mcp-xoxd-token" = {}; + }; - home.activation.configureGooseHomeAssistant = lib.hm.dag.entryAfter ["writeBoundary"] '' + home.activation.configureGooseExtensions = lib.hm.dag.entryAfter ["writeBoundary"] '' config_file="${config.xdg.configHome}/goose/config.yaml" - extension_file="${gooseHomeAssistantExtensionFile}" + extension_file="${gooseExtensionFile}" mkdir -p "$(dirname "$config_file")" if [ ! -e "$config_file" ]; then diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 62478a9..7c40f77 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -155,6 +155,8 @@ flat-manager: sloe_upload_token: ENC[AES256_GCM,data:fGoWQoD8bUlP7Phe/3OJzVcMLgSny5j5WzCXBxWGfOM+KGfZAswKiqWTe3bKZydkdkZcBMGLKFl4M17xD/oH2kd2Jnm4RHCQVy6epvYFK2JTr1B0vdTojQNgIsCnroeyDsHPJY64Rsvb+xszSGyEbTf+1npCkuPze6Hyu32dkSfAbOFjbiooQhE3ZJz0Dfdbupx0C0emNdqT49h+n/WD6UyyMY000tlHk4DvqAh2oHYGX+HLlaCoUAWLWBhAyRZXxl1H2n8Z+L8E+NUtoie4F7Ad3eqQhYvbrKWlmTiKvXrQE0suY5FQusZSEFnhjbvDdexuPbuhzInlIRgjBUQNU37lNdxziG1wOgW9zJAhKgJs9ldLjCV7+1Fo4D5Ril5jazngpx8rAWj6L8GT6lblkYoIrw/g3mNRcBpSsbLNx8e3KCaGXIbE2qhkdEn53Kz0NXWyDYLs8FxjQ+LwgcXVyA==,iv:MAoISxK1Ozv4OnXpRG8n689Ga35aLlMMm+hhILoevKk=,tag:DhF5i1zUICPjShRZK6fBKg==,type:str] goose: server_secret: ENC[AES256_GCM,data:VPqdv1poAXaLeRHG/IPE24ivA3/M8lpyLI+eyevsJDAt0mgJCM8Hs9hvuoEU1XK3SW4Sk1oTL23qKeZwUSjcvQ==,iv:cOt/IqfSZJwCGcyqnbpUp4MVZkViHcg62bgsRyrT53s=,tag:+HinnSyI7utC0BzN4FhG8w==,type:str] +slack: + mcp-xoxc-token: ENC[AES256_GCM,data:gvD8hyrDDDZh1p4aSvaQrHsH2ahyEkDkxN6Zx6+gBXk1DcTCnMmWLF09Q/I+Q2TyqBHsf32zeAQt5NypV8QbOif/eY5npkypga028l9lknG77qs2hXcYdRh1rjV5AmaeZM6lRgqUZE0yPKMQnqAvUQ==,iv:Hir6GFMMDGMKJ6hdTtLZKOZrKepRLtGMu9npQcZf3HY=,tag:EI3Ezv4B3AmjY1+Z1dbr9Q==,type:str] sops: age: - enc: | @@ -166,7 +168,7 @@ sops: ZtXTVClwMSmaUYhdSB2gKFrKVZHXTJZ4oAL5t/BpC0pOHyr+o96T3Q== -----END AGE ENCRYPTED FILE----- recipient: age1pw7kluxp7872c63ne4jecq75glj060jkmqwzkk6esatuyck9egfswufdpk - lastmodified: "2026-06-11T14:19:15Z" - mac: ENC[AES256_GCM,data:eC5TEJUvzF6r3vyqswimY7okOOwxXiJLvVVymRWQmW3uAy1+/MyTD6TCHKmX20q/JscRJJAMtDsuafgKuoMz/Le+WmWtr0qqFApKcY7PDvPXXTrdSRLpVPIZaUW+2hXuQdRTsPFr1wYQo4mcCmeXlIPhnVZJrztvcEGt44wqdwU=,iv:jkBxL1Q8a4tRiO72oqdxwbm+zd67zbj58aNEySYb5MY=,tag:svsW1PTVtgerDCCe1B87qA==,type:str] + lastmodified: "2026-06-16T21:59:54Z" + mac: ENC[AES256_GCM,data:+rk7r1cCb+Poyn/AAKZjxz6dhq9DqMTLSWwXoTIvuleZ2JBy9Mw03ajdQ430htbeE2Gy7F5Th4F4sOJYoDHnChiRSeHlaPEhLHKufA9YmrOenWxqbdXXv1Fwcog+9FGGPos4pNFwPZCGn5SgSFnypTtTRlyBAeQVKsdBsoQuN2A=,iv:Em+ELeM4q4bVBW7vh51Nc90gtepAVfzMU48plgrCGOg=,tag:UiChuoUxuhkjNSla5x1Nxw==,type:str] unencrypted_suffix: _unencrypted - version: 3.12.2 + version: 3.13.1 -- 2.51.2