feat(toggle-external): manage Magic MCP (21st-dev) — installed disabled by default
Add `magic` to the unified toggle-external.sh helper alongside gstack, emil-design-eng, darwin-skill, find-skills. MCPs are toggled via `claude mcp add|remove` instead of symlink moves. API key loaded from $REPO/.env (gitignored) via .env.example template. install-plugins.sh step 8.7 forces magic MCP off after each install run so the MCP doesn't load into every session unless explicitly enabled. Toggle: bash lib/toggle-external.sh enable|disable|status magic Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
07b8a207c1
commit
72920e032e
6
.env.example
Normal file
6
.env.example
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Local secrets for Claude Code plugin install scripts.
|
||||||
|
# Copy to .env and fill in real values. .env is gitignored.
|
||||||
|
#
|
||||||
|
# Used by: lib/toggle-external.sh enable|disable magic
|
||||||
|
# Get a key at: https://21st.dev/magic (dashboard → API keys)
|
||||||
|
MAGIC_API_KEY=your_21st_dev_magic_api_key_here
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -66,6 +66,10 @@ graphify-out/
|
|||||||
# Install logs
|
# Install logs
|
||||||
install-*.log
|
install-*.log
|
||||||
|
|
||||||
|
# Local secrets (MCP API keys etc.) — use .env.example as template
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
@ -500,6 +500,38 @@ else
|
|||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# STEP 8.7 — MAGIC MCP (21st-dev) — installed but DISABLED by default
|
||||||
|
# ============================================================
|
||||||
|
# Magic MCP is a stdio MCP server providing UI component generation
|
||||||
|
# from 21st.dev. Toggled via lib/toggle-external.sh (same interface as
|
||||||
|
# gstack, emil-design-eng, etc.). Registered in Claude Code user scope.
|
||||||
|
#
|
||||||
|
# Default policy: DISABLED at install time. Rationale: MCP tools load
|
||||||
|
# into every Claude Code session and consume context tokens. Enable
|
||||||
|
# only when you're actively using Magic.
|
||||||
|
#
|
||||||
|
# API key: read from $REPO/.env (MAGIC_API_KEY=...) — NEVER committed.
|
||||||
|
# Template: $REPO/.env.example. Get a key at https://21st.dev/magic
|
||||||
|
echo "── Step 8.7: Magic MCP (21st-dev) ──────────────────────────"
|
||||||
|
echo ""
|
||||||
|
if [ -x "$REPO/lib/toggle-external.sh" ]; then
|
||||||
|
MAGIC_STATUS="$(bash "$REPO/lib/toggle-external.sh" status magic 2>/dev/null || echo missing)"
|
||||||
|
if [ "$MAGIC_STATUS" = "enabled" ]; then
|
||||||
|
info "Disabling magic MCP by default (enable on demand)..."
|
||||||
|
bash "$REPO/lib/toggle-external.sh" disable magic >/dev/null
|
||||||
|
ok "magic MCP disabled — enable with: bash lib/toggle-external.sh enable magic"
|
||||||
|
else
|
||||||
|
ok "magic MCP disabled (default)"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$REPO/.env" ] || ! grep -q '^MAGIC_API_KEY=' "$REPO/.env" 2>/dev/null; then
|
||||||
|
warn "MAGIC_API_KEY not found in $REPO/.env — copy .env.example and set your key before enabling"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "lib/toggle-external.sh not found or not executable — skipping"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# STEP 9 — SHELL CONFIG (alias + env vars)
|
# STEP 9 — SHELL CONFIG (alias + env vars)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@ -573,6 +605,7 @@ echo " 🔄 graphifyy — codebase knowledge graph (pipx, PreToolUs
|
|||||||
echo " 🔄 emil-design-eng — UI polish, animations, component craft (curl → symlink)"
|
echo " 🔄 emil-design-eng — UI polish, animations, component craft (curl → symlink)"
|
||||||
echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)"
|
echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)"
|
||||||
echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)"
|
echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)"
|
||||||
|
echo " 🔄 magic MCP — 21st-dev UI generation MCP (toggle: lib/toggle-external.sh enable magic)"
|
||||||
echo ""
|
echo ""
|
||||||
echo " All plugins installed at: user scope (~/.claude/plugins/)"
|
echo " All plugins installed at: user scope (~/.claude/plugins/)"
|
||||||
echo " GStack skills symlinked individually into ~/.claude/skills/ (→ submodule)"
|
echo " GStack skills symlinked individually into ~/.claude/skills/ (→ submodule)"
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
# as symlinks inside skills/. This script moves those symlinks
|
# as symlinks inside skills/. This script moves those symlinks
|
||||||
# to/from skills-disabled/ so Claude Code stops/starts scanning them.
|
# to/from skills-disabled/ so Claude Code stops/starts scanning them.
|
||||||
#
|
#
|
||||||
|
# MCP servers are toggled via `claude mcp add|remove` (not symlinks).
|
||||||
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# toggle-external.sh list
|
# toggle-external.sh list
|
||||||
# toggle-external.sh status <tool>
|
# toggle-external.sh status <tool>
|
||||||
@ -19,6 +21,7 @@
|
|||||||
# emil-design-eng — single symlink → skills-external/emil-design-eng
|
# emil-design-eng — single symlink → skills-external/emil-design-eng
|
||||||
# darwin-skill — single symlink → ~/.agents/skills/darwin-skill
|
# darwin-skill — single symlink → ~/.agents/skills/darwin-skill
|
||||||
# find-skills — single symlink → ~/.agents/skills/find-skills
|
# find-skills — single symlink → ~/.agents/skills/find-skills
|
||||||
|
# magic — 21st-dev Magic MCP server (API key in .env)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@ -32,7 +35,18 @@ warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
|||||||
err() { echo -e "${RED}✗${NC} $1"; }
|
err() { echo -e "${RED}✗${NC} $1"; }
|
||||||
|
|
||||||
# All non-plugin tools this script can toggle.
|
# All non-plugin tools this script can toggle.
|
||||||
MANAGED_TOOLS=(gstack emil-design-eng darwin-skill find-skills)
|
MANAGED_TOOLS=(gstack emil-design-eng darwin-skill find-skills magic)
|
||||||
|
|
||||||
|
# Load MAGIC_API_KEY (and any other secrets) from $REPO/.env if present.
|
||||||
|
# Called only by the magic branch — other tools don't need env vars.
|
||||||
|
load_env() {
|
||||||
|
if [ -z "${MAGIC_API_KEY:-}" ] && [ -f "$REPO/.env" ]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$REPO/.env"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Prints the names (directory basenames) that belong to "gstack".
|
# Prints the names (directory basenames) that belong to "gstack".
|
||||||
# Source of truth: skills-external/gstack/*/SKILL.md. The repo's
|
# Source of truth: skills-external/gstack/*/SKILL.md. The repo's
|
||||||
@ -65,6 +79,14 @@ status_tool() {
|
|||||||
[ -d "$HOME/.agents/skills/$tool" ] || { echo "missing"; return; }
|
[ -d "$HOME/.agents/skills/$tool" ] || { echo "missing"; return; }
|
||||||
[ -e "$SKILLS_DIR/$tool" ] && echo "enabled" || echo "disabled"
|
[ -e "$SKILLS_DIR/$tool" ] && echo "enabled" || echo "disabled"
|
||||||
;;
|
;;
|
||||||
|
magic)
|
||||||
|
command -v claude >/dev/null || { echo "missing"; return; }
|
||||||
|
if claude mcp list 2>/dev/null | grep -q '^magic:'; then
|
||||||
|
echo "enabled"
|
||||||
|
else
|
||||||
|
echo "disabled"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "unknown"; return 1 ;;
|
echo "unknown"; return 1 ;;
|
||||||
esac
|
esac
|
||||||
@ -97,6 +119,14 @@ disable_tool() {
|
|||||||
warn "$tool already disabled"
|
warn "$tool already disabled"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
magic)
|
||||||
|
if [ "$(status_tool magic)" = "enabled" ]; then
|
||||||
|
claude mcp remove magic -s user >/dev/null
|
||||||
|
ok "magic disabled"
|
||||||
|
else
|
||||||
|
warn "magic already disabled"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*) err "Unknown tool: $tool"; return 1 ;;
|
*) err "Unknown tool: $tool"; return 1 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@ -134,6 +164,21 @@ enable_tool() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
magic)
|
||||||
|
load_env
|
||||||
|
if [ -z "${MAGIC_API_KEY:-}" ]; then
|
||||||
|
err "MAGIC_API_KEY not set — add it to $REPO/.env (template: .env.example)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$(status_tool magic)" = "enabled" ]; then
|
||||||
|
warn "magic already enabled"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
claude mcp add magic --scope user \
|
||||||
|
--env API_KEY="$MAGIC_API_KEY" \
|
||||||
|
-- npx -y @21st-dev/magic@latest
|
||||||
|
ok "magic enabled (user scope)"
|
||||||
|
;;
|
||||||
*) err "Unknown tool: $tool"; return 1 ;;
|
*) err "Unknown tool: $tool"; return 1 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user