Loading...
Loading...
MCP server for JavaScript reverse engineering in real browser environments with hooks, breakpoints, network tracing, deobfuscation, and environment reconstruction.
npx skill4agent add aradotso/mcp-skills jsreverser-mcp-javascript-reverse-engineeringSkill by ara.so — MCP Skills collection.
git clone https://github.com/NoOne-hub/JSReverser-MCP.git
cd JSReverser-MCP
npm install
npm run buildbuild/src/index.jsnpm run startclaude mcp add js-reverse node /ABSOLUTE/PATH/JSReverser-MCP/build/src/index.js{
"mcpServers": {
"js-reverse": {
"command": "node",
"args": ["/ABSOLUTE/PATH/JSReverser-MCP/build/src/index.js"]
}
}
}[mcp_servers.js-reverse]
command = "node"
args = ["/ABSOLUTE/PATH/JSReverser-MCP/build/src/index.js"]# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
# Linux
google-chrome --remote-debugging-port=9222
# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222--browserUrl[mcp_servers.js-reverse]
command = "node"
args = [
"/ABSOLUTE/PATH/JSReverser-MCP/build/src/index.js",
"--browserUrl=http://localhost:9222"
][mcp_servers.js-reverse]
command = "node"
args = ["/ABSOLUTE/PATH/JSReverser-MCP/build/src/index.js"]
[mcp_servers.js-reverse.env]
DEFAULT_LLM_PROVIDER = "anthropic"
ANTHROPIC_API_KEY = "your_anthropic_key_here"
ANTHROPIC_MODEL = "claude-3-5-sonnet-20241022"
# Alternative: OpenAI
# DEFAULT_LLM_PROVIDER = "openai"
# OPENAI_API_KEY = "your_openai_key_here"
# OPENAI_MODEL = "gpt-4o"
# Alternative: Gemini
# DEFAULT_LLM_PROVIDER = "gemini"
# GEMINI_API_KEY = "your_gemini_key_here"
# GEMINI_MODEL = "gemini-2.0-flash-exp"understand_codedetect_cryptouseAI=truedeobfuscate_codeanalyze_targetuseAI=true// List all loaded scripts
list_scripts({ includeSourceMaps: false })
// Get specific script source
get_script_source({
scriptId: "123",
url: "https://example.com/app.js"
})
// Find text in single script
find_in_script({
scriptId: "123",
searchText: "encrypt",
maxResults: 10
})
// Search across all scripts
search_in_scripts({
searchText: "signature",
maxResults: 20
})// Hook a global function
hook_function({
functionPath: "window.crypto.subtle.encrypt",
options: {
captureArgs: true,
captureReturn: true,
captureStack: true
}
})
// Create reusable hook definition
create_hook({
hookId: "crypto-monitor",
code: `
const original = crypto.subtle.encrypt;
crypto.subtle.encrypt = function(...args) {
console.log('[HOOK] encrypt called:', args);
return original.apply(this, args);
};
`
})
// Inject hook into page
inject_hook({ hookId: "crypto-monitor" })
// Retrieve hook data
get_hook_data({ hookId: "crypto-monitor" })
// Trace function calls
trace_function({
functionName: "generateSignature",
captureStack: true
})// Set breakpoint by line number
set_breakpoint({
scriptUrl: "https://example.com/sign.js",
lineNumber: 42
})
// Set breakpoint by code text
set_breakpoint_on_text({
scriptUrl: "https://example.com/sign.js",
searchText: "return signature",
lineOffset: 0
})
// Control execution
resume({ mode: "continue" })
pause()
step_over()
step_into()
step_out()// List all network requests
list_network_requests({
filterUrl: "api.example.com",
filterMethod: "POST"
})
// Get request details
get_network_request({
requestId: "12345.67"
})
// Find who triggered a request
get_request_initiator({
requestId: "12345.67"
})
// Break when XHR/Fetch fires
break_on_xhr({
urlPattern: "*sign*"
})// Collect page code
collect_code({
priority: ["inline", "webpack", "vendor"],
maxSize: 500000
})
// Understand code structure (requires AI)
understand_code({
source: "function _0x1234(){...}",
context: "encryption signature generation"
})
// Deobfuscate code
deobfuscate_code({
source: "var _0x1a2b=['push','length'];...",
options: {
renameVariables: true,
removeDeadCode: true,
simplifyExpressions: true
}
})
// Detect crypto usage
detect_crypto({
source: "...",
useAI: true
})
// Comprehensive risk analysis
risk_panel({
useAI: true,
includeNetworkRisk: true
})// List active WebSocket connections
list_websocket_connections()
// Analyze message patterns
analyze_websocket_messages({
wsId: "ws-123",
groupBy: "opcode"
})
// Get messages
get_websocket_messages({
wsId: "ws-123",
group: "binary-frames",
limit: 50
})// Export rebuild bundle
export_rebuild_bundle({
taskId: "jd-h5st-20240517",
includeScripts: true,
includeNetwork: true,
includeStorage: true
})
// Compare environment requirements
diff_env_requirements({
currentEnv: { navigator: true, document: false },
requiredEnv: { navigator: true, document: true, XMLHttpRequest: true }
})
// Record evidence
record_reverse_evidence({
taskId: "jd-h5st-20240517",
evidence: {
type: "hook-capture",
functionName: "h5st",
args: [...],
returnValue: "..."
}
})// Save current session
save_session_state({
snapshotId: "logged-in-state"
})
// Restore session
restore_session_state({
snapshotId: "logged-in-state"
})
// Export to file
dump_session_state({
snapshotId: "logged-in-state",
outputPath: "artifacts/tasks/my-task/session.json"
})
// Load from file
load_session_state({
source: "artifacts/tasks/my-task/session.json"
})// Navigate
navigate_page({ url: "https://example.com/login" })
// Query DOM
query_dom({ selector: "button.submit" })
// Click element
click_element({ selector: "button.submit" })
// Type text
type_text({
selector: "input[name='username']",
text: "testuser"
})
// Take screenshot
take_screenshot({
outputPath: "artifacts/tasks/my-task/screenshot.png"
})// Step 1: Check browser connection
check_browser_health()
// Step 2: Navigate to target page
navigate_page({ url: "https://example.com/api-page" })
// Step 3: List network requests
const requests = list_network_requests({
filterUrl: "*api*",
filterMethod: "POST"
})
// Step 4: Find target request
const targetRequest = get_network_request({
requestId: requests[0].id
})
// Notice: request has "sign" parameter
// Step 5: Search for "sign" in scripts
const searchResults = search_in_scripts({
searchText: "sign:",
maxResults: 10
})
// Step 6: Hook the sign function
hook_function({
functionPath: "window.generateSign",
options: {
captureArgs: true,
captureReturn: true,
captureStack: true
}
})
// Step 7: Trigger request again (click button, etc.)
click_element({ selector: "button.load-data" })
// Step 8: Get hook data
const hookData = get_hook_data({
hookId: "auto-hook-generateSign"
})
// Review arguments and return value
// Step 9: Get script source for deeper analysis
const scriptSource = get_script_source({
url: hookData.stack[0].url
})
// Step 10: Deobfuscate if needed
const cleaned = deobfuscate_code({
source: scriptSource,
options: { renameVariables: true, removeDeadCode: true }
})
// Step 11: Export rebuild bundle
export_rebuild_bundle({
taskId: "example-sign-20240517",
includeScripts: true,
includeNetwork: true,
includeStorage: true
})
// Step 12: Record evidence
record_reverse_evidence({
taskId: "example-sign-20240517",
evidence: {
type: "function-hook",
functionName: "generateSign",
sampleInput: hookData.calls[0].args,
sampleOutput: hookData.calls[0].return
}
})artifacts/tasks/<task-id>/artifacts/tasks/my-reverse-task/
├── task.json # Task metadata
├── runtime-evidence.jsonl # Hook/trace data
├── network.jsonl # Network requests
├── scripts.jsonl # Script sources
├── env/
│ ├── env.js # Base environment shims
│ ├── polyfills.js # Proxy diagnostics, watch
│ ├── entry.js # Entry point for local rebuild
│ └── capture.json # Runtime captures
├── run/ # Test runs
└── report.md # Analysis reportartifacts/tasks/_TEMPLATE/scripts/cases/jd-h5st-pure-node.mjsscripts/cases/ks-hxfalcon-pure-node.mjsscripts/cases/douyin-a-bogus-pure-node.mjsscripts/cases/README.md// Search for crypto keywords
search_in_scripts({ searchText: "CryptoJS.AES" })
// Hook the encryption call
hook_function({
functionPath: "CryptoJS.AES.encrypt",
options: { captureArgs: true, captureReturn: true }
})
// Trigger encryption, review hook data
get_hook_data({ hookId: "auto-hook-CryptoJS.AES.encrypt" })// Set breakpoint when request fires
break_on_xhr({ urlPattern: "*api.example.com*" })
// When paused, check call stack
// Identify the function that generated parameters
// Resume and hook that function
resume()
hook_function({ functionPath: "window.buildParams" })
// Trigger again, get hook data
get_hook_data({ hookId: "auto-hook-buildParams" })// Get obfuscated script
const script = get_script_source({ scriptId: "123" })
// Deobfuscate
const cleaned = deobfuscate_code({
source: script.source,
options: {
renameVariables: true,
removeDeadCode: true,
simplifyExpressions: true
}
})
// Understand with AI (requires provider configured)
understand_code({
source: cleaned.code,
context: "API signature generation"
})// After gathering evidence
export_rebuild_bundle({
taskId: "my-api-20240517",
includeScripts: true,
includeNetwork: true,
includeStorage: true
})
// Check artifacts/tasks/my-api-20240517/env/entry.js
// Run locally:
// node artifacts/tasks/my-api-20240517/env/entry.js
// If errors occur, diff environment
diff_env_requirements({
currentEnv: {}, // Populated from Node.js runtime check
requiredEnv: {} // Populated from error messages
})
// Patch env/env.js and env/polyfills.js iterativelycheck_browser_health--remote-debugging-port=9222--browserUrlhttp://localhost:9222get_hook_datainject_hooklist_console_messages()window.functionName{ renameVariables: false }understand_coderuntime-evidence.jsonldiff_env_requirementsenv/env.jswatchenv/polyfills.jsunderstand_codeDEFAULT_LLM_PROVIDERANTHROPIC_API_KEYOPENAI_API_KEYANTHROPIC_BASE_URLrestore_session_statehttpOnlydocs/reference/tool-reference.mddocs/reference/reverse-workflow.mddocs/reference/case-safety-policy.mddocs/reference/env-patching.mddocs/reference/reverse-artifacts.mddocs/guides/browser-connection.mddocs/guides/client-configuration.mdscripts/cases/