# Directory Structure
```
├── .gitignore
├── claude_desktop_config.json
├── glama.json
├── LICENSE
├── package.json
├── pnpm-lock.yaml
├── README.md
├── scripts
│ └── install.sh
├── src
│ └── index.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | .env
2 | node_modules
3 | build
4 | .DS_Store
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # Solana Agent Kit MCP Server
2 |
3 | [](https://www.npmjs.com/package/solana-mcp)
4 | [](https://opensource.org/licenses/ISC)
5 | <a href="https://cloud.phala.network/features/mcp-hosting/solana-mcp-by-sendai-and-dark" target="_blank" rel="noopener noreferrer" style="display:inline-flex;align-items:center;text-decoration:none;background:#fff;border:1px solid #e5e7eb;border-radius:6px;padding:2px 8px;font-size:16px;font-family:sans-serif;">
6 | <img src="https://raw.githubusercontent.com/Phala-Network/mcp-hosting/refs/heads/main/assets/logs/phala.png" alt="Phala Logo" height="24" style="vertical-align:middle;margin-right:8px;"/>
7 | <span style="color:#222;font-weight:600;">Check on Phala</span>
8 | </a>
9 |
10 | A Model Context Protocol (MCP) server that provides onchain tools for Claude AI, allowing it to interact with the Solana blockchain through a standardized interface. This implementation is based on the Solana Agent Kit and enables AI agents to perform blockchain operations seamlessly.
11 |
12 |
13 |
14 |
15 | ## Overview
16 |
17 | This MCP server extends Claude's capabilities by providing tools to:
18 |
19 | * Interact with Solana blockchain
20 | * Execute transactions
21 | * Query account information
22 | * Manage Solana wallets
23 |
24 | The server implements the Model Context Protocol specification to standardize blockchain interactions for AI agents.
25 |
26 | ## Prerequisites
27 |
28 | * Node.js (v16 or higher)
29 | * pnpm (recommended), npm, or yarn
30 | * Solana wallet with private key
31 | * Solana RPC URL (mainnet, testnet, or devnet)
32 |
33 | ## Installation
34 |
35 | ### Option 1: Quick Install (Recommended)
36 |
37 | ```bash
38 | # Download the installation script
39 | curl -fsSL https://raw.githubusercontent.com/sendaifun/solana-mcp/main/scripts/install.sh -o solana-mcp-install.sh
40 |
41 | # Make it executable and run
42 | chmod +x solana-mcp-install.sh && ./solana-mcp-install.sh --backup
43 | ```
44 |
45 | This will start an interactive installation process that will guide you through:
46 | - Setting up Node.js if needed
47 | - Configuring your Solana RPC URL and private key
48 | - Setting up the Claude Desktop integration
49 |
50 | ### Option 2: Install from npm ( recommend for clients like Cursor/Cline)
51 |
52 | ```bash
53 | # Install globally
54 | npm install -g solana-mcp
55 |
56 | # Or install locally in your project
57 | npm install solana-mcp
58 | ```
59 |
60 | ### Option 3: Build from Source
61 |
62 | 1. Clone this repository:
63 | ```bash
64 | git clone https://github.com/sendaifun/solana-mcp
65 | cd solana-mcp
66 | ```
67 |
68 | 2. Install dependencies:
69 | ```bash
70 | pnpm install
71 | ```
72 |
73 | 3. Build the project:
74 | ```bash
75 | pnpm run build
76 | ```
77 |
78 | ## Configuration
79 |
80 | ### Environment Setup
81 |
82 | Create a `.env` file with your credentials:
83 |
84 | ```env
85 | # Solana Configuration
86 | SOLANA_PRIVATE_KEY=your_private_key_here
87 | RPC_URL=your_solana_rpc_url_here
88 | OPENAI_API_KEY=your_openai_api_key # OPTIONAL
89 | ```
90 |
91 | ### Integration with Claude Desktop
92 |
93 | To add this MCP server to Claude Desktop, follow these steps:
94 |
95 | 1. **Locate the Claude Desktop Configuration File**
96 | - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
97 | - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
98 | - Linux: `~/.config/Claude/claude_desktop_config.json`
99 |
100 | 2. **Add the Configuration**
101 | Create or edit the configuration file and add the following JSON:
102 |
103 | If you installed via npm (Option 1):
104 | ```json
105 | {
106 | "mcpServers": {
107 | "solana-mcp": {
108 | "command": "npx",
109 | "args": ["solana-mcp"],
110 | "env": {
111 | "RPC_URL": "your_solana_rpc_url_here",
112 | "SOLANA_PRIVATE_KEY": "your_private_key_here",
113 | "OPENAI_API_KEY": "your_openai_api_key" // OPTIONAL
114 | },
115 | "disabled": false,
116 | "autoApprove": []
117 | }
118 | }
119 | }
120 | ```
121 |
122 | If you built from source (Option 2):
123 | ```json
124 | {
125 | "mcpServers": {
126 | "solana-mcp": {
127 | "command": "node",
128 | "args": ["/path/to/solana-mcp/build/index.js"],
129 | "env": {
130 | "RPC_URL": "your_solana_rpc_url_here",
131 | "SOLANA_PRIVATE_KEY": "your_private_key_here",
132 | "OPENAI_API_KEY": "your_openai_api_key" // OPTIONAL
133 | },
134 | "disabled": false,
135 | "autoApprove": []
136 | }
137 | }
138 | }
139 | ```
140 |
141 | 3. **Restart Claude Desktop**
142 | After making these changes, restart Claude Desktop for the configuration to take effect.
143 |
144 | ## Project Structure
145 |
146 | ```
147 | solana-agent-kit-mcp/
148 | ├── src/
149 | │ ├── index.ts # Main entry point
150 | ├── package.json
151 | └── tsconfig.json
152 | ```
153 |
154 | ## Available Tools
155 |
156 | The MCP server provides the following Solana blockchain tools:
157 |
158 | * `GET_ASSET` - Retrieve information about a Solana asset/token
159 | * `DEPLOY_TOKEN` - Deploy a new token on Solana
160 | * `GET_PRICE` - Fetch price information for tokens
161 | * `WALLET_ADDRESS` - Get the wallet address
162 | * `BALANCE` - Check wallet balance
163 | * `TRANSFER` - Transfer tokens between wallets
164 | * `MINT_NFT` - Create and mint new NFTs
165 | * `TRADE` - Execute token trades
166 | * `REQUEST_FUNDS` - Request funds (useful for testing/development)
167 | * `RESOLVE_DOMAIN` - Resolve Solana domain names
168 | * `GET_TPS` - Get current transactions per second on Solana
169 |
170 | ## Security Considerations
171 |
172 | * Keep your private key secure and never share it
173 | * Use environment variables for sensitive information
174 | * Consider using a dedicated wallet for AI agent operations
175 | * Regularly monitor and audit AI agent activities
176 | * Test operations on devnet/testnet before mainnet
177 |
178 | ## Troubleshooting
179 |
180 | If you encounter issues:
181 |
182 | 1. Verify your Solana private key is correct
183 | 2. Check your RPC URL is accessible
184 | 3. Ensure you're on the intended network (mainnet, testnet, or devnet)
185 | 4. Check Claude Desktop logs for error messages
186 | 5. Verify the build was successful
187 |
188 | ## Dependencies
189 |
190 | Key dependencies include:
191 | * [@solana/web3.js](https://github.com/solana-labs/solana-web3.js)
192 | * [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk)
193 | * [solana-agent-kit](https://github.com/sendaifun/solana-agent-kit)
194 |
195 | ## Contributing
196 |
197 | Contributions are welcome! Please feel free to submit a Pull Request.
198 |
199 | 1. Fork the repository
200 | 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
201 | 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
202 | 4. Push to the branch (`git push origin feature/amazing-feature`)
203 | 5. Open a Pull Request
204 |
205 | ## License
206 |
207 | This project is licensed under the MIT License.
208 |
```
--------------------------------------------------------------------------------
/glama.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "$schema": "https://glama.ai/mcp/schemas/server.json",
3 | "maintainers": [
4 | "thearyanag"
5 | ]
6 | }
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true
12 | },
13 | "include": ["src/**/*"],
14 | "exclude": ["node_modules"]
15 | }
```
--------------------------------------------------------------------------------
/claude_desktop_config.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "mcpServers": {
3 | "agent-kit": {
4 | "command": "node",
5 | "env" : {
6 | "OPENAI_API_KEY": "optional_openai_api_key_here",
7 | "RPC_URL": "your_rpc_url_here",
8 | "SOLANA_PRIVATE_KEY": "your_private_key_here"
9 | },
10 | "args": [
11 | "/absolute/path/to/build/index.js"
12 | ]
13 | }
14 | }
15 | }
16 |
17 |
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "solana-mcp",
3 | "version": "1.0.0",
4 | "description": "A Model Context Protocol server for interacting with the Solana blockchain, powered by the Solana Agent Kit (https://github.com/sendaifun/solana-agent-kit)",
5 | "main": "build/index.js",
6 | "type": "module",
7 | "bin": {
8 | "solana-mcp": "./build/index.js"
9 | },
10 | "scripts": {
11 | "build": "tsc",
12 | "start": "node build/index.js",
13 | "dev": "tsx watch src/index.ts"
14 | },
15 | "files": [
16 | "build"
17 | ],
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/sendaifun/solana-mcp"
21 | },
22 | "keywords": [
23 | "solana",
24 | "mcp",
25 | "solana-agent-kit",
26 | "solana-mcp"
27 | ],
28 | "author": "sendaifun",
29 | "license": "MIT",
30 | "dependencies": {
31 | "@modelcontextprotocol/sdk": "^1.11.4",
32 | "@solana-agent-kit/adapter-mcp": "^2.0.4",
33 | "@solana-agent-kit/plugin-god-mode": "^0.0.1",
34 | "@solana/web3.js": "^1.98.2",
35 | "bs58": "^6.0.0",
36 | "cors": "^2.8.5",
37 | "dotenv": "^16.4.7",
38 | "express": "^5.1.0",
39 | "solana-agent-kit": "2.0.4"
40 | },
41 | "devDependencies": {
42 | "@types/cors": "^2.8.17",
43 | "@types/express": "^5.0.1",
44 | "@types/node": "^22.13.4",
45 | "tsx": "^4.19.4",
46 | "typescript": "^5.7.3"
47 | },
48 | "packageManager": "[email protected]"
49 | }
50 |
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | // #!/usr/bin/env node
2 |
3 | import { SolanaAgentKit, KeypairWallet, type Action } from "solana-agent-kit";
4 | import { startMcpServer, createMcpServer } from "@solana-agent-kit/adapter-mcp";
5 | import GodModePlugin from "@solana-agent-kit/plugin-god-mode";
6 | import * as dotenv from "dotenv";
7 | import { Keypair } from "@solana/web3.js";
8 | import bs58 from "bs58";
9 | import express, { type Request, type Response } from "express";
10 | import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
11 | import cors from "cors";
12 |
13 | dotenv.config();
14 |
15 | // Validate required environment variables
16 | function validateEnvironment() {
17 | const requiredEnvVars = {
18 | SOLANA_PRIVATE_KEY: process.env.SOLANA_PRIVATE_KEY,
19 | RPC_URL: process.env.RPC_URL,
20 | };
21 |
22 | const missingVars = Object.entries(requiredEnvVars)
23 | .filter(([_, value]) => !value)
24 | .map(([key]) => key);
25 |
26 | if (missingVars.length > 0) {
27 | throw new Error(
28 | `Missing required environment variables: ${missingVars.join(", ")}`
29 | );
30 | }
31 | }
32 |
33 | // New function to start MCP server with SSE support
34 | async function startMcpServerWithSse(
35 | actions: Record<string, any>,
36 | agent: SolanaAgentKit,
37 | options: {
38 | name: string;
39 | version: string;
40 | },
41 | port: number = 3000
42 | ) {
43 | const app = express();
44 | app.use(cors());
45 | // Store active transport instances
46 | const transports: { [sessionId: string]: SSEServerTransport } = {};
47 |
48 | // SSE endpoint for client connections
49 | app.get("/sse", async (_req: Request, res: Response) => {
50 | console.log("Received connection on /sse");
51 | const transport = new SSEServerTransport("/messages", res);
52 |
53 | // Store the transport for this session
54 | transports[transport.sessionId] = transport;
55 |
56 | res.on("close", () => {
57 | console.log(`Connection closed for session ${transport.sessionId}`);
58 | delete transports[transport.sessionId];
59 | });
60 |
61 | // Create the server and connect it to this transport
62 | const server = createMcpServer(actions, agent, options);
63 | await server.connect(transport);
64 | });
65 |
66 | // Message endpoint for client-to-server communication
67 | app.post("/messages", async (req: Request, res: Response) => {
68 | const sessionId = req.query.sessionId as string;
69 | console.log(`Received message for session ${sessionId}`);
70 |
71 | const transport = transports[sessionId];
72 | if (transport) {
73 | await transport.handlePostMessage(req, res);
74 | } else {
75 | res.status(400).send("No transport found for sessionId");
76 | }
77 | });
78 |
79 | // Start the Express server
80 | app.listen(port, () => {
81 | console.log(`MCP SSE server listening on port ${port}`);
82 | });
83 |
84 | return app;
85 | }
86 |
87 | async function main() {
88 | try {
89 | // Validate environment before proceeding
90 | validateEnvironment();
91 |
92 | // Initialize the agent with error handling
93 | const decodedPrivateKey = bs58.decode(
94 | process.env.SOLANA_PRIVATE_KEY as string
95 | );
96 | const keypair = Keypair.fromSecretKey(decodedPrivateKey);
97 | const keypairWallet = new KeypairWallet(
98 | keypair,
99 | process.env.RPC_URL as string
100 | );
101 |
102 | const agent = new SolanaAgentKit(keypairWallet, keypairWallet.rpcUrl, {})
103 | .use(GodModePlugin);
104 |
105 | const mcp_actions: Record<string, Action> = {};
106 |
107 | for (const action of agent.actions) {
108 | mcp_actions[action.name] = action;
109 | }
110 |
111 | const serverOptions = {
112 | name: "sendai-agent",
113 | version: "0.0.1",
114 | };
115 |
116 | // Check if PORT environment variable exists to determine whether to use SSE
117 | if (process.env.PORT) {
118 | const port = Number.parseInt(process.env.PORT, 10);
119 | console.log(`Starting MCP server with SSE on port ${port}`);
120 | await startMcpServerWithSse(mcp_actions, agent, serverOptions, port);
121 | } else {
122 | // Start the MCP server with stdio transport (original behavior)
123 | console.log("Starting MCP server with stdio transport");
124 | await startMcpServer(mcp_actions, agent, serverOptions);
125 | }
126 | } catch (error) {
127 | console.error(
128 | "Failed to start MCP server:",
129 | error instanceof Error ? error.message : String(error)
130 | );
131 | process.exit(1);
132 | }
133 | }
134 |
135 | main();
136 |
```
--------------------------------------------------------------------------------
/scripts/install.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/bin/bash
2 |
3 | # Colors for output
4 | RED='\033[0;31m'
5 | GREEN='\033[0;32m'
6 | YELLOW='\033[1;33m'
7 | BLUE='\033[0;34m'
8 | NC='\033[0m' # No Color
9 |
10 | # ASCII Art Banner
11 | echo -e "${BLUE}"
12 | cat << "EOF"
13 | ____ _ __ __ ____ ____
14 | / ___| ___ | | __ _ _ __ __ _ | \/ |/ ___| _ \
15 | \___ \ / _ \| |/ _` | '_ \ / _` || |\/| | | | |_) |
16 | ___) | (_) | | (_| | | | | (_| || | | | |__| __/
17 | |____/ \___/|_|\__,_|_| |_|\__,_||_| |_|\____|_|
18 |
19 | EOF
20 | echo -e "${NC}"
21 |
22 | # Function to display help
23 | show_help() {
24 | echo -e "${BLUE}Solana MCP Server Installation Script${NC}"
25 | echo -e "This script helps you set up the Solana MCP server for Claude Desktop.\n"
26 | echo -e "The script will:"
27 | echo -e " 1. Check and install Node.js if needed"
28 | echo -e " 2. Install solana-mcp globally"
29 | echo -e " 3. Configure Claude Desktop settings\n"
30 | echo -e "Requirements:"
31 | echo -e " - Internet connection"
32 | echo -e " - Admin privileges (for some installations)"
33 | echo -e " - Solana RPC URL"
34 | echo -e " - Solana private key\n"
35 | echo -e "Options:"
36 | echo -e " -h, --help Show this help message"
37 | echo -e " -b, --backup Backup existing configuration before modifying"
38 | echo -e " -y, --yes Non-interactive mode (skip confirmations)\n"
39 | }
40 |
41 | # Function to validate Solana RPC URL
42 | validate_rpc_url() {
43 | local url=$1
44 | if [[ ! $url =~ ^https?:// ]]; then
45 | echo -e "${RED}Error: Invalid RPC URL format. URL should start with http:// or https://${NC}"
46 | return 1
47 | fi
48 | return 0
49 | }
50 |
51 | # Function to validate Solana private key
52 | validate_private_key() {
53 | local key=$1
54 | local key_length=${#key}
55 | echo -e "${YELLOW}Debug: Key length is $key_length characters${NC}"
56 | echo -e "${YELLOW}Debug: Key value: '$key'${NC}"
57 | if [[ ! $key =~ ^[0-9a-zA-Z]+$ ]]; then
58 | echo -e "${RED}Error: Invalid private key format. Should contain only alphanumeric characters${NC}"
59 | return 1
60 | fi
61 | return 0
62 | }
63 |
64 | # Function to backup config
65 | backup_config() {
66 | local config_file=$1
67 | if [ -f "$config_file" ]; then
68 | local backup_file="${config_file}.backup.$(date +%Y%m%d_%H%M%S)"
69 | cp "$config_file" "$backup_file"
70 | echo -e "${GREEN}Backup created: ${YELLOW}$backup_file${NC}"
71 | fi
72 | }
73 |
74 | # Parse command line arguments
75 | BACKUP=false
76 | NON_INTERACTIVE=false
77 |
78 | while [[ "$#" -gt 0 ]]; do
79 | case $1 in
80 | -h|--help) show_help; exit 0 ;;
81 | -b|--backup) BACKUP=true ;;
82 | -y|--yes) NON_INTERACTIVE=true ;;
83 | *) echo -e "${RED}Unknown parameter: $1${NC}"; show_help; exit 1 ;;
84 | esac
85 | shift
86 | done
87 |
88 | # Function to check if a command exists
89 | command_exists() {
90 | command -v "$1" >/dev/null 2>&1
91 | }
92 |
93 | # Function to get OS type
94 | get_os_type() {
95 | case "$(uname -s)" in
96 | Darwin*) echo "macos";;
97 | Linux*) echo "linux";;
98 | MINGW*|CYGWIN*|MSYS*) echo "windows";;
99 | *) echo "unknown";;
100 | esac
101 | }
102 |
103 | # Function to install Node.js and npm on macOS
104 | install_node_macos() {
105 | echo -e "${YELLOW}Installing Node.js and npm using Homebrew...${NC}"
106 | if ! command_exists brew; then
107 | echo -e "${YELLOW}Installing Homebrew first...${NC}"
108 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
109 | fi
110 | brew install node
111 | }
112 |
113 | # Function to install Node.js and npm on Linux
114 | install_node_linux() {
115 | echo -e "${YELLOW}Installing Node.js and npm using package manager...${NC}"
116 | if command_exists apt-get; then
117 | # Debian/Ubuntu
118 | curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
119 | sudo apt-get install -y nodejs
120 | elif command_exists dnf; then
121 | # Fedora
122 | sudo dnf install -y nodejs npm
123 | elif command_exists yum; then
124 | # CentOS/RHEL
125 | curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash -
126 | sudo yum install -y nodejs
127 | elif command_exists pacman; then
128 | # Arch Linux
129 | sudo pacman -S nodejs npm
130 | else
131 | echo -e "${RED}Unsupported Linux distribution. Please install Node.js manually.${NC}"
132 | exit 1
133 | fi
134 | }
135 |
136 | # Function to install Node.js and npm on Windows
137 | install_node_windows() {
138 | echo -e "${YELLOW}Installing Node.js and npm using winget...${NC}"
139 | if command_exists winget; then
140 | winget install -e --id OpenJS.NodeJS
141 | else
142 | echo -e "${RED}Please install Node.js manually from https://nodejs.org/${NC}"
143 | exit 1
144 | fi
145 | }
146 |
147 | # Function to install Node.js based on OS
148 | install_node() {
149 | local os_type=$1
150 | case "$os_type" in
151 | "macos")
152 | install_node_macos
153 | ;;
154 | "linux")
155 | install_node_linux
156 | ;;
157 | "windows")
158 | install_node_windows
159 | ;;
160 | *)
161 | echo -e "${RED}Unsupported operating system${NC}"
162 | exit 1
163 | ;;
164 | esac
165 | }
166 |
167 | # Function to get Claude config path based on OS
168 | get_claude_config_path() {
169 | local os_type=$1
170 | case "$os_type" in
171 | "macos")
172 | echo "$HOME/Library/Application Support/Claude/claude_desktop_config.json"
173 | ;;
174 | "linux")
175 | echo "$HOME/.config/Claude/claude_desktop_config.json"
176 | ;;
177 | "windows")
178 | echo "%APPDATA%\\Claude\\claude_desktop_config.json"
179 | ;;
180 | *)
181 | echo ""
182 | ;;
183 | esac
184 | }
185 |
186 | # Function to merge JSON configurations
187 | merge_config() {
188 | local config_file=$1
189 | local temp_file=$(mktemp)
190 |
191 | # Check if jq is installed
192 | if ! command_exists jq; then
193 | echo -e "${YELLOW}Installing jq for JSON processing...${NC}"
194 | case "$OS_TYPE" in
195 | "macos")
196 | brew install jq
197 | ;;
198 | "linux")
199 | if command_exists apt-get; then
200 | sudo apt-get install -y jq
201 | elif command_exists dnf; then
202 | sudo dnf install -y jq
203 | elif command_exists yum; then
204 | sudo yum install -y jq
205 | elif command_exists pacman; then
206 | sudo pacman -S jq
207 | fi
208 | ;;
209 | "windows")
210 | echo -e "${RED}Please install jq manually${NC}"
211 | exit 1
212 | ;;
213 | esac
214 | fi
215 |
216 | # Create new MCP config
217 | local mcp_config="{
218 | \"command\": \"npx\",
219 | \"args\": [\"solana-mcp\"],
220 | \"env\": {
221 | \"RPC_URL\": \"$RPC_URL\",
222 | \"SOLANA_PRIVATE_KEY\": \"$SOLANA_PRIVATE_KEY\""
223 |
224 | if [ ! -z "$OPENAI_API_KEY" ]; then
225 | mcp_config="$mcp_config,
226 | \"OPENAI_API_KEY\": \"$OPENAI_API_KEY\""
227 | fi
228 |
229 | mcp_config="$mcp_config
230 | },
231 | \"disabled\": false,
232 | \"autoApprove\": []
233 | }"
234 |
235 | if [ -f "$config_file" ]; then
236 | # File exists, merge configurations
237 | jq --arg mcp "$mcp_config" '.mcpServers."solana-mcp" = ($mcp | fromjson)' "$config_file" > "$temp_file"
238 | else
239 | # Create new config file
240 | echo "{
241 | \"mcpServers\": {
242 | \"solana-mcp\": $mcp_config
243 | }
244 | }" > "$temp_file"
245 | fi
246 |
247 | # Move temp file to config location
248 | mv "$temp_file" "$config_file"
249 | chmod 644 "$config_file"
250 | }
251 |
252 | echo -e "${BLUE}Welcome to Solana MCP Server Installation Script${NC}"
253 | echo -e "${YELLOW}This script will help you set up the Solana MCP server for Claude Desktop${NC}"
254 | echo "----------------------------------------"
255 |
256 | if [ "$NON_INTERACTIVE" = false ]; then
257 | read -p "Would you like to proceed with the installation? (y/N) " confirm
258 | if [[ ! $confirm =~ ^[Yy]$ ]]; then
259 | echo -e "${YELLOW}Installation cancelled by user${NC}"
260 | exit 0
261 | fi
262 | fi
263 |
264 | # Check OS type
265 | OS_TYPE=$(get_os_type)
266 | echo -e "\n${BLUE}System Information:${NC}"
267 | echo -e "Operating System: ${YELLOW}$OS_TYPE${NC}"
268 |
269 | # Check for Node.js and install if not present
270 | if ! command_exists node; then
271 | echo -e "\n${YELLOW}Node.js is not installed. Installing now...${NC}"
272 | if [ "$NON_INTERACTIVE" = false ]; then
273 | read -p "Would you like to install Node.js? (Y/n) " confirm
274 | if [[ ! $confirm =~ ^[Nn]$ ]]; then
275 | install_node "$OS_TYPE"
276 | else
277 | echo -e "${RED}Node.js is required for this installation. Exiting.${NC}"
278 | exit 1
279 | fi
280 | else
281 | install_node "$OS_TYPE"
282 | fi
283 |
284 | # Verify installation
285 | if ! command_exists node; then
286 | echo -e "${RED}Node.js installation failed. Please install manually from https://nodejs.org/${NC}"
287 | exit 1
288 | fi
289 | fi
290 |
291 | NODE_VERSION=$(node -v)
292 | echo -e "Node.js version: ${GREEN}$NODE_VERSION${NC}"
293 |
294 | # Check for npm and install if not present
295 | if ! command_exists npm; then
296 | echo -e "${YELLOW}npm is not installed. Installing now...${NC}"
297 | # npm usually comes with Node.js, but if not:
298 | case "$OS_TYPE" in
299 | "linux")
300 | sudo apt-get install -y npm || sudo dnf install -y npm || sudo yum install -y npm || sudo pacman -S npm
301 | ;;
302 | *)
303 | echo -e "${RED}npm installation failed. Please install manually${NC}"
304 | exit 1
305 | ;;
306 | esac
307 |
308 | # Verify installation
309 | if ! command_exists npm; then
310 | echo -e "${RED}npm installation failed. Please install manually${NC}"
311 | exit 1
312 | fi
313 | fi
314 |
315 | NPM_VERSION=$(npm -v)
316 | echo -e "npm version: ${GREEN}$NPM_VERSION${NC}"
317 |
318 | # Check if solana-mcp is already installed globally
319 | if npm list -g solana-mcp > /dev/null 2>&1; then
320 | SOLANA_MCP_VERSION=$(npm list -g solana-mcp | grep solana-mcp | cut -d@ -f2)
321 | echo -e "\nsolana-mcp is already installed globally (version: ${GREEN}$SOLANA_MCP_VERSION${NC})"
322 | if [ "$NON_INTERACTIVE" = false ]; then
323 | read -p "Would you like to reinstall/update solana-mcp? (y/N) " confirm
324 | if [[ $confirm =~ ^[Yy]$ ]]; then
325 | echo -e "\n${YELLOW}Updating solana-mcp globally...${NC}"
326 | npm install -g solana-mcp@latest
327 | fi
328 | fi
329 | else
330 | echo -e "\n${YELLOW}Installing solana-mcp globally...${NC}"
331 | npm install -g solana-mcp
332 | fi
333 |
334 | # Get Claude config path
335 | CONFIG_PATH=$(get_claude_config_path "$OS_TYPE")
336 | if [ -z "$CONFIG_PATH" ]; then
337 | echo -e "${RED}Unsupported operating system${NC}"
338 | exit 1
339 | fi
340 |
341 | # Backup existing config if requested
342 | if [ "$BACKUP" = true ] && [ -f "$CONFIG_PATH" ]; then
343 | backup_config "$CONFIG_PATH"
344 | fi
345 |
346 | # Collect required information with validation
347 | echo -e "\n${BLUE}Configuration Setup:${NC}"
348 | echo -e "${YELLOW}Please provide the following information:${NC}"
349 |
350 | while true; do
351 | read -p "Enter your Solana RPC URL: " RPC_URL
352 | if validate_rpc_url "$RPC_URL"; then
353 | break
354 | fi
355 | done
356 |
357 | while true; do
358 | read -p "Enter your Solana private key: " SOLANA_PRIVATE_KEY
359 | if validate_private_key "$SOLANA_PRIVATE_KEY"; then
360 | break
361 | fi
362 | done
363 |
364 | read -p "Enter your OpenAI API key (optional, press Enter to skip): " OPENAI_API_KEY
365 |
366 | # Create directory if it doesn't exist
367 | CONFIG_DIR=$(dirname "$CONFIG_PATH")
368 | mkdir -p "$CONFIG_DIR"
369 |
370 | # Merge or create configuration
371 | echo -e "\n${YELLOW}Updating Claude configuration...${NC}"
372 | merge_config "$CONFIG_PATH"
373 |
374 | echo -e "\n${GREEN}Installation completed successfully!${NC}"
375 | echo -e "Configuration file has been updated at: ${YELLOW}$CONFIG_PATH${NC}"
376 | echo -e "\n${BLUE}Next steps:${NC}"
377 | echo -e "1. Restart Claude Desktop for the changes to take effect"
378 | echo -e "2. Test the Solana MCP server functionality"
379 | echo -e "3. If you encounter any issues, check the logs in Claude Desktop\n"
380 |
381 | if [ "$BACKUP" = true ]; then
382 | echo -e "${YELLOW}Note: A backup of your previous configuration was created${NC}"
383 | fi
```