#!/bin/bash # ai-proj-helper 初始化脚本 # 配置 MCP 连接 + 安装技能到 ~/.claude/skills/ set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" MCP_CONFIG="$HOME/.claude/.mcp.json" MCP_BRIDGE_DIR="$SCRIPT_DIR/mcp-task-bridge" CONFIG_FILE="$SCRIPT_DIR/claude-config.yaml" API_BASE="https://ai.pipexerp.com/api/v1" SSE_URL="${API_BASE}/mcp/sse" # Default values MODE="" TOKEN="" # ── Parse command line arguments ────────────────────────────────────── while [[ $# -gt 0 ]]; do case $1 in --mode) MODE="$2"; shift 2 ;; --token) TOKEN="$2"; shift 2 ;; -h|--help) echo "Usage: ./init.sh [--mode sse|stdio] [--token MCP_API_KEY]" echo "" echo "Options:" echo " --mode MCP connection mode: sse (remote, recommended) or stdio (local)" echo " --token MCP API Key (aiproj_pk_xxx)" echo "" echo "Without arguments, runs in interactive mode." exit 0 ;; *) echo "Unknown option: $1"; exit 1 ;; esac done # ── Read config defaults ───────────────────────────────────────────── read_config_value() { local key="$1" local default="$2" if [ -f "$CONFIG_FILE" ]; then local val val=$(grep "^ ${key}:" "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/^[^:]*: *//' | sed 's/ *#.*//' | tr -d '"' | tr -d "'") if [ -n "$val" ]; then echo "$val" return fi fi echo "$default" } CONFIG_MODE=$(read_config_value "mode" "sse") # ── Detect claude CLI ──────────────────────────────────────────────── HAS_CLAUDE=false if command -v claude &>/dev/null; then HAS_CLAUDE=true fi # ── Interactive mode selection ──────────────────────────────────────── if [ -z "$MODE" ]; then echo "┌─────────────────────────────────────┐" echo "│ ai-proj MCP 初始化 │" echo "└─────────────────────────────────────┘" echo "" echo "MCP 连接模式:" echo " 1) sse - 远程连接 (推荐,零依赖)" echo " 2) stdio - 本地进程 (需要 Node.js + mcp-task-bridge)" echo "" read -p "选择模式 [1/2] (default: $([ "$CONFIG_MODE" = "stdio" ] && echo "2" || echo "1")): " mode_choice case "$mode_choice" in 2|stdio) MODE="stdio" ;; *) MODE="sse" ;; esac fi # ── Token input ─────────────────────────────────────────────────────── if [ -z "$TOKEN" ]; then echo "" echo "请输入 MCP API Key:" echo " 格式: aiproj_pk_xxxxxxxx" echo " 获取: 登录 AI-Proj → 设置 → MCP API Keys → 创建" echo "" read -sp "API Key: " TOKEN echo "" fi if [ -z "$TOKEN" ]; then echo "❌ API Key 不能为空" exit 1 fi echo "" echo "配置信息:" echo " 模式: $MODE" echo " Claude CLI: $($HAS_CLAUDE && echo '检测到' || echo '未检测到 (回退写 .mcp.json)')" if [ "$MODE" = "sse" ]; then echo " URL: $SSE_URL" else echo " API: $API_BASE" fi echo "" # ── Configure MCP ──────────────────────────────────────────────────── if [ "$MODE" = "sse" ]; then if $HAS_CLAUDE; then # 新版 Claude Code: 用 claude mcp add 注册(transport=http,即 Streamable HTTP) # 先移除旧配置(忽略错误) claude mcp remove -s user ai-proj 2>/dev/null || true claude mcp add ai-proj "$SSE_URL" -t http -s user -H "X-API-Key: $TOKEN" 2>&1 echo "✅ 已通过 claude mcp add 注册 (Streamable HTTP)" else # 旧版或无 CLI: 回退写 .mcp.json mkdir -p "$(dirname "$MCP_CONFIG")" cat > "$MCP_CONFIG" << EOF { "mcpServers": { "ai-proj": { "type": "sse", "url": "$SSE_URL", "headers": { "X-API-Key": "$TOKEN" } } } } EOF echo "✅ 已生成 $MCP_CONFIG (SSE 模式)" fi elif [ "$MODE" = "stdio" ]; then if [ ! -d "$MCP_BRIDGE_DIR" ]; then echo "📦 mcp-task-bridge 未找到,正在克隆..." git clone https://gitea.pipexerp.com/pipexerp/mcp-task-bridge.git "$MCP_BRIDGE_DIR" fi if [ ! -f "$MCP_BRIDGE_DIR/dist/index.js" ]; then echo "🔨 构建 mcp-task-bridge..." cd "$MCP_BRIDGE_DIR" npm install npm run build cd "$SCRIPT_DIR" fi BRIDGE_ENTRY="$MCP_BRIDGE_DIR/dist/index.js" if $HAS_CLAUDE; then claude mcp remove -s user ai-proj 2>/dev/null || true claude mcp add ai-proj -s user -e "NODE_ENV=production" -e "TASK_API_BASE=$API_BASE" -e "TASK_API_TOKEN=$TOKEN" -e "MCP_SERVER_NAME=ai-proj" -- node "$BRIDGE_ENTRY" 2>&1 echo "✅ 已通过 claude mcp add 注册 (stdio)" else mkdir -p "$(dirname "$MCP_CONFIG")" cat > "$MCP_CONFIG" << EOF { "mcpServers": { "ai-proj": { "command": "node", "args": ["$BRIDGE_ENTRY"], "env": { "NODE_ENV": "production", "TASK_API_BASE": "$API_BASE", "TASK_API_TOKEN": "$TOKEN", "MCP_SERVER_NAME": "ai-proj" } } } } EOF echo "✅ 已生成 $MCP_CONFIG (stdio 模式)" fi fi # ── Install skills to ~/.claude/skills/ ────────────────────────────── echo "📦 安装技能到 ~/.claude/skills/ ..." SKILLS_DIR="$HOME/.claude/skills" mkdir -p "$SKILLS_DIR" SKILL_COUNT=0 for plugin_dir in "$SCRIPT_DIR"/skills-*/; do for skill_path in "$plugin_dir"*-plugin/; do [ -d "$skill_path" ] || continue skill_md="$skill_path/skills/SKILL.md" [ -f "$skill_md" ] || continue # Extract skill name: ai-proj-plugin -> ai-proj dir_name=$(basename "$skill_path") skill_name="${dir_name%-plugin}" target_dir="$SKILLS_DIR/$skill_name" mkdir -p "$target_dir" # Copy SKILL.md (overwrite if exists) cp "$skill_md" "$target_dir/SKILL.md" SKILL_COUNT=$((SKILL_COUNT + 1)) done done echo " 已安装 $SKILL_COUNT 个技能" echo "✅ 技能安装完成 → $SKILLS_DIR" echo "" echo "┌─────────────────────────────────────┐" echo "│ ✅ 初始化完成! │" echo "└─────────────────────────────────────┘" echo "" echo "已完成配置:" if $HAS_CLAUDE; then echo " ✅ MCP 服务器 (claude mcp add)" else echo " ✅ MCP 服务器 → $MCP_CONFIG" fi echo " ✅ 技能 ($SKILL_COUNT 个) → $SKILLS_DIR" echo "" echo "重启 Claude Code 即可使用。" echo "如需更改配置,编辑 claude-config.yaml 后重新运行 ./init.sh"