windows-exe-decompiler-mcp-server 0.1.0

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 (190) hide show
  1. package/CODEX_INSTALLATION.md +69 -0
  2. package/COPILOT_INSTALLATION.md +77 -0
  3. package/LICENSE +21 -0
  4. package/README.md +314 -0
  5. package/bin/windows-exe-decompiler-mcp-server.js +3 -0
  6. package/dist/analysis-provenance.d.ts +184 -0
  7. package/dist/analysis-provenance.js +74 -0
  8. package/dist/analysis-task-runner.d.ts +31 -0
  9. package/dist/analysis-task-runner.js +160 -0
  10. package/dist/artifact-inventory.d.ts +23 -0
  11. package/dist/artifact-inventory.js +175 -0
  12. package/dist/cache-manager.d.ts +128 -0
  13. package/dist/cache-manager.js +454 -0
  14. package/dist/confidence-semantics.d.ts +66 -0
  15. package/dist/confidence-semantics.js +122 -0
  16. package/dist/config.d.ts +335 -0
  17. package/dist/config.js +193 -0
  18. package/dist/database.d.ts +227 -0
  19. package/dist/database.js +601 -0
  20. package/dist/decompiler-worker.d.ts +441 -0
  21. package/dist/decompiler-worker.js +1962 -0
  22. package/dist/dynamic-trace.d.ts +95 -0
  23. package/dist/dynamic-trace.js +629 -0
  24. package/dist/env-validator.d.ts +15 -0
  25. package/dist/env-validator.js +249 -0
  26. package/dist/error-handler.d.ts +28 -0
  27. package/dist/error-handler.example.d.ts +22 -0
  28. package/dist/error-handler.example.js +141 -0
  29. package/dist/error-handler.js +139 -0
  30. package/dist/ghidra-analysis-status.d.ts +49 -0
  31. package/dist/ghidra-analysis-status.js +178 -0
  32. package/dist/ghidra-config.d.ts +134 -0
  33. package/dist/ghidra-config.js +464 -0
  34. package/dist/index.d.ts +9 -0
  35. package/dist/index.js +200 -0
  36. package/dist/job-queue.d.ts +169 -0
  37. package/dist/job-queue.js +407 -0
  38. package/dist/logger.d.ts +106 -0
  39. package/dist/logger.js +176 -0
  40. package/dist/policy-guard.d.ts +115 -0
  41. package/dist/policy-guard.js +243 -0
  42. package/dist/process-output.d.ts +15 -0
  43. package/dist/process-output.js +90 -0
  44. package/dist/prompts/function-explanation-review.d.ts +5 -0
  45. package/dist/prompts/function-explanation-review.js +64 -0
  46. package/dist/prompts/semantic-name-review.d.ts +5 -0
  47. package/dist/prompts/semantic-name-review.js +63 -0
  48. package/dist/runtime-correlation.d.ts +34 -0
  49. package/dist/runtime-correlation.js +279 -0
  50. package/dist/runtime-paths.d.ts +3 -0
  51. package/dist/runtime-paths.js +11 -0
  52. package/dist/selection-diff.d.ts +667 -0
  53. package/dist/selection-diff.js +53 -0
  54. package/dist/semantic-name-suggestion-artifacts.d.ts +116 -0
  55. package/dist/semantic-name-suggestion-artifacts.js +314 -0
  56. package/dist/server.d.ts +129 -0
  57. package/dist/server.js +578 -0
  58. package/dist/tools/artifact-read.d.ts +235 -0
  59. package/dist/tools/artifact-read.js +317 -0
  60. package/dist/tools/artifacts-diff.d.ts +728 -0
  61. package/dist/tools/artifacts-diff.js +304 -0
  62. package/dist/tools/artifacts-list.d.ts +515 -0
  63. package/dist/tools/artifacts-list.js +389 -0
  64. package/dist/tools/attack-map.d.ts +290 -0
  65. package/dist/tools/attack-map.js +519 -0
  66. package/dist/tools/cache-observability.d.ts +4 -0
  67. package/dist/tools/cache-observability.js +36 -0
  68. package/dist/tools/code-function-cfg.d.ts +50 -0
  69. package/dist/tools/code-function-cfg.js +102 -0
  70. package/dist/tools/code-function-decompile.d.ts +55 -0
  71. package/dist/tools/code-function-decompile.js +103 -0
  72. package/dist/tools/code-function-disassemble.d.ts +43 -0
  73. package/dist/tools/code-function-disassemble.js +185 -0
  74. package/dist/tools/code-function-explain-apply.d.ts +255 -0
  75. package/dist/tools/code-function-explain-apply.js +225 -0
  76. package/dist/tools/code-function-explain-prepare.d.ts +535 -0
  77. package/dist/tools/code-function-explain-prepare.js +276 -0
  78. package/dist/tools/code-function-explain-review.d.ts +397 -0
  79. package/dist/tools/code-function-explain-review.js +589 -0
  80. package/dist/tools/code-function-rename-apply.d.ts +248 -0
  81. package/dist/tools/code-function-rename-apply.js +220 -0
  82. package/dist/tools/code-function-rename-prepare.d.ts +506 -0
  83. package/dist/tools/code-function-rename-prepare.js +279 -0
  84. package/dist/tools/code-function-rename-review.d.ts +574 -0
  85. package/dist/tools/code-function-rename-review.js +761 -0
  86. package/dist/tools/code-functions-list.d.ts +37 -0
  87. package/dist/tools/code-functions-list.js +91 -0
  88. package/dist/tools/code-functions-rank.d.ts +34 -0
  89. package/dist/tools/code-functions-rank.js +90 -0
  90. package/dist/tools/code-functions-reconstruct.d.ts +2725 -0
  91. package/dist/tools/code-functions-reconstruct.js +2807 -0
  92. package/dist/tools/code-functions-search.d.ts +39 -0
  93. package/dist/tools/code-functions-search.js +90 -0
  94. package/dist/tools/code-reconstruct-export.d.ts +1212 -0
  95. package/dist/tools/code-reconstruct-export.js +4002 -0
  96. package/dist/tools/code-reconstruct-plan.d.ts +274 -0
  97. package/dist/tools/code-reconstruct-plan.js +342 -0
  98. package/dist/tools/dotnet-metadata-extract.d.ts +541 -0
  99. package/dist/tools/dotnet-metadata-extract.js +355 -0
  100. package/dist/tools/dotnet-reconstruct-export.d.ts +567 -0
  101. package/dist/tools/dotnet-reconstruct-export.js +1151 -0
  102. package/dist/tools/dotnet-types-list.d.ts +325 -0
  103. package/dist/tools/dotnet-types-list.js +201 -0
  104. package/dist/tools/dynamic-dependencies.d.ts +115 -0
  105. package/dist/tools/dynamic-dependencies.js +213 -0
  106. package/dist/tools/dynamic-memory-import.d.ts +10 -0
  107. package/dist/tools/dynamic-memory-import.js +567 -0
  108. package/dist/tools/dynamic-trace-import.d.ts +10 -0
  109. package/dist/tools/dynamic-trace-import.js +235 -0
  110. package/dist/tools/entrypoint-fallback-disasm.d.ts +30 -0
  111. package/dist/tools/entrypoint-fallback-disasm.js +89 -0
  112. package/dist/tools/ghidra-analyze.d.ts +88 -0
  113. package/dist/tools/ghidra-analyze.js +208 -0
  114. package/dist/tools/ghidra-health.d.ts +37 -0
  115. package/dist/tools/ghidra-health.js +212 -0
  116. package/dist/tools/ioc-export.d.ts +209 -0
  117. package/dist/tools/ioc-export.js +542 -0
  118. package/dist/tools/packer-detect.d.ts +165 -0
  119. package/dist/tools/packer-detect.js +284 -0
  120. package/dist/tools/pe-exports-extract.d.ts +175 -0
  121. package/dist/tools/pe-exports-extract.js +253 -0
  122. package/dist/tools/pe-fingerprint.d.ts +234 -0
  123. package/dist/tools/pe-fingerprint.js +269 -0
  124. package/dist/tools/pe-imports-extract.d.ts +105 -0
  125. package/dist/tools/pe-imports-extract.js +245 -0
  126. package/dist/tools/report-generate.d.ts +157 -0
  127. package/dist/tools/report-generate.js +457 -0
  128. package/dist/tools/report-summarize.d.ts +2131 -0
  129. package/dist/tools/report-summarize.js +596 -0
  130. package/dist/tools/runtime-detect.d.ts +135 -0
  131. package/dist/tools/runtime-detect.js +247 -0
  132. package/dist/tools/sample-ingest.d.ts +94 -0
  133. package/dist/tools/sample-ingest.js +327 -0
  134. package/dist/tools/sample-profile-get.d.ts +183 -0
  135. package/dist/tools/sample-profile-get.js +121 -0
  136. package/dist/tools/sandbox-execute.d.ts +441 -0
  137. package/dist/tools/sandbox-execute.js +392 -0
  138. package/dist/tools/strings-extract.d.ts +375 -0
  139. package/dist/tools/strings-extract.js +314 -0
  140. package/dist/tools/strings-floss-decode.d.ts +143 -0
  141. package/dist/tools/strings-floss-decode.js +259 -0
  142. package/dist/tools/system-health.d.ts +434 -0
  143. package/dist/tools/system-health.js +446 -0
  144. package/dist/tools/task-cancel.d.ts +21 -0
  145. package/dist/tools/task-cancel.js +70 -0
  146. package/dist/tools/task-status.d.ts +27 -0
  147. package/dist/tools/task-status.js +106 -0
  148. package/dist/tools/task-sweep.d.ts +22 -0
  149. package/dist/tools/task-sweep.js +77 -0
  150. package/dist/tools/tool-help.d.ts +340 -0
  151. package/dist/tools/tool-help.js +261 -0
  152. package/dist/tools/yara-scan.d.ts +554 -0
  153. package/dist/tools/yara-scan.js +313 -0
  154. package/dist/types.d.ts +266 -0
  155. package/dist/types.js +41 -0
  156. package/dist/worker-pool.d.ts +204 -0
  157. package/dist/worker-pool.js +650 -0
  158. package/dist/workflows/deep-static.d.ts +104 -0
  159. package/dist/workflows/deep-static.js +276 -0
  160. package/dist/workflows/function-explanation-review.d.ts +655 -0
  161. package/dist/workflows/function-explanation-review.js +440 -0
  162. package/dist/workflows/reconstruct.d.ts +2053 -0
  163. package/dist/workflows/reconstruct.js +666 -0
  164. package/dist/workflows/semantic-name-review.d.ts +2418 -0
  165. package/dist/workflows/semantic-name-review.js +521 -0
  166. package/dist/workflows/triage.d.ts +659 -0
  167. package/dist/workflows/triage.js +1374 -0
  168. package/dist/workspace-manager.d.ts +150 -0
  169. package/dist/workspace-manager.js +411 -0
  170. package/ghidra_scripts/DecompileFunction.java +487 -0
  171. package/ghidra_scripts/DecompileFunction.py +150 -0
  172. package/ghidra_scripts/ExtractCFG.java +256 -0
  173. package/ghidra_scripts/ExtractCFG.py +233 -0
  174. package/ghidra_scripts/ExtractFunctions.java +442 -0
  175. package/ghidra_scripts/ExtractFunctions.py +101 -0
  176. package/ghidra_scripts/README.md +125 -0
  177. package/ghidra_scripts/SearchFunctionReferences.java +380 -0
  178. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -0
  179. package/helpers/DotNetMetadataProbe/Program.cs +566 -0
  180. package/install-to-codex.ps1 +178 -0
  181. package/install-to-copilot.ps1 +303 -0
  182. package/package.json +101 -0
  183. package/requirements.txt +9 -0
  184. package/workers/requirements-dynamic.txt +11 -0
  185. package/workers/requirements.txt +8 -0
  186. package/workers/speakeasy_compat.py +175 -0
  187. package/workers/static_worker.py +5183 -0
  188. package/workers/yara_rules/default.yar +33 -0
  189. package/workers/yara_rules/malware_families.yar +93 -0
  190. package/workers/yara_rules/packers.yar +80 -0
@@ -0,0 +1,178 @@
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
@@ -0,0 +1,303 @@
1
+ param(
2
+ [string]$ServerName = "windows-exe-decompiler",
3
+ [string]$ProjectRoot = (Get-Location).Path,
4
+ [string]$NodePath,
5
+ [string]$GhidraPath = "",
6
+ [string]$WorkspaceConfigPath,
7
+ [string]$CopilotCliConfigPath,
8
+ [switch]$SkipWorkspaceConfig,
9
+ [switch]$SkipCopilotCliConfig,
10
+ [switch]$InstallVsCodeUserProfile,
11
+ [switch]$NoBackup
12
+ )
13
+
14
+ Set-StrictMode -Version Latest
15
+ $ErrorActionPreference = "Stop"
16
+
17
+ function Write-Step {
18
+ param(
19
+ [string]$Message
20
+ )
21
+
22
+ Write-Host ""
23
+ Write-Host $Message -ForegroundColor Yellow
24
+ }
25
+
26
+ function Convert-ToConfigPath {
27
+ param(
28
+ [Parameter(Mandatory = $true)]
29
+ [string]$PathValue
30
+ )
31
+
32
+ $resolved = [System.IO.Path]::GetFullPath($PathValue)
33
+ return ($resolved -replace "\\", "/")
34
+ }
35
+
36
+ function Ensure-Directory {
37
+ param(
38
+ [Parameter(Mandatory = $true)]
39
+ [string]$FilePath
40
+ )
41
+
42
+ $directory = Split-Path -Path $FilePath -Parent
43
+ if ($directory -and -not (Test-Path -Path $directory)) {
44
+ New-Item -Path $directory -ItemType Directory -Force | Out-Null
45
+ }
46
+ }
47
+
48
+ function Backup-FileIfNeeded {
49
+ param(
50
+ [Parameter(Mandatory = $true)]
51
+ [string]$PathValue
52
+ )
53
+
54
+ if ($NoBackup -or -not (Test-Path -Path $PathValue)) {
55
+ return $null
56
+ }
57
+
58
+ $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
59
+ $backupPath = "$PathValue.$timestamp.bak"
60
+ Copy-Item -Path $PathValue -Destination $backupPath -Force
61
+ return $backupPath
62
+ }
63
+
64
+ function Load-JsonConfig {
65
+ param(
66
+ [Parameter(Mandatory = $true)]
67
+ [string]$PathValue,
68
+
69
+ [Parameter(Mandatory = $true)]
70
+ [string]$RootProperty
71
+ )
72
+
73
+ if (-not (Test-Path -Path $PathValue)) {
74
+ return [pscustomobject]@{
75
+ $RootProperty = [pscustomobject]@{}
76
+ }
77
+ }
78
+
79
+ $raw = Get-Content -Path $PathValue -Raw
80
+ if ([string]::IsNullOrWhiteSpace($raw)) {
81
+ return [pscustomobject]@{
82
+ $RootProperty = [pscustomobject]@{}
83
+ }
84
+ }
85
+
86
+ $config = $raw | ConvertFrom-Json
87
+ if ($null -eq $config) {
88
+ return [pscustomobject]@{
89
+ $RootProperty = [pscustomobject]@{}
90
+ }
91
+ }
92
+
93
+ if (-not ($config.PSObject.Properties.Name -contains $RootProperty)) {
94
+ $config | Add-Member -NotePropertyName $RootProperty -NotePropertyValue ([pscustomobject]@{})
95
+ }
96
+
97
+ return $config
98
+ }
99
+
100
+ function Set-NamedProperty {
101
+ param(
102
+ [Parameter(Mandatory = $true)]
103
+ [object]$Object,
104
+
105
+ [Parameter(Mandatory = $true)]
106
+ [string]$Name,
107
+
108
+ [Parameter(Mandatory = $true)]
109
+ [object]$Value
110
+ )
111
+
112
+ $existingProperty = $Object.PSObject.Properties[$Name]
113
+ if ($null -ne $existingProperty) {
114
+ $Object.$Name = $Value
115
+ return
116
+ }
117
+
118
+ $Object | Add-Member -NotePropertyName $Name -NotePropertyValue $Value
119
+ }
120
+
121
+ function Save-JsonConfig {
122
+ param(
123
+ [Parameter(Mandatory = $true)]
124
+ [string]$PathValue,
125
+
126
+ [Parameter(Mandatory = $true)]
127
+ [object]$Config
128
+ )
129
+
130
+ Ensure-Directory -FilePath $PathValue
131
+ $json = $Config | ConvertTo-Json -Depth 20
132
+ [System.IO.File]::WriteAllText($PathValue, $json + [Environment]::NewLine, [System.Text.UTF8Encoding]::new($false))
133
+ }
134
+
135
+ function Get-NodeExecutable {
136
+ if ($NodePath) {
137
+ if (-not (Test-Path -Path $NodePath)) {
138
+ throw "NodePath does not exist: $NodePath"
139
+ }
140
+
141
+ return [System.IO.Path]::GetFullPath($NodePath)
142
+ }
143
+
144
+ $nodeCommand = Get-Command node -ErrorAction SilentlyContinue
145
+ if ($null -eq $nodeCommand) {
146
+ throw "Node.js is not available in PATH. Install Node.js or pass -NodePath explicitly."
147
+ }
148
+
149
+ return $nodeCommand.Source
150
+ }
151
+
152
+ function Resolve-GhidraPath {
153
+ if ($GhidraPath) {
154
+ return $GhidraPath
155
+ }
156
+
157
+ if ($env:GHIDRA_PATH) {
158
+ return $env:GHIDRA_PATH
159
+ }
160
+
161
+ if ($env:GHIDRA_INSTALL_DIR) {
162
+ return $env:GHIDRA_INSTALL_DIR
163
+ }
164
+
165
+ return ""
166
+ }
167
+
168
+ Write-Host "=== Windows EXE Decompiler MCP Server - GitHub Copilot Install ===" -ForegroundColor Cyan
169
+
170
+ Write-Step "Step 1: Validate build output and runtime"
171
+ $projectRootFull = [System.IO.Path]::GetFullPath($ProjectRoot)
172
+ $distEntry = Join-Path -Path $projectRootFull -ChildPath "dist/index.js"
173
+ if (-not (Test-Path -Path $distEntry)) {
174
+ throw "dist/index.js was not found. Run 'npm run build' from the project root first."
175
+ }
176
+
177
+ $nodeExecutable = Get-NodeExecutable
178
+ $nodeExecutableConfig = Convert-ToConfigPath -PathValue $nodeExecutable
179
+ $distEntryConfig = Convert-ToConfigPath -PathValue $distEntry
180
+ $projectRootConfig = Convert-ToConfigPath -PathValue $projectRootFull
181
+ $ghidraPathResolved = Resolve-GhidraPath
182
+ $ghidraPathExists = $ghidraPathResolved -and (Test-Path -Path $ghidraPathResolved)
183
+ $ghidraPathConfig = if ($ghidraPathResolved) { Convert-ToConfigPath -PathValue $ghidraPathResolved } else { "" }
184
+
185
+ Write-Host "Project root: $projectRootConfig" -ForegroundColor Gray
186
+ Write-Host "Node path: $nodeExecutableConfig" -ForegroundColor Gray
187
+ Write-Host "Server entry: $distEntryConfig" -ForegroundColor Gray
188
+ if ($ghidraPathConfig -and $ghidraPathExists) {
189
+ Write-Host "Ghidra path: $ghidraPathConfig" -ForegroundColor Gray
190
+ } elseif ($ghidraPathConfig) {
191
+ Write-Host "Warning: the Ghidra path does not exist. The script will still write it into the config. Pass -GhidraPath to override it." -ForegroundColor Yellow
192
+ } else {
193
+ Write-Host "No Ghidra path supplied. The config will be written without GHIDRA_PATH." -ForegroundColor Yellow
194
+ }
195
+
196
+ if (-not $WorkspaceConfigPath) {
197
+ $WorkspaceConfigPath = Join-Path -Path $projectRootFull -ChildPath ".vscode/mcp.json"
198
+ }
199
+
200
+ if (-not $CopilotCliConfigPath) {
201
+ $copilotConfigRoot = if ($env:XDG_CONFIG_HOME) {
202
+ Join-Path -Path $env:XDG_CONFIG_HOME -ChildPath "copilot"
203
+ } else {
204
+ Join-Path -Path $HOME -ChildPath ".copilot"
205
+ }
206
+
207
+ $CopilotCliConfigPath = Join-Path -Path $copilotConfigRoot -ChildPath "mcp-config.json"
208
+ }
209
+
210
+ $workspaceServerConfig = [ordered]@{
211
+ type = "stdio"
212
+ command = $nodeExecutableConfig
213
+ args = @($distEntryConfig)
214
+ }
215
+
216
+ if ($ghidraPathConfig) {
217
+ $workspaceServerConfig.env = [ordered]@{
218
+ GHIDRA_PATH = $ghidraPathConfig
219
+ GHIDRA_INSTALL_DIR = $ghidraPathConfig
220
+ }
221
+ }
222
+
223
+ $copilotCliServerConfig = [ordered]@{
224
+ type = "local"
225
+ command = $nodeExecutableConfig
226
+ args = @($distEntryConfig)
227
+ cwd = $projectRootConfig
228
+ tools = @("*")
229
+ timeout = 300000
230
+ }
231
+
232
+ if ($ghidraPathConfig) {
233
+ $copilotCliServerConfig.env = [ordered]@{
234
+ GHIDRA_PATH = $ghidraPathConfig
235
+ GHIDRA_INSTALL_DIR = $ghidraPathConfig
236
+ }
237
+ }
238
+
239
+ if (-not $SkipWorkspaceConfig) {
240
+ Write-Step "Step 2: Write workspace GitHub Copilot / VS Code MCP config"
241
+ $workspaceBackup = Backup-FileIfNeeded -PathValue $WorkspaceConfigPath
242
+ $workspaceConfig = Load-JsonConfig -PathValue $WorkspaceConfigPath -RootProperty "servers"
243
+ Set-NamedProperty -Object $workspaceConfig.servers -Name $ServerName -Value $workspaceServerConfig
244
+ Save-JsonConfig -PathValue $WorkspaceConfigPath -Config $workspaceConfig
245
+
246
+ Write-Host "Workspace config written: $WorkspaceConfigPath" -ForegroundColor Green
247
+ if ($workspaceBackup) {
248
+ Write-Host "Backup file: $workspaceBackup" -ForegroundColor Gray
249
+ }
250
+ }
251
+
252
+ if (-not $SkipCopilotCliConfig) {
253
+ Write-Step "Step 3: Write GitHub Copilot CLI MCP config"
254
+ $cliBackup = Backup-FileIfNeeded -PathValue $CopilotCliConfigPath
255
+ $cliConfig = Load-JsonConfig -PathValue $CopilotCliConfigPath -RootProperty "mcpServers"
256
+ Set-NamedProperty -Object $cliConfig.mcpServers -Name $ServerName -Value $copilotCliServerConfig
257
+ Save-JsonConfig -PathValue $CopilotCliConfigPath -Config $cliConfig
258
+
259
+ Write-Host "CLI config written: $CopilotCliConfigPath" -ForegroundColor Green
260
+ if ($cliBackup) {
261
+ Write-Host "Backup file: $cliBackup" -ForegroundColor Gray
262
+ }
263
+ }
264
+
265
+ if ($InstallVsCodeUserProfile) {
266
+ Write-Step "Step 4: Try to install into the VS Code user-level MCP config"
267
+ $codeCommand = Get-Command code -ErrorAction SilentlyContinue
268
+ if ($null -eq $codeCommand) {
269
+ Write-Host "Warning: the 'code' command was not found. Skipping user-level VS Code installation." -ForegroundColor Yellow
270
+ } else {
271
+ $userProfilePayload = [pscustomobject]@{
272
+ name = $ServerName
273
+ type = "stdio"
274
+ command = $nodeExecutableConfig
275
+ args = @($distEntryConfig)
276
+ } | ConvertTo-Json -Depth 10 -Compress
277
+
278
+ if ($ghidraPathConfig) {
279
+ $userProfilePayload = [pscustomobject]@{
280
+ name = $ServerName
281
+ type = "stdio"
282
+ command = $nodeExecutableConfig
283
+ args = @($distEntryConfig)
284
+ env = [pscustomobject]@{
285
+ GHIDRA_PATH = $ghidraPathConfig
286
+ GHIDRA_INSTALL_DIR = $ghidraPathConfig
287
+ }
288
+ } | ConvertTo-Json -Depth 10 -Compress
289
+ }
290
+
291
+ & $codeCommand.Source --add-mcp $userProfilePayload
292
+ Write-Host "VS Code --add-mcp was invoked successfully." -ForegroundColor Green
293
+ }
294
+ }
295
+
296
+ Write-Step "Step 5: What to do next"
297
+ Write-Host "1. VS Code / GitHub Copilot Chat:" -ForegroundColor Cyan
298
+ Write-Host " Open this workspace. Copilot will read .vscode/mcp.json. Trust the MCP server when VS Code prompts you." -ForegroundColor White
299
+ Write-Host "2. GitHub Copilot CLI:" -ForegroundColor Cyan
300
+ Write-Host " Start 'copilot' and run '/mcp list' or '/mcp show $ServerName'." -ForegroundColor White
301
+ Write-Host "3. Use -SkipWorkspaceConfig or -SkipCopilotCliConfig if you only want to update one target." -ForegroundColor White
302
+ Write-Host ""
303
+ Write-Host "Installation complete." -ForegroundColor Green
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "windows-exe-decompiler-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Windows binary reverse engineering, PE triage, Ghidra-assisted analysis, and reconstruction workflows.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "windows-exe-decompiler-mcp-server": "./bin/windows-exe-decompiler-mcp-server.js"
10
+ },
11
+ "exports": {
12
+ ".": "./dist/index.js"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "dist/**/*.js",
17
+ "dist/**/*.d.ts",
18
+ "workers/static_worker.py",
19
+ "workers/speakeasy_compat.py",
20
+ "workers/requirements.txt",
21
+ "workers/requirements-dynamic.txt",
22
+ "workers/yara_rules/*.yar",
23
+ "ghidra_scripts/*.java",
24
+ "ghidra_scripts/*.py",
25
+ "ghidra_scripts/README.md",
26
+ "helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj",
27
+ "helpers/DotNetMetadataProbe/Program.cs",
28
+ "requirements.txt",
29
+ "install-to-codex.ps1",
30
+ "install-to-copilot.ps1",
31
+ "CODEX_INSTALLATION.md",
32
+ "COPILOT_INSTALLATION.md"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "clean": "node -e \"const fs=require('fs'); for (const p of ['dist']) { fs.rmSync(p,{recursive:true,force:true}); }\"",
37
+ "dev": "tsx watch src/index.ts",
38
+ "start": "node dist/index.js",
39
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
40
+ "test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch",
41
+ "lint": "eslint src --ext .ts",
42
+ "lint:fix": "eslint src --ext .ts --fix",
43
+ "format": "prettier --write \"src/**/*.ts\"",
44
+ "format:check": "prettier --check \"src/**/*.ts\"",
45
+ "prepack": "npm run build",
46
+ "pack:dry-run": "npm pack --dry-run",
47
+ "release:check": "npm run build && npm pack --dry-run"
48
+ },
49
+ "keywords": [
50
+ "mcp",
51
+ "reverse-engineering",
52
+ "decompiler",
53
+ "pe-analysis",
54
+ "malware-analysis",
55
+ "ghidra",
56
+ "windows",
57
+ "copilot",
58
+ "codex"
59
+ ],
60
+ "author": "",
61
+ "license": "MIT",
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "git+https://github.com/Last-emo-boy/windows-exe-decompiler-mcp-server.git"
65
+ },
66
+ "homepage": "https://github.com/Last-emo-boy/windows-exe-decompiler-mcp-server",
67
+ "bugs": {
68
+ "url": "https://github.com/Last-emo-boy/windows-exe-decompiler-mcp-server/issues"
69
+ },
70
+ "publishConfig": {
71
+ "access": "public"
72
+ },
73
+ "dependencies": {
74
+ "@modelcontextprotocol/sdk": "^1.27.1",
75
+ "better-sqlite3": "^12.6.2",
76
+ "pino": "^10.3.1",
77
+ "pino-pretty": "^13.1.3",
78
+ "uuid": "^13.0.0",
79
+ "zod": "^3.25.76"
80
+ },
81
+ "devDependencies": {
82
+ "@types/better-sqlite3": "^7.6.13",
83
+ "@types/jest": "^30.0.0",
84
+ "@types/node": "^25.3.5",
85
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
86
+ "@typescript-eslint/parser": "^8.56.1",
87
+ "cross-env": "^10.1.0",
88
+ "eslint": "^10.0.3",
89
+ "eslint-config-prettier": "^10.1.8",
90
+ "eslint-plugin-prettier": "^5.5.5",
91
+ "fast-check": "^4.6.0",
92
+ "jest": "^30.2.0",
93
+ "prettier": "^3.8.1",
94
+ "ts-jest": "^29.4.6",
95
+ "tsx": "^4.21.0",
96
+ "typescript": "^5.9.3"
97
+ },
98
+ "engines": {
99
+ "node": ">=18.0.0"
100
+ }
101
+ }
@@ -0,0 +1,9 @@
1
+ # Root Python dependency baseline for the reverse-engineering workers.
2
+ # Latest versions verified on PyPI 2026-03-10.
3
+ # For optional dynamic-analysis tooling, install workers/requirements-dynamic.txt as an extra step.
4
+
5
+ pefile==2024.8.26
6
+ lief==0.17.5
7
+ yara-python==4.5.4
8
+ flare-floss==3.1.1
9
+ dnfile==0.18.0
@@ -0,0 +1,11 @@
1
+ # Optional dynamic-analysis dependencies (install only in isolated lab environments)
2
+ # These are intentionally separated from the static baseline requirements.
3
+ # Latest verified on PyPI 2026-03-10.
4
+ # Note: the PyPI package named `speakeasy` is an unrelated metrics server.
5
+ # Use `speakeasy-emulator`, which provides the `speakeasy` malware-emulation module.
6
+ # Unicorn still imports `pkg_resources`, so keep setuptools below 81 for now.
7
+
8
+ speakeasy-emulator==1.5.11
9
+ setuptools<81
10
+ frida==17.8.0
11
+ psutil==7.2.2
@@ -0,0 +1,8 @@
1
+ # Python worker dependency baseline (root-synced, latest verified on PyPI 2026-03-10)
2
+ pefile==2024.8.26
3
+ lief==0.17.5
4
+ yara-python==4.5.4
5
+ flare-floss==3.1.1
6
+ dnfile==0.18.0
7
+
8
+ # Optional dynamic-analysis stack is maintained in requirements-dynamic.txt