Merge remote-tracking branch 'upstream/main' into feat/native-claude-cli-detection

This commit is contained in:
谢栋梁
2025-12-07 00:08:17 +08:00
122 changed files with 1439 additions and 1059 deletions

View File

@@ -2,7 +2,7 @@
set -euo pipefail
# ============================================================================
# Zen MCP Server Setup Script
# PAL MCP Server Setup Script
#
# A platform-agnostic setup script that works on macOS, Linux, and WSL.
# Handles environment setup, dependency installation, and configuration.
@@ -29,11 +29,12 @@ readonly RED='\033[0;31m'
readonly NC='\033[0m' # No Color
# Configuration
readonly VENV_PATH=".zen_venv"
readonly VENV_PATH=".pal_venv"
readonly DOCKER_CLEANED_FLAG=".docker_cleaned"
readonly DESKTOP_CONFIG_FLAG=".desktop_configured"
readonly LOG_DIR="logs"
readonly LOG_FILE="mcp_server.log"
readonly LEGACY_MCP_NAMES=("zen" "zen-mcp" "zen-mcp-server" "zen_mcp" "zen_mcp_server")
# Determine portable arguments for sed -i (GNU vs BSD)
declare -a SED_INPLACE_ARGS
@@ -753,7 +754,7 @@ setup_venv() {
print_error "Permission denied creating virtual environment"
echo ""
echo "Try running in a different directory:"
echo " cd ~ && git clone <repository-url> && cd zen-mcp-server && ./run-server.sh"
echo " cd ~ && git clone <repository-url> && cd pal-mcp-server && ./run-server.sh"
echo ""
exit 1
else
@@ -960,7 +961,7 @@ install_dependencies() {
fi
echo ""
print_info "Setting up Zen MCP Server..."
print_info "Setting up PAL MCP Server..."
echo "Installing required components:"
echo " • MCP protocol library"
echo " • AI model connectors"
@@ -1254,7 +1255,7 @@ check_claude_cli_integration() {
echo ""
print_warning "Claude CLI not found"
echo ""
read -p "Would you like to add Zen to Claude Code? (Y/n): " -n 1 -r
read -p "Would you like to add PAL to Claude Code? (Y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Claude Code integration"
@@ -1269,9 +1270,14 @@ check_claude_cli_integration() {
return 1
fi
# Check if zen is registered
# Remove legacy zen registrations to avoid duplicate errors after rename
for legacy_name in "${LEGACY_MCP_NAMES[@]}"; do
claude mcp remove "$legacy_name" -s user >/dev/null 2>&1 || true
done
# Check if pal is registered
local mcp_list=$(claude mcp list 2>/dev/null)
if echo "$mcp_list" | grep -q "zen"; then
if echo "$mcp_list" | grep -q "pal"; then
# Check if it's using the old Docker command
if echo "$mcp_list" | grep -E "zen.*docker|zen.*compose" &>/dev/null; then
print_warning "Found old Docker-based Zen registration, updating..."
@@ -1290,14 +1296,14 @@ check_claude_cli_integration() {
done <<< "$env_vars"
fi
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
if eval "$claude_cmd" 2>/dev/null; then
print_success "Updated Zen to become a standalone script with environment variables"
print_success "Updated PAL to become a standalone script with environment variables"
return 0
else
echo ""
echo "Failed to update MCP registration. Please run manually:"
echo " claude mcp remove zen -s user"
echo " claude mcp remove pal -s user"
echo " $claude_cmd"
return 1
fi
@@ -1307,8 +1313,8 @@ check_claude_cli_integration() {
if echo "$mcp_list" | grep -F "$server_path" &>/dev/null; then
return 0
else
print_warning "Zen registered with different path, updating..."
claude mcp remove zen -s user 2>/dev/null || true
print_warning "PAL registered with different path, updating..."
claude mcp remove pal -s user 2>/dev/null || true
# Re-add with current path and environment variables
local env_vars=$(parse_env_variables)
@@ -1323,14 +1329,14 @@ check_claude_cli_integration() {
done <<< "$env_vars"
fi
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
if eval "$claude_cmd" 2>/dev/null; then
print_success "Updated Zen with current path and environment variables"
print_success "Updated PAL with current path and environment variables"
return 0
else
echo ""
echo "Failed to update MCP registration. Please run manually:"
echo " claude mcp remove zen -s user"
echo " claude mcp remove pal -s user"
echo " $claude_cmd"
return 1
fi
@@ -1339,7 +1345,7 @@ check_claude_cli_integration() {
else
# Not registered at all, ask user if they want to add it
echo ""
read -p "Add Zen to Claude Code? (Y/n): " -n 1 -r
read -p "Add PAL to Claude Code? (Y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
local env_vars=$(parse_env_variables)
@@ -1355,11 +1361,11 @@ check_claude_cli_integration() {
fi
print_info "To add manually later, run:"
echo " claude mcp add zen -s user$env_args -- $python_cmd $server_path"
echo " claude mcp add pal -s user$env_args -- $python_cmd $server_path"
return 0
fi
print_info "Registering Zen with Claude Code..."
print_info "Registering PAL with Claude Code..."
# Add with environment variables
local env_vars=$(parse_env_variables)
@@ -1374,9 +1380,9 @@ check_claude_cli_integration() {
done <<< "$env_vars"
fi
local claude_cmd="claude mcp add zen -s user$env_args -- \"$python_cmd\" \"$server_path\""
local claude_cmd="claude mcp add pal -s user$env_args -- \"$python_cmd\" \"$server_path\""
if eval "$claude_cmd" 2>/dev/null; then
print_success "Successfully added Zen to Claude Code with environment variables"
print_success "Successfully added PAL to Claude Code with environment variables"
return 0
else
echo ""
@@ -1403,8 +1409,12 @@ check_claude_desktop_integration() {
return 0
fi
# Legacy MCP server names to clean out from previous releases
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
echo ""
read -p "Configure Zen for Claude Desktop? (Y/n): " -n 1 -r
read -p "Configure PAL for Claude Desktop? (Y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Claude Desktop integration"
@@ -1421,12 +1431,12 @@ check_claude_desktop_integration() {
print_info "Updating existing Claude Desktop config..."
# Check for old Docker config and remove it
if grep -q "docker.*compose.*zen\|zen.*docker" "$config_path" 2>/dev/null; then
if grep -q "docker.*compose.*pal\|pal.*docker" "$config_path" 2>/dev/null; then
print_warning "Removing old Docker-based MCP configuration..."
# Create backup
cp "$config_path" "${config_path}.backup_$(date +%Y%m%d_%H%M%S)"
# Remove old zen config using a more robust approach
# Remove old pal config using a more robust approach
local temp_file=$(mktemp)
python3 -c "
import json
@@ -1436,10 +1446,10 @@ try:
with open('$config_path', 'r') as f:
config = json.load(f)
# Remove zen from mcpServers if it exists
if 'mcpServers' in config and 'zen' in config['mcpServers']:
del config['mcpServers']['zen']
print('Removed old zen MCP configuration')
# Remove pal from mcpServers if it exists
if 'mcpServers' in config and 'pal' in config['mcpServers']:
del config['mcpServers']['pal']
print('Removed old pal MCP configuration')
with open('$temp_file', 'w') as f:
json.dump(config, f, indent=2)
@@ -1460,22 +1470,35 @@ except Exception as e:
echo "$env_vars" > "$env_file"
fi
python3 -c "
PAL_LEGACY_NAMES="$legacy_names_csv" python3 -c "
import json
import os
import sys
legacy_keys = [k for k in os.environ.get('PAL_LEGACY_NAMES', '').split(',') if k]
try:
with open('$config_path', 'r') as f:
config = json.load(f)
except:
except Exception:
config = {}
if not isinstance(config, dict):
config = {}
# Ensure mcpServers exists
if 'mcpServers' not in config:
if 'mcpServers' not in config or not isinstance(config.get('mcpServers'), dict):
config['mcpServers'] = {}
# Add zen server
zen_config = {
# Remove legacy entries from any known server blocks
for container in ('mcpServers', 'servers'):
servers = config.get(container)
if isinstance(servers, dict):
for key in legacy_keys:
servers.pop(key, None)
# Add pal server
pal_config = {
'command': '$python_cmd',
'args': ['$server_path']
}
@@ -1489,13 +1512,13 @@ try:
if '=' in line and line:
key, value = line.split('=', 1)
env_dict[key] = value
except:
except Exception:
pass
if env_dict:
zen_config['env'] = env_dict
pal_config['env'] = env_dict
config['mcpServers']['zen'] = zen_config
config['mcpServers']['pal'] = pal_config
with open('$temp_file', 'w') as f:
json.dump(config, f, indent=2)
@@ -1523,8 +1546,8 @@ import sys
config = {'mcpServers': {}}
# Add zen server
zen_config = {
# Add pal server
pal_config = {
'command': '$python_cmd',
'args': ['$server_path']
}
@@ -1542,9 +1565,9 @@ except:
pass
if env_dict:
zen_config['env'] = env_dict
pal_config['env'] = env_dict
config['mcpServers']['zen'] = zen_config
config['mcpServers']['pal'] = pal_config
with open('$temp_file', 'w') as f:
json.dump(config, f, indent=2)
@@ -1587,7 +1610,7 @@ with open('$temp_file', 'w') as f:
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"]$(if [[ -n "$example_env" ]]; then echo ","; fi)$(if [[ -n "$example_env" ]]; then echo "
\"env\": {
@@ -1603,7 +1626,7 @@ EOF
# Check and update Gemini CLI configuration
check_gemini_cli_integration() {
local script_dir="$1"
local zen_wrapper="$script_dir/zen-mcp-server"
local pal_wrapper="$script_dir/pal-mcp-server"
# Check if Gemini settings file exists
local gemini_config="$HOME/.gemini/settings.json"
@@ -1612,15 +1635,75 @@ check_gemini_cli_integration() {
return 0
fi
# Check if zen is already configured
if grep -q '"zen"' "$gemini_config" 2>/dev/null; then
# Already configured
# Clean up legacy zen entries and detect existing pal configuration
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
local gemini_status
gemini_status=$(
PAL_LEGACY_NAMES="$legacy_names_csv" PAL_WRAPPER="$pal_wrapper" PAL_GEMINI_CONFIG="$gemini_config" python3 - <<'PY' 2>/dev/null
import json
import os
import pathlib
import sys
config_path = pathlib.Path(os.environ["PAL_GEMINI_CONFIG"])
legacy = [n for n in os.environ.get("PAL_LEGACY_NAMES", "").split(",") if n]
wrapper = os.environ["PAL_WRAPPER"]
changed = False
has_pal = False
try:
data = json.loads(config_path.read_text())
except Exception:
data = {}
if not isinstance(data, dict):
data = {}
servers = data.get("mcpServers")
if not isinstance(servers, dict):
servers = {}
data["mcpServers"] = servers
for key in legacy:
if servers.pop(key, None) is not None:
changed = True
pal_cfg = servers.get("pal")
if isinstance(pal_cfg, dict):
has_pal = True
if pal_cfg.get("command") != wrapper:
pal_cfg["command"] = wrapper
servers["pal"] = pal_cfg
changed = True
if changed:
config_path.parent.mkdir(parents=True, exist_ok=True)
config_path.write_text(json.dumps(data, indent=2))
status = ("CHANGED" if changed else "UNCHANGED") + ":" + ("HAS_PAL" if has_pal else "NO_PAL")
sys.stdout.write(status)
sys.exit(0)
PY
) || true
local gemini_changed=false
local gemini_has_pal=false
[[ "$gemini_status" == CHANGED:* ]] && gemini_changed=true
[[ "$gemini_status" == *:HAS_PAL ]] && gemini_has_pal=true
if [[ "$gemini_has_pal" == true ]]; then
if [[ "$gemini_changed" == true ]]; then
print_success "Removed legacy Gemini MCP entries"
fi
return 0
fi
# Ask user if they want to add Zen to Gemini CLI
# Ask user if they want to add PAL to Gemini CLI
echo ""
read -p "Configure Zen for Gemini CLI? (Y/n): " -n 1 -r
read -p "Configure PAL for Gemini CLI? (Y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Gemini CLI integration"
@@ -1628,17 +1711,17 @@ check_gemini_cli_integration() {
fi
# Ensure wrapper script exists
if [[ ! -f "$zen_wrapper" ]]; then
if [[ ! -f "$pal_wrapper" ]]; then
print_info "Creating wrapper script for Gemini CLI..."
cat > "$zen_wrapper" << 'EOF'
cat > "$pal_wrapper" << 'EOF'
#!/bin/bash
# Wrapper script for Gemini CLI compatibility
DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$DIR"
exec .zen_venv/bin/python server.py "$@"
exec .pal_venv/bin/python server.py "$@"
EOF
chmod +x "$zen_wrapper"
print_success "Created zen-mcp-server wrapper script"
chmod +x "$pal_wrapper"
print_success "Created pal-mcp-server wrapper script"
fi
# Update Gemini settings
@@ -1647,7 +1730,7 @@ EOF
# Create backup
cp "$gemini_config" "${gemini_config}.backup_$(date +%Y%m%d_%H%M%S)"
# Add zen configuration using Python for proper JSON handling
# Add pal configuration using Python for proper JSON handling
local temp_file=$(mktemp)
python3 -c "
import json
@@ -1661,9 +1744,9 @@ try:
if 'mcpServers' not in config:
config['mcpServers'] = {}
# Add zen server
config['mcpServers']['zen'] = {
'command': '$zen_wrapper'
# Add pal server
config['mcpServers']['pal'] = {
'command': '$pal_wrapper'
}
with open('$temp_file', 'w') as f:
@@ -1677,7 +1760,7 @@ except Exception as e:
if [[ $? -eq 0 ]]; then
print_success "Successfully configured Gemini CLI"
echo " Config: $gemini_config"
echo " Restart Gemini CLI to use Zen MCP Server"
echo " Restart Gemini CLI to use PAL MCP Server"
else
print_error "Failed to update Gemini CLI config"
echo "Manual config location: $gemini_config"
@@ -1685,8 +1768,8 @@ except Exception as e:
cat << EOF
{
"mcpServers": {
"zen": {
"command": "$zen_wrapper"
"pal": {
"command": "$pal_wrapper"
}
}
}
@@ -1701,14 +1784,71 @@ check_codex_cli_integration() {
fi
local codex_config="$HOME/.codex/config.toml"
local codex_has_zen=false
if [[ -f "$codex_config" ]] && grep -q '\[mcp_servers\.zen\]' "$codex_config" 2>/dev/null; then
codex_has_zen=true
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
if [[ -f "$codex_config" ]]; then
local codex_cleanup_status
codex_cleanup_status=$(
PAL_LEGACY_NAMES="$legacy_names_csv" PAL_CODEX_CONFIG="$codex_config" python3 - <<'PY' 2>/dev/null
import os
import pathlib
import re
import sys
config_path = pathlib.Path(os.environ["PAL_CODEX_CONFIG"])
legacy = [n for n in os.environ.get("PAL_LEGACY_NAMES", "").split(",") if n]
if not config_path.exists():
sys.exit(0)
lines = config_path.read_text().splitlines()
output = []
skip = False
removed = False
section_re = re.compile(r"\s*\[([^\]]+)\]")
for line in lines:
match = section_re.match(line)
if match:
header = match.group(1).strip()
parts = header.split(".")
is_legacy = False
if len(parts) >= 2 and parts[0] == "mcp_servers":
section_key = ".".join(parts[1:])
for name in legacy:
if section_key == name or section_key.startswith(name + "."):
is_legacy = True
break
skip = is_legacy
if is_legacy:
removed = True
continue
if not skip:
output.append(line)
if removed:
config_path.write_text("\n".join(output).rstrip() + ("\n" if output else ""))
sys.stdout.write("REMOVED")
else:
sys.stdout.write("UNCHANGED")
sys.exit(0)
PY
) || true
if [[ "$codex_cleanup_status" == "REMOVED" ]]; then
print_success "Removed legacy Codex MCP entries"
fi
fi
if [[ "$codex_has_zen" == false ]]; then
local codex_has_pal=false
if [[ -f "$codex_config" ]] && grep -q '\[mcp_servers\.pal\]' "$codex_config" 2>/dev/null; then
codex_has_pal=true
fi
if [[ "$codex_has_pal" == false ]]; then
echo ""
read -p "Configure Zen for Codex CLI? (Y/n): " -n 1 -r
read -p "Configure PAL for Codex CLI? (Y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_info "Skipping Codex CLI integration"
@@ -1727,12 +1867,12 @@ check_codex_cli_integration() {
{
echo ""
echo "[mcp_servers.zen]"
echo "[mcp_servers.pal]"
echo "command = \"bash\""
echo "args = [\"-c\", \"for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1\"]"
echo "args = [\"-c\", \"for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1\"]"
echo "tool_timeout_sec = 1200"
echo ""
echo "[mcp_servers.zen.env]"
echo "[mcp_servers.pal.env]"
echo "PATH = \"/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin\""
if [[ -n "$env_vars" ]]; then
while IFS= read -r line; do
@@ -1752,12 +1892,12 @@ check_codex_cli_integration() {
echo "Manual config location: $codex_config"
echo "Add this configuration:"
cat <<'CODExEOF'
[mcp_servers.zen]
[mcp_servers.pal]
command = "sh"
args = ["-c", "exec \$(which uvx 2>/dev/null || echo uvx) --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server"]
args = ["-c", "exec \$(which uvx 2>/dev/null || echo uvx) --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server"]
tool_timeout_sec = 1200
[mcp_servers.zen.env]
[mcp_servers.pal.env]
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
[features]
@@ -1779,16 +1919,16 @@ CODExEOF
print_success "Successfully configured Codex CLI"
echo " Config: $codex_config"
echo " Restart Codex CLI to use Zen MCP Server"
codex_has_zen=true
echo " Restart Codex CLI to use PAL MCP Server"
codex_has_pal=true
else
print_info "Codex CLI already configured; refreshing Codex settings..."
fi
if [[ "$codex_has_zen" == true ]]; then
if [[ "$codex_has_pal" == true ]]; then
if ! grep -Eq '^\s*web_search_request\s*=' "$codex_config" 2>/dev/null; then
echo ""
print_info "Web search requests let Codex pull fresh documentation for Zen's API lookup tooling."
print_info "Web search requests let Codex pull fresh documentation for PAL's API lookup tooling."
read -p "Enable Codex CLI web search requests? (Y/n): " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
@@ -1923,7 +2063,7 @@ print_qwen_manual_instructions() {
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -1936,7 +2076,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -1976,6 +2116,43 @@ check_qwen_cli_integration() {
env_lines=$(printf '%s\n' "${env_array[@]}")
fi
local legacy_names_csv
legacy_names_csv=$(IFS=,; echo "${LEGACY_MCP_NAMES[*]}")
if [[ -f "$qwen_config" ]]; then
PAL_QWEN_LEGACY="$legacy_names_csv" PAL_QWEN_CONFIG="$qwen_config" python3 - <<'PYCLEANCONF' 2>/dev/null || true
import json
import os
import pathlib
import sys
config_path = pathlib.Path(os.environ.get("PAL_QWEN_CONFIG", ""))
legacy = [n for n in os.environ.get("PAL_QWEN_LEGACY", "").split(",") if n]
if not config_path.exists():
sys.exit(0)
try:
data = json.loads(config_path.read_text(encoding="utf-8"))
except Exception:
sys.exit(0)
if not isinstance(data, dict):
sys.exit(0)
servers = data.get("mcpServers")
if isinstance(servers, dict):
removed = False
for key in legacy:
if servers.pop(key, None) is not None:
removed = True
if removed:
config_path.write_text(json.dumps(data, indent=2))
sys.exit(0)
PYCLEANCONF
fi
local config_status=3
if [[ -f "$qwen_config" ]]; then
if python3 - "$qwen_config" "$python_cmd" "$server_path" "$script_dir" <<'PYCONF'
@@ -1995,7 +2172,7 @@ servers = data.get('mcpServers')
if not isinstance(servers, dict):
sys.exit(3)
config = servers.get('zen')
config = servers.get('pal')
if not isinstance(config, dict):
sys.exit(3)
@@ -2026,14 +2203,14 @@ PYCONF
echo ""
if [[ $config_status -eq 4 ]]; then
print_warning "Found existing Qwen CLI zen configuration with different settings."
print_warning "Found existing Qwen CLI pal configuration with different settings."
elif [[ $config_status -eq 5 ]]; then
print_warning "Unable to parse Qwen CLI settings; replacing with a fresh entry may help."
fi
local prompt="Configure Zen for Qwen CLI? (Y/n): "
local prompt="Configure PAL for Qwen CLI? (Y/n): "
if [[ $config_status -eq 4 || $config_status -eq 5 ]]; then
prompt="Update Qwen CLI zen configuration? (Y/n): "
prompt="Update Qwen CLI pal configuration? (Y/n): "
fi
read -p "$prompt" -n 1 -r
@@ -2051,17 +2228,17 @@ PYCONF
local update_output
local update_status=0
update_output=$(ZEN_QWEN_ENV="$env_lines" ZEN_QWEN_CMD="$python_cmd" ZEN_QWEN_ARG="$server_path" ZEN_QWEN_CWD="$script_dir" python3 - "$qwen_config" <<'PYUPDATE'
update_output=$(PAL_QWEN_ENV="$env_lines" PAL_QWEN_CMD="$python_cmd" PAL_QWEN_ARG="$server_path" PAL_QWEN_CWD="$script_dir" python3 - "$qwen_config" <<'PYUPDATE'
import json
import os
import pathlib
import sys
config_path = pathlib.Path(sys.argv[1])
cmd = os.environ['ZEN_QWEN_CMD']
arg = os.environ['ZEN_QWEN_ARG']
cwd = os.environ['ZEN_QWEN_CWD']
env_lines = os.environ.get('ZEN_QWEN_ENV', '').splitlines()
cmd = os.environ['PAL_QWEN_CMD']
arg = os.environ['PAL_QWEN_ARG']
cwd = os.environ['PAL_QWEN_CWD']
env_lines = os.environ.get('PAL_QWEN_ENV', '').splitlines()
env_map = {}
for line in env_lines:
@@ -2088,16 +2265,16 @@ if not isinstance(servers, dict):
servers = {}
data['mcpServers'] = servers
zen_config = {
pal_config = {
'command': cmd,
'args': [arg],
'cwd': cwd,
}
if env_map:
zen_config['env'] = env_map
pal_config['env'] = env_map
servers['zen'] = zen_config
servers['pal'] = pal_config
config_path.parent.mkdir(parents=True, exist_ok=True)
tmp_path = config_path.with_suffix(config_path.suffix + '.tmp')
@@ -2111,7 +2288,7 @@ PYUPDATE
if [[ $update_status -eq 0 ]]; then
print_success "Successfully configured Qwen CLI"
echo " Config: $qwen_config"
echo " Restart Qwen CLI to use Zen MCP Server"
echo " Restart Qwen CLI to use PAL MCP Server"
else
print_error "Failed to update Qwen CLI config"
if [[ -n "$update_output" ]]; then
@@ -2130,11 +2307,11 @@ display_config_instructions() {
local script_dir=$(dirname "$server_path")
echo ""
local config_header="ZEN MCP SERVER CONFIGURATION"
local config_header="PAL MCP SERVER CONFIGURATION"
echo "===== $config_header ====="
printf '%*s\n' "$((${#config_header} + 12))" | tr ' ' '='
echo ""
echo "To use Zen MCP Server with your CLI clients:"
echo "To use PAL MCP Server with your CLI clients:"
echo ""
print_info "1. For Claude Code (CLI):"
@@ -2148,7 +2325,7 @@ display_config_instructions() {
fi
done <<< "$env_vars"
fi
echo -e " ${GREEN}claude mcp add zen -s user$env_args -- $python_cmd $server_path${NC}"
echo -e " ${GREEN}claude mcp add pal -s user$env_args -- $python_cmd $server_path${NC}"
echo ""
print_info "2. For Claude Desktop:"
@@ -2179,7 +2356,7 @@ display_config_instructions() {
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -2194,7 +2371,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -2222,8 +2399,8 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"command": "$script_dir/zen-mcp-server"
"pal": {
"command": "$script_dir/pal-mcp-server"
}
}
}
@@ -2237,7 +2414,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir",
@@ -2252,7 +2429,7 @@ EOF
cat << EOF
{
"mcpServers": {
"zen": {
"pal": {
"command": "$python_cmd",
"args": ["$server_path"],
"cwd": "$script_dir"
@@ -2267,11 +2444,11 @@ EOF
echo " Add this configuration to ~/.codex/config.toml:"
echo ""
cat << EOF
[mcp_servers.zen]
[mcp_servers.pal]
command = "bash"
args = ["-c", "for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/zen-mcp-server.git zen-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
args = ["-c", "for p in \$(which uvx 2>/dev/null) \$HOME/.local/bin/uvx /opt/homebrew/bin/uvx /usr/local/bin/uvx uvx; do [ -x \\\"\$p\\\" ] && exec \\\"\$p\\\" --from git+https://github.com/BeehiveInnovations/pal-mcp-server.git pal-mcp-server; done; echo 'uvx not found' >&2; exit 1"]
[mcp_servers.zen.env]
[mcp_servers.pal.env]
PATH = "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/bin"
GEMINI_API_KEY = "your_gemini_api_key_here"
EOF
@@ -2288,7 +2465,7 @@ display_setup_instructions() {
echo "===== $setup_header ====="
printf '%*s\n' "$((${#setup_header} + 12))" | tr ' ' '='
echo ""
print_success "Zen is ready to use!"
print_success "PAL is ready to use!"
# Display enabled/disabled tools if DISABLED_TOOLS is configured
if [[ -n "${DISABLED_TOOLS:-}" ]]; then
@@ -2368,7 +2545,7 @@ display_setup_instructions() {
# Show help message
show_help() {
local version=$(get_version)
local header="🤖 Zen MCP Server v$version"
local header="🤖 PAL MCP Server v$version"
echo "$header"
printf '%*s\n' "${#header}" | tr ' ' '='
echo ""
@@ -2389,7 +2566,7 @@ show_help() {
echo " $0 --clear-cache Clear Python cache (fixes import issues)"
echo ""
echo "For more information, visit:"
echo " https://github.com/BeehiveInnovations/zen-mcp-server"
echo " https://github.com/BeehiveInnovations/pal-mcp-server"
}
# Show version only
@@ -2464,7 +2641,7 @@ main() {
esac
# Display header
local main_header="🤖 Zen MCP Server"
local main_header="🤖 PAL MCP Server"
echo "$main_header"
printf '%*s\n' "${#main_header}" | tr ' ' '='