#!/usr/bin/env bash
set -euo pipefail
# =====================================================================
# Excel MCP Server — One-Command Installer
# =====================================================================
BLUE='\033[0;34m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
BOLD='\033[1m'
info() { echo -e "${BLUE}[info]${NC} $*"; }
ok() { echo -e "${GREEN}[ok]${NC} $*"; }
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
fail() { echo -e "${RED}[error]${NC} $*"; exit 1; }
echo ""
echo -e "${BOLD}=== Excel Analytics MCP Server — Installer ===${NC}"
echo ""
# ------------------------------------------------------------------
# 1. Check Python 3.10+
# ------------------------------------------------------------------
info "Checking Python version..."
if command -v python3 &>/dev/null; then
PY=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
PY_MAJOR=$(echo "$PY" | cut -d. -f1)
PY_MINOR=$(echo "$PY" | cut -d. -f2)
if [ "$PY_MAJOR" -ge 3 ] && [ "$PY_MINOR" -ge 10 ]; then
ok "Python $PY found"
else
fail "Python 3.10+ required (found $PY). Install from https://python.org"
fi
else
fail "Python 3 not found. Install from https://python.org"
fi
# ------------------------------------------------------------------
# 2. Check / install uv
# ------------------------------------------------------------------
info "Checking for uv..."
if command -v uv &>/dev/null; then
ok "uv found: $(uv --version)"
else
info "Installing uv..."
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
if command -v uv &>/dev/null; then
ok "uv installed"
else
fail "Failed to install uv. Visit https://docs.astral.sh/uv/getting-started/installation/"
fi
fi
# ------------------------------------------------------------------
# 3. Create directory structure
# ------------------------------------------------------------------
MCP_HOME="$HOME/.excel-mcp"
info "Setting up $MCP_HOME ..."
mkdir -p "$MCP_HOME/tools" "$MCP_HOME/output"
ok "Directory structure ready"
# ------------------------------------------------------------------
# 4. Clone / copy project
# ------------------------------------------------------------------
PROJECT_DIR="$MCP_HOME/excel-mcp"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/pyproject.toml" ]; then
info "Copying project from $SCRIPT_DIR ..."
if [ "$SCRIPT_DIR" != "$PROJECT_DIR" ]; then
rm -rf "$PROJECT_DIR"
mkdir -p "$PROJECT_DIR"
# Copy everything except .venv, __pycache__, .git
rsync -a --exclude='.venv' --exclude='__pycache__' --exclude='.git' "$SCRIPT_DIR/" "$PROJECT_DIR/"
fi
ok "Project copied"
else
fail "Run this script from the excel-mcp project directory."
fi
# ------------------------------------------------------------------
# 5. Install dependencies with uv
# ------------------------------------------------------------------
info "Installing dependencies..."
cd "$PROJECT_DIR"
uv sync
ok "Dependencies installed"
# ------------------------------------------------------------------
# 6. Detect Claude Desktop config
# ------------------------------------------------------------------
info "Configuring Claude Desktop..."
if [ "$(uname)" = "Darwin" ]; then
CONFIG_DIR="$HOME/Library/Application Support/Claude"
else
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/Claude"
fi
CONFIG_FILE="$CONFIG_DIR/claude_desktop_config.json"
mkdir -p "$CONFIG_DIR"
# ------------------------------------------------------------------
# 7. Ask for DATA_DIR
# ------------------------------------------------------------------
DEFAULT_DATA_DIR="$HOME/Documents"
echo ""
echo -e "${BOLD}Where are your Excel files?${NC}"
echo -e " Press Enter for default: ${BLUE}$DEFAULT_DATA_DIR${NC}"
read -rp " Data directory: " USER_DATA_DIR
DATA_DIR="${USER_DATA_DIR:-$DEFAULT_DATA_DIR}"
DATA_DIR="${DATA_DIR/#\~/$HOME}"
ok "Data directory: $DATA_DIR"
# ------------------------------------------------------------------
# 8. Inject MCP server config
# ------------------------------------------------------------------
MCP_ENTRY=$(cat <<JSONEOF
{
"command": "uv",
"args": ["run", "--directory", "$PROJECT_DIR", "python", "-m", "excel_mcp"],
"env": {
"DATA_DIR": "$DATA_DIR"
}
}
JSONEOF
)
if [ -f "$CONFIG_FILE" ]; then
# Merge into existing config
if command -v python3 &>/dev/null; then
python3 -c "
import json, sys
with open('$CONFIG_FILE', 'r') as f:
try:
config = json.load(f)
except json.JSONDecodeError:
config = {}
config.setdefault('mcpServers', {})
config['mcpServers']['excel-analytics'] = json.loads('''$MCP_ENTRY''')
with open('$CONFIG_FILE', 'w') as f:
json.dump(config, f, indent=2)
"
ok "Updated existing Claude Desktop config"
else
warn "Could not update config automatically"
fi
else
cat > "$CONFIG_FILE" <<CONFEOF
{
"mcpServers": {
"excel-analytics": $MCP_ENTRY
}
}
CONFEOF
ok "Created Claude Desktop config"
fi
# ------------------------------------------------------------------
# 9. Save user config
# ------------------------------------------------------------------
cat > "$MCP_HOME/config.json" <<UCEOF
{
"data_dir": "$DATA_DIR",
"port": 8765,
"auto_scan": false
}
UCEOF
# ------------------------------------------------------------------
# Done!
# ------------------------------------------------------------------
echo ""
echo -e "${GREEN}${BOLD}=== Installation Complete! ===${NC}"
echo ""
echo -e " ${BOLD}Next steps:${NC}"
echo -e " 1. Restart Claude Desktop (quit and reopen)"
echo -e " 2. Open the dashboard: ${BLUE}http://localhost:8765${NC}"
echo -e " (available once you start a conversation with Claude)"
echo -e " 3. Drag your Excel files into the dashboard"
echo -e " 4. Ask Claude about your data!"
echo ""
echo -e " ${BOLD}Example prompts:${NC}"
echo -e " - \"What datasets do I have?\""
echo -e " - \"Show me a summary of the sales data\""
echo -e " - \"Find the top 10 customers by revenue\""
echo -e " - \"Save this analysis as a reusable tool\""
echo ""
echo -e " Config: ${BLUE}$MCP_HOME/config.json${NC}"
echo -e " Data: ${BLUE}$MCP_HOME/data.db${NC}"
echo -e " Tools: ${BLUE}$MCP_HOME/tools/${NC}"
echo ""