ScriptX MCP APK、资源与 Smali 工具
ScriptX MCP APK、资源与 Smali 工具
这一组工具围绕已经缓存的 APK 工作区工作,覆盖文件树、Smali、Manifest、原始 APK 条目、resources.arsc、安全检查和版本差异。
当前源码注册 18 个工具。本页每个二级标题都对应一个可直接调用的 MCP 工具;工具名和参数名区分大小写。
调用前提
- 这里记录的是 ScriptX 设置页启动的内置 MCP 服务,不是脚本侧用于自建服务的
mcpServer对象。 - 返回对象以
ok表示业务是否成功,message给出可读原因,具体数据位于result。HTTP 请求成功不等于工具执行成功。 - 需要 APK 工作区的工具,应先调用
get_analysis_state或list_apk_workspaces,再使用返回的真实projectDir。 - 带
confirm的安装、卸载、停止、导入等操作必须明确传true,避免外部 Agent 在未确认时产生副作用。
compare_apk_workspaces
比较两个已缓存 APK 的身份、Manifest、DEX 索引、资源、SO 和安全差异。结果提供精确计数与有界样本,不加载 apk_refs,也不会修改 APK 或缓存工作区。
显示名称:比较 APK 工作区
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
baseProjectDir | string | 是 | - | 基准 APK 工作区,通常为旧版本。 |
targetProjectDir | string | 是 | - | 目标 APK 工作区,通常为新版本。 |
sections | array | 否 | 数组项可填:manifest、dex、resources、native、security | 要比较的部分;默认全部。身份信息始终返回。 |
maxItems | number | 否 | 最小 1;最大 50 | 每种变化类型最多返回的样本数,默认 20,最大 50;总计数不受此限制。 |
includeSignature | boolean | 否 | true / false;默认 true | security 部分是否校验并比较 APK 签名;默认 true。 |
maxComponents | number | 否 | 最小 1;最大 2000 | 每个 APK 最多检查的 Manifest 组件数,默认 500,最大 2000。 |
maxFindings | number | 否 | 最小 1;最大 500 | 每个 APK 最多返回的安全发现数,默认 100,最大 500。 |
requireSamePackage | boolean | 否 | true / false;默认 true | 是否要求两个 APK 包名一致;默认 true,防止把不同应用误判为版本升级。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"compare_apk_workspaces","arguments":{"baseProjectDir":"project_old","targetProjectDir":"project_new","sections":["manifest","dex","resources","native","security"],"maxItems":20,"includeSignature":true,"requireSamePackage":true}}
find_usages
用途
在当前活动工作区里追踪类或方法被谁引用了,适合逆向时找调用点、找入口、找某个类被哪些地方触达。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
signature | string | 是 | 完整类或方法签名 | 例如类描述符或完整方法签名 |
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
signature | string | 你传入的目标签名 |
text | string | 面向人阅读的引用摘要文本,每行类似 [METHOD] source -> target @ file:line |
hits | object[] | 结构化引用数组 |
hits[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
sourceSignature | string | 发起引用的一侧签名 |
targetSignature | string | 你当前查的目标签名,或者与之对应的引用目标 |
filePath | string | 引用出现的文件路径 |
lineNumber | number | 引用出现行号 |
refType | string | 引用类型 |
refType 常见值
CLASSFIELDMETHOD
示例
按方法签名查引用:
{
"name": "find_usages",
"arguments": {
"signature": "Lcom/example/Utils;->login(Ljava/lang/String;)V"
}
}
返回示例
{
"ok": true,
"message": "已返回引用列表",
"result": {
"signature": "Lcom/example/Utils;->login(Ljava/lang/String;)V",
"text": "[METHOD] Lcom/example/MainActivity;->onClickLogin()V -> Lcom/example/Utils;->login(Ljava/lang/String;)V @ smali/com/example/MainActivity.smali:88",
"hits": [
{
"sourceSignature": "Lcom/example/MainActivity;->onClickLogin()V",
"targetSignature": "Lcom/example/Utils;->login(Ljava/lang/String;)V",
"filePath": "smali/com/example/MainActivity.smali",
"lineNumber": 88,
"refType": "METHOD"
}
]
}
}
按类描述符查引用:
{
"name": "find_usages",
"arguments": {
"signature": "Lcom/example/MainActivity;"
}
}
补充说明
- 如果你现在只知道一个模糊关键词,先
search_code,再把搜出来的类描述符或方法签名喂给这里。
get_analysis_state
用途
看当前 APK 缓存是什么状态,有没有活动工作区,索引走到哪一步了,以及缓存里一共挂着几个工作区。
参数
这个工具没有参数。
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
state | object | 当前活动工作区状态对象;这是最核心的一块 |
activeWorkspace | object | null | 当前活动工作区摘要;没有活动工作区时可能为 null |
workspaceCount | number | 当前缓存里有多少个 APK 工作区 |
workspaces | object[] | 所有缓存工作区的摘要数组 |
state 字段详解
| 字段 | 类型 | 典型值 | 说明 |
|---|---|---|---|
projectDir | string | null | project_xxx | 当前活动工作区目录名;没有活动工作区时可能为 null |
status | string | IDLE、INDEXING、READY、ERROR | 当前工作区整体状态 |
indexing | boolean | true / false | 当前是否正在建索引 |
progressStage | string | COPYING、PARSING 等 | 当前索引阶段 |
progressPercent | number | 0 到 100 | 当前阶段进度百分比 |
hasWorkspace | boolean | true / false | 当前是否有可用活动工作区 |
isReady | boolean | true / false | 当前活动工作区是否已经 ready |
sourceName | string | 例如 APK 文件名 | 导入源文件名;没有活动工作区时通常为空字符串 |
sourceUri | string | URI 字符串 | 导入时记录的源 URI |
sourceSha256 | string | 一段哈希值 | 源 APK 的 SHA-256 |
packageName | string | com.example.app | APK 包名 |
appLabel | string | 应用名 | APK 应用显示名 |
versionName | string | 1.0.0 | APK 版本名 |
versionCode | number | 1、10086 | APK 版本号 |
cachedApkPath | string | 本地绝对路径 | 缓存后的 APK 文件路径 |
smaliRootPath | string | 本地绝对路径 | 当前工作区 Smali 根目录路径 |
manifestPath | string | 本地绝对路径 | Manifest 文件路径 |
dexCount | number | 非负整数 | Dex 数量 |
classCount | number | 非负整数 | 类数量 |
methodCount | number | 非负整数 | 方法数量 |
fieldCount | number | 非负整数 | 字段数量 |
stringCount | number | 非负整数 | 字符串常量数量 |
refCount | number | 非负整数 | 引用关系数量 |
lastIndexedAt | number | 时间戳 | 最近一次完成索引的 Unix 毫秒时间戳 |
lastError | string | 错误信息 | 最近一次错误信息;没有错误时通常为空字符串 |
status 可选值
IDLE:当前没有可用活动工作区INDEXING:正在建索引READY:工作区可正常使用ERROR:上次索引或读取失败
progressStage 可选值
IDLECOPYINGPREPARINGDISASSEMBLINGPARSINGPERSISTING
activeWorkspace / workspaces[] 摘要字段
这两个对象的字段结构是同一套,区别只是:
activeWorkspace:当前那一个workspaces[]:全部缓存工作区列表
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 工作区名 |
sourceName | string | 源 APK 名 |
packageName | string | APK 包名 |
appLabel | string | 应用显示名 |
versionName | string | 版本名 |
versionCode | number | 版本号 |
indexStatus | string | 当前索引状态,常见 READY / INDEXING / ERROR |
lastError | string | 最近一次错误信息 |
cachedApkPath | string | 缓存 APK 绝对路径 |
smaliRootPath | string | 工作区根路径 |
manifestPath | string | Manifest 路径 |
dexCount | number | Dex 数量 |
classCount | number | 类数量 |
methodCount | number | 方法数量 |
fieldCount | number | 字段数量 |
stringCount | number | 字符串数量 |
refCount | number | 引用数量 |
createdAt | number | 创建时间的 Unix 毫秒时间戳 |
updatedAt | number | 最近更新时间的 Unix 毫秒时间戳 |
lastIndexedAt | number | 最近索引完成时间的 Unix 毫秒时间戳 |
示例
{
"name": "get_analysis_state",
"arguments": {}
}
返回示例
{
"ok": true,
"message": "APK 分析状态已返回",
"result": {
"state": {
"projectDir": "project_demo",
"status": "READY",
"indexing": false,
"progressStage": "IDLE",
"progressPercent": 0,
"hasWorkspace": true,
"isReady": true,
"sourceName": "demo.apk",
"sourceUri": "content://apk/demo.apk",
"sourceSha256": "abc123",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"cachedApkPath": "/apkcache/project_demo/source.apk",
"smaliRootPath": "/apkcache/project_demo",
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"dexCount": 2,
"classCount": 860,
"methodCount": 7421,
"fieldCount": 1948,
"stringCount": 3288,
"refCount": 12004,
"lastIndexedAt": 1715000000000,
"lastError": ""
},
"activeWorkspace": {
"projectDir": "project_demo",
"sourceName": "demo.apk",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"indexStatus": "READY",
"lastError": "",
"cachedApkPath": "/apkcache/project_demo/source.apk",
"smaliRootPath": "/apkcache/project_demo",
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"dexCount": 2,
"classCount": 860,
"methodCount": 7421,
"fieldCount": 1948,
"stringCount": 3288,
"refCount": 12004,
"createdAt": 1714999999000,
"updatedAt": 1715000000000,
"lastIndexedAt": 1715000000000
},
"workspaceCount": 1,
"workspaces": [
{
"projectDir": "project_demo",
"sourceName": "demo.apk",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"indexStatus": "READY",
"lastError": "",
"cachedApkPath": "/apkcache/project_demo/source.apk",
"smaliRootPath": "/apkcache/project_demo",
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"dexCount": 2,
"classCount": 860,
"methodCount": 7421,
"fieldCount": 1948,
"stringCount": 3288,
"refCount": 12004,
"createdAt": 1714999999000,
"updatedAt": 1715000000000,
"lastIndexedAt": 1715000000000
}
]
}
}
补充说明
- 这是 APK 分析链路里最适合第一个调的工具。
- 如果你看到
status=INDEXING,后面很多读取类工具暂时都不该急着调。
get_class_by_descriptor
用途
你已经知道完整类描述符时,不想先搜路径,直接一步定位类。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | 形如 project_xxx | 目标工作区 |
classDescriptor | string | 是 | 完整类描述符 | 例如 Lcom/example/MainActivity; |
适合场景
- 你已经从
search_code、日志、别的分析工具拿到了类描述符 - 你不想再自己拼
smali/.../*.smali路径
返回结构
这个工具当前返回的结构和 get_class_info 同形,本质上也是一份完整类快照,因此你可以直接按 get_class_info 那套字段表理解:
projectDirfileclassInfofieldsmethodsstrings
示例
{
"name": "get_class_by_descriptor",
"arguments": {
"projectDir": "project_xxx",
"classDescriptor": "Lcom/example/MainActivity;"
}
}
返回示例
{
"ok": true,
"message": "类已定位",
"result": {
"projectDir": "project_demo",
"file": {
"relativePath": "smali/com/example/MainActivity.smali",
"displayName": "MainActivity.smali",
"kind": "SMALI",
"classDescriptor": "Lcom/example/MainActivity;"
},
"classInfo": {
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"packageName": "com.example",
"filePath": "smali/com/example/MainActivity.smali",
"superClass": "Landroid/app/Activity;",
"interfaces": [],
"accessFlags": "public",
"fieldCount": 1,
"methodCount": 3
},
"fields": [
{
"fieldSignature": "Lcom/example/MainActivity;->title:Ljava/lang/String;",
"fieldName": "title"
}
],
"methods": [
{
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"methodName": "onCreate"
}
],
"strings": [
{
"value": "hello",
"lineNumber": 39
}
]
}
}
补充说明
- 这个工具按
projectDir + classDescriptor直接查数据库里的类记录,再回到对应文件抓完整类快照。 - 如果当前还在建索引,会先提示你等待索引完成。
get_class_info
用途
按 Smali 文件读取类的结构化元数据,适合你要拿字段、方法、字符串列表继续做程序化处理的时候用。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
filePath | string | 是 | Smali 类文件路径 | 推荐完整写成 project_xxx/... |
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 当前类所在工作区 |
file | object | 这个类文件本身的元数据 |
classInfo | object | 类本体的结构信息 |
fields | object[] | 当前类的字段数组 |
methods | object[] | 当前类的方法数组 |
strings | object[] | 当前类里提取到的字符串常量数组 |
file 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 工作区名 |
relativePath | string | 工作区内相对路径 |
parentPath | string | 父目录相对路径 |
displayName | string | 展示名,通常就是文件名 |
isDirectory | boolean | 这里一般应为 false,因为它是类文件 |
kind | string | 常见为 SMALI |
classDescriptor | string | null | 该文件对应的类描述符 |
byteSize | number | 文件字节数 |
lineCount | number | 行数 |
classInfo 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 工作区名 |
classDescriptor | string | 完整类描述符,如 Lcom/example/MainActivity; |
className | string | 类名 |
packageName | string | 包名 |
filePath | string | 类文件相对路径 |
superClass | string | null | 父类描述符 |
interfaces | string[] | 接口描述符数组 |
sourceFile | string | null | 源文件名标记 |
accessFlags | string | 访问修饰信息,如 public final、abstract 等组合 |
lineNumber | number | 类声明行号 |
fieldCount | number | 字段数量 |
methodCount | number | 方法数量 |
fields[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
fieldSignature | string | 完整字段签名 |
classDescriptor | string | 所属类描述符 |
className | string | 所属类名 |
fieldName | string | 字段名 |
typeDescriptor | string | 字段类型描述符 |
accessFlags | string | 字段访问修饰 |
filePath | string | 所在文件路径 |
lineNumber | number | 字段声明行号 |
initialValue | string | null | 初始值;没有时可能为空 |
methods[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
methodSignature | string | 完整方法签名 |
classDescriptor | string | 所属类描述符 |
className | string | 所属类名 |
methodName | string | 方法名 |
descriptor | string | 方法描述符,不含类前缀 |
returnType | string | 返回值类型 |
parameterTypes | string[] | 参数类型数组,按声明顺序排列 |
accessFlags | string | 方法访问修饰 |
filePath | string | 所在文件路径 |
startLine | number | 方法起始行 |
endLine | number | 方法结束行 |
bodyLineCount | number | 方法体行数 |
strings[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
value | string | 字符串字面量内容 |
classDescriptor | string | 所属类描述符 |
methodSignature | string | null | 所在方法签名;如果无法归属到具体方法,可能为空 |
filePath | string | 所在文件路径 |
lineNumber | number | 出现行号 |
示例
{
"name": "get_class_info",
"arguments": {
"filePath": "project_xxx/smali/com/example/MainActivity.smali"
}
}
返回示例
{
"ok": true,
"message": "已读取类信息",
"result": {
"projectDir": "project_demo",
"file": {
"projectDir": "project_demo",
"relativePath": "smali/com/example/MainActivity.smali",
"parentPath": "smali/com/example",
"displayName": "MainActivity.smali",
"isDirectory": false,
"kind": "SMALI",
"classDescriptor": "Lcom/example/MainActivity;",
"byteSize": 4182,
"lineCount": 156
},
"classInfo": {
"projectDir": "project_demo",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"packageName": "com.example",
"filePath": "smali/com/example/MainActivity.smali",
"superClass": "Landroid/app/Activity;",
"interfaces": [],
"sourceFile": "MainActivity.java",
"accessFlags": "public",
"lineNumber": 1,
"fieldCount": 1,
"methodCount": 3
},
"fields": [
{
"projectDir": "project_demo",
"fieldSignature": "Lcom/example/MainActivity;->title:Ljava/lang/String;",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"fieldName": "title",
"typeDescriptor": "Ljava/lang/String;",
"accessFlags": "private",
"filePath": "smali/com/example/MainActivity.smali",
"lineNumber": 8,
"initialValue": null
}
],
"methods": [
{
"projectDir": "project_demo",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"methodName": "onCreate",
"descriptor": "(Landroid/os/Bundle;)V",
"returnType": "V",
"parameterTypes": [
"Landroid/os/Bundle;"
],
"accessFlags": "protected",
"filePath": "smali/com/example/MainActivity.smali",
"startLine": 28,
"endLine": 56,
"bodyLineCount": 29
}
],
"strings": [
{
"projectDir": "project_demo",
"value": "hello",
"classDescriptor": "Lcom/example/MainActivity;",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"filePath": "smali/com/example/MainActivity.smali",
"lineNumber": 39
}
]
}
}
补充说明
- 这个工具要求目标文件真的是 Smali 类文件;如果你塞的是别的路径,会报错。
get_manifest
用途
读取某个 APK 工作区的 AndroidManifest.xml,同时带回包名、应用名、版本号这些基础信息。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | 形如 project_xxx | 工作区目录名 |
返回字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 工作区名 |
packageName | string | APK 包名 |
appLabel | string | 应用显示名 |
versionName | string | 版本名 |
versionCode | number | 版本号 |
manifestPath | string | Manifest 文件的本地绝对路径 |
manifestXml | string | Manifest 原始 XML 文本 |
text | string | 和 manifestXml 相同的兼容字段,方便某些客户端统一按 text 读正文 |
示例
{
"name": "get_manifest",
"arguments": {
"projectDir": "project_xxx"
}
}
返回示例
{
"ok": true,
"message": "已读取 Manifest",
"result": {
"projectDir": "project_demo",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"manifestXml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.example.demo\" />",
"text": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.example.demo\" />"
}
}
补充说明
- 如果你只是想拿原始文本,
read_file读project_xxx/AndroidManifest.xml也能做到。 - 如果你需要包名、版本号、路径这些结构化信息,这个工具更合适。
get_method_by_signature
用途
你已经知道完整方法签名时,直接一步拿到方法元数据和方法体。这是定位重载方法时最稳的方式。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | 形如 project_xxx | 目标工作区 |
methodSignature | string | 是 | 完整方法签名 | 例如 Lcom/example/Utils;->login(Ljava/lang/String;)V |
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 目标工作区 |
methodSignature | string | 你传入的完整方法签名 |
workspace | object | null | 工作区摘要对象;字段结构和上面 get_analysis_state 里的 activeWorkspace 相同 |
filePath | string | 该方法所在 Smali 文件的工作区相对路径 |
method | object | 这个方法本身的结构化信息 |
content | string | 方法体正文 |
text | string | 和 content 相同的兼容字段 |
method 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 工作区名 |
methodSignature | string | 完整方法签名 |
classDescriptor | string | 所属类描述符 |
className | string | 所属类名 |
methodName | string | 方法名 |
descriptor | string | 方法描述符本体 |
returnType | string | 返回值类型 |
parameterTypes | string[] | 参数类型数组;常见元素如 Ljava/lang/String;、I、Z |
accessFlags | string | 方法访问修饰 |
filePath | string | 所在文件相对路径 |
startLine | number | 当前方法在清洗后文本里的起始行 |
endLine | number | 当前方法在清洗后文本里的结束行 |
bodyLineCount | number | 当前方法正文总行数 |
示例
{
"name": "get_method_by_signature",
"arguments": {
"projectDir": "project_xxx",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V"
}
}
返回示例
{
"ok": true,
"message": "方法已定位",
"result": {
"projectDir": "project_demo",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"workspace": {
"projectDir": "project_demo",
"sourceName": "demo.apk",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"indexStatus": "READY",
"lastError": "",
"cachedApkPath": "/apkcache/project_demo/source.apk",
"smaliRootPath": "/apkcache/project_demo",
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"dexCount": 2,
"classCount": 860,
"methodCount": 7421,
"fieldCount": 1948,
"stringCount": 3288,
"refCount": 12004,
"createdAt": 1714999999000,
"updatedAt": 1715000000000,
"lastIndexedAt": 1715000000000
},
"filePath": "smali/com/example/MainActivity.smali",
"method": {
"projectDir": "project_demo",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"methodName": "onCreate",
"descriptor": "(Landroid/os/Bundle;)V",
"returnType": "V",
"parameterTypes": [
"Landroid/os/Bundle;"
],
"accessFlags": "protected",
"filePath": "smali/com/example/MainActivity.smali",
"startLine": 28,
"endLine": 56,
"bodyLineCount": 29
},
"content": ".method protected onCreate(Landroid/os/Bundle;)V\n .locals 1\n return-void\n.end method",
"text": ".method protected onCreate(Landroid/os/Bundle;)V\n .locals 1\n return-void\n.end method"
}
}
补充说明
- 和
get_method_content相比,这个工具不会先按方法名猜;你给什么完整签名,它就精确找什么。 - 如果你处理的是重载非常多的方法,这个工具通常是首选。
get_method_content
用途
当你只知道方法名,不知道完整签名时,用它从某个 Smali 文件里提一个方法体出来。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
filePath | string | 是 | Smali 文件路径 | 推荐完整写成 project_xxx/... |
methodName | string | 是 | 方法名 | 支持精确名和包含匹配 |
匹配规则
- 先做忽略大小写的精确方法名匹配
- 如果精确匹配不到,再做包含匹配
- 候选结果会按
startLine再按methodSignature排序 - 真正返回给你的主结果是排序后的第一个,全部候选同时会放在
candidates里
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 当前工作区名 |
filePath | string | 目标 Smali 文件相对路径 |
classDescriptor | string | null | 当前文件对应的类描述符 |
method | object | 最终选中的那个方法对象;字段结构和 get_method_by_signature 里的 method 相同 |
candidates | object[] | 所有候选方法数组;字段结构也和 method 相同 |
content | string | 最终选中方法的方法体正文 |
text | string | 和 content 相同的兼容字段 |
示例
{
"name": "get_method_content",
"arguments": {
"filePath": "project_xxx/smali/com/example/MainActivity.smali",
"methodName": "onCreate"
}
}
返回示例
{
"ok": true,
"message": "已提取方法",
"result": {
"projectDir": "project_demo",
"filePath": "smali/com/example/MainActivity.smali",
"classDescriptor": "Lcom/example/MainActivity;",
"method": {
"projectDir": "project_demo",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"methodName": "onCreate",
"descriptor": "(Landroid/os/Bundle;)V",
"returnType": "V",
"parameterTypes": [
"Landroid/os/Bundle;"
],
"accessFlags": "protected",
"filePath": "smali/com/example/MainActivity.smali",
"startLine": 28,
"endLine": 56,
"bodyLineCount": 29
},
"candidates": [
{
"projectDir": "project_demo",
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"methodName": "onCreate",
"descriptor": "(Landroid/os/Bundle;)V",
"returnType": "V",
"parameterTypes": [
"Landroid/os/Bundle;"
],
"accessFlags": "protected",
"filePath": "smali/com/example/MainActivity.smali",
"startLine": 28,
"endLine": 56,
"bodyLineCount": 29
}
],
"content": ".method protected onCreate(Landroid/os/Bundle;)V\n .locals 1\n return-void\n.end method",
"text": ".method protected onCreate(Landroid/os/Bundle;)V\n .locals 1\n return-void\n.end method"
}
}
补充说明
- 如果同一个类里有多个同名重载方法,这个工具仍然能用,但你要自己看
candidates。 - 已经知道完整方法签名时,
get_method_by_signature更稳。
inspect_apk_security
聚合检查 Manifest、权限、导出组件、深链、备份和网络配置、FileProvider、框架特征及 APK 签名,返回有证据的分级发现。
显示名称:APK 安全总览
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | - | APK 工作区目录名。 |
includeSignature | boolean | 否 | true / false;默认 true | 是否校验 APK 签名并返回证书摘要,默认 true。 |
maxComponents | number | 否 | 最小 1;最大 2000 | 最多返回的组件数,默认 500,最大 2000。 |
maxFindings | number | 否 | 最小 1;最大 500 | 最多返回的安全发现数,默认 100,最大 500。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"inspect_apk_security","arguments":{"projectDir":"project_xxx","includeSignature":true}}
inspect_class
用途
快速看一个类的整体结构。名字更偏“先浏览一下”,适合从陌生类开始看继承、字段、方法列表。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
path | string | 是 | Smali 类文件路径 | 推荐完整写成 project_xxx/... |
返回结构
这个工具当前返回的结构和 get_class_info 完全同形,也就是同样会返回:
projectDirfileclassInfofieldsmethodsstrings
示例
{
"name": "inspect_class",
"arguments": {
"path": "project_xxx/smali/com/example/MainActivity.smali"
}
}
返回示例
{
"ok": true,
"message": "已读取类结构",
"result": {
"projectDir": "project_demo",
"file": {
"relativePath": "smali/com/example/MainActivity.smali",
"displayName": "MainActivity.smali",
"kind": "SMALI"
},
"classInfo": {
"classDescriptor": "Lcom/example/MainActivity;",
"className": "MainActivity",
"superClass": "Landroid/app/Activity;",
"interfaces": [],
"fieldCount": 1,
"methodCount": 3
},
"fields": [
{
"fieldSignature": "Lcom/example/MainActivity;->title:Ljava/lang/String;",
"fieldName": "title",
"typeDescriptor": "Ljava/lang/String;"
}
],
"methods": [
{
"methodSignature": "Lcom/example/MainActivity;->onCreate(Landroid/os/Bundle;)V",
"methodName": "onCreate",
"accessFlags": "protected"
}
],
"strings": [
{
"value": "hello",
"lineNumber": 39
}
]
}
}
补充说明
- 当前实现底层就是走和
get_class_info相同的类快照数据。 - 也就是说,结果结构基本一样;区别主要在于你调用它时的阅读语义:
inspect_class更像“先总览一下”,get_class_info更像“我要结构化数据”。
list_apk_entries
按需浏览缓存 APK 的原始 ZIP 文件树,覆盖 assets、res、resources.arsc、DEX、SO 与 META-INF,并返回压缩和 MIME 元数据。
显示名称:浏览 APK 原始条目
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | - | APK 工作区目录名,例如 project_xxx。 |
prefix | string | 否 | - | APK 内路径前缀,例如 assets 或 res/xml;默认根目录。 |
kind | string | 否 | 可填:all、assets、res、xml、arsc、manifest、native、dex、meta、other | 条目类型,默认 all。 |
extension | string | 否 | - | 可选扩展名过滤,例如 json、xml 或 png。 |
recursive | boolean | 否 | true / false;默认 false | 是否递归列出全部后代;默认 false,只返回当前层。 |
cursor | string | 否 | - | 上一页返回的游标。 |
limit | number | 否 | 最小 1;最大 500 | 每页条目数,默认 100,最大 500。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"list_apk_entries","arguments":{"projectDir":"project_xxx","prefix":"assets","kind":"assets","recursive":true,"limit":100}}
list_apk_workspaces
用途
列出当前缓存中的 APK 工作区,方便你确认到底缓存了哪些 APK,以及当前激活的是哪一个。
参数
这个工具没有参数。
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
activeProjectDir | string | null | 当前活动工作区名;没有活动工作区时可能为 null |
workspaceCount | number | 当前缓存中的工作区数量 |
workspaces | object[] | 工作区摘要数组 |
workspaces[] 字段
workspaces[] 的字段结构和上面 get_analysis_state 里的 activeWorkspace / workspaces[] 摘要对象相同,最常看的仍然是:
projectDirsourceNamepackageNameappLabelversionNameversionCodeindexStatuslastError
indexStatus 可选值
READYINDEXINGERROR
示例
{
"name": "list_apk_workspaces",
"arguments": {}
}
返回示例
{
"ok": true,
"message": "APK 工作区列表已返回",
"result": {
"activeProjectDir": "project_demo",
"workspaceCount": 1,
"workspaces": [
{
"projectDir": "project_demo",
"sourceName": "demo.apk",
"packageName": "com.example.demo",
"appLabel": "Demo",
"versionName": "1.0.0",
"versionCode": 1,
"indexStatus": "READY",
"lastError": "",
"cachedApkPath": "/apkcache/project_demo/source.apk",
"smaliRootPath": "/apkcache/project_demo",
"manifestPath": "/apkcache/project_demo/AndroidManifest.xml",
"dexCount": 2,
"classCount": 860,
"methodCount": 7421,
"fieldCount": 1948,
"stringCount": 3288,
"refCount": 12004,
"createdAt": 1714999999000,
"updatedAt": 1715000000000,
"lastIndexedAt": 1715000000000
}
]
}
}
补充说明
- 如果你缓存过多个 APK,这个工具特别适合先把它们列出来,再决定后面要查哪一个。
list_files
用途
列出 APK 工作区里的目录或文件,适合先在 smali/、smali_classes2/、AndroidManifest.xml 这些入口之间浏览。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | 形如 project_xxx | 工作区目录名 |
relativePath | string | 否 | 默认根目录 | 工作区内相对路径 |
路径规则
relativePath为空时,列工作区根目录。- 推荐写相对路径,比如
smali/com/example。 - 即使你把
relativePath写成project_xxx/smali/com/example,内部也会尽量帮你剥掉前缀。 - 如果
relativePath指到的是一个文件而不是目录,当前实现返回的是它所在父目录的列表,不是文件内容。
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | 你传入的工作区名 |
relativePath | string | 你传入的相对路径;为空字符串时表示根目录 |
text | string | 面向人阅读的简短目录文本,比如 [DIR] smali、[FILE] AndroidManifest.xml |
entries | object[] | 结构化目录项数组 |
entries[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 目录项显示名 |
path | string | 目录项在工作区里的相对路径 |
kind | string | 目录项类型 |
isDirectory | boolean | 是否为目录 |
kind 常见值
DIRSMALIMANIFEST
示例
列根目录:
{
"name": "list_files",
"arguments": {
"projectDir": "project_xxx"
}
}
列某个包目录:
{
"name": "list_files",
"arguments": {
"projectDir": "project_xxx",
"relativePath": "smali/com/example"
}
}
返回示例
{
"ok": true,
"message": "已返回文件列表",
"result": {
"projectDir": "project_demo",
"relativePath": "smali/com/example",
"text": "[FILE] MainActivity.smali\n[FILE] Utils.smali",
"entries": [
{
"name": "MainActivity.smali",
"path": "smali/com/example/MainActivity.smali",
"kind": "SMALI",
"isDirectory": false
},
{
"name": "Utils.smali",
"path": "smali/com/example/Utils.smali",
"kind": "SMALI",
"isDirectory": false
}
]
}
}
补充说明
- 想读文件正文时,用
read_file,不要拿list_files代替。
read_apk_entry
受限读取 APK 内的文本或二进制条目,支持文本、二进制 XML 解码、十六进制、Base64、元数据与字节范围。
显示名称:读取 APK 原始条目
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | - | APK 工作区目录名。 |
path | string | 是 | - | APK 内的精确条目路径,例如 assets/config.json。 |
mode | string | 否 | 可填:auto、text、decoded_xml、hex、base64、metadata | 读取模式,默认 auto。 |
offset | number | 否 | 最小 0;最大 16777216 | 原始条目的字节偏移,默认 0,最大 16777216;decoded_xml 不支持非零偏移。 |
limit | number | 否 | 最小 1;最大 262144 | 最多返回的原始或解码后字节数,默认 65536,最大 262144。 |
encoding | string | 否 | auto / UTF-8 / UTF-16LE / UTF-16BE / GB18030 / ISO-8859-1;默认 auto | text 模式编码,默认 auto;可选 UTF-8、UTF-16LE、UTF-16BE、GB18030、ISO-8859-1。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"read_apk_entry","arguments":{"projectDir":"project_xxx","path":"res/xml/network_security_config.xml","mode":"decoded_xml"}}
read_file
用途
读取指定工作区文件的正文。最常见的是读 .smali 文件,也可以读 AndroidManifest.xml。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
path | string | 是 | 工作区文件路径 | 最稳的写法是 project_xxx/... |
路径规则
- 推荐写完整路径,例如:
project_xxx/smali/com/example/MainActivity.smaliproject_xxx/AndroidManifest.xml
- 如果当前已经有活动工作区,也可以只写相对路径;但为了不串工作区,不推荐省略。
行为细节
- 读取 Smali 内容时,会清理掉
.line这类调试指令,方便你直接阅读。 - 读 Manifest 时,也会返回文本正文。
返回字段
| 字段 | 类型 | 说明 |
|---|---|---|
path | string | 你传入的路径 |
content | string | 读取到的正文文本;Smali 会先清理掉 .line 等调试指令 |
示例
读取 Smali:
{
"name": "read_file",
"arguments": {
"path": "project_xxx/smali/com/example/MainActivity.smali"
}
}
返回示例
{
"ok": true,
"message": "已读取文件",
"result": {
"path": "project_demo/AndroidManifest.xml",
"content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.example.demo\" />"
}
}
读取 Manifest:
{
"name": "read_file",
"arguments": {
"path": "project_xxx/AndroidManifest.xml"
}
}
补充说明
- 想看结构化 Manifest 信息时,优先
get_manifest。 - 想提单个方法体时,优先
get_method_content或get_method_by_signature。
resolve_apk_resource
把 0x7f...、@type/name 或资源名称解析为资源 ID、全部限定符配置、复杂值与有界引用链;损坏配置会被跳过并通过 warnings 返回。
显示名称:解析 APK 资源
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | - | APK 工作区目录名。 |
resource | string | 是 | - | 资源 ID、@type/name、package:type/name 或无类型资源名。 |
followReferences | boolean | 否 | true / false;默认 true | 是否返回引用链,默认 true。 |
maxMatches | number | 否 | 最小 1;最大 100 | 无类型名称查询最多返回的候选数,默认 25,最大 100。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"resolve_apk_resource","arguments":{"projectDir":"project_xxx","resource":"0x7f12008a","followReferences":true}}
search_apk_resources
统一搜索 APK 路径、assets 文本、res 文本、解码 XML 以及 resources.arsc 中的资源名称和值;损坏资源会被跳过并通过 warnings 返回。
显示名称:搜索 APK 资源
参数
| 参数 | 类型 | 必填 | 可填值 / 范围 | 说明 |
|---|---|---|---|---|
projectDir | string | 是 | - | APK 工作区目录名。 |
query | string | 是 | - | 搜索关键字或正则表达式。 |
scope | string | 否 | 可填:all、assets、res、xml、arsc、paths | 搜索范围,默认 all。 |
match | string | 否 | 可填:contains、exact、regex | 匹配方式,默认 contains。 |
caseSensitive | boolean | 否 | true / false;默认 false | 是否区分大小写,默认 false。 |
cursor | string | 否 | - | 上一页返回的游标。 |
limit | number | 否 | 最小 1;最大 200 | 每页命中数,默认 50,最大 200。 |
maxScanBytes | number | 否 | 最小 1;最大 33554432 | 本次最多扫描的资源内容字节数,默认 4194304,最大 33554432。 |
maxResources | number | 否 | 最小 1;最大 250000 | 本次最多检查的 ARSC 资源数,默认 100000,最大 250000。 |
返回值
返回统一 MCP 结果对象:ok 表示调用是否成功,message 是可读说明,具体数据放在 result。分析尚未准备好、后端安装中或需要先缓存 APK 时,ok 可能为 false,应先读 message 与 result 中的状态字段再决定下一步。
示例
{"name":"search_apk_resources","arguments":{"projectDir":"project_xxx","query":"api.example.com","scope":"all","limit":50}}
search_code
用途
在当前活动工作区里搜索类、方法、字段和字符串常量。
参数
| 参数 | 类型 | 必填 | 可填值 / 默认 | 说明 |
|---|---|---|---|---|
query | string | 是 | 非空关键字 | 搜索词 |
匹配行为
- 这是包含式搜索,不是整词匹配。
- 当前实现会搜索 4 类对象:
CLASSMETHODFIELDSTRING
- 结果会按
filePath -> lineNumber -> kind -> signature排序。
顶层 result 字段
| 字段 | 类型 | 说明 |
|---|---|---|
projectDir | string | null | 当前活动工作区名;理论上正常可用时应有值 |
query | string | 你传入的搜索词 |
text | string | 面向人阅读的搜索摘要文本,每行类似 [METHOD] ... @ file:line |
hits | object[] | 结构化命中数组 |
hits[] 字段
| 字段 | 类型 | 说明 |
|---|---|---|
kind | string | 命中类型,当前可选 CLASS、METHOD、FIELD、STRING |
signature | string | 命中的完整签名或字符串内容 |
filePath | string | 命中所在文件的相对路径 |
lineNumber | number | 命中行号 |
示例
{
"name": "search_code",
"arguments": {
"query": "login"
}
}
返回示例
{
"ok": true,
"message": "已返回搜索结果",
"result": {
"projectDir": "project_demo",
"query": "login",
"text": "[METHOD] Lcom/example/Utils;->login(Ljava/lang/String;)V @ smali/com/example/Utils.smali:42",
"hits": [
{
"kind": "METHOD",
"signature": "Lcom/example/Utils;->login(Ljava/lang/String;)V",
"filePath": "smali/com/example/Utils.smali",
"lineNumber": 42
}
]
}
}
补充说明
- 这个工具没有
projectDir参数,所以你得先保证当前活动工作区就是你想查的那个。 - 如果你已经知道完整类描述符或方法签名,直接用
get_class_by_descriptor/get_method_by_signature会更准。
