param(
[string]$RepoPath = (Split-Path $PSScriptRoot -Parent),
[string]$ClaudeConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json",
[switch]$SkipRestart,
[string]$ServerName = 'schwab'
)
$ErrorActionPreference = 'Stop'
function Ensure-Property {
param(
[Parameter(Mandatory = $true)] $Object,
[Parameter(Mandatory = $true)][string] $Name,
$Default
)
if (-not ($Object.PSObject.Properties.Name -contains $Name)) {
$Object | Add-Member -MemberType NoteProperty -Name $Name -Value $Default
}
}
function Update-JsonConfig {
param([string]$Path)
Write-Host "Updating MCP config at '$Path'..."
if (-not (Test-Path $Path)) {
throw "Claude Desktop config not found at $Path"
}
$config = Get-Content -Raw -Path $Path | ConvertFrom-Json
Ensure-Property -Object $config -Name 'mcpServers' -Default ([pscustomobject]@{})
Ensure-Property -Object $config.mcpServers -Name 'schwab' -Default ([pscustomobject]@{})
$schwab = $config.mcpServers.schwab
Ensure-Property -Object $schwab -Name 'command' -Default ''
Ensure-Property -Object $schwab -Name 'args' -Default @()
Ensure-Property -Object $schwab -Name 'cwd' -Default ''
Ensure-Property -Object $schwab -Name 'env' -Default ([pscustomobject]@{})
$schwab.command = Join-Path $RepoPath "venv\Scripts\python.exe"
$schwab.args = @('-m', 'schwab_mcp.server')
$schwab.cwd = $RepoPath
Ensure-Property -Object $schwab.env -Name 'PYTHONPATH' -Default ''
$schwab.env.PYTHONPATH = Join-Path $RepoPath 'src'
$json = $config | ConvertTo-Json -Depth 6
Set-Content -Path $Path -Value $json -Encoding UTF8
Write-Host "Config updated."
}
function Remove-ClaudeMcpCache {
param(
[string]$BasePath,
[string]$ServerName
)
$patterns = @(
"logs/*$ServerName*",
'logs/*mcp*',
"Cache/*$ServerName*",
'Cache/*mcp*',
"Network/*$ServerName*",
'Network/*mcp*',
"Session Storage/*$ServerName*",
'Session Storage/*mcp*',
"Local Storage/*$ServerName*",
'Local Storage/*mcp*',
"blob_storage/*$ServerName*",
'blob_storage/*mcp*'
)
$removed = $false
foreach ($pattern in $patterns) {
$targets = Get-ChildItem -Path (Join-Path $BasePath $pattern) -Recurse -Force -ErrorAction SilentlyContinue
foreach ($target in $targets) {
Write-Host "Removing cached item '$($target.FullName)'..."
Remove-Item -Path $target.FullName -Recurse -Force -ErrorAction SilentlyContinue
$removed = $true
}
}
if (-not $removed) {
Write-Host "No $ServerName-specific cached items found under $BasePath."
}
}
function Stop-ClaudeDesktop {
$proc = Get-Process -Name 'Claude' -ErrorAction SilentlyContinue
if (-not $proc) {
return $false
}
$answer = Read-Host 'Claude Desktop is running. Quit it now? (y/N)'
if ($answer -notmatch '^(y|yes)$') {
Write-Host 'Aborted by user.'
exit 1
}
Write-Host 'Stopping Claude Desktop...'
$proc | Stop-Process -Force
Start-Sleep -Seconds 2
return $true
}
function Start-ClaudeDesktop {
param([string]$Executable)
if ($SkipRestart) {
Write-Host 'SkipRestart requested; not starting Claude Desktop.'
return
}
if (-not (Test-Path $Executable)) {
Write-Warning "Claude executable not found at '$Executable'. Start it manually."
return
}
Write-Host 'Starting Claude Desktop...'
Start-Process -FilePath $Executable | Out-Null
}
if (-not (Test-Path $RepoPath)) {
throw "Repo path not found: $RepoPath"
}
$claudeBase = Split-Path $ClaudeConfigPath -Parent
$claudeExe = Join-Path $env:LOCALAPPDATA 'AnthropicClaude/claude.exe'
$stopped = Stop-ClaudeDesktop
Remove-ClaudeMcpCache -BasePath $claudeBase -ServerName $ServerName
Update-JsonConfig -Path $ClaudeConfigPath
Start-ClaudeDesktop -Executable $claudeExe
Write-Host 'Done.'