|
#!/bin/bash |
|
# ========================================================================= |
|
# Claude Desktop MCP Server Installer |
|
# ========================================================================= |
|
# |
|
# This script installs and configures MCP servers for Claude Desktop. |
|
# It will: |
|
# - Check for required dependencies |
|
# - Set up necessary directories |
|
# - Configure MCP servers in Claude Desktop |
|
# - Optionally restart Claude Desktop |
|
# |
|
# Run with: |
|
# curl -fsSL https://gist.githubusercontent.com/raw/GIST_ID/claude-mcp-setup.sh | bash |
|
# |
|
# Dependencies: jq, curl, uv/uvx, npx |
|
# |
|
# ========================================================================= |
|
|
|
# Text formatting |
|
RED='\033[0;31m' |
|
GREEN='\033[0;32m' |
|
YELLOW='\033[0;33m' |
|
BLUE='\033[0;34m' |
|
NC='\033[0m' # No Color |
|
BOLD='\033[1m' |
|
|
|
# Ensure script exits on any error |
|
set -e |
|
|
|
echo -e "${BOLD}===============================================================${NC}" |
|
echo -e "${BOLD} Claude Desktop MCP Server Installer ${NC}" |
|
echo -e "${BOLD}===============================================================${NC}" |
|
echo "" |
|
|
|
# Check if running on macOS |
|
if [[ "$(uname)" != "Darwin" ]]; then |
|
echo -e "${RED}Error: This script is designed for macOS only.${NC}" |
|
exit 1 |
|
fi |
|
|
|
# ----- Check Dependencies ----- |
|
echo -e "${BLUE}Checking dependencies...${NC}" |
|
|
|
# Check for jq |
|
if ! command -v jq &> /dev/null; then |
|
echo -e "${YELLOW}jq not found. Installing via Homebrew...${NC}" |
|
if command -v brew &> /dev/null; then |
|
brew install jq |
|
else |
|
echo -e "${RED}Error: Homebrew not found. Please install jq manually:${NC}" |
|
echo "1. Install Homebrew from https://brew.sh/" |
|
echo "2. Run: brew install jq" |
|
exit 1 |
|
fi |
|
fi |
|
|
|
# Check for npx |
|
if ! command -v npx &> /dev/null; then |
|
echo -e "${YELLOW}npx not found. Please install Node.js:${NC}" |
|
echo "1. Visit https://nodejs.org/" |
|
echo "2. Download and install the LTS version" |
|
exit 1 |
|
fi |
|
|
|
# Check for uv/uvx |
|
if ! command -v uv &> /dev/null; then |
|
echo -e "${YELLOW}uv not found. Installing...${NC}" |
|
curl -LsSf https://astral.sh/uv/install.sh | sh |
|
# Add to PATH for current session |
|
export PATH="$HOME/.cargo/bin:$PATH" |
|
fi |
|
|
|
echo -e "${GREEN}All dependencies found or installed!${NC}" |
|
echo "" |
|
|
|
# ----- Set up directories ----- |
|
echo -e "${BLUE}Setting up directories...${NC}" |
|
|
|
# Ask for base code directory or use default |
|
read -p "Enter base directory for code/data [default: $HOME/Code]: " CODE_DIR |
|
CODE_DIR=${CODE_DIR:-"$HOME/Code"} |
|
|
|
# Create directory if it doesn't exist |
|
mkdir -p "$CODE_DIR" |
|
mkdir -p "$CODE_DIR/data" |
|
echo -e "${GREEN}Directories created!${NC}" |
|
echo "" |
|
|
|
# ----- Claude config setup ----- |
|
echo -e "${BLUE}Setting up Claude Desktop configuration...${NC}" |
|
|
|
CONFIG_DIR="$HOME/Library/Application Support/Anthropic/Claude" |
|
CONFIG_FILE="$CONFIG_DIR/claude_desktop_config.json" |
|
BACKUP_FILE="$CONFIG_FILE.bak.$(date +%Y%m%d%H%M%S)" |
|
|
|
# Create config directory if it doesn't exist |
|
mkdir -p "$CONFIG_DIR" |
|
|
|
# Backup existing config if it exists |
|
if [ -f "$CONFIG_FILE" ]; then |
|
cp "$CONFIG_FILE" "$BACKUP_FILE" |
|
echo -e "${GREEN}Backed up existing config to ${BACKUP_FILE}${NC}" |
|
else |
|
echo '{}' > "$CONFIG_FILE" |
|
echo -e "${GREEN}Created new config file at ${CONFIG_FILE}${NC}" |
|
fi |
|
|
|
echo "" |
|
|
|
# ----- MCP Servers Selection ----- |
|
echo -e "${BLUE}MCP Server Selection${NC}" |
|
echo "Select which MCP servers to install:" |
|
echo "" |
|
echo -e "${BOLD}Available MCP Servers:${NC}" |
|
echo "1. YouTube Transcript - Fetch and analyze YouTube video transcripts" |
|
echo "2. DuckDuckGo Search - Search the web for information" |
|
echo "3. Fetch - Retrieve and parse web content" |
|
echo "4. Filesystem - Access and manipulate files on your computer" |
|
echo "5. Git - Interact with Git repositories" |
|
echo "6. MCP Installer - A utility for installing other MCP servers" |
|
echo "7. Memory - Store and retrieve information across conversations" |
|
echo "8. Shell Server - Execute shell commands" |
|
echo "9. Python REPL - Execute Python code within Claude" |
|
echo "10. Sequential Thinking - Break down complex problems step by step" |
|
echo "11. Playwright - Automate web browser interactions" |
|
echo "12. Obsidian - Interact with your Obsidian vault" |
|
echo "13. ClickHouse - Connect to ClickHouse databases" |
|
echo "14. Kubernetes - Manage Kubernetes clusters" |
|
echo "15. Figma - View and analyze Figma designs" |
|
echo "" |
|
|
|
read -p "Install all MCP servers? (y/n): " install_all |
|
|
|
if [ "$install_all" != "y" ] && [ "$install_all" != "Y" ]; then |
|
selected_servers="" |
|
|
|
read -p "Install YouTube Transcript? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="youtube " |
|
|
|
read -p "Install DuckDuckGo Search? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="ddg " |
|
|
|
read -p "Install Fetch? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="fetch " |
|
|
|
read -p "Install Filesystem? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="filesystem " |
|
|
|
read -p "Install Git? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="git " |
|
|
|
read -p "Install MCP Installer? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="installer " |
|
|
|
read -p "Install Memory? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="memory " |
|
|
|
read -p "Install Shell Server? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="shell " |
|
|
|
read -p "Install Python REPL? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="python " |
|
|
|
read -p "Install Sequential Thinking? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="sequential " |
|
|
|
read -p "Install Playwright? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="playwright " |
|
|
|
read -p "Install Obsidian? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="obsidian " |
|
|
|
read -p "Install ClickHouse? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="clickhouse " |
|
|
|
read -p "Install Kubernetes? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="kubernetes " |
|
|
|
read -p "Install Figma? (y/n): " yn |
|
[[ "$yn" == [Yy]* ]] && selected_servers+="figma " |
|
else |
|
# All servers selected |
|
selected_servers="youtube ddg fetch filesystem git installer memory shell python sequential playwright obsidian clickhouse kubernetes figma" |
|
fi |
|
|
|
echo "" |
|
|
|
# Function to prompt for optional API key and return formatted env block |
|
prompt_env() { |
|
local name="$1" |
|
shift |
|
local -A envs=() |
|
|
|
echo -e "${BLUE}${name} Configuration${NC}" |
|
|
|
for var in "$@"; do |
|
# Use read -s for sensitive inputs (keys and passwords) |
|
if [[ "$var" == *"KEY"* ]] || [[ "$var" == *"PASSWORD"* ]] || [[ "$var" == *"SECRET"* ]]; then |
|
read -s -p "Enter $var (sensitive, leave blank to skip): " value |
|
echo # Add a newline after hidden input |
|
else |
|
read -p "Enter $var (leave blank to skip): " value |
|
fi |
|
|
|
if [ -n "$value" ]; then |
|
envs[$var]="$value" |
|
fi |
|
done |
|
|
|
if [ ${#envs[@]} -eq 0 ]; then |
|
echo "null" |
|
else |
|
printf '{' |
|
first=true |
|
for key in "${!envs[@]}"; do |
|
if [ "$first" = true ]; then |
|
first=false |
|
else |
|
printf ',' |
|
fi |
|
printf '"%s":"%s"' "$key" "${envs[$key]}" |
|
done |
|
printf '}' |
|
fi |
|
|
|
echo "" |
|
} |
|
|
|
# Start with an empty config |
|
echo '{"mcpServers":{}}' > "$CONFIG_FILE" |
|
|
|
# Add selected servers |
|
for server in $selected_servers; do |
|
case $server in |
|
youtube) |
|
echo -e "${BLUE}Adding YouTube Transcript server...${NC}" |
|
jq '.mcpServers."@kimtaeyoon83-mcp-server-youtube-transcript" = {"command": "npx", "args": ["-y", "@smithery/cli@latest", "run", "@kimtaeyoon83/mcp-server-youtube-transcript", "--config", "{}"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
ddg) |
|
echo -e "${BLUE}Adding DuckDuckGo Search server...${NC}" |
|
jq '.mcpServers."ddg-search" = {"command": "uvx", "args": ["duckduckgo-mcp-server"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
fetch) |
|
echo -e "${BLUE}Adding Fetch server...${NC}" |
|
jq '.mcpServers.fetch = {"command": "uvx", "args": ["mcp-server-fetch"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
filesystem) |
|
echo -e "${BLUE}Adding Filesystem server...${NC}" |
|
jq --arg codedir "$CODE_DIR" '.mcpServers.filesystem = {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", $codedir]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
git) |
|
echo -e "${BLUE}Adding Git server...${NC}" |
|
jq --arg codedir "$CODE_DIR" '.mcpServers.git = {"command": "uvx", "args": ["mcp-server-git", "--repository", $codedir]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
installer) |
|
echo -e "${BLUE}Adding MCP Installer server...${NC}" |
|
jq '.mcpServers."mcp-installer" = {"command": "npx", "args": ["@anaisbetts/mcp-installer"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
memory) |
|
echo -e "${BLUE}Adding Memory server...${NC}" |
|
jq --arg memory_path "$CODE_DIR/data/memory.json" '.mcpServers.memory = {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-memory"], "env": {"MEMORY_FILE_PATH": $memory_path}}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
shell) |
|
echo -e "${BLUE}Adding Shell server...${NC}" |
|
jq '.mcpServers."shell-server" = {"command": "npx", "args": ["mcp-shell"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
python) |
|
echo -e "${BLUE}Adding Python REPL server...${NC}" |
|
# Ensure directory exists |
|
mkdir -p "$CODE_DIR/mcp-python/src" |
|
jq --arg codedir "$CODE_DIR" '.mcpServers."python-repl" = {"command": "uv", "args": ["--directory", $codedir + "/mcp-python/src", "run", "mcp_python"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
sequential) |
|
echo -e "${BLUE}Adding Sequential Thinking server...${NC}" |
|
jq '.mcpServers."sequential-thinking" = {"command": "npx", "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
playwright) |
|
echo -e "${BLUE}Adding Playwright server...${NC}" |
|
jq '.mcpServers.playwright = {"command": "npx", "args": ["@playwright/mcp@latest", "--vision"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
obsidian) |
|
echo -e "${BLUE}Adding Obsidian server...${NC}" |
|
jq '.mcpServers."mcp-obsidian" = {"command": "uvx", "args": ["mcp-obsidian"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
echo "For Obsidian integration, you'll need to set up the Claude plugin in Obsidian." |
|
echo "More info: https://github.com/ollama/mcp-obsidian" |
|
O=$(prompt_env "Obsidian" OBSIDIAN_API_KEY) |
|
if [ "$O" != "null" ]; then |
|
jq --argjson obsidian_env "$O" '.mcpServers."mcp-obsidian".env = $obsidian_env' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
fi |
|
;; |
|
|
|
clickhouse) |
|
echo -e "${BLUE}Adding ClickHouse server...${NC}" |
|
jq '.mcpServers."clickhouse-test" = {"command": "uv", "args": ["run", "--with", "mcp-clickhouse", "--python", "3.13", "mcp-clickhouse"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
echo "ClickHouse connection details needed:" |
|
C=$(prompt_env "ClickHouse" CLICKHOUSE_HOST CLICKHOUSE_PORT CLICKHOUSE_USER CLICKHOUSE_PASSWORD CLICKHOUSE_SECURE CLICKHOUSE_VERIFY CLICKHOUSE_CONNECT_TIMEOUT CLICKHOUSE_SEND_RECEIVE_TIMEOUT) |
|
if [ "$C" != "null" ]; then |
|
jq --argjson clickhouse_env "$C" '.mcpServers."clickhouse-test".env = $clickhouse_env' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
fi |
|
;; |
|
|
|
kubernetes) |
|
echo -e "${BLUE}Adding Kubernetes server...${NC}" |
|
jq '.mcpServers.kubernetes = {"command": "npx", "args": ["mcp-server-kubernetes"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
;; |
|
|
|
figma) |
|
echo -e "${BLUE}Adding Figma server...${NC}" |
|
jq '.mcpServers.figma = {"command": "npx", "args": ["-y", "figma-developer-mcp"]}' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
echo "Figma API key setup:" |
|
echo "Get your Figma API key from: https://www.figma.com/developers/api#access-tokens" |
|
F=$(prompt_env "Figma" FGM_API_KEY) |
|
if [ "$F" != "null" ]; then |
|
jq --argjson figma_env "$F" '.mcpServers.figma.env = $figma_env' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE" |
|
fi |
|
;; |
|
esac |
|
done |
|
|
|
echo -e "${GREEN}✅ Claude Desktop MCP config updated!${NC}" |
|
echo "" |
|
|
|
# ----- Finalize ----- |
|
echo -e "${BLUE}Finalizing installation...${NC}" |
|
|
|
# Ask about restarting Claude |
|
read -p "Do you want to restart Claude Desktop now? (y/n): " restart_claude |
|
|
|
if [ "$restart_claude" == "y" ] || [ "$restart_claude" == "Y" ]; then |
|
echo "Attempting to restart Claude Desktop..." |
|
# Check if Claude is running |
|
if pgrep -x "Claude" > /dev/null; then |
|
echo "Closing Claude Desktop..." |
|
pkill -x "Claude" |
|
sleep 2 |
|
fi |
|
echo "Starting Claude Desktop..." |
|
if open -a "Claude"; then |
|
echo -e "${GREEN}Claude Desktop restarted successfully!${NC}" |
|
else |
|
echo -e "${YELLOW}Could not start Claude Desktop. Please start it manually.${NC}" |
|
fi |
|
else |
|
echo -e "${YELLOW}Please restart Claude Desktop manually for changes to take effect.${NC}" |
|
fi |
|
|
|
echo "" |
|
echo -e "${BOLD}===============================================================${NC}" |
|
echo -e "${BOLD} Installation Complete! ${NC}" |
|
echo -e "${BOLD}===============================================================${NC}" |
|
echo "" |
|
echo -e "${GREEN}MCP servers have been configured for Claude Desktop.${NC}" |
|
echo "" |
|
echo -e "${BOLD}Next steps:${NC}" |
|
echo "1. Start Claude Desktop if not already running" |
|
echo "2. Create a new conversation to test the MCP servers" |
|
echo "3. If you have issues, check the console output in Claude Desktop" |
|
echo " (View > Developer > Toggle Developer Tools)" |
|
echo "" |
|
echo -e "${BOLD}Support:${NC}" |
|
echo "- Documentation: https://anthropic.com/claude" |
|
echo "- Issues: https://github.com/Anthropic/claude-mcps/issues" |
|
echo "" |
|
echo -e "${YELLOW}Note: This script created a backup of your previous config at:${NC}" |
|
echo "$BACKUP_FILE" |
|
echo "" |
|
echo -e "${GREEN}Happy Claude-ing! 🤖${NC}" |