# mosaic-ensure-sequential-thinking.ps1 $ErrorActionPreference = "Stop" param( [switch]$Check ) $Pkg = "@modelcontextprotocol/server-sequential-thinking" function Require-Binary { param([string]$Name) if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) { throw "Required binary missing: $Name" } } function Warm-Package { $null = & npx -y $Pkg --help 2>$null } function Set-ClaudeConfig { $path = Join-Path $env:USERPROFILE ".claude\settings.json" New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null $data = @{} if (Test-Path $path) { try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} } } if (-not $data.ContainsKey("mcpServers") -or -not ($data["mcpServers"] -is [hashtable])) { $data["mcpServers"] = @{} } $data["mcpServers"]["sequential-thinking"] = @{ command = "npx" args = @("-y", "@modelcontextprotocol/server-sequential-thinking") } $data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8 } function Set-CodexConfig { $path = Join-Path $env:USERPROFILE ".codex\config.toml" New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null if (-not (Test-Path $path)) { New-Item -ItemType File -Path $path -Force | Out-Null } $content = Get-Content $path -Raw $content = [regex]::Replace($content, "(?ms)^\[mcp_servers\.(sequential-thinking|sequential_thinking)\].*?(?=^\[|\z)", "") $content = $content.TrimEnd() + "`n`n[mcp_servers.sequential-thinking]`ncommand = \"npx\"`nargs = [\"-y\", \"@modelcontextprotocol/server-sequential-thinking\"]`n" Set-Content -Path $path -Value $content -Encoding UTF8 } function Set-OpenCodeConfig { $path = Join-Path $env:USERPROFILE ".config\opencode\config.json" New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null $data = @{} if (Test-Path $path) { try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} } } if (-not $data.ContainsKey("mcp") -or -not ($data["mcp"] -is [hashtable])) { $data["mcp"] = @{} } $data["mcp"]["sequential-thinking"] = @{ type = "local" command = @("npx", "-y", "@modelcontextprotocol/server-sequential-thinking") enabled = $true } $data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8 } function Test-Configs { $claudeOk = $false $codexOk = $false $opencodeOk = $false $claudePath = Join-Path $env:USERPROFILE ".claude\settings.json" if (Test-Path $claudePath) { try { $c = Get-Content $claudePath -Raw | ConvertFrom-Json -AsHashtable $claudeOk = $c.ContainsKey("mcpServers") -and $c["mcpServers"].ContainsKey("sequential-thinking") } catch {} } $codexPath = Join-Path $env:USERPROFILE ".codex\config.toml" if (Test-Path $codexPath) { $raw = Get-Content $codexPath -Raw $codexOk = $raw -match "\[mcp_servers\.(sequential-thinking|sequential_thinking)\]" -and $raw -match "@modelcontextprotocol/server-sequential-thinking" } $opencodePath = Join-Path $env:USERPROFILE ".config\opencode\config.json" if (Test-Path $opencodePath) { try { $o = Get-Content $opencodePath -Raw | ConvertFrom-Json -AsHashtable $opencodeOk = $o.ContainsKey("mcp") -and $o["mcp"].ContainsKey("sequential-thinking") } catch {} } if (-not ($claudeOk -and $codexOk -and $opencodeOk)) { throw "Sequential-thinking MCP runtime config is incomplete" } } Require-Binary node Require-Binary npx Warm-Package if ($Check) { Test-Configs Write-Host "[mosaic-seq] sequential-thinking MCP is configured and available" exit 0 } Set-ClaudeConfig Set-CodexConfig Set-OpenCodeConfig Write-Host "[mosaic-seq] sequential-thinking MCP configured for Claude, Codex, and OpenCode"