windows-exe-decompiler-mcp-server 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CLAUDE_INSTALLATION.md +129 -0
  2. package/CODEX_INSTALLATION.md +25 -1
  3. package/COPILOT_INSTALLATION.md +29 -1
  4. package/LICENSE +21 -21
  5. package/README.md +232 -110
  6. package/dist/analysis-provenance.d.ts +50 -2
  7. package/dist/analysis-provenance.js +1 -0
  8. package/dist/analysis-task-runner.js +92 -0
  9. package/dist/config.d.ts +35 -16
  10. package/dist/config.js +37 -3
  11. package/dist/database.js +115 -115
  12. package/dist/decompiler-worker.d.ts +10 -5
  13. package/dist/decompiler-worker.js +240 -58
  14. package/dist/dynamic-trace.d.ts +6 -0
  15. package/dist/dynamic-trace.js +52 -1
  16. package/dist/ghidra-config.js +17 -1
  17. package/dist/index.js +38 -8
  18. package/dist/pe-runtime-functions.d.ts +90 -0
  19. package/dist/pe-runtime-functions.js +452 -0
  20. package/dist/prompts/module-reconstruction-review.d.ts +5 -0
  21. package/dist/prompts/module-reconstruction-review.js +65 -0
  22. package/dist/runtime-correlation.d.ts +5 -0
  23. package/dist/runtime-correlation.js +179 -2
  24. package/dist/sample-workspace.d.ts +28 -0
  25. package/dist/sample-workspace.js +186 -0
  26. package/dist/semantic-name-suggestion-artifacts.d.ts +56 -0
  27. package/dist/semantic-name-suggestion-artifacts.js +87 -0
  28. package/dist/server.js +1 -1
  29. package/dist/setup-guidance.d.ts +73 -0
  30. package/dist/setup-guidance.js +211 -0
  31. package/dist/tools/artifact-read.d.ts +10 -10
  32. package/dist/tools/artifacts-diff.d.ts +8 -8
  33. package/dist/tools/artifacts-list.d.ts +16 -16
  34. package/dist/tools/attack-map.d.ts +8 -8
  35. package/dist/tools/binary-role-profile.d.ts +1197 -0
  36. package/dist/tools/binary-role-profile.js +575 -0
  37. package/dist/tools/code-function-explain-apply.d.ts +12 -12
  38. package/dist/tools/code-function-explain-prepare.d.ts +12 -12
  39. package/dist/tools/code-function-explain-review.d.ts +58 -58
  40. package/dist/tools/code-function-rename-apply.d.ts +12 -12
  41. package/dist/tools/code-function-rename-prepare.d.ts +14 -14
  42. package/dist/tools/code-function-rename-review.d.ts +66 -66
  43. package/dist/tools/code-functions-define.d.ts +337 -0
  44. package/dist/tools/code-functions-define.js +337 -0
  45. package/dist/tools/code-functions-list.js +1 -1
  46. package/dist/tools/code-functions-rank.js +1 -1
  47. package/dist/tools/code-functions-reconstruct.d.ts +368 -58
  48. package/dist/tools/code-functions-reconstruct.js +130 -10
  49. package/dist/tools/code-functions-smart-recover.d.ts +352 -0
  50. package/dist/tools/code-functions-smart-recover.js +190 -0
  51. package/dist/tools/code-module-review-apply.d.ts +233 -0
  52. package/dist/tools/code-module-review-apply.js +209 -0
  53. package/dist/tools/code-module-review-prepare.d.ts +756 -0
  54. package/dist/tools/code-module-review-prepare.js +343 -0
  55. package/dist/tools/code-module-review.d.ts +474 -0
  56. package/dist/tools/code-module-review.js +566 -0
  57. package/dist/tools/code-reconstruct-export.d.ts +193 -21
  58. package/dist/tools/code-reconstruct-export.js +578 -21
  59. package/dist/tools/code-reconstruct-plan.d.ts +20 -20
  60. package/dist/tools/com-role-profile.d.ts +353 -0
  61. package/dist/tools/com-role-profile.js +186 -0
  62. package/dist/tools/dll-export-profile.d.ts +625 -0
  63. package/dist/tools/dll-export-profile.js +230 -0
  64. package/dist/tools/dotnet-metadata-extract.d.ts +122 -122
  65. package/dist/tools/dotnet-reconstruct-export.d.ts +49 -49
  66. package/dist/tools/dotnet-types-list.d.ts +66 -66
  67. package/dist/tools/dynamic-dependencies.d.ts +144 -8
  68. package/dist/tools/dynamic-dependencies.js +20 -1
  69. package/dist/tools/dynamic-memory-import.js +105 -2
  70. package/dist/tools/ghidra-analyze.d.ts +20 -0
  71. package/dist/tools/ghidra-analyze.js +10 -2
  72. package/dist/tools/ghidra-health.d.ts +177 -0
  73. package/dist/tools/ghidra-health.js +28 -0
  74. package/dist/tools/ioc-export.d.ts +8 -8
  75. package/dist/tools/packer-detect.d.ts +14 -14
  76. package/dist/tools/packer-detect.js +6 -9
  77. package/dist/tools/pe-exports-extract.d.ts +8 -8
  78. package/dist/tools/pe-exports-extract.js +6 -9
  79. package/dist/tools/pe-fingerprint.d.ts +36 -36
  80. package/dist/tools/pe-imports-extract.d.ts +8 -8
  81. package/dist/tools/pe-imports-extract.js +6 -9
  82. package/dist/tools/pe-pdata-extract.d.ts +448 -0
  83. package/dist/tools/pe-pdata-extract.js +219 -0
  84. package/dist/tools/pe-symbols-recover.d.ts +227 -0
  85. package/dist/tools/pe-symbols-recover.js +316 -0
  86. package/dist/tools/report-generate.d.ts +15 -1
  87. package/dist/tools/report-generate.js +139 -16
  88. package/dist/tools/report-summarize.d.ts +2242 -8
  89. package/dist/tools/report-summarize.js +246 -10
  90. package/dist/tools/runtime-detect.d.ts +8 -8
  91. package/dist/tools/runtime-detect.js +2 -12
  92. package/dist/tools/rust-binary-analyze.d.ts +2047 -0
  93. package/dist/tools/rust-binary-analyze.js +443 -0
  94. package/dist/tools/sample-profile-get.d.ts +135 -16
  95. package/dist/tools/sample-profile-get.js +35 -32
  96. package/dist/tools/sandbox-execute.d.ts +10 -10
  97. package/dist/tools/strings-extract.d.ts +8 -8
  98. package/dist/tools/strings-extract.js +2 -12
  99. package/dist/tools/strings-floss-decode.d.ts +8 -8
  100. package/dist/tools/system-health.d.ts +172 -36
  101. package/dist/tools/system-health.js +14 -0
  102. package/dist/tools/system-setup-guide.d.ts +179 -0
  103. package/dist/tools/system-setup-guide.js +62 -0
  104. package/dist/tools/tool-help.d.ts +16 -16
  105. package/dist/tools/tool-help.js +172 -0
  106. package/dist/tools/yara-scan.d.ts +8 -8
  107. package/dist/types.d.ts +2 -0
  108. package/dist/workflows/function-explanation-review.d.ts +3034 -76
  109. package/dist/workflows/function-explanation-review.js +172 -42
  110. package/dist/workflows/function-index-recover.d.ts +333 -0
  111. package/dist/workflows/function-index-recover.js +291 -0
  112. package/dist/workflows/module-reconstruction-review.d.ts +3537 -0
  113. package/dist/workflows/module-reconstruction-review.js +354 -0
  114. package/dist/workflows/reconstruct.d.ts +2182 -223
  115. package/dist/workflows/reconstruct.js +575 -32
  116. package/dist/workflows/semantic-name-review.d.ts +1436 -85
  117. package/dist/workflows/semantic-name-review.js +150 -58
  118. package/dist/workflows/triage.d.ts +8 -8
  119. package/ghidra_scripts/DecompileFunction.java +487 -487
  120. package/ghidra_scripts/ExtractCFG.java +256 -256
  121. package/ghidra_scripts/ExtractFunctions.java +442 -442
  122. package/ghidra_scripts/README.md +112 -112
  123. package/ghidra_scripts/SearchFunctionReferences.java +380 -380
  124. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -9
  125. package/helpers/DotNetMetadataProbe/Program.cs +566 -566
  126. package/install-to-claude.ps1 +432 -0
  127. package/install-to-codex.ps1 +256 -178
  128. package/install-to-copilot.ps1 +389 -303
  129. package/package.json +4 -2
  130. package/requirements.txt +9 -9
  131. package/workers/requirements-dynamic.txt +11 -11
  132. package/workers/requirements.txt +8 -8
  133. package/workers/speakeasy_compat.py +175 -175
  134. package/workers/static_worker.py +3474 -3474
@@ -1,178 +1,256 @@
1
- param(
2
- [string]$ServerName = "windows-exe-decompiler",
3
- [string]$ProjectRoot = (Get-Location).Path,
4
- [string]$NodePath,
5
- [string]$GhidraPath = "",
6
- [string]$ConfigPath = "$env:USERPROFILE\.codex\config.toml",
7
- [switch]$NoBackup
8
- )
9
-
10
- Set-StrictMode -Version Latest
11
- $ErrorActionPreference = "Stop"
12
-
13
- function Write-Step {
14
- param([string]$Message)
15
- Write-Host ""
16
- Write-Host $Message -ForegroundColor Yellow
17
- }
18
-
19
- function Convert-ToConfigPath {
20
- param([Parameter(Mandatory = $true)][string]$PathValue)
21
- return ([System.IO.Path]::GetFullPath($PathValue) -replace "\\", "/")
22
- }
23
-
24
- function Get-NodeExecutable {
25
- if ($NodePath) {
26
- if (-not (Test-Path -Path $NodePath)) {
27
- throw "NodePath does not exist: $NodePath"
28
- }
29
-
30
- return [System.IO.Path]::GetFullPath($NodePath)
31
- }
32
-
33
- $nodeCommand = Get-Command node -ErrorAction SilentlyContinue
34
- if ($null -eq $nodeCommand) {
35
- throw "Node.js was not found in PATH. Install Node.js or pass -NodePath."
36
- }
37
-
38
- return $nodeCommand.Source
39
- }
40
-
41
- function Resolve-GhidraPath {
42
- if ($GhidraPath) {
43
- return $GhidraPath
44
- }
45
-
46
- if ($env:GHIDRA_PATH) {
47
- return $env:GHIDRA_PATH
48
- }
49
-
50
- if ($env:GHIDRA_INSTALL_DIR) {
51
- return $env:GHIDRA_INSTALL_DIR
52
- }
53
-
54
- return ""
55
- }
56
-
57
- function Backup-FileIfNeeded {
58
- param([Parameter(Mandatory = $true)][string]$PathValue)
59
-
60
- if ($NoBackup -or -not (Test-Path -Path $PathValue)) {
61
- return $null
62
- }
63
-
64
- $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
65
- $backupPath = "$PathValue.$timestamp.bak"
66
- Copy-Item -Path $PathValue -Destination $backupPath -Force
67
- return $backupPath
68
- }
69
-
70
- function Ensure-ParentDirectory {
71
- param([Parameter(Mandatory = $true)][string]$PathValue)
72
-
73
- $parent = Split-Path -Path $PathValue -Parent
74
- if ($parent -and -not (Test-Path -Path $parent)) {
75
- New-Item -Path $parent -ItemType Directory -Force | Out-Null
76
- }
77
- }
78
-
79
- function Build-ServerBlock {
80
- param(
81
- [Parameter(Mandatory = $true)][string]$NodeExecutableConfig,
82
- [Parameter(Mandatory = $true)][string]$EntryPathConfig,
83
- [Parameter(Mandatory = $true)][string]$ProjectRootConfig,
84
- [string]$GhidraPathConfig
85
- )
86
-
87
- $lines = @(
88
- "[mcp_servers.$ServerName]"
89
- "command = `"$NodeExecutableConfig`""
90
- "args = [`"$EntryPathConfig`"]"
91
- "cwd = `"$ProjectRootConfig`""
92
- "startup_timeout_sec = 30"
93
- "tool_timeout_sec = 300"
94
- "enabled = true"
95
- )
96
-
97
- if ($GhidraPathConfig) {
98
- $lines += "env = { GHIDRA_PATH = `"$GhidraPathConfig`", GHIDRA_INSTALL_DIR = `"$GhidraPathConfig`" }"
99
- }
100
-
101
- return ($lines -join [Environment]::NewLine)
102
- }
103
-
104
- function Upsert-ConfigBlock {
105
- param(
106
- [Parameter(Mandatory = $true)][string]$PathValue,
107
- [Parameter(Mandatory = $true)][string]$BlockText
108
- )
109
-
110
- Ensure-ParentDirectory -PathValue $PathValue
111
-
112
- $existing = ""
113
- if (Test-Path -Path $PathValue) {
114
- $existing = Get-Content -Path $PathValue -Raw
115
- }
116
-
117
- $pattern = "(?ms)^\[mcp_servers\.$([regex]::Escape($ServerName))\]\r?\n.*?(?=^\[|\z)"
118
- if ($existing -match $pattern) {
119
- $updated = [regex]::Replace($existing, $pattern, $BlockText + [Environment]::NewLine)
120
- } else {
121
- $separator = if ([string]::IsNullOrWhiteSpace($existing)) { "" } else { [Environment]::NewLine + [Environment]::NewLine }
122
- $updated = $existing.TrimEnd() + $separator + $BlockText + [Environment]::NewLine
123
- }
124
-
125
- [System.IO.File]::WriteAllText($PathValue, $updated, [System.Text.UTF8Encoding]::new($false))
126
- }
127
-
128
- Write-Host "=== Windows EXE Decompiler MCP Server - Codex Install ===" -ForegroundColor Cyan
129
-
130
- Write-Step "Step 1: Validate build output"
131
- $projectRootFull = [System.IO.Path]::GetFullPath($ProjectRoot)
132
- $entryPath = Join-Path -Path $projectRootFull -ChildPath "dist/index.js"
133
- if (-not (Test-Path -Path $entryPath)) {
134
- throw "dist/index.js was not found. Run 'npm run build' from the project root first."
135
- }
136
-
137
- $nodeExecutable = Get-NodeExecutable
138
- $ghidraPathResolved = Resolve-GhidraPath
139
-
140
- $nodeExecutableConfig = Convert-ToConfigPath -PathValue $nodeExecutable
141
- $entryPathConfig = Convert-ToConfigPath -PathValue $entryPath
142
- $projectRootConfig = Convert-ToConfigPath -PathValue $projectRootFull
143
- $ghidraPathConfig = if ($ghidraPathResolved) { Convert-ToConfigPath -PathValue $ghidraPathResolved } else { "" }
144
-
145
- Write-Host "Project root: $projectRootConfig" -ForegroundColor Gray
146
- Write-Host "Node path: $nodeExecutableConfig" -ForegroundColor Gray
147
- Write-Host "Server entry: $entryPathConfig" -ForegroundColor Gray
148
- if ($ghidraPathConfig) {
149
- Write-Host "Ghidra path: $ghidraPathConfig" -ForegroundColor Gray
150
- } else {
151
- Write-Host "No Ghidra path supplied. The config will be written without GHIDRA_PATH." -ForegroundColor Yellow
152
- }
153
-
154
- Write-Step "Step 2: Register MCP server with Codex"
155
- & codex mcp add $ServerName -- $nodeExecutableConfig $entryPathConfig
156
- if ($LASTEXITCODE -ne 0) {
157
- throw "codex mcp add failed."
158
- }
159
- Write-Host "Codex registration completed." -ForegroundColor Green
160
-
161
- Write-Step "Step 3: Update Codex config"
162
- $backupPath = Backup-FileIfNeeded -PathValue $ConfigPath
163
- $serverBlock = Build-ServerBlock -NodeExecutableConfig $nodeExecutableConfig -EntryPathConfig $entryPathConfig -ProjectRootConfig $projectRootConfig -GhidraPathConfig $ghidraPathConfig
164
- Upsert-ConfigBlock -PathValue $ConfigPath -BlockText $serverBlock
165
- Write-Host "Config written: $ConfigPath" -ForegroundColor Green
166
- if ($backupPath) {
167
- Write-Host "Backup file: $backupPath" -ForegroundColor Gray
168
- }
169
-
170
- Write-Step "Step 4: Verify installation"
171
- & codex mcp list
172
-
173
- Write-Step "Next steps"
174
- Write-Host "1. Restart Codex if it was already running." -ForegroundColor White
175
- Write-Host "2. Ask Codex to call 'tool.help' or 'workflow.triage'." -ForegroundColor White
176
- Write-Host "3. If native analysis is needed, pass -GhidraPath or set GHIDRA_PATH." -ForegroundColor White
177
- Write-Host ""
178
- Write-Host "Installation complete." -ForegroundColor Green
1
+ param(
2
+ [string]$ServerName = "windows-exe-decompiler",
3
+ [string]$ProjectRoot = (Get-Location).Path,
4
+ [string]$NodePath,
5
+ [string]$GhidraPath = "",
6
+ [string]$WorkspaceRoot = "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\workspaces",
7
+ [string]$DatabasePath = "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\data\\database.db",
8
+ [string]$CacheRoot = "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\cache",
9
+ [string]$AuditLogPath = "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\audit.log",
10
+ [string]$ConfigPath = "$env:USERPROFILE\.codex\config.toml",
11
+ [switch]$NoBackup
12
+ )
13
+
14
+ Set-StrictMode -Version Latest
15
+ $ErrorActionPreference = "Stop"
16
+
17
+ function Write-Step {
18
+ param([string]$Message)
19
+ Write-Host ""
20
+ Write-Host $Message -ForegroundColor Yellow
21
+ }
22
+
23
+ function Convert-ToConfigPath {
24
+ param([Parameter(Mandatory = $true)][string]$PathValue)
25
+ return ([System.IO.Path]::GetFullPath($PathValue) -replace "\\", "/")
26
+ }
27
+
28
+ function Get-NodeExecutable {
29
+ if ($NodePath) {
30
+ if (-not (Test-Path -Path $NodePath)) {
31
+ throw "NodePath does not exist: $NodePath"
32
+ }
33
+
34
+ return [System.IO.Path]::GetFullPath($NodePath)
35
+ }
36
+
37
+ $nodeCommand = Get-Command node -ErrorAction SilentlyContinue
38
+ if ($null -eq $nodeCommand) {
39
+ throw "Node.js was not found in PATH. Install Node.js or pass -NodePath."
40
+ }
41
+
42
+ return $nodeCommand.Source
43
+ }
44
+
45
+ function Resolve-GhidraPath {
46
+ if ($GhidraPath) {
47
+ return $GhidraPath
48
+ }
49
+
50
+ if ($env:GHIDRA_PATH) {
51
+ return $env:GHIDRA_PATH
52
+ }
53
+
54
+ if ($env:GHIDRA_INSTALL_DIR) {
55
+ return $env:GHIDRA_INSTALL_DIR
56
+ }
57
+
58
+ return ""
59
+ }
60
+
61
+ function Resolve-WorkspaceRoot {
62
+ if ($WorkspaceRoot) {
63
+ return $WorkspaceRoot
64
+ }
65
+
66
+ if ($env:WORKSPACE_ROOT) {
67
+ return $env:WORKSPACE_ROOT
68
+ }
69
+
70
+ return "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\workspaces"
71
+ }
72
+
73
+ function Resolve-DatabasePath {
74
+ if ($DatabasePath) {
75
+ return $DatabasePath
76
+ }
77
+
78
+ if ($env:DB_PATH) {
79
+ return $env:DB_PATH
80
+ }
81
+
82
+ return "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\data\\database.db"
83
+ }
84
+
85
+ function Resolve-CacheRoot {
86
+ if ($CacheRoot) {
87
+ return $CacheRoot
88
+ }
89
+
90
+ if ($env:CACHE_ROOT) {
91
+ return $env:CACHE_ROOT
92
+ }
93
+
94
+ return "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\cache"
95
+ }
96
+
97
+ function Resolve-AuditLogPath {
98
+ if ($AuditLogPath) {
99
+ return $AuditLogPath
100
+ }
101
+
102
+ if ($env:AUDIT_LOG_PATH) {
103
+ return $env:AUDIT_LOG_PATH
104
+ }
105
+
106
+ return "$env:USERPROFILE\\.windows-exe-decompiler-mcp-server\\audit.log"
107
+ }
108
+
109
+ function Backup-FileIfNeeded {
110
+ param([Parameter(Mandatory = $true)][string]$PathValue)
111
+
112
+ if ($NoBackup -or -not (Test-Path -Path $PathValue)) {
113
+ return $null
114
+ }
115
+
116
+ $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
117
+ $backupPath = "$PathValue.$timestamp.bak"
118
+ Copy-Item -Path $PathValue -Destination $backupPath -Force
119
+ return $backupPath
120
+ }
121
+
122
+ function Ensure-ParentDirectory {
123
+ param([Parameter(Mandatory = $true)][string]$PathValue)
124
+
125
+ $parent = Split-Path -Path $PathValue -Parent
126
+ if ($parent -and -not (Test-Path -Path $parent)) {
127
+ New-Item -Path $parent -ItemType Directory -Force | Out-Null
128
+ }
129
+ }
130
+
131
+ function Build-ServerBlock {
132
+ param(
133
+ [Parameter(Mandatory = $true)][string]$NodeExecutableConfig,
134
+ [Parameter(Mandatory = $true)][string]$EntryPathConfig,
135
+ [Parameter(Mandatory = $true)][string]$ProjectRootConfig,
136
+ [Parameter(Mandatory = $true)][string]$WorkspaceRootConfig,
137
+ [Parameter(Mandatory = $true)][string]$DatabasePathConfig,
138
+ [Parameter(Mandatory = $true)][string]$CacheRootConfig,
139
+ [Parameter(Mandatory = $true)][string]$AuditLogPathConfig,
140
+ [string]$GhidraPathConfig
141
+ )
142
+
143
+ $lines = @(
144
+ "[mcp_servers.$ServerName]"
145
+ "command = `"$NodeExecutableConfig`""
146
+ "args = [`"$EntryPathConfig`"]"
147
+ "cwd = `"$ProjectRootConfig`""
148
+ "startup_timeout_sec = 30"
149
+ "tool_timeout_sec = 300"
150
+ "enabled = true"
151
+ )
152
+
153
+ $envEntries = @(
154
+ "WORKSPACE_ROOT = `"$WorkspaceRootConfig`"",
155
+ "DB_PATH = `"$DatabasePathConfig`"",
156
+ "CACHE_ROOT = `"$CacheRootConfig`"",
157
+ "AUDIT_LOG_PATH = `"$AuditLogPathConfig`""
158
+ )
159
+
160
+ if ($GhidraPathConfig) {
161
+ $envEntries += "GHIDRA_PATH = `"$GhidraPathConfig`""
162
+ $envEntries += "GHIDRA_INSTALL_DIR = `"$GhidraPathConfig`""
163
+ }
164
+
165
+ $lines += "env = { $($envEntries -join ', ') }"
166
+
167
+ return ($lines -join [Environment]::NewLine)
168
+ }
169
+
170
+ function Upsert-ConfigBlock {
171
+ param(
172
+ [Parameter(Mandatory = $true)][string]$PathValue,
173
+ [Parameter(Mandatory = $true)][string]$BlockText
174
+ )
175
+
176
+ Ensure-ParentDirectory -PathValue $PathValue
177
+
178
+ $existing = ""
179
+ if (Test-Path -Path $PathValue) {
180
+ $existing = Get-Content -Path $PathValue -Raw
181
+ }
182
+
183
+ $pattern = "(?ms)^\[mcp_servers\.$([regex]::Escape($ServerName))\]\r?\n.*?(?=^\[|\z)"
184
+ if ($existing -match $pattern) {
185
+ $updated = [regex]::Replace($existing, $pattern, $BlockText + [Environment]::NewLine)
186
+ } else {
187
+ $separator = if ([string]::IsNullOrWhiteSpace($existing)) { "" } else { [Environment]::NewLine + [Environment]::NewLine }
188
+ $updated = $existing.TrimEnd() + $separator + $BlockText + [Environment]::NewLine
189
+ }
190
+
191
+ [System.IO.File]::WriteAllText($PathValue, $updated, [System.Text.UTF8Encoding]::new($false))
192
+ }
193
+
194
+ Write-Host "=== Windows EXE Decompiler MCP Server - Codex Install ===" -ForegroundColor Cyan
195
+
196
+ Write-Step "Step 1: Validate build output"
197
+ $projectRootFull = [System.IO.Path]::GetFullPath($ProjectRoot)
198
+ $entryPath = Join-Path -Path $projectRootFull -ChildPath "dist/index.js"
199
+ if (-not (Test-Path -Path $entryPath)) {
200
+ throw "dist/index.js was not found. Run 'npm run build' from the project root first."
201
+ }
202
+
203
+ $nodeExecutable = Get-NodeExecutable
204
+ $ghidraPathResolved = Resolve-GhidraPath
205
+ $workspaceRootResolved = Resolve-WorkspaceRoot
206
+ $databasePathResolved = Resolve-DatabasePath
207
+ $cacheRootResolved = Resolve-CacheRoot
208
+ $auditLogPathResolved = Resolve-AuditLogPath
209
+
210
+ $nodeExecutableConfig = Convert-ToConfigPath -PathValue $nodeExecutable
211
+ $entryPathConfig = Convert-ToConfigPath -PathValue $entryPath
212
+ $projectRootConfig = Convert-ToConfigPath -PathValue $projectRootFull
213
+ $ghidraPathConfig = if ($ghidraPathResolved) { Convert-ToConfigPath -PathValue $ghidraPathResolved } else { "" }
214
+ $workspaceRootConfig = Convert-ToConfigPath -PathValue $workspaceRootResolved
215
+ $databasePathConfig = Convert-ToConfigPath -PathValue $databasePathResolved
216
+ $cacheRootConfig = Convert-ToConfigPath -PathValue $cacheRootResolved
217
+ $auditLogPathConfig = Convert-ToConfigPath -PathValue $auditLogPathResolved
218
+
219
+ Write-Host "Project root: $projectRootConfig" -ForegroundColor Gray
220
+ Write-Host "Node path: $nodeExecutableConfig" -ForegroundColor Gray
221
+ Write-Host "Server entry: $entryPathConfig" -ForegroundColor Gray
222
+ Write-Host "Workspace root: $workspaceRootConfig" -ForegroundColor Gray
223
+ Write-Host "Database path: $databasePathConfig" -ForegroundColor Gray
224
+ Write-Host "Cache root: $cacheRootConfig" -ForegroundColor Gray
225
+ Write-Host "Audit log path: $auditLogPathConfig" -ForegroundColor Gray
226
+ if ($ghidraPathConfig) {
227
+ Write-Host "Ghidra path: $ghidraPathConfig" -ForegroundColor Gray
228
+ } else {
229
+ Write-Host "No Ghidra path supplied. The config will be written without GHIDRA_PATH." -ForegroundColor Yellow
230
+ }
231
+
232
+ Write-Step "Step 2: Register MCP server with Codex"
233
+ & codex mcp add $ServerName -- $nodeExecutableConfig $entryPathConfig
234
+ if ($LASTEXITCODE -ne 0) {
235
+ throw "codex mcp add failed."
236
+ }
237
+ Write-Host "Codex registration completed." -ForegroundColor Green
238
+
239
+ Write-Step "Step 3: Update Codex config"
240
+ $backupPath = Backup-FileIfNeeded -PathValue $ConfigPath
241
+ $serverBlock = Build-ServerBlock -NodeExecutableConfig $nodeExecutableConfig -EntryPathConfig $entryPathConfig -ProjectRootConfig $projectRootConfig -WorkspaceRootConfig $workspaceRootConfig -DatabasePathConfig $databasePathConfig -CacheRootConfig $cacheRootConfig -AuditLogPathConfig $auditLogPathConfig -GhidraPathConfig $ghidraPathConfig
242
+ Upsert-ConfigBlock -PathValue $ConfigPath -BlockText $serverBlock
243
+ Write-Host "Config written: $ConfigPath" -ForegroundColor Green
244
+ if ($backupPath) {
245
+ Write-Host "Backup file: $backupPath" -ForegroundColor Gray
246
+ }
247
+
248
+ Write-Step "Step 4: Verify installation"
249
+ & codex mcp list
250
+
251
+ Write-Step "Next steps"
252
+ Write-Host "1. Restart Codex if it was already running." -ForegroundColor White
253
+ Write-Host "2. Ask Codex to call 'tool.help' or 'workflow.triage'." -ForegroundColor White
254
+ Write-Host "3. If native analysis is needed, pass -GhidraPath or set GHIDRA_PATH." -ForegroundColor White
255
+ Write-Host ""
256
+ Write-Host "Installation complete." -ForegroundColor Green