@reverse-craft/ai-tools 1.0.0 → 1.0.1
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.
- package/README.md +85 -75
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +418 -0
- package/dist/server.js.map +7 -0
- package/dist/tools/ToolDefinition.d.ts +24 -0
- package/dist/tools/ToolDefinition.d.ts.map +1 -0
- package/dist/tools/findJsvmpDispatcher.d.ts +41 -0
- package/dist/tools/findJsvmpDispatcher.d.ts.map +1 -0
- package/dist/tools/findJsvmpDispatcherTool.d.ts +31 -0
- package/dist/tools/findJsvmpDispatcherTool.d.ts.map +1 -0
- package/dist/tools/findJsvmpDispatcherTool.test.d.ts +7 -0
- package/dist/tools/findJsvmpDispatcherTool.test.d.ts.map +1 -0
- package/dist/tools/index.d.ts +21 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# @reverse-craft/ai-tools
|
|
2
2
|
|
|
3
|
-
AI-powered
|
|
3
|
+
MCP server for AI-powered JSVMP detection. Provides LLM-driven code analysis tools for identifying JavaScript Virtual Machine Protection patterns.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
+
- **MCP Server** - Model Context Protocol server for AI assistant integration
|
|
7
8
|
- **JSVMP Detection** - Detect VM protection patterns using LLM analysis
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
9
|
+
- **Multiple Pattern Types** - Identifies dispatchers, instruction arrays, stack operations
|
|
10
|
+
- **Confidence Levels** - Results include ultra_high, high, medium, low confidence ratings
|
|
10
11
|
|
|
11
12
|
## Installation
|
|
12
13
|
|
|
@@ -24,106 +25,115 @@ export OPENAI_API_KEY=your-api-key
|
|
|
24
25
|
|
|
25
26
|
# Optional (defaults shown)
|
|
26
27
|
export OPENAI_BASE_URL=https://api.openai.com/v1
|
|
27
|
-
export OPENAI_MODEL=gpt-
|
|
28
|
+
export OPENAI_MODEL=gpt-4o-mini
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
## Usage
|
|
31
|
+
## MCP Server Usage
|
|
31
32
|
|
|
32
|
-
###
|
|
33
|
+
### Running the Server
|
|
33
34
|
|
|
34
|
-
```
|
|
35
|
-
|
|
35
|
+
```bash
|
|
36
|
+
# Via npx
|
|
37
|
+
npx @reverse-craft/ai-tools
|
|
38
|
+
|
|
39
|
+
# Or if installed globally
|
|
40
|
+
ai-tools-mcp
|
|
41
|
+
```
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
'./obfuscated.js',
|
|
39
|
-
1, // startLine
|
|
40
|
-
500, // endLine
|
|
41
|
-
{ charLimit: 300 }
|
|
42
|
-
);
|
|
43
|
+
### MCP Configuration
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
Add to your MCP client configuration (e.g., Claude Desktop, Kiro):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"ai-tools": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["@reverse-craft/ai-tools"],
|
|
53
|
+
"env": {
|
|
54
|
+
"OPENAI_API_KEY": "your-api-key"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
```
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
Or with a local installation:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"ai-tools": {
|
|
67
|
+
"command": "node",
|
|
68
|
+
"args": ["/path/to/ai-tools/dist/server.js"],
|
|
69
|
+
"env": {
|
|
70
|
+
"OPENAI_API_KEY": "your-api-key"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
62
74
|
}
|
|
63
75
|
```
|
|
64
76
|
|
|
65
|
-
|
|
77
|
+
## MCP Tools
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
import { formatCodeForAnalysis } from '@reverse-craft/ai-tools';
|
|
79
|
+
### find_jsvmp_dispatcher
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
'./app.min.js',
|
|
72
|
-
1, // startLine
|
|
73
|
-
100, // endLine
|
|
74
|
-
300 // charLimit
|
|
75
|
-
);
|
|
81
|
+
Detect JSVMP (JavaScript Virtual Machine Protection) patterns in code using LLM analysis.
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
// Output: "LineNo SourceLoc Code" format
|
|
79
|
-
```
|
|
83
|
+
**Parameters:**
|
|
80
84
|
|
|
81
|
-
|
|
85
|
+
| Name | Type | Required | Description |
|
|
86
|
+
|------|------|----------|-------------|
|
|
87
|
+
| filePath | string | Yes | Path to the JavaScript file to analyze |
|
|
88
|
+
| startLine | number | Yes | Start line number (1-based) |
|
|
89
|
+
| endLine | number | Yes | End line number (1-based) |
|
|
90
|
+
| charLimit | number | No | Character limit for string truncation (default: 300) |
|
|
82
91
|
|
|
83
|
-
|
|
92
|
+
**Detection Types:**
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| "Switch Dispatcher"
|
|
90
|
-
| "Instruction Array"
|
|
91
|
-
| "Stack Operation";
|
|
94
|
+
- **If-Else Dispatcher** - Nested if-else chains for instruction dispatch
|
|
95
|
+
- **Switch Dispatcher** - Large switch statements (>20 cases) for opcode handling
|
|
96
|
+
- **Instruction Array** - Arrays storing bytecode instructions
|
|
97
|
+
- **Stack Operation** - Virtual stack push/pop patterns
|
|
92
98
|
|
|
93
|
-
|
|
99
|
+
**Confidence Levels:**
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
confidence: ConfidenceLevel;
|
|
100
|
-
description: string;
|
|
101
|
-
}
|
|
101
|
+
- `ultra_high` - Multiple JSVMP features present (loop + dispatcher + stack)
|
|
102
|
+
- `high` - Clear dispatcher structure (>20 cases or >10 nesting levels)
|
|
103
|
+
- `medium` - Partial JSVMP features
|
|
104
|
+
- `low` - Possible but uncertain patterns
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
**Example Response:**
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
=== JSVMP Dispatcher Detection Result ===
|
|
110
|
+
File: ./obfuscated.js (1-500)
|
|
111
|
+
|
|
112
|
+
Summary: 检测到典型的 JSVMP 保护结构,包含主分发器和栈操作
|
|
113
|
+
|
|
114
|
+
Detected Regions:
|
|
115
|
+
[ultra_high] Lines 45-280: Switch Dispatcher
|
|
116
|
+
大型 switch 语句包含 47 个 case,典型的 JSVMP 指令分发器
|
|
117
|
+
|
|
118
|
+
[high] Lines 12-44: Stack Operation
|
|
119
|
+
虚拟栈初始化和操作,使用数组索引进行 push/pop
|
|
112
120
|
```
|
|
113
121
|
|
|
114
|
-
|
|
122
|
+
## What is JSVMP?
|
|
123
|
+
|
|
124
|
+
JSVMP (JavaScript Virtual Machine Protection) is a code protection technique that:
|
|
125
|
+
|
|
126
|
+
1. Converts JavaScript source code to custom bytecode
|
|
127
|
+
2. Implements a virtual machine to execute the bytecode
|
|
128
|
+
3. Uses dispatchers (switch/if-else) to handle different opcodes
|
|
129
|
+
4. Maintains a virtual stack for operand storage
|
|
115
130
|
|
|
116
|
-
|
|
117
|
-
- `formatCodeForAnalysis(filePath, startLine, endLine, charLimit?)` - Format code for LLM
|
|
118
|
-
- `parseDetectionResult(jsonString)` - Parse LLM response
|
|
119
|
-
- `getLLMConfig()` - Get LLM configuration from environment
|
|
120
|
-
- `isLLMConfigured()` - Check if LLM is configured
|
|
121
|
-
- `createLLMClient(config)` - Create LLM client instance
|
|
131
|
+
This makes reverse engineering significantly harder as the original logic is hidden behind VM interpretation.
|
|
122
132
|
|
|
123
133
|
## Related Packages
|
|
124
134
|
|
|
125
|
-
- **[@reverse-craft/smart-fs](https://github.com/reverse-craft/smart-fs)** - Core library
|
|
126
|
-
- **[@reverse-craft/smart-fs-mcp](https://github.com/reverse-craft/smart-fs-mcp)** - MCP server
|
|
135
|
+
- **[@reverse-craft/smart-fs](https://github.com/reverse-craft/smart-fs)** - Core library for code processing
|
|
136
|
+
- **[@reverse-craft/smart-fs-mcp](https://github.com/reverse-craft/smart-fs-mcp)** - MCP server for smart-fs
|
|
127
137
|
|
|
128
138
|
## License
|
|
129
139
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AI Tools - AI-powered
|
|
2
|
+
* AI Tools - MCP server for AI-powered JSVMP detection
|
|
3
3
|
*
|
|
4
|
-
* This package provides LLM-driven functionality for code analysis,
|
|
4
|
+
* This package provides an MCP server with LLM-driven functionality for code analysis,
|
|
5
5
|
* including JSVMP (JavaScript Virtual Machine Protection) detection.
|
|
6
6
|
*
|
|
7
|
+
* Run as MCP server: npx @reverse-craft/ai-tools
|
|
8
|
+
*
|
|
7
9
|
* @packageDocumentation
|
|
8
10
|
*/
|
|
9
11
|
export { type LLMConfig, type LLMClient, getLLMConfig, isLLMConfigured, createLLMClient, } from './llmConfig.js';
|
|
10
12
|
export { type FormattedCode, type DetectionType, type ConfidenceLevel, type DetectionRegion, type DetectionResult, type JsvmpDetectionOptions, type JsvmpDetectionResult, formatCodeForAnalysis, parseDetectionResult, findJsvmpDispatcher, } from './jsvmpDetector.js';
|
|
13
|
+
export { tools } from './tools/index.js';
|
|
14
|
+
export { findJsvmpDispatcherTool, FindJsvmpDispatcherInputSchema } from './tools/findJsvmpDispatcherTool.js';
|
|
15
|
+
export { ToolDefinition, defineTool } from './tools/ToolDefinition.js';
|
|
11
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AAC7G,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/server.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { z as z2 } from "zod";
|
|
7
|
+
|
|
8
|
+
// src/tools/findJsvmpDispatcherTool.ts
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
11
|
+
// src/tools/ToolDefinition.ts
|
|
12
|
+
function defineTool(definition) {
|
|
13
|
+
return definition;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/jsvmpDetector.ts
|
|
17
|
+
import { SourceMapConsumer } from "source-map-js";
|
|
18
|
+
import { ensureBeautified, truncateCodeHighPerf } from "@reverse-craft/smart-fs";
|
|
19
|
+
import { existsSync } from "fs";
|
|
20
|
+
|
|
21
|
+
// src/llmConfig.ts
|
|
22
|
+
function getLLMConfig() {
|
|
23
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
24
|
+
if (!apiKey) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const baseUrl = process.env.OPENAI_BASE_URL || "https://api.openai.com/v1";
|
|
28
|
+
const model = process.env.OPENAI_MODEL || "gpt-4o-mini";
|
|
29
|
+
return {
|
|
30
|
+
apiKey,
|
|
31
|
+
baseUrl,
|
|
32
|
+
model
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function buildJSVMPSystemPrompt() {
|
|
36
|
+
return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 JavaScript \u9006\u5411\u5DE5\u7A0B\u4E13\u5BB6\uFF0C\u4E13\u95E8\u8BC6\u522B JSVMP\uFF08JavaScript Virtual Machine Protection\uFF09\u4FDD\u62A4\u4EE3\u7801\u3002
|
|
37
|
+
|
|
38
|
+
JSVMP \u662F\u4E00\u79CD\u4EE3\u7801\u4FDD\u62A4\u6280\u672F\uFF0C\u5C06 JavaScript \u4EE3\u7801\u8F6C\u6362\u4E3A\u5B57\u8282\u7801\uFF0C\u5E76\u901A\u8FC7\u865A\u62DF\u673A\u6267\u884C\u3002\u5178\u578B\u7279\u5F81\u5305\u62EC\uFF1A
|
|
39
|
+
|
|
40
|
+
1. **\u865A\u62DF\u6808\uFF08Virtual Stack\uFF09**\uFF1A\u4E2D\u592E\u6570\u7EC4\u7528\u4E8E\u5B58\u50A8\u64CD\u4F5C\u6570\u548C\u7ED3\u679C
|
|
41
|
+
2. **\u5206\u53D1\u5668\uFF08Dispatcher\uFF09**\uFF1A\u5927\u578B switch \u8BED\u53E5\u6216\u5D4C\u5957 if-else \u94FE\uFF0C\u6839\u636E\u6307\u4EE4\u7801\u6267\u884C\u4E0D\u540C\u64CD\u4F5C
|
|
42
|
+
3. **\u6307\u4EE4\u6570\u7EC4\uFF08Instruction Array\uFF09**\uFF1A\u5B58\u50A8\u5B57\u8282\u7801\u6307\u4EE4\u7684\u6570\u7EC4
|
|
43
|
+
4. **\u4E3B\u5FAA\u73AF\uFF08Main Loop\uFF09**\uFF1Awhile \u5FAA\u73AF\u6301\u7EED\u6267\u884C\u6307\u4EE4
|
|
44
|
+
|
|
45
|
+
\u68C0\u6D4B\u89C4\u5219\uFF1A
|
|
46
|
+
|
|
47
|
+
**Ultra High \u7F6E\u4FE1\u5EA6**\uFF1A
|
|
48
|
+
- \u540C\u65F6\u51FA\u73B0\uFF1A\u4E3B\u5FAA\u73AF + \u5206\u53D1\u5668 + \u6808\u64CD\u4F5C
|
|
49
|
+
- \u5206\u53D1\u5668\u6709 >20 \u4E2A case \u6216 >10 \u5C42\u5D4C\u5957
|
|
50
|
+
- \u660E\u786E\u7684\u6808\u64CD\u4F5C\u6A21\u5F0F\uFF08push/pop/\u6570\u7EC4\u7D22\u5F15\uFF09
|
|
51
|
+
|
|
52
|
+
**High \u7F6E\u4FE1\u5EA6**\uFF1A
|
|
53
|
+
- \u72EC\u7ACB\u7684\u5927\u578B\u5206\u53D1\u5668\u7ED3\u6784\uFF08>20 case \u7684 switch \u6216 >10 \u5C42\u5D4C\u5957\u7684 if-else\uFF09
|
|
54
|
+
- \u660E\u786E\u7684\u6307\u4EE4\u6570\u7EC4\u548C\u7A0B\u5E8F\u8BA1\u6570\u5668\u6A21\u5F0F
|
|
55
|
+
|
|
56
|
+
**Medium \u7F6E\u4FE1\u5EA6**\uFF1A
|
|
57
|
+
- \u5B64\u7ACB\u7684\u6808\u64CD\u4F5C\u6216\u53EF\u7591\u7684 while \u5FAA\u73AF
|
|
58
|
+
- \u90E8\u5206 JSVMP \u7279\u5F81\u4F46\u4E0D\u5B8C\u6574
|
|
59
|
+
|
|
60
|
+
**Low \u7F6E\u4FE1\u5EA6**\uFF1A
|
|
61
|
+
- \u901A\u7528\u6DF7\u6DC6\u6A21\u5F0F
|
|
62
|
+
- \u53EF\u80FD\u76F8\u5173\u4F46\u4E0D\u786E\u5B9A\u7684\u7ED3\u6784
|
|
63
|
+
|
|
64
|
+
\u8BF7\u5206\u6790\u63D0\u4F9B\u7684\u4EE3\u7801\uFF0C\u8BC6\u522B JSVMP \u76F8\u5173\u533A\u57DF\u3002\u8FD4\u56DE JSON \u683C\u5F0F\uFF1A
|
|
65
|
+
|
|
66
|
+
{
|
|
67
|
+
"summary": "\u5206\u6790\u6458\u8981\uFF08\u4E2D\u6587\uFF09",
|
|
68
|
+
"regions": [
|
|
69
|
+
{
|
|
70
|
+
"start": \u8D77\u59CB\u884C\u53F7,
|
|
71
|
+
"end": \u7ED3\u675F\u884C\u53F7,
|
|
72
|
+
"type": "If-Else Dispatcher" | "Switch Dispatcher" | "Instruction Array" | "Stack Operation",
|
|
73
|
+
"confidence": "ultra_high" | "high" | "medium" | "low",
|
|
74
|
+
"description": "\u8BE6\u7EC6\u63CF\u8FF0\uFF08\u4E2D\u6587\uFF09"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
\u5982\u679C\u6CA1\u6709\u68C0\u6D4B\u5230 JSVMP \u7279\u5F81\uFF0C\u8FD4\u56DE\u7A7A\u7684 regions \u6570\u7EC4\u3002`;
|
|
80
|
+
}
|
|
81
|
+
function createLLMClient(config) {
|
|
82
|
+
return {
|
|
83
|
+
async analyzeJSVMP(formattedCode) {
|
|
84
|
+
const systemPrompt = buildJSVMPSystemPrompt();
|
|
85
|
+
const requestBody = {
|
|
86
|
+
model: config.model,
|
|
87
|
+
messages: [
|
|
88
|
+
{
|
|
89
|
+
role: "system",
|
|
90
|
+
content: systemPrompt
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
role: "user",
|
|
94
|
+
content: `\u8BF7\u5206\u6790\u4EE5\u4E0B\u4EE3\u7801\uFF0C\u8BC6\u522B JSVMP \u4FDD\u62A4\u7ED3\u6784\uFF1A
|
|
95
|
+
|
|
96
|
+
${formattedCode}`
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
temperature: 0.1,
|
|
100
|
+
response_format: { type: "json_object" }
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
const response = await fetch(`${config.baseUrl}/chat/completions`, {
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers: {
|
|
106
|
+
"Content-Type": "application/json",
|
|
107
|
+
"Authorization": `Bearer ${config.apiKey}`
|
|
108
|
+
},
|
|
109
|
+
body: JSON.stringify(requestBody)
|
|
110
|
+
});
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const errorText = await response.text();
|
|
113
|
+
throw new Error(`API \u8BF7\u6C42\u5931\u8D25 (${response.status}): ${errorText}`);
|
|
114
|
+
}
|
|
115
|
+
const data = await response.json();
|
|
116
|
+
if (!data.choices || !data.choices[0] || !data.choices[0].message) {
|
|
117
|
+
throw new Error("API \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF1A\u7F3A\u5C11 choices \u6216 message \u5B57\u6BB5");
|
|
118
|
+
}
|
|
119
|
+
const content = data.choices[0].message.content;
|
|
120
|
+
if (typeof content !== "string") {
|
|
121
|
+
throw new Error("API \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF1Amessage.content \u4E0D\u662F\u5B57\u7B26\u4E32");
|
|
122
|
+
}
|
|
123
|
+
return content;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error instanceof Error) {
|
|
126
|
+
throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25: ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25: ${String(error)}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/jsvmpDetector.ts
|
|
135
|
+
function formatSourcePosition(line, column) {
|
|
136
|
+
if (line !== null && column !== null) {
|
|
137
|
+
return `L${line}:${column}`;
|
|
138
|
+
}
|
|
139
|
+
return "";
|
|
140
|
+
}
|
|
141
|
+
function formatCodeLine(lineNumber, sourcePos, code) {
|
|
142
|
+
const lineNumStr = String(lineNumber).padStart(5, " ");
|
|
143
|
+
const srcPosPadded = sourcePos ? sourcePos.padEnd(10, " ") : " ";
|
|
144
|
+
return `${lineNumStr} ${srcPosPadded} ${code}`;
|
|
145
|
+
}
|
|
146
|
+
async function formatCodeForAnalysis(filePath, startLine, endLine, charLimit = 300) {
|
|
147
|
+
const beautifyResult = await ensureBeautified(filePath);
|
|
148
|
+
const { code, rawMap } = beautifyResult;
|
|
149
|
+
const truncatedCode = truncateCodeHighPerf(code, charLimit);
|
|
150
|
+
const lines = truncatedCode.split("\n");
|
|
151
|
+
const totalLines = lines.length;
|
|
152
|
+
const effectiveStartLine = Math.max(1, Math.min(totalLines, startLine));
|
|
153
|
+
const effectiveEndLine = Math.max(effectiveStartLine, Math.min(totalLines, endLine));
|
|
154
|
+
const formattedLines = [];
|
|
155
|
+
let consumer = null;
|
|
156
|
+
if (rawMap && rawMap.sources && rawMap.names && rawMap.mappings) {
|
|
157
|
+
consumer = new SourceMapConsumer({
|
|
158
|
+
version: String(rawMap.version),
|
|
159
|
+
sources: rawMap.sources,
|
|
160
|
+
names: rawMap.names,
|
|
161
|
+
mappings: rawMap.mappings,
|
|
162
|
+
file: rawMap.file,
|
|
163
|
+
sourceRoot: rawMap.sourceRoot
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
for (let lineNum = effectiveStartLine; lineNum <= effectiveEndLine; lineNum++) {
|
|
167
|
+
const lineIndex = lineNum - 1;
|
|
168
|
+
const lineContent = lines[lineIndex] ?? "";
|
|
169
|
+
let sourcePos = "";
|
|
170
|
+
if (consumer) {
|
|
171
|
+
const originalPos = consumer.originalPositionFor({
|
|
172
|
+
line: lineNum,
|
|
173
|
+
column: 0
|
|
174
|
+
});
|
|
175
|
+
sourcePos = formatSourcePosition(originalPos.line, originalPos.column);
|
|
176
|
+
}
|
|
177
|
+
formattedLines.push(formatCodeLine(lineNum, sourcePos, lineContent));
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
content: formattedLines.join("\n"),
|
|
181
|
+
totalLines,
|
|
182
|
+
startLine: effectiveStartLine,
|
|
183
|
+
endLine: effectiveEndLine
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
var VALID_DETECTION_TYPES = [
|
|
187
|
+
"If-Else Dispatcher",
|
|
188
|
+
"Switch Dispatcher",
|
|
189
|
+
"Instruction Array",
|
|
190
|
+
"Stack Operation"
|
|
191
|
+
];
|
|
192
|
+
var VALID_CONFIDENCE_LEVELS = [
|
|
193
|
+
"ultra_high",
|
|
194
|
+
"high",
|
|
195
|
+
"medium",
|
|
196
|
+
"low"
|
|
197
|
+
];
|
|
198
|
+
function isValidDetectionType(value) {
|
|
199
|
+
return VALID_DETECTION_TYPES.includes(value);
|
|
200
|
+
}
|
|
201
|
+
function isValidConfidenceLevel(value) {
|
|
202
|
+
return VALID_CONFIDENCE_LEVELS.includes(value);
|
|
203
|
+
}
|
|
204
|
+
function parseDetectionResult(jsonString) {
|
|
205
|
+
let parsed;
|
|
206
|
+
try {
|
|
207
|
+
parsed = JSON.parse(jsonString);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 LLM \u54CD\u5E94: ${error instanceof Error ? error.message : String(error)}`);
|
|
210
|
+
}
|
|
211
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
212
|
+
throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u671F\u671B\u5BF9\u8C61\u7C7B\u578B");
|
|
213
|
+
}
|
|
214
|
+
const obj = parsed;
|
|
215
|
+
if (typeof obj.summary !== "string") {
|
|
216
|
+
throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: summary");
|
|
217
|
+
}
|
|
218
|
+
if (!Array.isArray(obj.regions)) {
|
|
219
|
+
throw new Error("LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: regions");
|
|
220
|
+
}
|
|
221
|
+
const validatedRegions = [];
|
|
222
|
+
for (let i = 0; i < obj.regions.length; i++) {
|
|
223
|
+
const region = obj.regions[i];
|
|
224
|
+
if (typeof region !== "object" || region === null) {
|
|
225
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u4E0D\u662F\u5BF9\u8C61`);
|
|
226
|
+
}
|
|
227
|
+
if (typeof region.start !== "number") {
|
|
228
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: start`);
|
|
229
|
+
}
|
|
230
|
+
if (typeof region.end !== "number") {
|
|
231
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: end`);
|
|
232
|
+
}
|
|
233
|
+
if (typeof region.type !== "string") {
|
|
234
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: type`);
|
|
235
|
+
}
|
|
236
|
+
if (typeof region.confidence !== "string") {
|
|
237
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: confidence`);
|
|
238
|
+
}
|
|
239
|
+
if (typeof region.description !== "string") {
|
|
240
|
+
throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: description`);
|
|
241
|
+
}
|
|
242
|
+
if (!isValidDetectionType(region.type)) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}].type \u503C\u65E0\u6548: "${region.type}". \u6709\u6548\u503C: ${VALID_DETECTION_TYPES.join(", ")}`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
if (!isValidConfidenceLevel(region.confidence)) {
|
|
248
|
+
throw new Error(
|
|
249
|
+
`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}].confidence \u503C\u65E0\u6548: "${region.confidence}". \u6709\u6548\u503C: ${VALID_CONFIDENCE_LEVELS.join(", ")}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
validatedRegions.push({
|
|
253
|
+
start: region.start,
|
|
254
|
+
end: region.end,
|
|
255
|
+
type: region.type,
|
|
256
|
+
confidence: region.confidence,
|
|
257
|
+
description: region.description
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
summary: obj.summary,
|
|
262
|
+
regions: validatedRegions
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function formatDetectionResultOutput(result, filePath, startLine, endLine) {
|
|
266
|
+
const lines = [];
|
|
267
|
+
lines.push("=== JSVMP Dispatcher Detection Result ===");
|
|
268
|
+
lines.push(`File: ${filePath} (${startLine}-${endLine})`);
|
|
269
|
+
lines.push("");
|
|
270
|
+
lines.push(`Summary: ${result.summary}`);
|
|
271
|
+
lines.push("");
|
|
272
|
+
if (result.regions.length > 0) {
|
|
273
|
+
lines.push("Detected Regions:");
|
|
274
|
+
for (const region of result.regions) {
|
|
275
|
+
lines.push(`[${region.confidence}] Lines ${region.start}-${region.end}: ${region.type}`);
|
|
276
|
+
lines.push(` ${region.description}`);
|
|
277
|
+
lines.push("");
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
lines.push("No JSVMP dispatcher patterns detected.");
|
|
281
|
+
}
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
async function findJsvmpDispatcher(filePath, startLine, endLine, options) {
|
|
285
|
+
const charLimit = options?.charLimit ?? 300;
|
|
286
|
+
const config = getLLMConfig();
|
|
287
|
+
if (!config) {
|
|
288
|
+
return {
|
|
289
|
+
success: false,
|
|
290
|
+
filePath,
|
|
291
|
+
startLine,
|
|
292
|
+
endLine,
|
|
293
|
+
error: "\u672A\u914D\u7F6E LLM\u3002\u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF OPENAI_API_KEY \u4EE5\u542F\u7528 JSVMP dispatcher \u68C0\u6D4B\u529F\u80FD\u3002"
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if (!existsSync(filePath)) {
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
filePath,
|
|
300
|
+
startLine,
|
|
301
|
+
endLine,
|
|
302
|
+
error: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const formattedCode = await formatCodeForAnalysis(
|
|
307
|
+
filePath,
|
|
308
|
+
startLine,
|
|
309
|
+
endLine,
|
|
310
|
+
charLimit
|
|
311
|
+
);
|
|
312
|
+
const client = createLLMClient(config);
|
|
313
|
+
const llmResponse = await client.analyzeJSVMP(formattedCode.content);
|
|
314
|
+
const result = parseDetectionResult(llmResponse);
|
|
315
|
+
const formattedOutput = formatDetectionResultOutput(result, filePath, startLine, endLine);
|
|
316
|
+
return {
|
|
317
|
+
success: true,
|
|
318
|
+
filePath,
|
|
319
|
+
startLine: formattedCode.startLine,
|
|
320
|
+
endLine: formattedCode.endLine,
|
|
321
|
+
result,
|
|
322
|
+
formattedOutput
|
|
323
|
+
};
|
|
324
|
+
} catch (error) {
|
|
325
|
+
return {
|
|
326
|
+
success: false,
|
|
327
|
+
filePath,
|
|
328
|
+
startLine,
|
|
329
|
+
endLine,
|
|
330
|
+
error: error instanceof Error ? error.message : String(error)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// src/tools/findJsvmpDispatcherTool.ts
|
|
336
|
+
var FindJsvmpDispatcherInputSchema = {
|
|
337
|
+
filePath: z.string().describe("Path to the JavaScript file to analyze"),
|
|
338
|
+
startLine: z.number().int().positive().describe("Start line number (1-based)"),
|
|
339
|
+
endLine: z.number().int().positive().describe("End line number (1-based)"),
|
|
340
|
+
charLimit: z.number().int().positive().optional().describe("Character limit for string truncation (default: 300)")
|
|
341
|
+
};
|
|
342
|
+
var findJsvmpDispatcherTool = defineTool({
|
|
343
|
+
name: "find_jsvmp_dispatcher",
|
|
344
|
+
description: `Detect JSVMP (JavaScript Virtual Machine Protection) patterns in code using LLM analysis.
|
|
345
|
+
|
|
346
|
+
JSVMP is a code protection technique that converts JavaScript to bytecode executed by a virtual machine. This tool identifies:
|
|
347
|
+
- If-Else Dispatchers: Nested if-else chains for instruction dispatch
|
|
348
|
+
- Switch Dispatchers: Large switch statements (>20 cases) for opcode handling
|
|
349
|
+
- Instruction Arrays: Arrays storing bytecode instructions
|
|
350
|
+
- Stack Operations: Virtual stack push/pop patterns
|
|
351
|
+
|
|
352
|
+
Returns detection results with confidence levels (ultra_high, high, medium, low) and detailed descriptions.
|
|
353
|
+
|
|
354
|
+
Requires OPENAI_API_KEY environment variable. Optional: OPENAI_BASE_URL, OPENAI_MODEL.`,
|
|
355
|
+
schema: FindJsvmpDispatcherInputSchema,
|
|
356
|
+
handler: async (params) => {
|
|
357
|
+
const { filePath, startLine, endLine, charLimit } = params;
|
|
358
|
+
if (endLine < startLine) {
|
|
359
|
+
throw new Error("endLine must be >= startLine");
|
|
360
|
+
}
|
|
361
|
+
const result = await findJsvmpDispatcher(filePath, startLine, endLine, {
|
|
362
|
+
charLimit: charLimit ?? 300
|
|
363
|
+
});
|
|
364
|
+
if (!result.success) {
|
|
365
|
+
throw new Error(result.error ?? "Detection failed");
|
|
366
|
+
}
|
|
367
|
+
return result.formattedOutput ?? "No output generated";
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// src/tools/index.ts
|
|
372
|
+
var tools = [
|
|
373
|
+
findJsvmpDispatcherTool
|
|
374
|
+
];
|
|
375
|
+
|
|
376
|
+
// src/server.ts
|
|
377
|
+
var server = new McpServer({
|
|
378
|
+
name: "ai-tools-mcp",
|
|
379
|
+
version: "1.0.0"
|
|
380
|
+
});
|
|
381
|
+
function registerTool(tool) {
|
|
382
|
+
const zodSchema = z2.object(tool.schema);
|
|
383
|
+
server.registerTool(
|
|
384
|
+
tool.name,
|
|
385
|
+
{
|
|
386
|
+
description: tool.description,
|
|
387
|
+
inputSchema: tool.schema
|
|
388
|
+
},
|
|
389
|
+
async (params, _extra) => {
|
|
390
|
+
try {
|
|
391
|
+
const validatedParams = zodSchema.parse(params);
|
|
392
|
+
const result = await tool.handler(validatedParams);
|
|
393
|
+
return {
|
|
394
|
+
content: [{ type: "text", text: result }]
|
|
395
|
+
};
|
|
396
|
+
} catch (error) {
|
|
397
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
398
|
+
return {
|
|
399
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
400
|
+
isError: true
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
for (const tool of tools) {
|
|
407
|
+
registerTool(tool);
|
|
408
|
+
}
|
|
409
|
+
async function main() {
|
|
410
|
+
const transport = new StdioServerTransport();
|
|
411
|
+
await server.connect(transport);
|
|
412
|
+
console.error("AI Tools MCP Server running on stdio");
|
|
413
|
+
}
|
|
414
|
+
main().catch((error) => {
|
|
415
|
+
console.error("Fatal error:", error);
|
|
416
|
+
process.exit(1);
|
|
417
|
+
});
|
|
418
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/server.ts", "../src/tools/findJsvmpDispatcherTool.ts", "../src/tools/ToolDefinition.ts", "../src/jsvmpDetector.ts", "../src/llmConfig.ts", "../src/tools/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { tools } from './tools/index.js';\n\n// Create MCP Server instance\nconst server = new McpServer({\n name: 'ai-tools-mcp',\n version: '1.0.0',\n});\n\n/**\n * Register a tool with the MCP server.\n */\nfunction registerTool(tool: {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (params: Record<string, unknown>) => Promise<string>;\n}): void {\n const zodSchema = z.object(tool.schema);\n\n server.registerTool(\n tool.name,\n {\n description: tool.description,\n inputSchema: tool.schema,\n },\n async (params, _extra) => {\n try {\n const validatedParams = zodSchema.parse(params);\n const result = await tool.handler(validatedParams as Record<string, unknown>);\n\n return {\n content: [{ type: 'text' as const, text: result }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n };\n }\n }\n );\n}\n\n// Register all tools\nfor (const tool of tools) {\n registerTool(tool as unknown as {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (params: Record<string, unknown>) => Promise<string>;\n });\n}\n\n// Main entry point\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('AI Tools MCP Server running on stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n", "import { z } from 'zod';\nimport { defineTool } from './ToolDefinition.js';\nimport { findJsvmpDispatcher } from '../jsvmpDetector.js';\n\n/**\n * Input schema for find_jsvmp_dispatcher tool\n */\nexport const FindJsvmpDispatcherInputSchema = {\n filePath: z.string().describe('Path to the JavaScript file to analyze'),\n startLine: z.number().int().positive().describe('Start line number (1-based)'),\n endLine: z.number().int().positive().describe('End line number (1-based)'),\n charLimit: z.number().int().positive().optional().describe('Character limit for string truncation (default: 300)'),\n};\n\n/**\n * MCP Tool: find_jsvmp_dispatcher\n * \n * Uses LLM to detect JSVMP (JavaScript Virtual Machine Protection) patterns in code.\n * \n * JSVMP is a code protection technique that converts JavaScript to bytecode\n * executed by a virtual machine. This tool identifies:\n * - If-Else Dispatchers\n * - Switch Dispatchers \n * - Instruction Arrays\n * - Stack Operations\n * \n * Requires OPENAI_API_KEY environment variable to be set.\n */\nexport const findJsvmpDispatcherTool = defineTool({\n name: 'find_jsvmp_dispatcher',\n description: `Detect JSVMP (JavaScript Virtual Machine Protection) patterns in code using LLM analysis.\n\nJSVMP is a code protection technique that converts JavaScript to bytecode executed by a virtual machine. This tool identifies:\n- If-Else Dispatchers: Nested if-else chains for instruction dispatch\n- Switch Dispatchers: Large switch statements (>20 cases) for opcode handling\n- Instruction Arrays: Arrays storing bytecode instructions\n- Stack Operations: Virtual stack push/pop patterns\n\nReturns detection results with confidence levels (ultra_high, high, medium, low) and detailed descriptions.\n\nRequires OPENAI_API_KEY environment variable. Optional: OPENAI_BASE_URL, OPENAI_MODEL.`,\n schema: FindJsvmpDispatcherInputSchema,\n handler: async (params): Promise<string> => {\n const { filePath, startLine, endLine, charLimit } = params;\n\n // Validate endLine >= startLine\n if (endLine < startLine) {\n throw new Error('endLine must be >= startLine');\n }\n\n const result = await findJsvmpDispatcher(filePath, startLine, endLine, {\n charLimit: charLimit ?? 300,\n });\n\n if (!result.success) {\n throw new Error(result.error ?? 'Detection failed');\n }\n\n return result.formattedOutput ?? 'No output generated';\n },\n});\n", "import { z } from 'zod';\n\n/**\n * Tool definition interface for MCP tools.\n * Each tool has a name, description, schema (Zod raw shape), and async handler.\n */\nexport interface ToolDefinition<TSchema extends z.ZodRawShape = z.ZodRawShape> {\n /** Unique tool name (e.g., 'find_jsvmp_dispatcher') */\n name: string;\n /** Human-readable description of what the tool does */\n description: string;\n /** Zod schema object defining input parameters */\n schema: TSchema;\n /** Async handler function that processes the tool request */\n handler: (params: z.infer<z.ZodObject<TSchema>>) => Promise<string>;\n}\n\n/**\n * Helper function to create a type-safe tool definition.\n * Validates the tool definition structure at compile time.\n * \n * @param definition - The tool definition object\n * @returns The same definition with proper typing\n */\nexport function defineTool<TSchema extends z.ZodRawShape>(\n definition: ToolDefinition<TSchema>\n): ToolDefinition<TSchema> {\n return definition;\n}\n", "/**\n * JSVMP Detector Module\n * AI-powered detection of JSVMP (JavaScript Virtual Machine Protection) patterns\n */\n\nimport { SourceMapConsumer } from 'source-map-js';\nimport { ensureBeautified, truncateCodeHighPerf } from '@reverse-craft/smart-fs';\nimport { existsSync } from 'fs';\nimport { getLLMConfig, createLLMClient } from './llmConfig.js';\n\n/**\n * Formatted code result interface\n */\nexport interface FormattedCode {\n content: string; // \u683C\u5F0F\u5316\u540E\u7684\u4EE3\u7801\u5B57\u7B26\u4E32\n totalLines: number; // \u603B\u884C\u6570\n startLine: number; // \u5B9E\u9645\u8D77\u59CB\u884C\n endLine: number; // \u5B9E\u9645\u7ED3\u675F\u884C\n}\n\n/**\n * Detection type for JSVMP patterns\n */\nexport type DetectionType = \n | \"If-Else Dispatcher\" \n | \"Switch Dispatcher\" \n | \"Instruction Array\" \n | \"Stack Operation\";\n\n/**\n * Confidence level for detection results\n */\nexport type ConfidenceLevel = \"ultra_high\" | \"high\" | \"medium\" | \"low\";\n\n/**\n * A detected region in the code\n */\nexport interface DetectionRegion {\n start: number; // \u8D77\u59CB\u884C\u53F7\n end: number; // \u7ED3\u675F\u884C\u53F7\n type: DetectionType; // \u68C0\u6D4B\u7C7B\u578B\n confidence: ConfidenceLevel; // \u7F6E\u4FE1\u5EA6\n description: string; // \u63CF\u8FF0\uFF08\u4E2D\u6587\uFF09\n}\n\n/**\n * Complete detection result from LLM analysis\n */\nexport interface DetectionResult {\n summary: string; // \u5206\u6790\u6458\u8981\uFF08\u4E2D\u6587\uFF09\n regions: DetectionRegion[];\n}\n\n/**\n * Options for JSVMP detection\n */\nexport interface JsvmpDetectionOptions {\n charLimit?: number;\n}\n\n/**\n * Result from findJsvmpDispatcher function\n */\nexport interface JsvmpDetectionResult {\n success: boolean;\n filePath: string;\n startLine: number;\n endLine: number;\n result?: DetectionResult;\n formattedOutput?: string;\n error?: string;\n}\n\n/**\n * Format source position as \"L{line}:{column}\" or empty placeholder\n */\nfunction formatSourcePosition(line: number | null, column: number | null): string {\n if (line !== null && column !== null) {\n return `L${line}:${column}`;\n }\n return '';\n}\n\n/**\n * Format a single code line with line number, source coordinates, and content\n * Format: \"LineNo SourceLoc Code\"\n */\nfunction formatCodeLine(lineNumber: number, sourcePos: string, code: string): string {\n const lineNumStr = String(lineNumber).padStart(5, ' ');\n const srcPosPadded = sourcePos ? sourcePos.padEnd(10, ' ') : ' ';\n return `${lineNumStr} ${srcPosPadded} ${code}`;\n}\n\n/**\n * \u683C\u5F0F\u5316\u4EE3\u7801\u4E3A LLM \u5206\u6790\u683C\u5F0F\n * \u683C\u5F0F: \"LineNo SourceLoc Code\"\n * \n * \u5904\u7406\u6D41\u7A0B\uFF1A\n * 1. \u8C03\u7528 ensureBeautified \u7F8E\u5316\u4EE3\u7801\n * 2. \u8C03\u7528 truncateCodeHighPerf \u622A\u65AD\u957F\u5B57\u7B26\u4E32\n * 3. \u4F7F\u7528 SourceMapConsumer \u83B7\u53D6\u539F\u59CB\u5750\u6807\n * 4. \u683C\u5F0F\u5316\u4E3A \"LineNo SourceLoc Code\" \u683C\u5F0F\n * \n * @param filePath - Path to the JavaScript file\n * @param startLine - Start line number (1-based)\n * @param endLine - End line number (1-based)\n * @param charLimit - Character limit for string truncation (default 300)\n * @returns FormattedCode object with formatted content and metadata\n */\nexport async function formatCodeForAnalysis(\n filePath: string,\n startLine: number,\n endLine: number,\n charLimit: number = 300\n): Promise<FormattedCode> {\n // Step 1: Beautify the file and get source map\n const beautifyResult = await ensureBeautified(filePath);\n const { code, rawMap } = beautifyResult;\n\n // Step 2: Truncate long strings\n const truncatedCode = truncateCodeHighPerf(code, charLimit);\n\n // Split into lines\n const lines = truncatedCode.split('\\n');\n const totalLines = lines.length;\n\n // Step 3: Adjust line range boundaries\n const effectiveStartLine = Math.max(1, Math.min(totalLines, startLine));\n const effectiveEndLine = Math.max(effectiveStartLine, Math.min(totalLines, endLine));\n\n // Step 4: Format each line with \"LineNo SourceLoc Code\" format\n const formattedLines: string[] = [];\n\n // Create source map consumer if available\n let consumer: SourceMapConsumer | null = null;\n if (rawMap && rawMap.sources && rawMap.names && rawMap.mappings) {\n consumer = new SourceMapConsumer({\n version: String(rawMap.version),\n sources: rawMap.sources,\n names: rawMap.names,\n mappings: rawMap.mappings,\n file: rawMap.file,\n sourceRoot: rawMap.sourceRoot,\n });\n }\n\n for (let lineNum = effectiveStartLine; lineNum <= effectiveEndLine; lineNum++) {\n const lineIndex = lineNum - 1;\n const lineContent = lines[lineIndex] ?? '';\n\n // Get original position from source map if available\n let sourcePos = '';\n if (consumer) {\n const originalPos = consumer.originalPositionFor({\n line: lineNum,\n column: 0,\n });\n sourcePos = formatSourcePosition(originalPos.line, originalPos.column);\n }\n \n formattedLines.push(formatCodeLine(lineNum, sourcePos, lineContent));\n }\n\n return {\n content: formattedLines.join('\\n'),\n totalLines,\n startLine: effectiveStartLine,\n endLine: effectiveEndLine,\n };\n}\n\n/**\n * Valid detection types for validation\n */\nconst VALID_DETECTION_TYPES: DetectionType[] = [\n \"If-Else Dispatcher\",\n \"Switch Dispatcher\",\n \"Instruction Array\",\n \"Stack Operation\"\n];\n\n/**\n * Valid confidence levels for validation\n */\nconst VALID_CONFIDENCE_LEVELS: ConfidenceLevel[] = [\n \"ultra_high\",\n \"high\",\n \"medium\",\n \"low\"\n];\n\n/**\n * Check if a value is a valid DetectionType\n */\nfunction isValidDetectionType(value: unknown): value is DetectionType {\n return VALID_DETECTION_TYPES.includes(value as DetectionType);\n}\n\n/**\n * Check if a value is a valid ConfidenceLevel\n */\nfunction isValidConfidenceLevel(value: unknown): value is ConfidenceLevel {\n return VALID_CONFIDENCE_LEVELS.includes(value as ConfidenceLevel);\n}\n\n/**\n * Parse and validate LLM detection result from JSON string\n * \n * Validates:\n * - JSON is parseable\n * - Required fields exist: summary, regions\n * - Each region has required fields: start, end, type, confidence, description\n * - Enum values are valid\n * \n * @param jsonString - JSON string from LLM response\n * @returns Parsed and validated DetectionResult\n * @throws Error if JSON is invalid or structure doesn't match expected format\n */\nexport function parseDetectionResult(jsonString: string): DetectionResult {\n // Parse JSON\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonString);\n } catch (error) {\n throw new Error(`\u65E0\u6CD5\u89E3\u6790 LLM \u54CD\u5E94: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n // Validate required top-level fields\n if (typeof parsed !== 'object' || parsed === null) {\n throw new Error('LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u671F\u671B\u5BF9\u8C61\u7C7B\u578B');\n }\n\n const obj = parsed as Record<string, unknown>;\n\n if (typeof obj.summary !== 'string') {\n throw new Error('LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: summary');\n }\n\n if (!Array.isArray(obj.regions)) {\n throw new Error('LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: regions');\n }\n\n // Validate each region\n const validatedRegions: DetectionRegion[] = [];\n\n for (let i = 0; i < obj.regions.length; i++) {\n const region = obj.regions[i] as Record<string, unknown>;\n\n // Check region is an object\n if (typeof region !== 'object' || region === null) {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u4E0D\u662F\u5BF9\u8C61`);\n }\n\n // Validate required fields exist and have correct types\n if (typeof region.start !== 'number') {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: start`);\n }\n\n if (typeof region.end !== 'number') {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: end`);\n }\n\n if (typeof region.type !== 'string') {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: type`);\n }\n\n if (typeof region.confidence !== 'string') {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: confidence`);\n }\n\n if (typeof region.description !== 'string') {\n throw new Error(`LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}] \u7F3A\u5C11\u5FC5\u9700\u5B57\u6BB5: description`);\n }\n\n // Validate enum values\n if (!isValidDetectionType(region.type)) {\n throw new Error(\n `LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}].type \u503C\u65E0\u6548: \"${region.type}\". ` +\n `\u6709\u6548\u503C: ${VALID_DETECTION_TYPES.join(', ')}`\n );\n }\n\n if (!isValidConfidenceLevel(region.confidence)) {\n throw new Error(\n `LLM \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF0Cregions[${i}].confidence \u503C\u65E0\u6548: \"${region.confidence}\". ` +\n `\u6709\u6548\u503C: ${VALID_CONFIDENCE_LEVELS.join(', ')}`\n );\n }\n\n validatedRegions.push({\n start: region.start,\n end: region.end,\n type: region.type,\n confidence: region.confidence,\n description: region.description,\n });\n }\n\n return {\n summary: obj.summary,\n regions: validatedRegions,\n };\n}\n\n/**\n * Format detection result for display\n */\nfunction formatDetectionResultOutput(\n result: DetectionResult,\n filePath: string,\n startLine: number,\n endLine: number\n): string {\n const lines: string[] = [];\n \n lines.push('=== JSVMP Dispatcher Detection Result ===');\n lines.push(`File: ${filePath} (${startLine}-${endLine})`);\n lines.push('');\n lines.push(`Summary: ${result.summary}`);\n lines.push('');\n \n if (result.regions.length > 0) {\n lines.push('Detected Regions:');\n for (const region of result.regions) {\n lines.push(`[${region.confidence}] Lines ${region.start}-${region.end}: ${region.type}`);\n lines.push(` ${region.description}`);\n lines.push('');\n }\n } else {\n lines.push('No JSVMP dispatcher patterns detected.');\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Find JSVMP dispatcher patterns in JavaScript code using LLM analysis\n * \n * @param filePath - Path to the JavaScript file to analyze\n * @param startLine - Start line number (1-based)\n * @param endLine - End line number (1-based)\n * @param options - Optional configuration\n * @returns JsvmpDetectionResult with detection results or error\n */\nexport async function findJsvmpDispatcher(\n filePath: string,\n startLine: number,\n endLine: number,\n options?: JsvmpDetectionOptions\n): Promise<JsvmpDetectionResult> {\n const charLimit = options?.charLimit ?? 300;\n \n // Check LLM configuration\n const config = getLLMConfig();\n if (!config) {\n return {\n success: false,\n filePath,\n startLine,\n endLine,\n error: '\u672A\u914D\u7F6E LLM\u3002\u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF OPENAI_API_KEY \u4EE5\u542F\u7528 JSVMP dispatcher \u68C0\u6D4B\u529F\u80FD\u3002'\n };\n }\n \n // Check file exists\n if (!existsSync(filePath)) {\n return {\n success: false,\n filePath,\n startLine,\n endLine,\n error: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`\n };\n }\n \n try {\n // Format code for analysis\n const formattedCode = await formatCodeForAnalysis(\n filePath,\n startLine,\n endLine,\n charLimit\n );\n \n // Create LLM client and analyze\n const client = createLLMClient(config);\n const llmResponse = await client.analyzeJSVMP(formattedCode.content);\n \n // Parse detection result\n const result = parseDetectionResult(llmResponse);\n \n // Format output\n const formattedOutput = formatDetectionResultOutput(result, filePath, startLine, endLine);\n \n return {\n success: true,\n filePath,\n startLine: formattedCode.startLine,\n endLine: formattedCode.endLine,\n result,\n formattedOutput\n };\n \n } catch (error) {\n return {\n success: false,\n filePath,\n startLine,\n endLine,\n error: error instanceof Error ? error.message : String(error)\n };\n }\n}\n", "/**\n * LLM Configuration Module\n * Handles reading and validating LLM configuration from environment variables\n */\n\nexport interface LLMConfig {\n apiKey: string;\n baseUrl: string;\n model: string;\n}\n\n/**\n * \u4ECE\u73AF\u5883\u53D8\u91CF\u8BFB\u53D6 LLM \u914D\u7F6E\n * @returns LLMConfig | null (null \u8868\u793A\u672A\u914D\u7F6E)\n */\nexport function getLLMConfig(): LLMConfig | null {\n const apiKey = process.env.OPENAI_API_KEY;\n \n // API Key is required\n if (!apiKey) {\n return null;\n }\n \n // Use defaults for optional configuration\n const baseUrl = process.env.OPENAI_BASE_URL || \"https://api.openai.com/v1\";\n const model = process.env.OPENAI_MODEL || \"gpt-4o-mini\";\n \n return {\n apiKey,\n baseUrl,\n model\n };\n}\n\n/**\n * \u68C0\u67E5 LLM \u662F\u5426\u5DF2\u914D\u7F6E\n */\nexport function isLLMConfigured(): boolean {\n return getLLMConfig() !== null;\n}\n\n/**\n * LLM Client Interface\n */\nexport interface LLMClient {\n /**\n * \u53D1\u9001 JSVMP \u68C0\u6D4B\u8BF7\u6C42\u5230 LLM\n * @param formattedCode \u683C\u5F0F\u5316\u540E\u7684\u4EE3\u7801\n * @returns LLM \u8FD4\u56DE\u7684\u539F\u59CB JSON \u5B57\u7B26\u4E32\n */\n analyzeJSVMP(formattedCode: string): Promise<string>;\n}\n\n/**\n * \u6784\u5EFA JSVMP \u68C0\u6D4B\u7CFB\u7EDF\u63D0\u793A\u8BCD\n */\nfunction buildJSVMPSystemPrompt(): string {\n return `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 JavaScript \u9006\u5411\u5DE5\u7A0B\u4E13\u5BB6\uFF0C\u4E13\u95E8\u8BC6\u522B JSVMP\uFF08JavaScript Virtual Machine Protection\uFF09\u4FDD\u62A4\u4EE3\u7801\u3002\n\nJSVMP \u662F\u4E00\u79CD\u4EE3\u7801\u4FDD\u62A4\u6280\u672F\uFF0C\u5C06 JavaScript \u4EE3\u7801\u8F6C\u6362\u4E3A\u5B57\u8282\u7801\uFF0C\u5E76\u901A\u8FC7\u865A\u62DF\u673A\u6267\u884C\u3002\u5178\u578B\u7279\u5F81\u5305\u62EC\uFF1A\n\n1. **\u865A\u62DF\u6808\uFF08Virtual Stack\uFF09**\uFF1A\u4E2D\u592E\u6570\u7EC4\u7528\u4E8E\u5B58\u50A8\u64CD\u4F5C\u6570\u548C\u7ED3\u679C\n2. **\u5206\u53D1\u5668\uFF08Dispatcher\uFF09**\uFF1A\u5927\u578B switch \u8BED\u53E5\u6216\u5D4C\u5957 if-else \u94FE\uFF0C\u6839\u636E\u6307\u4EE4\u7801\u6267\u884C\u4E0D\u540C\u64CD\u4F5C\n3. **\u6307\u4EE4\u6570\u7EC4\uFF08Instruction Array\uFF09**\uFF1A\u5B58\u50A8\u5B57\u8282\u7801\u6307\u4EE4\u7684\u6570\u7EC4\n4. **\u4E3B\u5FAA\u73AF\uFF08Main Loop\uFF09**\uFF1Awhile \u5FAA\u73AF\u6301\u7EED\u6267\u884C\u6307\u4EE4\n\n\u68C0\u6D4B\u89C4\u5219\uFF1A\n\n**Ultra High \u7F6E\u4FE1\u5EA6**\uFF1A\n- \u540C\u65F6\u51FA\u73B0\uFF1A\u4E3B\u5FAA\u73AF + \u5206\u53D1\u5668 + \u6808\u64CD\u4F5C\n- \u5206\u53D1\u5668\u6709 >20 \u4E2A case \u6216 >10 \u5C42\u5D4C\u5957\n- \u660E\u786E\u7684\u6808\u64CD\u4F5C\u6A21\u5F0F\uFF08push/pop/\u6570\u7EC4\u7D22\u5F15\uFF09\n\n**High \u7F6E\u4FE1\u5EA6**\uFF1A\n- \u72EC\u7ACB\u7684\u5927\u578B\u5206\u53D1\u5668\u7ED3\u6784\uFF08>20 case \u7684 switch \u6216 >10 \u5C42\u5D4C\u5957\u7684 if-else\uFF09\n- \u660E\u786E\u7684\u6307\u4EE4\u6570\u7EC4\u548C\u7A0B\u5E8F\u8BA1\u6570\u5668\u6A21\u5F0F\n\n**Medium \u7F6E\u4FE1\u5EA6**\uFF1A\n- \u5B64\u7ACB\u7684\u6808\u64CD\u4F5C\u6216\u53EF\u7591\u7684 while \u5FAA\u73AF\n- \u90E8\u5206 JSVMP \u7279\u5F81\u4F46\u4E0D\u5B8C\u6574\n\n**Low \u7F6E\u4FE1\u5EA6**\uFF1A\n- \u901A\u7528\u6DF7\u6DC6\u6A21\u5F0F\n- \u53EF\u80FD\u76F8\u5173\u4F46\u4E0D\u786E\u5B9A\u7684\u7ED3\u6784\n\n\u8BF7\u5206\u6790\u63D0\u4F9B\u7684\u4EE3\u7801\uFF0C\u8BC6\u522B JSVMP \u76F8\u5173\u533A\u57DF\u3002\u8FD4\u56DE JSON \u683C\u5F0F\uFF1A\n\n{\n \"summary\": \"\u5206\u6790\u6458\u8981\uFF08\u4E2D\u6587\uFF09\",\n \"regions\": [\n {\n \"start\": \u8D77\u59CB\u884C\u53F7,\n \"end\": \u7ED3\u675F\u884C\u53F7,\n \"type\": \"If-Else Dispatcher\" | \"Switch Dispatcher\" | \"Instruction Array\" | \"Stack Operation\",\n \"confidence\": \"ultra_high\" | \"high\" | \"medium\" | \"low\",\n \"description\": \"\u8BE6\u7EC6\u63CF\u8FF0\uFF08\u4E2D\u6587\uFF09\"\n }\n ]\n}\n\n\u5982\u679C\u6CA1\u6709\u68C0\u6D4B\u5230 JSVMP \u7279\u5F81\uFF0C\u8FD4\u56DE\u7A7A\u7684 regions \u6570\u7EC4\u3002`;\n}\n\n/**\n * \u521B\u5EFA LLM \u5BA2\u6237\u7AEF\u5B9E\u4F8B\n */\nexport function createLLMClient(config: LLMConfig): LLMClient {\n return {\n async analyzeJSVMP(formattedCode: string): Promise<string> {\n const systemPrompt = buildJSVMPSystemPrompt();\n \n const requestBody = {\n model: config.model,\n messages: [\n {\n role: \"system\",\n content: systemPrompt\n },\n {\n role: \"user\",\n content: `\u8BF7\u5206\u6790\u4EE5\u4E0B\u4EE3\u7801\uFF0C\u8BC6\u522B JSVMP \u4FDD\u62A4\u7ED3\u6784\uFF1A\\n\\n${formattedCode}`\n }\n ],\n temperature: 0.1,\n response_format: { type: \"json_object\" }\n };\n \n try {\n const response = await fetch(`${config.baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${config.apiKey}`\n },\n body: JSON.stringify(requestBody)\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API \u8BF7\u6C42\u5931\u8D25 (${response.status}): ${errorText}`);\n }\n \n const data = await response.json();\n \n if (!data.choices || !data.choices[0] || !data.choices[0].message) {\n throw new Error(\"API \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF1A\u7F3A\u5C11 choices \u6216 message \u5B57\u6BB5\");\n }\n \n const content = data.choices[0].message.content;\n \n if (typeof content !== \"string\") {\n throw new Error(\"API \u54CD\u5E94\u683C\u5F0F\u65E0\u6548\uFF1Amessage.content \u4E0D\u662F\u5B57\u7B26\u4E32\");\n }\n \n return content;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25: ${error.message}`);\n }\n throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25: ${String(error)}`);\n }\n }\n };\n}\n", "/**\n * Tool aggregation module\n * Collects all tool definitions and exports them as a unified array.\n */\n\nimport { findJsvmpDispatcherTool, FindJsvmpDispatcherInputSchema } from './findJsvmpDispatcherTool.js';\n\n/**\n * Array of all available MCP tool definitions.\n * To add a new tool:\n * 1. Create a new tool module in src/tools/\n * 2. Import it here\n * 3. Add it to this array\n */\nexport const tools = [\n findJsvmpDispatcherTool,\n] as const;\n\n// Re-export ToolDefinition interface and defineTool helper\nexport { ToolDefinition, defineTool } from './ToolDefinition.js';\n\n// Re-export tool and input schema\nexport { findJsvmpDispatcherTool, FindJsvmpDispatcherInputSchema };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["z", "z"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Tool definition interface for MCP tools.
|
|
4
|
+
* Each tool has a name, description, schema (Zod raw shape), and async handler.
|
|
5
|
+
*/
|
|
6
|
+
export interface ToolDefinition<TSchema extends z.ZodRawShape = z.ZodRawShape> {
|
|
7
|
+
/** Unique tool name (e.g., 'find_jsvmp_dispatcher') */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Human-readable description of what the tool does */
|
|
10
|
+
description: string;
|
|
11
|
+
/** Zod schema object defining input parameters */
|
|
12
|
+
schema: TSchema;
|
|
13
|
+
/** Async handler function that processes the tool request */
|
|
14
|
+
handler: (params: z.infer<z.ZodObject<TSchema>>) => Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Helper function to create a type-safe tool definition.
|
|
18
|
+
* Validates the tool definition structure at compile time.
|
|
19
|
+
*
|
|
20
|
+
* @param definition - The tool definition object
|
|
21
|
+
* @returns The same definition with proper typing
|
|
22
|
+
*/
|
|
23
|
+
export declare function defineTool<TSchema extends z.ZodRawShape>(definition: ToolDefinition<TSchema>): ToolDefinition<TSchema>;
|
|
24
|
+
//# sourceMappingURL=ToolDefinition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolDefinition.d.ts","sourceRoot":"","sources":["../../src/tools/ToolDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IAC3E,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,WAAW,EACtD,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,GAClC,cAAc,CAAC,OAAO,CAAC,CAEzB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Input schema for find_jsvmp_dispatcher tool
|
|
4
|
+
*/
|
|
5
|
+
export declare const FindJsvmpDispatcherInputSchema: {
|
|
6
|
+
filePath: z.ZodString;
|
|
7
|
+
startLine: z.ZodNumber;
|
|
8
|
+
endLine: z.ZodNumber;
|
|
9
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* MCP Tool: find_jsvmp_dispatcher
|
|
13
|
+
*
|
|
14
|
+
* Uses LLM to detect JSVMP (JavaScript Virtual Machine Protection) patterns in code.
|
|
15
|
+
*
|
|
16
|
+
* JSVMP is a code protection technique that converts JavaScript to bytecode
|
|
17
|
+
* executed by a virtual machine. This tool identifies:
|
|
18
|
+
* - If-Else Dispatchers
|
|
19
|
+
* - Switch Dispatchers
|
|
20
|
+
* - Instruction Arrays
|
|
21
|
+
* - Stack Operations
|
|
22
|
+
*
|
|
23
|
+
* Requires OPENAI_API_KEY environment variable to be set.
|
|
24
|
+
*/
|
|
25
|
+
export declare const findJsvmpDispatcherTool: {
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
schema: {
|
|
29
|
+
filePath: z.ZodString;
|
|
30
|
+
startLine: z.ZodNumber;
|
|
31
|
+
endLine: z.ZodNumber;
|
|
32
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
};
|
|
34
|
+
handler: (params: {
|
|
35
|
+
filePath: string;
|
|
36
|
+
startLine: number;
|
|
37
|
+
endLine: number;
|
|
38
|
+
charLimit?: number;
|
|
39
|
+
}) => Promise<string>;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=findJsvmpDispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findJsvmpDispatcher.d.ts","sourceRoot":"","sources":["../../src/tools/findJsvmpDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,eAAO,MAAM,8BAA8B;;;;;CAK1C,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;sBAcV;QACtB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,KAAG,OAAO,CAAC,MAAM,CAAC;CAapB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Input schema for find_jsvmp_dispatcher tool
|
|
4
|
+
*/
|
|
5
|
+
export declare const FindJsvmpDispatcherInputSchema: {
|
|
6
|
+
filePath: z.ZodString;
|
|
7
|
+
startLine: z.ZodNumber;
|
|
8
|
+
endLine: z.ZodNumber;
|
|
9
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* MCP Tool: find_jsvmp_dispatcher
|
|
13
|
+
*
|
|
14
|
+
* Uses LLM to detect JSVMP (JavaScript Virtual Machine Protection) patterns in code.
|
|
15
|
+
*
|
|
16
|
+
* JSVMP is a code protection technique that converts JavaScript to bytecode
|
|
17
|
+
* executed by a virtual machine. This tool identifies:
|
|
18
|
+
* - If-Else Dispatchers
|
|
19
|
+
* - Switch Dispatchers
|
|
20
|
+
* - Instruction Arrays
|
|
21
|
+
* - Stack Operations
|
|
22
|
+
*
|
|
23
|
+
* Requires OPENAI_API_KEY environment variable to be set.
|
|
24
|
+
*/
|
|
25
|
+
export declare const findJsvmpDispatcherTool: import("./ToolDefinition.js").ToolDefinition<{
|
|
26
|
+
filePath: z.ZodString;
|
|
27
|
+
startLine: z.ZodNumber;
|
|
28
|
+
endLine: z.ZodNumber;
|
|
29
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
}>;
|
|
31
|
+
//# sourceMappingURL=findJsvmpDispatcherTool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findJsvmpDispatcherTool.d.ts","sourceRoot":"","sources":["../../src/tools/findJsvmpDispatcherTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;GAEG;AACH,eAAO,MAAM,8BAA8B;;;;;CAK1C,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB;;;;;EAgClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findJsvmpDispatcherTool.test.d.ts","sourceRoot":"","sources":["../../src/tools/findJsvmpDispatcherTool.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool aggregation module
|
|
3
|
+
* Collects all tool definitions and exports them as a unified array.
|
|
4
|
+
*/
|
|
5
|
+
import { findJsvmpDispatcherTool, FindJsvmpDispatcherInputSchema } from './findJsvmpDispatcherTool.js';
|
|
6
|
+
/**
|
|
7
|
+
* Array of all available MCP tool definitions.
|
|
8
|
+
* To add a new tool:
|
|
9
|
+
* 1. Create a new tool module in src/tools/
|
|
10
|
+
* 2. Import it here
|
|
11
|
+
* 3. Add it to this array
|
|
12
|
+
*/
|
|
13
|
+
export declare const tools: readonly [import("./ToolDefinition.js").ToolDefinition<{
|
|
14
|
+
filePath: import("zod").ZodString;
|
|
15
|
+
startLine: import("zod").ZodNumber;
|
|
16
|
+
endLine: import("zod").ZodNumber;
|
|
17
|
+
charLimit: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
18
|
+
}>];
|
|
19
|
+
export { ToolDefinition, defineTool } from './ToolDefinition.js';
|
|
20
|
+
export { findJsvmpDispatcherTool, FindJsvmpDispatcherInputSchema };
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAEvG;;;;;;GAMG;AACH,eAAO,MAAM,KAAK;;;;;GAER,CAAC;AAGX,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjE,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reverse-craft/ai-tools",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "AI-powered
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "MCP server for AI-powered JSVMP detection - provides LLM-driven code analysis tools",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "dist/
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
".": {
|
|
10
|
-
"import": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts"
|
|
12
|
-
}
|
|
6
|
+
"main": "dist/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ai-tools-mcp": "./dist/server.js"
|
|
13
9
|
},
|
|
14
10
|
"scripts": {
|
|
15
|
-
"build": "
|
|
11
|
+
"build": "node build.js",
|
|
16
12
|
"build:types": "tsc --emitDeclarationOnly",
|
|
13
|
+
"start": "node dist/server.js",
|
|
17
14
|
"test": "vitest --run",
|
|
18
15
|
"prepublishOnly": "npm run build"
|
|
19
16
|
},
|
|
20
17
|
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
21
20
|
"ai",
|
|
22
21
|
"llm",
|
|
23
22
|
"openai",
|
|
@@ -44,7 +43,9 @@
|
|
|
44
43
|
"node": ">=18"
|
|
45
44
|
},
|
|
46
45
|
"dependencies": {
|
|
47
|
-
"
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
47
|
+
"source-map-js": "^1.2.1",
|
|
48
|
+
"zod": "^4.2.1"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@reverse-craft/smart-fs": "^2.0.0"
|
|
@@ -52,6 +53,8 @@
|
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@reverse-craft/smart-fs": "^2.0.0",
|
|
54
55
|
"@types/node": "^22.15.29",
|
|
56
|
+
"esbuild": "^0.27.2",
|
|
57
|
+
"fast-check": "^4.5.2",
|
|
55
58
|
"typescript": "^5.8.3",
|
|
56
59
|
"vitest": "^4.0.16"
|
|
57
60
|
}
|