Files
ai-proj-helper/init.sh
John Qiu c303b534fc fix: update init.sh with lessons from MCP SSE debugging
- Rename mode "sse" → "remote" (actual transport is Streamable HTTP)
- Fix .mcp.json fallback: "type": "sse" → "type": "http"
- Add post-install connection verification (curl initialize test)
- Accept "sse" as alias for backward compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:41:10 +10:30

238 lines
8.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 remote|stdio] [--token MCP_API_KEY]"
echo ""
echo "Options:"
echo " --mode MCP connection mode: remote (Streamable HTTP, recommended) or stdio (local Node.js)"
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" "remote")
# Normalize mode aliases: sse → remote
if [ "$MODE" = "sse" ]; then
MODE="remote"
fi
# ── 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) remote - 远程连接 (推荐零依赖Streamable HTTP)"
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="remote" ;;
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" = "remote" ]; then
echo " URL: $SSE_URL"
else
echo " API: $API_BASE"
fi
echo ""
# ── Configure MCP ────────────────────────────────────────────────────
if [ "$MODE" = "remote" ]; 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使用 http transport
mkdir -p "$(dirname "$MCP_CONFIG")"
cat > "$MCP_CONFIG" << EOF
{
"mcpServers": {
"ai-proj": {
"type": "http",
"url": "$SSE_URL",
"headers": {
"X-API-Key": "$TOKEN"
}
}
}
}
EOF
echo "✅ 已生成 $MCP_CONFIG (Streamable HTTP 模式)"
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"
# ── Verify MCP connection ────────────────────────────────────────────
echo ""
echo "🔍 验证 MCP 连接..."
if [ "$MODE" = "remote" ]; then
VERIFY_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$SSE_URL" \
-H "Content-Type: application/json" \
-H "X-API-Key: $TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"init-verify","version":"1.0"}}}' \
--connect-timeout 10 --max-time 15 2>/dev/null)
if [ "$VERIFY_RESPONSE" = "200" ]; then
echo " ✅ MCP 服务端连接正常 (HTTP $VERIFY_RESPONSE)"
else
echo " ⚠️ MCP 服务端连接异常 (HTTP $VERIFY_RESPONSE)"
echo " 请检查: 1) API Key 是否正确 2) 服务端是否运行 3) 网络是否通畅"
echo " 测试命令: curl -s -X POST '$SSE_URL' -H 'X-API-Key: \$TOKEN' -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{}}'"
fi
fi
echo ""
echo "┌─────────────────────────────────────┐"
echo "│ ✅ 初始化完成! │"
echo "└─────────────────────────────────────┘"
echo ""
echo "已完成配置:"
if $HAS_CLAUDE; then
echo " ✅ MCP 服务器 (claude mcp add, transport=http)"
else
echo " ✅ MCP 服务器 → $MCP_CONFIG"
fi
echo " ✅ 技能 ($SKILL_COUNT 个) → $SKILLS_DIR"
echo ""
echo "重启 Claude Code 即可使用。"
echo "如需更改配置,编辑 claude-config.yaml 后重新运行 ./init.sh"