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,53 @@
1
+ import { z } from 'zod';
2
+ import { ArtifactSelectionProvenanceSchema } from './analysis-provenance.js';
3
+ export const ArtifactSelectionDiffSchema = z.object({
4
+ label: z.enum(['runtime', 'semantic_names', 'semantic_explanations']),
5
+ current: ArtifactSelectionProvenanceSchema,
6
+ baseline: ArtifactSelectionProvenanceSchema,
7
+ added_artifact_ids: z.array(z.string()),
8
+ removed_artifact_ids: z.array(z.string()),
9
+ added_session_tags: z.array(z.string()),
10
+ removed_session_tags: z.array(z.string()),
11
+ artifact_count_delta: z.number().int(),
12
+ summary: z.string(),
13
+ });
14
+ export const AnalysisSelectionDiffSchema = z.object({
15
+ runtime: ArtifactSelectionDiffSchema.optional(),
16
+ semantic_names: ArtifactSelectionDiffSchema.optional(),
17
+ semantic_explanations: ArtifactSelectionDiffSchema.optional(),
18
+ });
19
+ function diffStrings(current, baseline) {
20
+ const currentSet = new Set(current);
21
+ const baselineSet = new Set(baseline);
22
+ return {
23
+ added: current.filter((item) => !baselineSet.has(item)),
24
+ removed: baseline.filter((item) => !currentSet.has(item)),
25
+ };
26
+ }
27
+ export function buildArtifactSelectionDiff(label, current, baseline) {
28
+ const artifactDiff = diffStrings(current.artifact_ids, baseline.artifact_ids);
29
+ const sessionDiff = diffStrings(current.session_tags, baseline.session_tags);
30
+ const artifactCountDelta = current.artifact_count - baseline.artifact_count;
31
+ const targetLabel = label === 'runtime'
32
+ ? 'runtime selection'
33
+ : label === 'semantic_names'
34
+ ? 'semantic naming selection'
35
+ : 'semantic explanation selection';
36
+ const summary = `Compared ${targetLabel} against baseline scope=${baseline.scope}` +
37
+ `${baseline.session_selector ? ` selector=${baseline.session_selector}` : ''}: ` +
38
+ `artifact_delta=${artifactCountDelta >= 0 ? '+' : ''}${artifactCountDelta}, ` +
39
+ `added=${artifactDiff.added.length}, removed=${artifactDiff.removed.length}, ` +
40
+ `session_tag_delta=${sessionDiff.added.length}/${sessionDiff.removed.length}.`;
41
+ return {
42
+ label,
43
+ current,
44
+ baseline,
45
+ added_artifact_ids: artifactDiff.added,
46
+ removed_artifact_ids: artifactDiff.removed,
47
+ added_session_tags: sessionDiff.added,
48
+ removed_session_tags: sessionDiff.removed,
49
+ artifact_count_delta: artifactCountDelta,
50
+ summary,
51
+ };
52
+ }
53
+ //# sourceMappingURL=selection-diff.js.map
@@ -0,0 +1,116 @@
1
+ import type { ArtifactRef } from './types.js';
2
+ import type { WorkspaceManager } from './workspace-manager.js';
3
+ import type { DatabaseManager } from './database.js';
4
+ export declare const SEMANTIC_NAME_SUGGESTIONS_ARTIFACT_TYPE = "semantic_name_suggestions";
5
+ export declare const SEMANTIC_NAME_PREPARE_BUNDLE_ARTIFACT_TYPE = "semantic_name_prepare_bundle";
6
+ export declare const SEMANTIC_EXPLANATION_PREPARE_BUNDLE_ARTIFACT_TYPE = "semantic_explanation_prepare_bundle";
7
+ export declare const SEMANTIC_FUNCTION_EXPLANATIONS_ARTIFACT_TYPE = "semantic_function_explanations";
8
+ export interface SemanticNameSuggestionEntry {
9
+ address?: string | null;
10
+ function?: string | null;
11
+ candidate_name: string;
12
+ normalized_candidate_name?: string | null;
13
+ confidence: number;
14
+ why: string;
15
+ required_assumptions?: string[];
16
+ evidence_used?: string[];
17
+ }
18
+ export interface SemanticNameSuggestionArtifactPayload {
19
+ schema_version: 1;
20
+ sample_id: string;
21
+ created_at: string;
22
+ session_tag?: string | null;
23
+ client_name?: string | null;
24
+ model_name?: string | null;
25
+ prepare_artifact_id?: string | null;
26
+ suggestions: SemanticNameSuggestionEntry[];
27
+ }
28
+ export interface LoadedSemanticNameSuggestion {
29
+ address: string | null;
30
+ function: string | null;
31
+ candidate_name: string;
32
+ normalized_candidate_name: string | null;
33
+ confidence: number;
34
+ why: string;
35
+ required_assumptions: string[];
36
+ evidence_used: string[];
37
+ artifact_id: string;
38
+ created_at: string;
39
+ client_name: string | null;
40
+ model_name: string | null;
41
+ session_tag: string | null;
42
+ prepare_artifact_id: string | null;
43
+ }
44
+ export interface SemanticNameSuggestionIndex {
45
+ byAddress: Map<string, LoadedSemanticNameSuggestion>;
46
+ byFunction: Map<string, LoadedSemanticNameSuggestion>;
47
+ marker: string;
48
+ artifact_ids: string[];
49
+ session_tags: string[];
50
+ earliest_created_at: string | null;
51
+ latest_created_at: string | null;
52
+ scope_note: string;
53
+ }
54
+ export type SemanticArtifactScope = 'all' | 'latest' | 'session';
55
+ export interface LoadSemanticArtifactOptions {
56
+ scope?: SemanticArtifactScope;
57
+ sessionTag?: string;
58
+ }
59
+ export interface SemanticFunctionExplanationEntry {
60
+ address?: string | null;
61
+ function?: string | null;
62
+ summary: string;
63
+ behavior: string;
64
+ confidence: number;
65
+ assumptions?: string[];
66
+ evidence_used?: string[];
67
+ rewrite_guidance?: string[];
68
+ }
69
+ export interface SemanticFunctionExplanationArtifactPayload {
70
+ schema_version: 1;
71
+ sample_id: string;
72
+ created_at: string;
73
+ session_tag?: string | null;
74
+ client_name?: string | null;
75
+ model_name?: string | null;
76
+ prepare_artifact_id?: string | null;
77
+ explanations: SemanticFunctionExplanationEntry[];
78
+ }
79
+ export interface LoadedSemanticFunctionExplanation {
80
+ address: string | null;
81
+ function: string | null;
82
+ summary: string;
83
+ behavior: string;
84
+ confidence: number;
85
+ assumptions: string[];
86
+ evidence_used: string[];
87
+ rewrite_guidance: string[];
88
+ artifact_id: string;
89
+ created_at: string;
90
+ client_name: string | null;
91
+ model_name: string | null;
92
+ session_tag: string | null;
93
+ prepare_artifact_id: string | null;
94
+ }
95
+ export interface SemanticFunctionExplanationIndex {
96
+ byAddress: Map<string, LoadedSemanticFunctionExplanation>;
97
+ byFunction: Map<string, LoadedSemanticFunctionExplanation>;
98
+ marker: string;
99
+ artifact_ids: string[];
100
+ session_tags: string[];
101
+ earliest_created_at: string | null;
102
+ latest_created_at: string | null;
103
+ scope_note: string;
104
+ }
105
+ export declare function normalizeFunctionKey(value: string | null | undefined): string | null;
106
+ export declare function normalizeAddressKey(value: string | null | undefined): string | null;
107
+ export declare function sanitizeSemanticName(value: string | null | undefined): string | null;
108
+ export declare function persistSemanticNamePrepareBundleArtifact(workspaceManager: WorkspaceManager, database: DatabaseManager, sampleId: string, payload: unknown, sessionTag?: string | null): Promise<ArtifactRef>;
109
+ export declare function persistSemanticExplanationPrepareBundleArtifact(workspaceManager: WorkspaceManager, database: DatabaseManager, sampleId: string, payload: unknown, sessionTag?: string | null): Promise<ArtifactRef>;
110
+ export declare function persistSemanticFunctionExplanationsArtifact(workspaceManager: WorkspaceManager, database: DatabaseManager, payload: SemanticFunctionExplanationArtifactPayload): Promise<ArtifactRef>;
111
+ export declare function persistSemanticNameSuggestionsArtifact(workspaceManager: WorkspaceManager, database: DatabaseManager, payload: SemanticNameSuggestionArtifactPayload): Promise<ArtifactRef>;
112
+ export declare function loadSemanticNameSuggestionIndex(workspaceManager: WorkspaceManager, database: DatabaseManager, sampleId: string, options?: LoadSemanticArtifactOptions): Promise<SemanticNameSuggestionIndex>;
113
+ export declare function loadSemanticFunctionExplanationIndex(workspaceManager: WorkspaceManager, database: DatabaseManager, sampleId: string, options?: LoadSemanticArtifactOptions): Promise<SemanticFunctionExplanationIndex>;
114
+ export declare function findSemanticNameSuggestion(index: SemanticNameSuggestionIndex | null | undefined, address: string | null | undefined, funcName: string | null | undefined): LoadedSemanticNameSuggestion | null;
115
+ export declare function findSemanticFunctionExplanation(index: SemanticFunctionExplanationIndex | null | undefined, address: string | null | undefined, funcName: string | null | undefined): LoadedSemanticFunctionExplanation | null;
116
+ //# sourceMappingURL=semantic-name-suggestion-artifacts.d.ts.map
@@ -0,0 +1,314 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { createHash, randomUUID } from 'crypto';
4
+ import { deriveArtifactSessionTag } from './artifact-inventory.js';
5
+ export const SEMANTIC_NAME_SUGGESTIONS_ARTIFACT_TYPE = 'semantic_name_suggestions';
6
+ export const SEMANTIC_NAME_PREPARE_BUNDLE_ARTIFACT_TYPE = 'semantic_name_prepare_bundle';
7
+ export const SEMANTIC_EXPLANATION_PREPARE_BUNDLE_ARTIFACT_TYPE = 'semantic_explanation_prepare_bundle';
8
+ export const SEMANTIC_FUNCTION_EXPLANATIONS_ARTIFACT_TYPE = 'semantic_function_explanations';
9
+ const LATEST_SEMANTIC_ARTIFACT_WINDOW_MS = 10 * 1000;
10
+ function sanitizePathSegment(value, fallback) {
11
+ const normalized = (value || fallback)
12
+ .trim()
13
+ .toLowerCase()
14
+ .replace(/[^a-z0-9._-]+/g, '_')
15
+ .replace(/^_+|_+$/g, '');
16
+ return normalized.length > 0 ? normalized.slice(0, 64) : fallback;
17
+ }
18
+ export function normalizeFunctionKey(value) {
19
+ if (!value) {
20
+ return null;
21
+ }
22
+ const normalized = value.trim().toLowerCase();
23
+ return normalized.length > 0 ? normalized : null;
24
+ }
25
+ export function normalizeAddressKey(value) {
26
+ if (!value) {
27
+ return null;
28
+ }
29
+ const normalized = value.trim().replace(/^0x/i, '').toLowerCase();
30
+ return normalized.length > 0 ? normalized : null;
31
+ }
32
+ export function sanitizeSemanticName(value) {
33
+ if (!value) {
34
+ return null;
35
+ }
36
+ const collapsed = value
37
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
38
+ .replace(/[^A-Za-z0-9]+/g, '_')
39
+ .replace(/^_+|_+$/g, '')
40
+ .toLowerCase();
41
+ if (!collapsed) {
42
+ return null;
43
+ }
44
+ if (/^[0-9]/.test(collapsed)) {
45
+ return `fn_${collapsed}`;
46
+ }
47
+ return collapsed;
48
+ }
49
+ async function persistSemanticNamingJsonArtifact(workspaceManager, database, sampleId, artifactType, filePrefix, payload, sessionTag) {
50
+ const workspace = await workspaceManager.createWorkspace(sampleId);
51
+ const sessionSegment = sanitizePathSegment(sessionTag || undefined, 'default');
52
+ const reportDir = path.join(workspace.reports, 'semantic_naming', sessionSegment);
53
+ await fs.mkdir(reportDir, { recursive: true });
54
+ const fileName = `${filePrefix}_${Date.now()}.json`;
55
+ const absolutePath = path.join(reportDir, fileName);
56
+ const serialized = JSON.stringify(payload, null, 2);
57
+ await fs.writeFile(absolutePath, serialized, 'utf-8');
58
+ const artifactId = randomUUID();
59
+ const artifactSha256 = createHash('sha256').update(serialized).digest('hex');
60
+ const relativePath = path.relative(workspace.root, absolutePath).replace(/\\/g, '/');
61
+ const createdAt = new Date().toISOString();
62
+ database.insertArtifact({
63
+ id: artifactId,
64
+ sample_id: sampleId,
65
+ type: artifactType,
66
+ path: relativePath,
67
+ sha256: artifactSha256,
68
+ mime: 'application/json',
69
+ created_at: createdAt,
70
+ });
71
+ return {
72
+ id: artifactId,
73
+ type: artifactType,
74
+ path: relativePath,
75
+ sha256: artifactSha256,
76
+ mime: 'application/json',
77
+ };
78
+ }
79
+ export async function persistSemanticNamePrepareBundleArtifact(workspaceManager, database, sampleId, payload, sessionTag) {
80
+ return persistSemanticNamingJsonArtifact(workspaceManager, database, sampleId, SEMANTIC_NAME_PREPARE_BUNDLE_ARTIFACT_TYPE, 'prepare_bundle', payload, sessionTag);
81
+ }
82
+ export async function persistSemanticExplanationPrepareBundleArtifact(workspaceManager, database, sampleId, payload, sessionTag) {
83
+ return persistSemanticNamingJsonArtifact(workspaceManager, database, sampleId, SEMANTIC_EXPLANATION_PREPARE_BUNDLE_ARTIFACT_TYPE, 'explain_bundle', payload, sessionTag);
84
+ }
85
+ export async function persistSemanticFunctionExplanationsArtifact(workspaceManager, database, payload) {
86
+ return persistSemanticNamingJsonArtifact(workspaceManager, database, payload.sample_id, SEMANTIC_FUNCTION_EXPLANATIONS_ARTIFACT_TYPE, 'semantic_function_explanations', payload, payload.session_tag);
87
+ }
88
+ export async function persistSemanticNameSuggestionsArtifact(workspaceManager, database, payload) {
89
+ return persistSemanticNamingJsonArtifact(workspaceManager, database, payload.sample_id, SEMANTIC_NAME_SUGGESTIONS_ARTIFACT_TYPE, 'semantic_name_suggestions', payload, payload.session_tag);
90
+ }
91
+ async function readArtifactJson(workspaceManager, database, sampleId, artifactId) {
92
+ const artifact = database.findArtifacts(sampleId).find((item) => item.id === artifactId);
93
+ if (!artifact) {
94
+ return null;
95
+ }
96
+ try {
97
+ const workspace = await workspaceManager.getWorkspace(sampleId);
98
+ const absolutePath = workspaceManager.normalizePath(workspace.root, artifact.path);
99
+ const content = await fs.readFile(absolutePath, 'utf-8');
100
+ return JSON.parse(content);
101
+ }
102
+ catch {
103
+ return null;
104
+ }
105
+ }
106
+ function collectSemanticArtifactSessionTags(artifactPath, payloadSessionTag) {
107
+ const sessionTags = new Set();
108
+ const derivedSessionTag = deriveArtifactSessionTag(artifactPath);
109
+ if (derivedSessionTag) {
110
+ sessionTags.add(derivedSessionTag);
111
+ }
112
+ if (typeof payloadSessionTag === 'string' && payloadSessionTag.trim().length > 0) {
113
+ sessionTags.add(payloadSessionTag.trim());
114
+ }
115
+ const basename = path.basename(artifactPath, path.extname(artifactPath)).trim();
116
+ if (basename.length > 0) {
117
+ sessionTags.add(basename);
118
+ }
119
+ return Array.from(sessionTags);
120
+ }
121
+ function filterSemanticArtifactsByScope(artifacts, options = {}) {
122
+ const scope = options.scope || 'all';
123
+ const normalizedSelector = options.sessionTag?.trim().toLowerCase() || null;
124
+ let selectedArtifacts = artifacts;
125
+ if (normalizedSelector) {
126
+ selectedArtifacts = selectedArtifacts.filter(({ artifact, payload }) => {
127
+ if (artifact.path.toLowerCase().includes(normalizedSelector)) {
128
+ return true;
129
+ }
130
+ return collectSemanticArtifactSessionTags(artifact.path, payload?.session_tag).some((tag) => tag.toLowerCase() === normalizedSelector);
131
+ });
132
+ }
133
+ if (scope === 'latest' && selectedArtifacts.length > 1) {
134
+ const latestTimestamp = selectedArtifacts.reduce((maxValue, { artifact }) => {
135
+ const timestamp = new Date(artifact.created_at).getTime();
136
+ return Number.isFinite(timestamp) && timestamp > maxValue ? timestamp : maxValue;
137
+ }, Number.NEGATIVE_INFINITY);
138
+ if (Number.isFinite(latestTimestamp)) {
139
+ selectedArtifacts = selectedArtifacts.filter(({ artifact }) => {
140
+ const timestamp = new Date(artifact.created_at).getTime();
141
+ return Number.isFinite(timestamp) && latestTimestamp - timestamp <= LATEST_SEMANTIC_ARTIFACT_WINDOW_MS;
142
+ });
143
+ }
144
+ }
145
+ return selectedArtifacts;
146
+ }
147
+ export async function loadSemanticNameSuggestionIndex(workspaceManager, database, sampleId, options = {}) {
148
+ const byAddress = new Map();
149
+ const byFunction = new Map();
150
+ const artifacts = database.findArtifactsByType(sampleId, SEMANTIC_NAME_SUGGESTIONS_ARTIFACT_TYPE);
151
+ const loadedArtifacts = [];
152
+ for (const artifact of artifacts) {
153
+ const payload = (await readArtifactJson(workspaceManager, database, sampleId, artifact.id));
154
+ loadedArtifacts.push({ artifact, payload });
155
+ }
156
+ const filteredArtifacts = filterSemanticArtifactsByScope(loadedArtifacts, options);
157
+ for (const { artifact, payload } of filteredArtifacts) {
158
+ if (!payload || !Array.isArray(payload.suggestions)) {
159
+ continue;
160
+ }
161
+ for (const suggestion of payload.suggestions) {
162
+ const normalizedCandidateName = suggestion.normalized_candidate_name || sanitizeSemanticName(suggestion.candidate_name);
163
+ const loaded = {
164
+ address: suggestion.address || null,
165
+ function: suggestion.function || null,
166
+ candidate_name: suggestion.candidate_name,
167
+ normalized_candidate_name: normalizedCandidateName,
168
+ confidence: suggestion.confidence,
169
+ why: suggestion.why,
170
+ required_assumptions: suggestion.required_assumptions || [],
171
+ evidence_used: suggestion.evidence_used || [],
172
+ artifact_id: artifact.id,
173
+ created_at: artifact.created_at,
174
+ client_name: payload.client_name || null,
175
+ model_name: payload.model_name || null,
176
+ session_tag: payload.session_tag || null,
177
+ prepare_artifact_id: payload.prepare_artifact_id || null,
178
+ };
179
+ const addressKey = normalizeAddressKey(suggestion.address);
180
+ if (addressKey && !byAddress.has(addressKey)) {
181
+ byAddress.set(addressKey, loaded);
182
+ }
183
+ const functionKey = normalizeFunctionKey(suggestion.function);
184
+ if (functionKey && !byFunction.has(functionKey)) {
185
+ byFunction.set(functionKey, loaded);
186
+ }
187
+ }
188
+ }
189
+ return {
190
+ byAddress,
191
+ byFunction,
192
+ marker: filteredArtifacts.length > 0
193
+ ? filteredArtifacts.map(({ artifact }) => `${artifact.id}:${artifact.sha256}`).join('|')
194
+ : 'none',
195
+ artifact_ids: filteredArtifacts.map(({ artifact }) => artifact.id),
196
+ session_tags: Array.from(new Set(filteredArtifacts.flatMap(({ artifact, payload }) => collectSemanticArtifactSessionTags(artifact.path, payload?.session_tag)))),
197
+ earliest_created_at: filteredArtifacts.length > 0
198
+ ? filteredArtifacts
199
+ .map(({ artifact }) => artifact.created_at)
200
+ .filter((item) => typeof item === 'string' && item.length > 0)
201
+ .sort()[0] || null
202
+ : null,
203
+ latest_created_at: filteredArtifacts.length > 0
204
+ ? filteredArtifacts
205
+ .map(({ artifact }) => artifact.created_at)
206
+ .filter((item) => typeof item === 'string' && item.length > 0)
207
+ .sort()
208
+ .slice(-1)[0] || null
209
+ : null,
210
+ scope_note: options.scope === 'session' && options.sessionTag?.trim()
211
+ ? `Semantic naming artifacts are limited to session selector "${options.sessionTag.trim()}".`
212
+ : options.scope === 'latest'
213
+ ? 'Semantic naming artifacts are limited to the latest artifact window.'
214
+ : 'Semantic naming artifacts reflect the selected artifact scope.',
215
+ };
216
+ }
217
+ export async function loadSemanticFunctionExplanationIndex(workspaceManager, database, sampleId, options = {}) {
218
+ const byAddress = new Map();
219
+ const byFunction = new Map();
220
+ const artifacts = database.findArtifactsByType(sampleId, SEMANTIC_FUNCTION_EXPLANATIONS_ARTIFACT_TYPE);
221
+ const loadedArtifacts = [];
222
+ for (const artifact of artifacts) {
223
+ const payload = (await readArtifactJson(workspaceManager, database, sampleId, artifact.id));
224
+ loadedArtifacts.push({ artifact, payload });
225
+ }
226
+ const filteredArtifacts = filterSemanticArtifactsByScope(loadedArtifacts, options);
227
+ for (const { artifact, payload } of filteredArtifacts) {
228
+ if (!payload || !Array.isArray(payload.explanations)) {
229
+ continue;
230
+ }
231
+ for (const explanation of payload.explanations) {
232
+ const loaded = {
233
+ address: explanation.address || null,
234
+ function: explanation.function || null,
235
+ summary: explanation.summary,
236
+ behavior: explanation.behavior,
237
+ confidence: explanation.confidence,
238
+ assumptions: explanation.assumptions || [],
239
+ evidence_used: explanation.evidence_used || [],
240
+ rewrite_guidance: explanation.rewrite_guidance || [],
241
+ artifact_id: artifact.id,
242
+ created_at: artifact.created_at,
243
+ client_name: payload.client_name || null,
244
+ model_name: payload.model_name || null,
245
+ session_tag: payload.session_tag || null,
246
+ prepare_artifact_id: payload.prepare_artifact_id || null,
247
+ };
248
+ const addressKey = normalizeAddressKey(explanation.address);
249
+ if (addressKey && !byAddress.has(addressKey)) {
250
+ byAddress.set(addressKey, loaded);
251
+ }
252
+ const functionKey = normalizeFunctionKey(explanation.function);
253
+ if (functionKey && !byFunction.has(functionKey)) {
254
+ byFunction.set(functionKey, loaded);
255
+ }
256
+ }
257
+ }
258
+ return {
259
+ byAddress,
260
+ byFunction,
261
+ marker: filteredArtifacts.length > 0
262
+ ? filteredArtifacts.map(({ artifact }) => `${artifact.id}:${artifact.sha256}`).join('|')
263
+ : 'none',
264
+ artifact_ids: filteredArtifacts.map(({ artifact }) => artifact.id),
265
+ session_tags: Array.from(new Set(filteredArtifacts.flatMap(({ artifact, payload }) => collectSemanticArtifactSessionTags(artifact.path, payload?.session_tag)))),
266
+ earliest_created_at: filteredArtifacts.length > 0
267
+ ? filteredArtifacts
268
+ .map(({ artifact }) => artifact.created_at)
269
+ .filter((item) => typeof item === 'string' && item.length > 0)
270
+ .sort()[0] || null
271
+ : null,
272
+ latest_created_at: filteredArtifacts.length > 0
273
+ ? filteredArtifacts
274
+ .map(({ artifact }) => artifact.created_at)
275
+ .filter((item) => typeof item === 'string' && item.length > 0)
276
+ .sort()
277
+ .slice(-1)[0] || null
278
+ : null,
279
+ scope_note: options.scope === 'session' && options.sessionTag?.trim()
280
+ ? `Semantic explanation artifacts are limited to session selector "${options.sessionTag.trim()}".`
281
+ : options.scope === 'latest'
282
+ ? 'Semantic explanation artifacts are limited to the latest artifact window.'
283
+ : 'Semantic explanation artifacts reflect the selected artifact scope.',
284
+ };
285
+ }
286
+ export function findSemanticNameSuggestion(index, address, funcName) {
287
+ if (!index) {
288
+ return null;
289
+ }
290
+ const addressKey = normalizeAddressKey(address);
291
+ if (addressKey && index.byAddress.has(addressKey)) {
292
+ return index.byAddress.get(addressKey) || null;
293
+ }
294
+ const functionKey = normalizeFunctionKey(funcName);
295
+ if (functionKey && index.byFunction.has(functionKey)) {
296
+ return index.byFunction.get(functionKey) || null;
297
+ }
298
+ return null;
299
+ }
300
+ export function findSemanticFunctionExplanation(index, address, funcName) {
301
+ if (!index) {
302
+ return null;
303
+ }
304
+ const addressKey = normalizeAddressKey(address);
305
+ if (addressKey && index.byAddress.has(addressKey)) {
306
+ return index.byAddress.get(addressKey) || null;
307
+ }
308
+ const functionKey = normalizeFunctionKey(funcName);
309
+ if (functionKey && index.byFunction.has(functionKey)) {
310
+ return index.byFunction.get(functionKey) || null;
311
+ }
312
+ return null;
313
+ }
314
+ //# sourceMappingURL=semantic-name-suggestion-artifacts.js.map
@@ -0,0 +1,129 @@
1
+ /**
2
+ * MCP Server implementation
3
+ * Implements the Model Context Protocol with JSON-RPC 2.0 message handling
4
+ */
5
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
+ import { type ClientCapabilities, type CreateMessageRequest, type CreateMessageResult, type CreateMessageResultWithTools, type Implementation, Prompt, Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
7
+ import pino from 'pino';
8
+ import type { Config } from './config.js';
9
+ import type { ToolDefinition, ToolArgs, ToolResult, WorkerResult, PromptDefinition, PromptArgs, PromptResult } from './types.js';
10
+ /**
11
+ * Tool handler function type - can return either WorkerResult or ToolResult
12
+ */
13
+ type ToolHandler = (args: ToolArgs) => Promise<WorkerResult | ToolResult>;
14
+ type PromptHandler = (args: PromptArgs) => Promise<PromptResult>;
15
+ /**
16
+ * MCP Server class implementing the Model Context Protocol
17
+ */
18
+ export declare class MCPServer {
19
+ private server;
20
+ private logger;
21
+ private tools;
22
+ private handlers;
23
+ private prompts;
24
+ private promptHandlers;
25
+ constructor(config: Config);
26
+ /**
27
+ * Setup MCP protocol handlers
28
+ */
29
+ private setupHandlers;
30
+ /**
31
+ * Register a tool with its definition and handler
32
+ */
33
+ registerTool(definition: ToolDefinition, handler: ToolHandler): void;
34
+ /**
35
+ * Register a prompt with its definition and handler
36
+ */
37
+ registerPrompt(definition: PromptDefinition, handler: PromptHandler): void;
38
+ getToolDefinitions(): ToolDefinition[];
39
+ getToolDefinition(name: string): ToolDefinition | undefined;
40
+ getPromptDefinitions(): PromptDefinition[];
41
+ getPromptDefinition(name: string): PromptDefinition | undefined;
42
+ /**
43
+ * List all available tools (MCP protocol method)
44
+ */
45
+ listTools(): Promise<Tool[]>;
46
+ /**
47
+ * List all available prompts (MCP protocol method)
48
+ */
49
+ listPrompts(): Promise<Prompt[]>;
50
+ /**
51
+ * Convert Zod schema to JSON Schema format
52
+ * Basic implementation for common Zod types
53
+ */
54
+ private zodToJsonSchema;
55
+ /**
56
+ * Determine whether a field is required in object schema.
57
+ * Optional/default/catch wrappers should not be marked as required.
58
+ */
59
+ private isFieldRequired;
60
+ /**
61
+ * Attach schema description when available.
62
+ */
63
+ private withDescription;
64
+ /**
65
+ * Convert Zod field schema to JSON Schema property
66
+ */
67
+ private zodFieldToJsonSchema;
68
+ /**
69
+ * Call a tool by name with arguments (MCP protocol method)
70
+ */
71
+ callTool(name: string, args: unknown): Promise<CallToolResult>;
72
+ /**
73
+ * Resolve a prompt by name and arguments (MCP protocol method)
74
+ */
75
+ getPrompt(name: string, args: Record<string, unknown>): Promise<PromptResult>;
76
+ private validatePromptArgs;
77
+ /**
78
+ * Validate tool arguments against schema
79
+ * Provides clear error messages with field paths and validation details
80
+ */
81
+ private validateArgs;
82
+ /**
83
+ * Generate an example object from a Zod schema
84
+ * Helps users understand the expected input format
85
+ */
86
+ private generateSchemaExample;
87
+ /**
88
+ * Generate an example value for a specific field schema
89
+ */
90
+ private generateFieldExample;
91
+ /**
92
+ * Convert worker result to MCP tool result
93
+ */
94
+ private workerResultToToolResult;
95
+ /**
96
+ * Start the MCP server with stdio transport
97
+ */
98
+ start(): Promise<void>;
99
+ /**
100
+ * Stop the MCP server
101
+ */
102
+ stop(): Promise<void>;
103
+ /**
104
+ * Get server instance for testing
105
+ */
106
+ getServer(): Server;
107
+ /**
108
+ * Get connected client capabilities after MCP initialization.
109
+ */
110
+ getClientCapabilities(): ClientCapabilities | undefined;
111
+ /**
112
+ * Get connected client implementation info after MCP initialization.
113
+ */
114
+ getClientVersion(): Implementation | undefined;
115
+ /**
116
+ * Whether the connected MCP client advertised sampling support.
117
+ */
118
+ supportsSampling(): boolean;
119
+ /**
120
+ * Request client-mediated MCP sampling from the connected client.
121
+ */
122
+ createMessage(params: CreateMessageRequest['params']): Promise<CreateMessageResult | CreateMessageResultWithTools>;
123
+ /**
124
+ * Get logger instance
125
+ */
126
+ getLogger(): pino.Logger;
127
+ }
128
+ export {};
129
+ //# sourceMappingURL=server.d.ts.map