tools-sync: MCP 审计自动排除 Codex 插件 MCP(按 cwd 识别),并修 -ExcludeName 逗号传参

HJ_PC 上 code-review / codex_app 以 cmd.exe 启动、cwd 在 plugins\cache\openai-bundled,
旧逻辑只看 command 识别不出,-Apply 把它们复制进了 Claude;
powershell -File 传 -ExcludeName a,b 时绑定成单个字符串 a,b,排除也失效。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Myfro9
2026-10-20 23:15:06 +08:00
co-authored by Claude Opus 5.5
parent 007376f8fd
commit e85690adbc
@@ -36,6 +36,8 @@ param(
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
# `powershell -File x.ps1 -ExcludeName a,b` binds the single string "a,b"; split it ourselves.
$ExcludeName = @($ExcludeName | ForEach-Object { $_ -split ',' } | ForEach-Object { $_.Trim() } | Where-Object { $_ })
$script:CodexBackupMade = $false $script:CodexBackupMade = $false
$script:Failures = @() $script:Failures = @()
$script:Unsupported = @() $script:Unsupported = @()
@@ -156,12 +158,13 @@ function Get-CodexMcpsFromCli {
$t = $s.transport $t = $s.transport
$transport = if ($t.type) { [string]$t.type } elseif ($t.url) { "http" } else { "stdio" } $transport = if ($t.type) { [string]$t.type } elseif ($t.url) { "http" } else { "stdio" }
if ($transport -eq "streamable_http") { $transport = "http" } if ($transport -eq "streamable_http") { $transport = "http" }
$result[[string]$s.name] = New-CanonicalMcp ([string]$s.name) $transport ([string]$t.command) ` $mcp = New-CanonicalMcp ([string]$s.name) $transport ([string]$t.command) `
@($t.args) (ConvertTo-StringMap $t.env) ([string]$t.url) ` @($t.args) (ConvertTo-StringMap $t.env) ([string]$t.url) `
(ConvertTo-StringMap $t.http_headers) ([string]$t.bearer_token_env_var) "Codex" (ConvertTo-StringMap $t.http_headers) ([string]$t.bearer_token_env_var) "Codex"
# Not part of the drift comparison; Test-CodexManaged needs it because bundled # Not part of the drift comparison; Test-CodexManaged needs it because bundled
# plugin MCPs launch as plain `cmd.exe` and only their cwd names the plugin cache. # plugin MCPs launch as plain `cmd.exe` and only their cwd names the plugin cache.
$result[[string]$s.name] | Add-Member -NotePropertyName cwd -NotePropertyValue ([string]$t.cwd) $mcp | Add-Member -NotePropertyName cwd -NotePropertyValue ([string]$t.cwd)
$result[[string]$s.name] = $mcp
} }
return $result return $result
} }
@@ -208,6 +211,8 @@ function Test-CodexManaged($Mcp) {
# codex-cli 0.162: code-review / codex_app are `cmd.exe /c scripts\launch_*.cmd` with # codex-cli 0.162: code-review / codex_app are `cmd.exe /c scripts\launch_*.cmd` with
# cwd under .codex\plugins\cache\openai-bundled -- the command alone looks portable. # cwd under .codex\plugins\cache\openai-bundled -- the command alone looks portable.
if ([string]$Mcp.cwd -match '(?i)[\\/]\.codex[\\/](runtimes|plugins[\\/]cache)[\\/]') { return $true } if ([string]$Mcp.cwd -match '(?i)[\\/]\.codex[\\/](runtimes|plugins[\\/]cache)[\\/]') { return $true }
# The plugin cache may also live outside ~\.codex (e.g. orca's codex-runtime-home). 2026-10-08 HJ_PC.
if ([string]$Mcp.cwd -match '(?i)[\\/]plugins[\\/]cache[\\/]') { return $true }
# The Codex desktop app also bundles MCPs from its own install dir (MSIX # The Codex desktop app also bundles MCPs from its own install dir (MSIX
# WindowsApps, or AppData\Local\OpenAI\Codex). Host-owned, not portable. # WindowsApps, or AppData\Local\OpenAI\Codex). Host-owned, not portable.
return ($command -match '(?i)[\\/](WindowsApps[\\/]OpenAI\.Codex|OpenAI[\\/]Codex[\\/])') return ($command -match '(?i)[\\/](WindowsApps[\\/]OpenAI\.Codex|OpenAI[\\/]Codex[\\/])')