Skip to content

Commit d1e6f07

Browse files
committed
install: broaden OS/MCP coverage and enforce server auth
1 parent 62b0e2e commit d1e6f07

1 file changed

Lines changed: 136 additions & 35 deletions

File tree

scripts/install.sh

Lines changed: 136 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,60 @@ REPO="agentralabs/codebase"
2525
BINARY_NAME="acb-mcp"
2626
SERVER_KEY="agentic-codebase"
2727
INSTALL_DIR="$HOME/.local/bin"
28+
INSTALL_DIR_EXPLICIT=false
2829
VERSION="latest"
2930
PROFILE="${AGENTRA_INSTALL_PROFILE:-desktop}"
3031
DRY_RUN=false
3132
BAR_ONLY="${AGENTRA_INSTALL_BAR_ONLY:-1}"
3233
MCP_ENTRYPOINT=""
34+
HOST_OS=""
3335
SERVER_ARGS_JSON='[]'
3436
SERVER_ARGS_TEXT='[]'
3537
SERVER_CHECK_CMD_SUFFIX=""
3638
MCP_CONFIGURED_CLIENTS=()
3739
MCP_SCANNED_CONFIG_FILES=()
3840

3941
# ── Parse arguments ──────────────────────────────────────────────────
40-
for arg in "$@"; do
41-
case "$arg" in
42-
--version=*) VERSION="${arg#*=}" ;;
43-
--dir=*) INSTALL_DIR="${arg#*=}" ;;
44-
--profile=*) PROFILE="${arg#*=}" ;;
45-
--dry-run) DRY_RUN=true ;;
42+
while [ $# -gt 0 ]; do
43+
case "$1" in
44+
--version=*)
45+
VERSION="${1#*=}"
46+
shift
47+
;;
48+
--version)
49+
VERSION="${2:-}"
50+
shift 2
51+
;;
52+
--dir=*)
53+
INSTALL_DIR="${1#*=}"
54+
INSTALL_DIR_EXPLICIT=true
55+
shift
56+
;;
57+
--dir)
58+
INSTALL_DIR="${2:-}"
59+
INSTALL_DIR_EXPLICIT=true
60+
shift 2
61+
;;
62+
--profile=*)
63+
PROFILE="${1#*=}"
64+
shift
65+
;;
66+
--profile)
67+
PROFILE="${2:-}"
68+
shift 2
69+
;;
70+
--dry-run)
71+
DRY_RUN=true
72+
shift
73+
;;
4674
--help|-h)
47-
echo "Usage: install.sh [--version=X.Y.Z] [--dir=/path] [--profile=desktop|terminal|server] [--dry-run]"
75+
echo "Usage: install.sh [--version X.Y.Z|--version=X.Y.Z] [--dir /path|--dir=/path] [--profile desktop|terminal|server|--profile=desktop|terminal|server] [--dry-run]"
4876
exit 0
4977
;;
78+
*)
79+
echo "Error: unknown option '$1'" >&2
80+
exit 1
81+
;;
5082
esac
5183
done
5284

@@ -136,6 +168,7 @@ detect_platform() {
136168
case "$os" in
137169
darwin) os="darwin" ;;
138170
linux) os="linux" ;;
171+
msys*|mingw*|cygwin*|windows_nt) os="windows" ;;
139172
*) echo "Error: Unsupported OS: $os" >&2; exit 1 ;;
140173
esac
141174

@@ -145,20 +178,21 @@ detect_platform() {
145178
*) echo "Error: Unsupported architecture: $arch" >&2; exit 1 ;;
146179
esac
147180

181+
HOST_OS="$os"
148182
echo "${os}-${arch}"
149183
}
150184

151185
# ── Check dependencies ────────────────────────────────────────────────
152186
check_deps() {
153-
for cmd in curl jq; do
154-
if ! command -v "$cmd" &>/dev/null; then
155-
echo "Error: '$cmd' is required but not installed." >&2
156-
if [ "$cmd" = "jq" ]; then
157-
echo " Install: brew install jq (macOS) or apt install jq (Linux)" >&2
158-
fi
159-
exit 1
160-
fi
161-
done
187+
if ! command -v curl &>/dev/null; then
188+
echo "Error: 'curl' is required but not installed." >&2
189+
exit 1
190+
fi
191+
if ! command -v jq &>/dev/null && ! command -v python3 &>/dev/null; then
192+
echo "Error: JSON merge requires 'jq' or 'python3'." >&2
193+
echo " Install jq (preferred) or python3, then rerun." >&2
194+
exit 1
195+
fi
162196
}
163197

164198
# ── Get latest release tag (empty when unavailable) ──────────────────
@@ -279,13 +313,15 @@ args=("\$@")
279313
has_graph=0
280314
has_name=0
281315
has_command=0
316+
serve_requested=0
282317
283318
for arg in "\${args[@]}"; do
284319
case "\$arg" in
285320
-h|--help|-V|--version) has_command=1 ;;
286321
--graph|--graph=*|-g) has_graph=1 ;;
287322
--name|--name=*) has_name=1 ;;
288-
serve|help) has_command=1 ;;
323+
serve) has_command=1; serve_requested=1 ;;
324+
help) has_command=1 ;;
289325
esac
290326
done
291327
@@ -301,14 +337,59 @@ if [ "\$has_graph" -eq 0 ]; then
301337
fi
302338
303339
if [ "\$has_command" -eq 0 ]; then
340+
serve_requested=1
304341
args+=("serve")
305342
fi
306343
344+
if [ "\$serve_requested" -eq 1 ]; then
345+
if [ "\${AGENTRA_RUNTIME_MODE:-}" = "server" ] || [ "\${AGENTRA_SERVER:-}" = "1" ] || [ "\${AGENTRA_INSTALL_PROFILE:-}" = "server" ]; then
346+
if [ -z "\${AGENTIC_TOKEN:-}" ] && [ -z "\${AGENTIC_TOKEN_FILE:-}" ] && [ -z "\${AGENTRA_AUTH_TOKEN_FILE:-}" ]; then
347+
echo "Error: server mode requires AGENTIC_TOKEN or AGENTIC_TOKEN_FILE." >&2
348+
exit 2
349+
fi
350+
fi
351+
fi
352+
307353
exec "\$BIN" "\${args[@]}"
308354
EOF
309355
chmod +x "${MCP_ENTRYPOINT}"
310356
}
311357

358+
merge_config_with_python() {
359+
local config_file="$1"
360+
python3 - "$config_file" "$SERVER_KEY" "$MCP_ENTRYPOINT" "$SERVER_ARGS_JSON" <<'PY'
361+
import json
362+
import os
363+
import sys
364+
365+
path, key, command, args_json = sys.argv[1:]
366+
args = json.loads(args_json)
367+
cfg = {}
368+
369+
if os.path.exists(path) and os.path.getsize(path) > 0:
370+
try:
371+
with open(path, "r", encoding="utf-8") as handle:
372+
loaded = json.load(handle)
373+
if isinstance(loaded, dict):
374+
cfg = loaded
375+
except Exception:
376+
cfg = {}
377+
378+
mcp = cfg.get("mcpServers")
379+
if not isinstance(mcp, dict):
380+
mcp = {}
381+
cfg["mcpServers"] = mcp
382+
mcp[key] = {"command": command, "args": args}
383+
384+
os.makedirs(os.path.dirname(path), exist_ok=True)
385+
tmp = f"{path}.tmp"
386+
with open(tmp, "w", encoding="utf-8") as handle:
387+
json.dump(cfg, handle, indent=2)
388+
handle.write("\n")
389+
os.replace(tmp, path)
390+
PY
391+
}
392+
312393
# ── Merge MCP server into a config file ───────────────────────────────
313394
# Uses jq to add our server WITHOUT touching other servers.
314395
merge_config() {
@@ -323,20 +404,25 @@ merge_config() {
323404

324405
mkdir -p "$config_dir"
325406

326-
if [ -f "$config_file" ] && [ -s "$config_file" ]; then
327-
echo " Existing config found, merging..."
328-
jq --arg key "$SERVER_KEY" \
329-
--arg cmd "${MCP_ENTRYPOINT}" \
330-
--argjson args "$SERVER_ARGS_JSON" \
331-
'.mcpServers //= {} | .mcpServers[$key] = {"command": $cmd, "args": $args}' \
332-
"$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file"
407+
if command -v jq >/dev/null 2>&1; then
408+
if [ -f "$config_file" ] && [ -s "$config_file" ]; then
409+
echo " Existing config found, merging..."
410+
jq --arg key "$SERVER_KEY" \
411+
--arg cmd "${MCP_ENTRYPOINT}" \
412+
--argjson args "$SERVER_ARGS_JSON" \
413+
'.mcpServers //= {} | .mcpServers[$key] = {"command": $cmd, "args": $args}' \
414+
"$config_file" > "$config_file.tmp" && mv "$config_file.tmp" "$config_file"
415+
else
416+
echo " Creating new config..."
417+
jq -n --arg key "$SERVER_KEY" \
418+
--arg cmd "${MCP_ENTRYPOINT}" \
419+
--argjson args "$SERVER_ARGS_JSON" \
420+
'{ "mcpServers": { ($key): { "command": $cmd, "args": $args } } }' \
421+
> "$config_file"
422+
fi
333423
else
334-
echo " Creating new config..."
335-
jq -n --arg key "$SERVER_KEY" \
336-
--arg cmd "${MCP_ENTRYPOINT}" \
337-
--argjson args "$SERVER_ARGS_JSON" \
338-
'{ "mcpServers": { ($key): { "command": $cmd, "args": $args } } }' \
339-
> "$config_file"
424+
echo " Merging with python3 fallback..."
425+
merge_config_with_python "$config_file"
340426
fi
341427
}
342428

@@ -404,9 +490,11 @@ configure_json_client_if_present() {
404490
# ── Configure Claude Desktop ─────────────────────────────────────────
405491
configure_claude_desktop() {
406492
local config_file
407-
case "$(uname -s)" in
493+
case "${HOST_OS}" in
408494
Darwin) config_file="$HOME/Library/Application Support/Claude/claude_desktop_config.json" ;;
409-
Linux) config_file="${XDG_CONFIG_HOME:-$HOME/.config}/Claude/claude_desktop_config.json" ;;
495+
darwin) config_file="$HOME/Library/Application Support/Claude/claude_desktop_config.json" ;;
496+
Linux|linux) config_file="${XDG_CONFIG_HOME:-$HOME/.config}/Claude/claude_desktop_config.json" ;;
497+
windows) config_file="${APPDATA:-$HOME/AppData/Roaming}/Claude/claude_desktop_config.json" ;;
410498
*) return ;;
411499
esac
412500

@@ -467,6 +555,8 @@ configure_generic_mcp_json_files() {
467555
local roots=(
468556
"$HOME/.config"
469557
"$HOME/Library/Application Support"
558+
"${APPDATA:-$HOME/AppData/Roaming}"
559+
"${LOCALAPPDATA:-$HOME/AppData/Local}"
470560
"$HOME/.cursor"
471561
"$HOME/.windsurf"
472562
"$HOME/.codeium"
@@ -497,10 +587,16 @@ configure_mcp_clients() {
497587
configure_json_client_if_present "Cursor" "$HOME/.cursor/mcp.json" "$HOME/.cursor"
498588
configure_json_client_if_present "Windsurf" "$HOME/.windsurf/mcp.json" "$HOME/.windsurf"
499589
configure_json_client_if_present "Windsurf (Codeium)" "$HOME/.codeium/windsurf/mcp_config.json" "$HOME/.codeium/windsurf"
500-
if [ "$(uname -s)" = "Darwin" ]; then
590+
if [ "${HOST_OS}" = "darwin" ]; then
501591
configure_json_client_if_present "VS Code" "$HOME/Library/Application Support/Code/User/mcp.json" "$HOME/Library/Application Support/Code/User"
502592
configure_json_client_if_present "VS Code + Cline" "$HOME/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json" "$HOME/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev"
503593
configure_json_client_if_present "VSCodium" "$HOME/Library/Application Support/VSCodium/User/mcp.json" "$HOME/Library/Application Support/VSCodium/User"
594+
elif [ "${HOST_OS}" = "windows" ]; then
595+
configure_json_client_if_present "Cursor" "${APPDATA:-$HOME/AppData/Roaming}/Cursor/User/mcp.json" "${APPDATA:-$HOME/AppData/Roaming}/Cursor/User"
596+
configure_json_client_if_present "Windsurf" "${APPDATA:-$HOME/AppData/Roaming}/Windsurf/User/mcp.json" "${APPDATA:-$HOME/AppData/Roaming}/Windsurf/User"
597+
configure_json_client_if_present "VS Code" "${APPDATA:-$HOME/AppData/Roaming}/Code/User/mcp.json" "${APPDATA:-$HOME/AppData/Roaming}/Code/User"
598+
configure_json_client_if_present "VS Code + Cline" "${APPDATA:-$HOME/AppData/Roaming}/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json" "${APPDATA:-$HOME/AppData/Roaming}/Code/User/globalStorage/saoudrizwan.claude-dev"
599+
configure_json_client_if_present "VSCodium" "${APPDATA:-$HOME/AppData/Roaming}/VSCodium/User/mcp.json" "${APPDATA:-$HOME/AppData/Roaming}/VSCodium/User"
504600
else
505601
configure_json_client_if_present "VS Code" "${XDG_CONFIG_HOME:-$HOME/.config}/Code/User/mcp.json" "${XDG_CONFIG_HOME:-$HOME/.config}/Code/User"
506602
configure_json_client_if_present "VS Code + Cline" "${XDG_CONFIG_HOME:-$HOME/.config}/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json" "${XDG_CONFIG_HOME:-$HOME/.config}/Code/User/globalStorage/saoudrizwan.claude-dev"
@@ -594,9 +690,9 @@ check_path() {
594690
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
595691
echo ""
596692
echo "Note: Add ${INSTALL_DIR} to your PATH if not already:"
597-
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
693+
echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
598694
echo ""
599-
echo "Add this line to your ~/.zshrc or ~/.bashrc to make it permanent."
695+
echo "Add this line to your shell profile to make it permanent."
600696
fi
601697
}
602698

@@ -616,6 +712,11 @@ main() {
616712
echo "Platform: ${platform}"
617713
validate_profile
618714
echo "Profile: ${PROFILE}"
715+
if [ "${HOST_OS}" = "windows" ] && [ "$INSTALL_DIR_EXPLICIT" = false ]; then
716+
INSTALL_DIR="${HOME}/.agentra/bin"
717+
fi
718+
MCP_ENTRYPOINT="${INSTALL_DIR}/${BINARY_NAME}-agentra"
719+
echo "Install dir: ${INSTALL_DIR}"
619720

620721
set_progress 30 "Resolving release"
621722
local installed_from_release=false

0 commit comments

Comments
 (0)