Skip to content

Commit d1b2111

Browse files
thestack_aiclaude
andcommitted
feat: auto-start Brain + auto-register Claude Code MCP
1. Orb (Tauri Rust): spawns Brain Lite WebSocket server on app start - Detects ~/.jarvis-orb/jarvis_brain, launches python -m jarvis_brain.demo_server - Falls back to standalone mode if Brain not installed - Works on macOS + Windows 2. Installers: auto-register MCP in Claude Code settings.json - macOS: Python script modifies settings.json - Windows: PowerShell modifies settings.json - Both: graceful fallback to manual instructions if auto-config fails User flow: install → open Orb → everything works. No manual steps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 65c4711 commit d1b2111

5 files changed

Lines changed: 106 additions & 13 deletions

File tree

install.ps1

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,46 @@ Write-Ok "Brain launcher → $BrainBin\jarvis-brain.bat"
8080
# ── Step 3: Claude Code MCP ──
8181
Write-Step "Configuring Claude Code"
8282

83-
$claudeSettings = "$env:USERPROFILE\.claude\settings.json"
83+
$claudeDir = "$env:USERPROFILE\.claude"
84+
$claudeSettings = "$claudeDir\settings.json"
85+
8486
if (Test-Path $claudeSettings) {
8587
$content = Get-Content $claudeSettings -Raw
8688
if ($content -match "jarvis-brain") {
8789
Write-Ok "Already configured"
8890
} else {
89-
Write-Info "Add to your Claude Code MCP config:"
90-
Write-Host ""
91-
Write-Host ' "jarvis-brain": {' -ForegroundColor White
92-
Write-Host " `"command`": `"$BrainBin\jarvis-brain.bat`"" -ForegroundColor White
93-
Write-Host ' }' -ForegroundColor White
94-
Write-Host ""
91+
try {
92+
$settings = $content | ConvertFrom-Json
93+
# Add mcpServers if not exists
94+
if (-not $settings.mcpServers) {
95+
$settings | Add-Member -NotePropertyName "mcpServers" -NotePropertyValue @{} -Force
96+
}
97+
$brainCmd = "$BrainBin\jarvis-brain.bat"
98+
$settings.mcpServers | Add-Member -NotePropertyName "jarvis-brain" -NotePropertyValue @{
99+
command = $brainCmd
100+
} -Force
101+
$settings | ConvertTo-Json -Depth 10 | Set-Content $claudeSettings -Encoding UTF8
102+
Write-Ok "MCP server registered in Claude Code"
103+
} catch {
104+
Write-Info "Add to your Claude Code MCP config:"
105+
Write-Host ""
106+
Write-Host ' "jarvis-brain": {' -ForegroundColor White
107+
Write-Host " `"command`": `"$BrainBin\jarvis-brain.bat`"" -ForegroundColor White
108+
Write-Host ' }' -ForegroundColor White
109+
Write-Host ""
110+
}
111+
}
112+
} elseif (Test-Path $claudeDir) {
113+
# settings.json doesn't exist but .claude dir does — create it
114+
$newSettings = @{
115+
mcpServers = @{
116+
"jarvis-brain" = @{
117+
command = "$BrainBin\jarvis-brain.bat"
118+
}
119+
}
95120
}
121+
$newSettings | ConvertTo-Json -Depth 10 | Set-Content $claudeSettings -Encoding UTF8
122+
Write-Ok "Created Claude Code settings with MCP config"
96123
} else {
97124
Write-Info "Claude Code not found — configure MCP manually after install"
98125
}

install.sh

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,29 @@ if [ -d "$CLAUDE_DIR" ]; then
119119
if grep -q "jarvis-brain" "$CLAUDE_SETTINGS" 2>/dev/null; then
120120
ok "Already configured"
121121
else
122-
info "Add to your Claude Code MCP config:"
123-
echo ""
124-
echo -e " ${WHITE}\"jarvis-brain\": {${R}"
125-
echo -e " ${WHITE} \"command\": \"$BRAIN_BIN/jarvis-brain\"${R}"
126-
echo -e " ${WHITE}}${R}"
127-
echo ""
122+
if [ -f "$CLAUDE_SETTINGS" ] && command -v python3 &>/dev/null; then
123+
python3 -c "
124+
import json, sys
125+
try:
126+
with open('$CLAUDE_SETTINGS') as f:
127+
s = json.load(f)
128+
if 'mcpServers' not in s:
129+
s['mcpServers'] = {}
130+
s['mcpServers']['jarvis-brain'] = {'command': '$BRAIN_BIN/jarvis-brain'}
131+
with open('$CLAUDE_SETTINGS', 'w') as f:
132+
json.dump(s, f, indent=2, ensure_ascii=False)
133+
print('done')
134+
except Exception as e:
135+
print(f'fail:{e}', file=sys.stderr)
136+
sys.exit(1)
137+
" 2>/dev/null && ok "MCP server registered in Claude Code" || {
138+
info "Add to your Claude Code MCP config:"
139+
echo -e " ${WHITE}\"jarvis-brain\": { \"command\": \"$BRAIN_BIN/jarvis-brain\" }${R}"
140+
}
141+
else
142+
info "Add to your Claude Code MCP config:"
143+
echo -e " ${WHITE}\"jarvis-brain\": { \"command\": \"$BRAIN_BIN/jarvis-brain\" }${R}"
144+
fi
128145
fi
129146
else
130147
info "Claude Code not found — configure MCP manually after install"

orb/src-tauri/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

orb/src-tauri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
tauri = { version = "2", features = [] }
88
serde = { version = "1", features = ["derive"] }
99
serde_json = "1"
10+
dirs = "6"
1011

1112
[build-dependencies]
1213
tauri-build = { version = "2", features = [] }

orb/src-tauri/src/main.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,53 @@
11
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
22

3+
use std::process::Command;
4+
5+
fn start_brain() {
6+
let home = dirs::home_dir().unwrap_or_default();
7+
let brain_dir = home.join(".jarvis-orb");
8+
let brain_module = brain_dir.join("jarvis_brain");
9+
10+
// Only start if brain is installed
11+
if !brain_module.exists() {
12+
eprintln!("[Orb] Brain not found at {:?}, running in standalone mode", brain_module);
13+
return;
14+
}
15+
16+
let lib_dir = brain_dir.join("lib");
17+
let pythonpath = format!(
18+
"{}{}{}",
19+
lib_dir.display(),
20+
if cfg!(windows) { ";" } else { ":" },
21+
brain_dir.display()
22+
);
23+
24+
// Find python
25+
let python = if cfg!(windows) { "python" } else { "python3" };
26+
27+
match Command::new(python)
28+
.args(["-m", "jarvis_brain.demo_server"])
29+
.env("PYTHONPATH", &pythonpath)
30+
.current_dir(&brain_dir)
31+
.stdout(std::process::Stdio::null())
32+
.stderr(std::process::Stdio::null())
33+
.spawn()
34+
{
35+
Ok(child) => {
36+
eprintln!("[Orb] Brain started (PID: {})", child.id());
37+
// Don't wait — let it run as background process
38+
// It will be killed when Orb exits (child process)
39+
std::mem::forget(child);
40+
}
41+
Err(e) => {
42+
eprintln!("[Orb] Failed to start Brain: {}", e);
43+
}
44+
}
45+
}
46+
347
fn main() {
48+
// Start Brain Lite WebSocket server before Tauri
49+
start_brain();
50+
451
tauri::Builder::default()
552
.run(tauri::generate_context!())
653
.expect("error while running Jarvis Orb");

0 commit comments

Comments
 (0)