cat > ~/setup_memgraph_complete.sh << 'EOF'
#!/bin/bash
# Complete automated setup for Memgraph + Claude Desktop
echo "========================================"
echo "Memgraph + Claude Desktop Setup"
echo "========================================"
echo ""
# Step 1: Install Rancher Desktop
echo "Step 1/7: Installing Rancher Desktop..."
# Check if Docker daemon is already running
DOCKER_RUNNING=false
if command -v docker &> /dev/null && docker info &> /dev/null 2>&1; then
echo "Container runtime is already running!"
DOCKER_RUNNING=true
fi
if [ "$DOCKER_RUNNING" = false ]; then
# Check if Homebrew is installed
if ! command -v brew &> /dev/null; then
echo "Installing Homebrew first..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH for Apple Silicon Macs
if [[ $(uname -m) == 'arm64' ]]; then
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
# Check if Rancher Desktop is installed
RANCHER_INSTALLED=false
if brew list --cask rancher 2>/dev/null | grep -q rancher; then
RANCHER_INSTALLED=true
echo "Rancher Desktop is installed via Homebrew."
fi
# If not installed, install it
if [ "$RANCHER_INSTALLED" = false ]; then
echo "Installing Rancher Desktop..."
brew install --cask rancher
sleep 3
fi
echo "Starting Rancher Desktop..."
# Launch Rancher Desktop
if [ -d "/Applications/Rancher Desktop.app" ]; then
echo "Launching Rancher Desktop from /Applications..."
open "/Applications/Rancher Desktop.app"
sleep 5
else
echo ""
echo "Please launch Rancher Desktop manually:"
echo " 1. Press Cmd+Space"
echo " 2. Type 'Rancher Desktop'"
echo " 3. Press Enter"
echo ""
echo "Waiting for you to launch Rancher Desktop..."
echo "Press Enter once you've started Rancher Desktop"
read
fi
# Add Rancher Desktop to PATH
export PATH="$HOME/.rd/bin:$PATH"
echo "Waiting for container runtime to start (this may take 30-60 seconds)..."
# Wait for docker command to become available
for i in {1..60}; do
if command -v docker &> /dev/null && docker info &> /dev/null 2>&1; then
echo ""
echo "Container runtime is running!"
break
fi
echo -n "."
sleep 3
done
if ! command -v docker &> /dev/null || ! docker info &> /dev/null 2>&1; then
echo ""
echo "Rancher Desktop is taking longer than expected. Please:"
echo "1. Wait for Rancher Desktop to fully initialize"
echo "2. Accept any permissions requests"
echo "3. Once you see 'Kubernetes is running' in Rancher Desktop, press Enter"
read
# Try to add Rancher Desktop to PATH
export PATH="$HOME/.rd/bin:$PATH"
# Check one more time
if ! command -v docker &> /dev/null || ! docker info &> /dev/null 2>&1; then
echo "Container runtime still not responding."
echo "Please ensure Rancher Desktop is fully started and try again."
exit 1
fi
fi
fi
# Ensure docker is in PATH for the rest of the script
export PATH="$HOME/.rd/bin:$PATH"
echo ""
echo "Step 2/7: Installing Memgraph container..."
# Stop and remove existing container if it exists
if docker ps -a 2>/dev/null | grep -q memgraph; then
echo "Removing existing Memgraph container..."
docker stop memgraph 2>/dev/null || true
docker rm memgraph 2>/dev/null || true
fi
docker pull memgraph/memgraph-platform || { echo "Failed to pull Memgraph image"; exit 1; }
docker run -d -p 7687:7687 -p 7444:7444 -p 3000:3000 \
--name memgraph \
-v memgraph_data:/var/lib/memgraph \
memgraph/memgraph-platform || { echo "Failed to start Memgraph container"; exit 1; }
echo "Waiting for Memgraph to be ready..."
sleep 10
echo ""
echo "Step 3/7: Installing Python and Memgraph MCP server..."
# Install Python if not present
if ! command -v python3 &> /dev/null; then
echo "Installing Python..."
brew install python3
fi
# Install uv package manager
if ! command -v uv &> /dev/null; then
echo "Installing uv package manager..."
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
fi
echo "Memgraph MCP will be configured to run via uv..."
echo ""
echo "Step 4/7: Configuring Claude Desktop..."
CONFIG_DIR="$HOME/Library/Application Support/Claude"
CONFIG_FILE="$CONFIG_DIR/claude_desktop_config.json"
mkdir -p "$CONFIG_DIR"
if [ -f "$CONFIG_FILE" ] && [ -s "$CONFIG_FILE" ]; then
echo "Backing up existing Claude configuration..."
cp "$CONFIG_FILE" "$CONFIG_FILE.backup.$(date +%s)"
fi
# Get the full path to uv
UV_PATH=$(which uv 2>/dev/null || echo "$HOME/.local/bin/uv")
# Merge memgraph config with existing config
if [ -f "$CONFIG_FILE" ] && [ -s "$CONFIG_FILE" ]; then
echo "Merging memgraph config with existing MCP servers..."
# Use Python to merge JSON (more reliable than jq which may not be installed)
python3 << PYTHON_MERGE
import json
import sys
config_file = "$CONFIG_FILE"
uv_path = "${UV_PATH}"
try:
# Read existing config
with open(config_file, 'r') as f:
config = json.load(f)
# Ensure mcpServers exists
if 'mcpServers' not in config:
config['mcpServers'] = {}
# Add/update memgraph server
config['mcpServers']['memgraph'] = {
"command": uv_path,
"args": [
"run",
"--with",
"mcp-memgraph",
"--python",
"3.13",
"mcp-memgraph"
],
"env": {
"MEMGRAPH_HOST": "localhost",
"MEMGRAPH_PORT": "7687"
}
}
# Write merged config
with open(config_file, 'w') as f:
json.dump(config, f, indent=2)
print("Successfully merged memgraph config")
sys.exit(0)
except Exception as e:
print(f"Error merging config: {e}", file=sys.stderr)
sys.exit(1)
PYTHON_MERGE
if [ $? -ne 0 ]; then
echo "Failed to merge config, creating new one..."
cat > "$CONFIG_FILE" << JSON
{
"mcpServers": {
"memgraph": {
"command": "${UV_PATH}",
"args": [
"run",
"--with",
"mcp-memgraph",
"--python",
"3.13",
"mcp-memgraph"
],
"env": {
"MEMGRAPH_HOST": "localhost",
"MEMGRAPH_PORT": "7687"
}
}
}
}
JSON
fi
else
echo "Creating new Claude Desktop configuration..."
cat > "$CONFIG_FILE" << JSON
{
"mcpServers": {
"memgraph": {
"command": "${UV_PATH}",
"args": [
"run",
"--with",
"mcp-memgraph",
"--python",
"3.13",
"mcp-memgraph"
],
"env": {
"MEMGRAPH_HOST": "localhost",
"MEMGRAPH_PORT": "7687"
}
}
}
}
JSON
fi
echo "Claude Desktop configured!"
echo ""
echo "Step 5/7: Setting up mgconsole..."
echo "mgconsole will be used via Docker (included in memgraph/memgraph-platform)"
echo ""
echo "Step 6/7: Setting up database schema..."
sleep 5 # Give Memgraph extra time to be ready
echo "Clearing existing data..."
echo "MATCH (n) DETACH DELETE n;" | docker exec -i memgraph mgconsole --host 127.0.0.1 --port 7687
echo "Creating indexes..."
cat <<'CYPHER' | docker exec -i memgraph mgconsole --host 127.0.0.1 --port 7687
CREATE INDEX ON :Account(account_id);
CREATE INDEX ON :Account(account_type);
CREATE INDEX ON :Person(person_id);
CYPHER
echo ""
echo "Step 7/7: Populating test data..."
echo "Loading core mule account data..."
cat <<'CYPHER' | docker exec -i memgraph mgconsole --host 127.0.0.1 --port 7687
CREATE (p1:Person {person_id: 'P001', name: 'John Smith', age: 45, risk_score: 'low'})
CREATE (a1:Account {account_id: 'ACC001', account_type: 'checking', balance: 15000, opened_date: '2020-01-15', status: 'active'})
CREATE (p1)-[:OWNS {since: '2020-01-15'}]->(a1)
CREATE (p2:Person {person_id: 'P002', name: 'Sarah Johnson', age: 38, risk_score: 'low'})
CREATE (a2:Account {account_id: 'ACC002', account_type: 'savings', balance: 25000, opened_date: '2019-06-10', status: 'active'})
CREATE (p2)-[:OWNS {since: '2019-06-10'}]->(a2)
CREATE (p3:Person {person_id: 'P003', name: 'Michael Brown', age: 22, risk_score: 'high'})
CREATE (a3:Account {account_id: 'ACC003', account_type: 'checking', balance: 500, opened_date: '2024-08-01', status: 'active'})
CREATE (p3)-[:OWNS {since: '2024-08-01'}]->(a3)
CREATE (p4:Person {person_id: 'P004', name: 'Lisa Chen', age: 19, risk_score: 'high'})
CREATE (a4:Account {account_id: 'ACC004', account_type: 'checking', balance: 300, opened_date: '2024-08-05', status: 'active'})
CREATE (p4)-[:OWNS {since: '2024-08-05'}]->(a4)
CREATE (p5:Person {person_id: 'P005', name: 'David Martinez', age: 21, risk_score: 'high'})
CREATE (a5:Account {account_id: 'ACC005', account_type: 'checking', balance: 450, opened_date: '2024-08-03', status: 'active'})
CREATE (p5)-[:OWNS {since: '2024-08-03'}]->(a5)
CREATE (p6:Person {person_id: 'P006', name: 'Robert Wilson', age: 35, risk_score: 'critical'})
CREATE (a6:Account {account_id: 'ACC006', account_type: 'business', balance: 2000, opened_date: '2024-07-15', status: 'active'})
CREATE (p6)-[:OWNS {since: '2024-07-15'}]->(a6)
CREATE (p7:Person {person_id: 'P007', name: 'Unknown Entity', risk_score: 'critical'})
CREATE (a7:Account {account_id: 'ACC007', account_type: 'business', balance: 150000, opened_date: '2024-06-01', status: 'active'})
CREATE (p7)-[:OWNS {since: '2024-06-01'}]->(a7)
CREATE (a7)-[:TRANSACTION {transaction_id: 'TXN001', amount: 50000, timestamp: '2024-09-01T10:15:00', type: 'wire_transfer', flagged: true}]->(a6)
CREATE (a6)-[:TRANSACTION {transaction_id: 'TXN002', amount: 9500, timestamp: '2024-09-01T14:30:00', type: 'transfer', flagged: true}]->(a3)
CREATE (a6)-[:TRANSACTION {transaction_id: 'TXN003', amount: 9500, timestamp: '2024-09-01T14:32:00', type: 'transfer', flagged: true}]->(a4)
CREATE (a6)-[:TRANSACTION {transaction_id: 'TXN004', amount: 9500, timestamp: '2024-09-01T14:35:00', type: 'transfer', flagged: true}]->(a5)
CREATE (a3)-[:TRANSACTION {transaction_id: 'TXN005', amount: 9000, timestamp: '2024-09-02T09:00:00', type: 'cash_withdrawal', flagged: true}]->(a6)
CREATE (a4)-[:TRANSACTION {transaction_id: 'TXN006', amount: 9000, timestamp: '2024-09-02T09:15:00', type: 'cash_withdrawal', flagged: true}]->(a6)
CREATE (a5)-[:TRANSACTION {transaction_id: 'TXN007', amount: 9000, timestamp: '2024-09-02T09:30:00', type: 'cash_withdrawal', flagged: true}]->(a6)
CREATE (a7)-[:TRANSACTION {transaction_id: 'TXN008', amount: 45000, timestamp: '2024-09-15T11:20:00', type: 'wire_transfer', flagged: true}]->(a6)
CREATE (a6)-[:TRANSACTION {transaction_id: 'TXN009', amount: 9800, timestamp: '2024-09-15T15:00:00', type: 'transfer', flagged: true}]->(a3)
CREATE (a6)-[:TRANSACTION {transaction_id: 'TXN010', amount: 9800, timestamp: '2024-09-15T15:05:00', type: 'transfer', flagged: true}]->(a4)
CREATE (a1)-[:TRANSACTION {transaction_id: 'TXN011', amount: 150, timestamp: '2024-09-10T12:00:00', type: 'debit_card', flagged: false}]->(a2)
CREATE (a2)-[:TRANSACTION {transaction_id: 'TXN012', amount: 1000, timestamp: '2024-09-12T10:00:00', type: 'transfer', flagged: false}]->(a1);
CYPHER
echo "Loading noise data (50 accounts, 500 transactions)..."
cat <<'CYPHER' | docker exec -i memgraph mgconsole --host 127.0.0.1 --port 7687
UNWIND range(1, 50) AS i
WITH i,
['Alice', 'Bob', 'Carol', 'David', 'Emma', 'Frank', 'Grace', 'Henry', 'Iris', 'Jack',
'Karen', 'Leo', 'Mary', 'Nathan', 'Olivia', 'Peter', 'Quinn', 'Rachel', 'Steve', 'Tina',
'Uma', 'Victor', 'Wendy', 'Xavier', 'Yara', 'Zack', 'Amy', 'Ben', 'Chloe', 'Daniel',
'Eva', 'Fred', 'Gina', 'Hugo', 'Ivy', 'James', 'Kate', 'Luke', 'Mia', 'Noah',
'Opal', 'Paul', 'Rosa', 'Sam', 'Tara', 'Umar', 'Vera', 'Will', 'Xena', 'Yuki'] AS firstNames,
['Anderson', 'Baker', 'Clark', 'Davis', 'Evans', 'Foster', 'Garcia', 'Harris', 'Irwin', 'Jones',
'King', 'Lopez', 'Miller', 'Nelson', 'Owens', 'Parker', 'Quinn', 'Reed', 'Scott', 'Taylor',
'Underwood', 'Vargas', 'White', 'Young', 'Zhao', 'Adams', 'Brooks', 'Collins', 'Duncan', 'Ellis'] AS lastNames,
['checking', 'savings', 'checking', 'savings', 'checking'] AS accountTypes,
['low', 'low', 'low', 'medium', 'low'] AS riskScores,
['2018-03-15', '2018-07-22', '2019-01-10', '2019-05-18', '2019-09-30', '2020-02-14', '2020-06-25', '2020-11-08', '2021-04-17', '2021-08-29', '2022-01-20', '2022-05-12', '2022-10-03', '2023-02-28', '2023-07-15'] AS dates
WITH i,
firstNames[toInteger(rand() * size(firstNames))] + ' ' + lastNames[toInteger(rand() * size(lastNames))] AS fullName,
accountTypes[toInteger(rand() * size(accountTypes))] AS accType,
riskScores[toInteger(rand() * size(riskScores))] AS risk,
toInteger(rand() * 40 + 25) AS age,
toInteger(rand() * 80000 + 1000) AS balance,
dates[toInteger(rand() * size(dates))] AS openDate
CREATE (p:Person {person_id: 'NOISE_P' + toString(i), name: fullName, age: age, risk_score: risk})
CREATE (a:Account {account_id: 'NOISE_ACC' + toString(i), account_type: accType, balance: balance, opened_date: openDate, status: 'active'})
CREATE (p)-[:OWNS {since: openDate}]->(a);
UNWIND range(1, 500) AS i
WITH i,
toInteger(rand() * 50 + 1) AS fromIdx,
toInteger(rand() * 50 + 1) AS toIdx,
['transfer', 'debit_card', 'check', 'atm_withdrawal', 'direct_deposit', 'wire_transfer', 'mobile_payment'] AS txnTypes,
['2024-01-15', '2024-02-20', '2024-03-10', '2024-04-05', '2024-05-18', '2024-06-22', '2024-07-14', '2024-08-09', '2024-09-25', '2024-10-30'] AS dates
WHERE fromIdx <> toIdx
WITH i, fromIdx, toIdx, txnTypes, dates,
txnTypes[toInteger(rand() * size(txnTypes))] AS txnType,
toInteger(rand() * 5000 + 10) AS amount,
(rand() < 0.05) AS shouldFlag,
dates[toInteger(rand() * size(dates))] AS txnDate
MATCH (from:Account {account_id: 'NOISE_ACC' + toString(fromIdx)})
MATCH (to:Account {account_id: 'NOISE_ACC' + toString(toIdx)})
CREATE (from)-[:TRANSACTION {
transaction_id: 'NOISE_TXN' + toString(i),
amount: amount,
timestamp: txnDate + 'T' + toString(toInteger(rand() * 24)) + ':' + toString(toInteger(rand() * 60)) + ':00',
type: txnType,
flagged: shouldFlag
}]->(to);
CYPHER
echo ""
echo "========================================"
echo "Setup Complete!"
echo "========================================"
echo ""
echo "Next steps:"
echo "1. Restart Claude Desktop (Quit and reopen)"
echo "2. Open Memgraph Lab at https://localhost:3000"
echo "3. Start asking Claude questions about the mule account data!"
echo ""
echo "Example query: 'Show me all accounts owned by people with high or critical risk scores in Memgraph'"
echo ""
EOF
chmod +x ~/setup_memgraph_complete.sh
~/setup_memgraph_complete.sh