Solana Agent Kit MCP Server
by sendaifun
- solana-mcp
- scripts
#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ASCII Art Banner
echo -e "${BLUE}"
cat << "EOF"
____ _ __ __ ____ ____
/ ___| ___ | | __ _ _ __ __ _ | \/ |/ ___| _ \
\___ \ / _ \| |/ _` | '_ \ / _` || |\/| | | | |_) |
___) | (_) | | (_| | | | | (_| || | | | |__| __/
|____/ \___/|_|\__,_|_| |_|\__,_||_| |_|\____|_|
EOF
echo -e "${NC}"
# Function to display help
show_help() {
echo -e "${BLUE}Solana MCP Server Installation Script${NC}"
echo -e "This script helps you set up the Solana MCP server for Claude Desktop.\n"
echo -e "The script will:"
echo -e " 1. Check and install Node.js if needed"
echo -e " 2. Install solana-mcp globally"
echo -e " 3. Configure Claude Desktop settings\n"
echo -e "Requirements:"
echo -e " - Internet connection"
echo -e " - Admin privileges (for some installations)"
echo -e " - Solana RPC URL"
echo -e " - Solana private key\n"
echo -e "Options:"
echo -e " -h, --help Show this help message"
echo -e " -b, --backup Backup existing configuration before modifying"
echo -e " -y, --yes Non-interactive mode (skip confirmations)\n"
}
# Function to validate Solana RPC URL
validate_rpc_url() {
local url=$1
if [[ ! $url =~ ^https?:// ]]; then
echo -e "${RED}Error: Invalid RPC URL format. URL should start with http:// or https://${NC}"
return 1
fi
return 0
}
# Function to validate Solana private key
validate_private_key() {
local key=$1
local key_length=${#key}
echo -e "${YELLOW}Debug: Key length is $key_length characters${NC}"
echo -e "${YELLOW}Debug: Key value: '$key'${NC}"
if [[ ! $key =~ ^[0-9a-zA-Z]+$ ]]; then
echo -e "${RED}Error: Invalid private key format. Should contain only alphanumeric characters${NC}"
return 1
fi
return 0
}
# Function to backup config
backup_config() {
local config_file=$1
if [ -f "$config_file" ]; then
local backup_file="${config_file}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$config_file" "$backup_file"
echo -e "${GREEN}Backup created: ${YELLOW}$backup_file${NC}"
fi
}
# Parse command line arguments
BACKUP=false
NON_INTERACTIVE=false
while [[ "$#" -gt 0 ]]; do
case $1 in
-h|--help) show_help; exit 0 ;;
-b|--backup) BACKUP=true ;;
-y|--yes) NON_INTERACTIVE=true ;;
*) echo -e "${RED}Unknown parameter: $1${NC}"; show_help; exit 1 ;;
esac
shift
done
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to get OS type
get_os_type() {
case "$(uname -s)" in
Darwin*) echo "macos";;
Linux*) echo "linux";;
MINGW*|CYGWIN*|MSYS*) echo "windows";;
*) echo "unknown";;
esac
}
# Function to install Node.js and npm on macOS
install_node_macos() {
echo -e "${YELLOW}Installing Node.js and npm using Homebrew...${NC}"
if ! command_exists brew; then
echo -e "${YELLOW}Installing Homebrew first...${NC}"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
brew install node
}
# Function to install Node.js and npm on Linux
install_node_linux() {
echo -e "${YELLOW}Installing Node.js and npm using package manager...${NC}"
if command_exists apt-get; then
# Debian/Ubuntu
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs
elif command_exists dnf; then
# Fedora
sudo dnf install -y nodejs npm
elif command_exists yum; then
# CentOS/RHEL
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash -
sudo yum install -y nodejs
elif command_exists pacman; then
# Arch Linux
sudo pacman -S nodejs npm
else
echo -e "${RED}Unsupported Linux distribution. Please install Node.js manually.${NC}"
exit 1
fi
}
# Function to install Node.js and npm on Windows
install_node_windows() {
echo -e "${YELLOW}Installing Node.js and npm using winget...${NC}"
if command_exists winget; then
winget install -e --id OpenJS.NodeJS
else
echo -e "${RED}Please install Node.js manually from https://nodejs.org/${NC}"
exit 1
fi
}
# Function to install Node.js based on OS
install_node() {
local os_type=$1
case "$os_type" in
"macos")
install_node_macos
;;
"linux")
install_node_linux
;;
"windows")
install_node_windows
;;
*)
echo -e "${RED}Unsupported operating system${NC}"
exit 1
;;
esac
}
# Function to get Claude config path based on OS
get_claude_config_path() {
local os_type=$1
case "$os_type" in
"macos")
echo "$HOME/Library/Application Support/Claude/claude_desktop_config.json"
;;
"linux")
echo "$HOME/.config/Claude/claude_desktop_config.json"
;;
"windows")
echo "%APPDATA%\\Claude\\claude_desktop_config.json"
;;
*)
echo ""
;;
esac
}
# Function to merge JSON configurations
merge_config() {
local config_file=$1
local temp_file=$(mktemp)
# Check if jq is installed
if ! command_exists jq; then
echo -e "${YELLOW}Installing jq for JSON processing...${NC}"
case "$OS_TYPE" in
"macos")
brew install jq
;;
"linux")
if command_exists apt-get; then
sudo apt-get install -y jq
elif command_exists dnf; then
sudo dnf install -y jq
elif command_exists yum; then
sudo yum install -y jq
elif command_exists pacman; then
sudo pacman -S jq
fi
;;
"windows")
echo -e "${RED}Please install jq manually${NC}"
exit 1
;;
esac
fi
# Create new MCP config
local mcp_config="{
\"command\": \"npx\",
\"args\": [\"solana-mcp\"],
\"env\": {
\"RPC_URL\": \"$RPC_URL\",
\"SOLANA_PRIVATE_KEY\": \"$SOLANA_PRIVATE_KEY\""
if [ ! -z "$OPENAI_API_KEY" ]; then
mcp_config="$mcp_config,
\"OPENAI_API_KEY\": \"$OPENAI_API_KEY\""
fi
mcp_config="$mcp_config
},
\"disabled\": false,
\"autoApprove\": []
}"
if [ -f "$config_file" ]; then
# File exists, merge configurations
jq --arg mcp "$mcp_config" '.mcpServers."solana-mcp" = ($mcp | fromjson)' "$config_file" > "$temp_file"
else
# Create new config file
echo "{
\"mcpServers\": {
\"solana-mcp\": $mcp_config
}
}" > "$temp_file"
fi
# Move temp file to config location
mv "$temp_file" "$config_file"
chmod 644 "$config_file"
}
echo -e "${BLUE}Welcome to Solana MCP Server Installation Script${NC}"
echo -e "${YELLOW}This script will help you set up the Solana MCP server for Claude Desktop${NC}"
echo "----------------------------------------"
if [ "$NON_INTERACTIVE" = false ]; then
read -p "Would you like to proceed with the installation? (y/N) " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}Installation cancelled by user${NC}"
exit 0
fi
fi
# Check OS type
OS_TYPE=$(get_os_type)
echo -e "\n${BLUE}System Information:${NC}"
echo -e "Operating System: ${YELLOW}$OS_TYPE${NC}"
# Check for Node.js and install if not present
if ! command_exists node; then
echo -e "\n${YELLOW}Node.js is not installed. Installing now...${NC}"
if [ "$NON_INTERACTIVE" = false ]; then
read -p "Would you like to install Node.js? (Y/n) " confirm
if [[ ! $confirm =~ ^[Nn]$ ]]; then
install_node "$OS_TYPE"
else
echo -e "${RED}Node.js is required for this installation. Exiting.${NC}"
exit 1
fi
else
install_node "$OS_TYPE"
fi
# Verify installation
if ! command_exists node; then
echo -e "${RED}Node.js installation failed. Please install manually from https://nodejs.org/${NC}"
exit 1
fi
fi
NODE_VERSION=$(node -v)
echo -e "Node.js version: ${GREEN}$NODE_VERSION${NC}"
# Check for npm and install if not present
if ! command_exists npm; then
echo -e "${YELLOW}npm is not installed. Installing now...${NC}"
# npm usually comes with Node.js, but if not:
case "$OS_TYPE" in
"linux")
sudo apt-get install -y npm || sudo dnf install -y npm || sudo yum install -y npm || sudo pacman -S npm
;;
*)
echo -e "${RED}npm installation failed. Please install manually${NC}"
exit 1
;;
esac
# Verify installation
if ! command_exists npm; then
echo -e "${RED}npm installation failed. Please install manually${NC}"
exit 1
fi
fi
NPM_VERSION=$(npm -v)
echo -e "npm version: ${GREEN}$NPM_VERSION${NC}"
# Check if solana-mcp is already installed globally
if npm list -g solana-mcp > /dev/null 2>&1; then
SOLANA_MCP_VERSION=$(npm list -g solana-mcp | grep solana-mcp | cut -d@ -f2)
echo -e "\nsolana-mcp is already installed globally (version: ${GREEN}$SOLANA_MCP_VERSION${NC})"
if [ "$NON_INTERACTIVE" = false ]; then
read -p "Would you like to reinstall/update solana-mcp? (y/N) " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
echo -e "\n${YELLOW}Updating solana-mcp globally...${NC}"
npm install -g solana-mcp@latest
fi
fi
else
echo -e "\n${YELLOW}Installing solana-mcp globally...${NC}"
npm install -g solana-mcp
fi
# Get Claude config path
CONFIG_PATH=$(get_claude_config_path "$OS_TYPE")
if [ -z "$CONFIG_PATH" ]; then
echo -e "${RED}Unsupported operating system${NC}"
exit 1
fi
# Backup existing config if requested
if [ "$BACKUP" = true ] && [ -f "$CONFIG_PATH" ]; then
backup_config "$CONFIG_PATH"
fi
# Collect required information with validation
echo -e "\n${BLUE}Configuration Setup:${NC}"
echo -e "${YELLOW}Please provide the following information:${NC}"
while true; do
read -p "Enter your Solana RPC URL: " RPC_URL
if validate_rpc_url "$RPC_URL"; then
break
fi
done
while true; do
read -p "Enter your Solana private key: " SOLANA_PRIVATE_KEY
if validate_private_key "$SOLANA_PRIVATE_KEY"; then
break
fi
done
read -p "Enter your OpenAI API key (optional, press Enter to skip): " OPENAI_API_KEY
# Create directory if it doesn't exist
CONFIG_DIR=$(dirname "$CONFIG_PATH")
mkdir -p "$CONFIG_DIR"
# Merge or create configuration
echo -e "\n${YELLOW}Updating Claude configuration...${NC}"
merge_config "$CONFIG_PATH"
echo -e "\n${GREEN}Installation completed successfully!${NC}"
echo -e "Configuration file has been updated at: ${YELLOW}$CONFIG_PATH${NC}"
echo -e "\n${BLUE}Next steps:${NC}"
echo -e "1. Restart Claude Desktop for the changes to take effect"
echo -e "2. Test the Solana MCP server functionality"
echo -e "3. If you encounter any issues, check the logs in Claude Desktop\n"
if [ "$BACKUP" = true ]; then
echo -e "${YELLOW}Note: A backup of your previous configuration was created${NC}"
fi