npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ktbtw/verify-mcp

v0.2.34

Published

MCP server for Verify ApiToken public APIs

Readme

verify_mcp

基于 TypeScript 的 MCP 服务,用于把现有 ApiToken 公共接口封装成可供智能体直接调用的 MCP tools。

已发布 npm 包名:

@ktbtw/verify-mcp

目标

  • 运行形态:stdio
  • 后端来源:现有 /api/app-token/* 公共接口与旧加固提交接口。
  • 鉴权方式:VERIFY_API_TOKEN 用于配置/编译工具,VERIFY_PROTECT_TOKEN 用于 VMP、混淆、Dex2C、SO、注入等加固工具;两者可以只配置一个,调用未配置 token 的工具时会返回明确错误。
  • 当前已接入:
    • 上下文查询
    • 应用列表查询
    • 应用 apiKey / secretKey 查询
    • 验证接口签名规则与调用示例查询
    • 次数卡幂等消费
    • 配置列表/详情/创建/更新/删除
    • dex/zip 文件读取与更新
    • ShadowHook 运行库、host bridge、资源包与云代码入口一体化安装
    • Root 设备“持久化 WiFi ADB”模块批量安装、热激活与重连验证
    • 云端代码读取与推送
    • 编译配置修改
    • 云端代码编译
    • 编译任务列表/详情/下载/删除
    • 编译配额查询
    • Xposed 应用专属 ITHook.apk 构建预处理与下载
    • VMP / 混淆 / Dex2C / SO / 注入加固任务提交、列表、详情、下载、删除
    • 高阶流程工具:从工作区目录推送并编译、编译成功后写回配置、等待编译结果、获取轻量配置快照

最近更新

0.2.25

  • ShadowHook bridge 改为追加到云端入口的 DexClassLoader,不再创建独立 bridge loader。
  • Xposed/Inject runtime 会在创建云 loader 时绑定固定的私有 native 目录,校验 Bridge 与云端入口的定义 ClassLoader 相同,并将动态 Jar/SO 设置为只读。

0.2.24

  • 新增崩溃问题组查询、组内事件详情以及原始报告/事件 JSON/问题组 ZIP 下载。
  • 下载默认落盘到 ~/.cache/verify-mcp/downloads/runtime-crashes,避免把完整报告 Base64 放进模型上下文。

0.2.21

  • 新增 install_wifi_adb_module,从 Verify 服务器下载并校验“持久化 WiFi ADB”模块后批量安装到在线设备。
  • 支持 Magisk/Alpha/Kitsune、KernelSU/Next/SukiSU 和 APatch,默认单台失败后继续其他设备。
  • 默认无需重启:热激活固定端口、自动连接 IP:PORT 并返回逐台健康状态。
  • 修复 MenuPro 模板静态下载链路;下载器会在 SHA-256 前检查响应类型和 ZIP 文件头。

0.2.20

  • 新增 install_shadowhook,支持 Xposed/Inject 配置完整安装 ShadowHook 2.0.1。
  • 自动校验官方 AAR、合并并保留已有 resource zip、生成 host bridge 加载入口,并包装原业务云代码入口后编译写回。
  • 支持双 ABI、可选自定义 Hook SO、确定性重复安装、dryRun、本地回滚 ZIP 和已有 Dex 保护。

0.2.19

  • 新增 consume_count_card,自动调用 /api/consume 消费一次次数卡。
  • 普通模式使用 code + "\n" + requestId 参与签名;安全模式自动处理 RC4/AES-CBC 请求加密、响应验签和解密。
  • requestId 可省略,省略时自动生成 UUID,并在结果或错误信息中返回实际 ID。
  • get_card_verification_guide 增加次数卡、requestId 幂等和重试规则;get_verification_examples 增加 /api/consume 三种语言调用示例。

0.2.18

  • 新增 unbind_card,自动读取应用凭据并调用强制签名的公开解绑接口。
  • 自动支持普通签名、RC4、AES-CBC 请求加密、响应验签和解密。
  • get_verification_examples 增加 /api/unbind 的 curl、JavaScript、Python 示例。

0.2.17

  • 新增 prepare_ithook_apk,可通过 ApiToken 检查并触发 Xposed 应用专属 ITHook.apk 构建。
  • 新增 download_ithook_apk,可等待构建完成后下载专属 ITHook.apk;传 outputPath 时直接保存到本地路径。
  • 后端新增 /api/app-token/ithook-apk/prepare 与 /api/app-token/ithook-apk/download,不再依赖网页登录 Session 的当前应用。

0.2.16

  • 新增 download_menupro_java_ui_template,可直接下载 MenuPro 纯 Java 悬浮菜单 UI 模板源码 zip 到指定本地目录并解压。
  • 默认源码包地址为 https://www.xyapi.top/downloads/menupro-java-ui-template.zip,工具内置 sha256 与 ZIP 文件头校验并自动清理临时压缩包。
  • 解压使用 Node 内置的 fflate,Windows、macOS、Linux 均不依赖系统 unzip 命令。
  • profile=verify-cloud 会自动移除演示 Activity/Service,避免 Verify 云代码扫描时引入 AndroidX 或 Manifest 依赖。

0.2.15

  • 上传类工具不再要求调用方手动准备 Base64。
  • submit_vmp_protect_task / submit_obfuscate_protect_task / submit_dex2c_protect_task / submit_so_protect_task / submit_inject_protect_task 改为传 filePath;mapping 文件改为传 mappingPath。
  • create_config 与 update_config_files 改为传 dexPath / zipPath,工具内部自动读取、计算 sha256 并转 Base64 后提交。
  • 移除重复的 create_config_from_paths 与 update_config_files_from_paths,保留 create_config / update_config_files 作为唯一配置文件上传入口。

0.2.14

  • 新增运行时 token 切换工具:set_api_token、set_protect_token、clear_runtime_tokens。
  • server_info 新增 tokens 结构,可查看当前 ApiToken / ProtectToken 来源是 env、runtime 还是 missing。
  • 切换后的 token 只影响当前 MCP 进程;重启后仍以 MCP 配置里的环境变量为准。

0.2.8

  • server_info 默认版本号改为读取 package.json 的 version,发布后不再依赖源码硬编码。
  • VERIFY_SERVER_VERSION 仍可显式覆盖版本号,适合特殊部署或调试场景。

0.2.7

  • 新增 publish_cloud_code_from_workspace:传本地源码目录即可自动扫描 .java、生成编辑器文件树、推送、编译,并可选写回配置。
  • 新增 apply_compile_task_to_config:把成功编译任务直接下载为 dex 并写入配置,默认只更新 dex,不清已有 zip。
  • 新增 apply_compile_task_to_configs:把一份完整编译产物批量绑定到同一应用的多个配置;启用 VMP 时会同步复用 Native Bundle。
  • publish_cloud_code 新增 applyToConfig,成功后直接返回 compiled/appliedToConfig/hasDexFile/dexSize/dexHash。
  • get_full_config_snapshot 默认轻量返回,云端源码内容需显式 includeCloudCodeFiles=true。
  • validate_cloud_code_layout 失败时返回文件数量和差异列表,便于定位漏传。

0.2.6

  • 新增 list_apps,ACCOUNT 级 ApiToken 可列出账号下全部应用,不再依赖配置列表反推应用。
  • get_app_credentials 与 get_verification_examples 支持 ACCOUNT 级 ApiToken 不传 appId 时返回全部应用。

0.2.5

  • 新增 get_app_credentials,通过 ApiToken 权限读取应用 apiKey / secretKey。
  • 新增 get_verification_examples,返回验证接口签名规则和 curl / JavaScript / Python 调用示例。
  • APP 级 Token 可直接读取绑定应用;ACCOUNT 级 Token 需传 appId;CONFIG 级 Token 不允许读取应用密钥。

0.2.4

  • create_config 支持账号级 ApiToken 传入 appId,用于在“全部应用”Token 下指定新配置归属应用。
  • get_context 说明补充账号级 ApiToken 上下文。

0.2.2

  • 默认 MCP 服务名改为 verify,与前端复制出的配置保持一致。
  • 更新 README 与 .env.example 中的客户端配置示例,移除 verify-api-token 旧命名。

0.2.1

  • 新增 VERIFY_PROTECT_TOKEN,加固工具复用旧加固提交接口,不使用独立 /api/protect-token/* 接口。
  • MCP 允许只配置 VERIFY_API_TOKEN 或 VERIFY_PROTECT_TOKEN 其中一个;调用未配置 token 的工具时返回明确错误。
  • server_info 区分返回 apiTokenMasked 与 protectTokenMasked。

0.2.0

  • 新增 list_runtime_api_classes
  • 新增 get_runtime_api_doc
  • 运行时文档按真实源码区分 xposed 与 inject
  • 可准确识别 HookHelper.getModuleContext() 只属于 Xposed,不再把它误判为 InjectHelper 可用方法
  • smoke 测试已覆盖新增工具,并验证 inject 在 includeInternal=false 时不会返回 getModuleContext
  • 新增迁移知识层、生命周期、资源与编译语义说明工具
  • 新增 validate_cloud_runtime、simulate_resource_layout、validate_cloud_code_layout
  • push_cloud_code / publish_cloud_code 改为强校验模式,缺少 fileTree 或 currentFilePath 会直接拒绝

升级后,如果你希望 MCP 客户端立即使用这版,建议显式指定:

{
  "mcpServers": {
    "verify": {
      "command": "npx",
      "args": ["-y", "@ktbtw/[email protected]"],
      "env": {
        "VERIFY_BASE_URL": "https://www.xyapi.top/verfiy",
        "VERIFY_API_TOKEN": "vat_xxx_replace_me",
        "VERIFY_PROTECT_TOKEN": "vpt_xxx_replace_me",
        "VERIFY_TIMEOUT_MS": "30000"
      }
    }
  }
}

安装

直接给 MCP 客户端使用时,优先走 npx,不需要单独安装:

{
  "mcpServers": {
    "verify": {
      "command": "npx",
      "args": ["-y", "@ktbtw/verify-mcp"],
      "env": {
        "VERIFY_BASE_URL": "https://www.xyapi.top/verfiy",
        "VERIFY_API_TOKEN": "vat_xxx_replace_me",
        "VERIFY_TIMEOUT_MS": "30000"
      }
    }
  }
}

如果你要本地开发,再使用下面的方式:

cd /Users/yuminghao/Downloads/verfiy/verify_mcp
cp .env.example .env
pnpm install

然后修改 .env:

VERIFY_BASE_URL=https://www.xyapi.top/verfiy
VERIFY_API_TOKEN=你的_api_token
VERIFY_TIMEOUT_MS=30000

运行

开发模式:

pnpm dev

构建:

pnpm build

生产运行:

pnpm start

回归测试

先构建,再执行 smoke test:

pnpm build
pnpm -s smoke

smoke 会通过 MCP stdio 客户端实际连接当前服务,并验证:

  • list_runtime_api_classes
  • get_runtime_api_doc
  • tools 列表
  • get_context
  • list_apps
  • list_configs
  • get_compile_quota
  • publish_cloud_code
  • publish_cloud_code_from_workspace
  • apply_compile_task_to_config
  • apply_compile_task_to_configs
  • wait_compile_result
  • get_full_config_snapshot

Inspector 调试

pnpm build
pnpm inspect

工具列表

  • list_runtime_api_classes

  • get_runtime_api_doc

  • get_runtime_migration_guide

  • get_runtime_lifecycle_guide

  • get_resource_and_native_rules

  • get_compile_semantics

  • get_card_verification_guide

  • validate_cloud_runtime

  • simulate_resource_layout

  • validate_cloud_code_layout

  • server_info

  • set_api_token

    • 运行时切换配置、应用、卡密、云端代码、编译等工具使用的 ApiToken
  • set_protect_token

    • 运行时切换 VMP、混淆、Dex2C、SO、注入等加固工具使用的 ProtectToken
  • clear_runtime_tokens

    • 清除运行时切换过的 token,恢复使用 MCP 启动时环境变量中的 token
  • submit_vmp_protect_task

    • 传本地 filePath,工具自动读取上传;可选 mappingPath
  • submit_obfuscate_protect_task

    • 传本地 filePath,工具自动读取上传;可选 mappingPath
  • submit_dex2c_protect_task

    • 传本地 filePath,工具自动读取上传;可选 mappingPath
  • submit_so_protect_task

    • 传本地 filePath,工具自动读取上传
  • submit_inject_protect_task

    • 传本地 filePath,工具自动读取上传
  • list_protect_tasks

  • get_protect_task

  • download_protect_task

    • 默认保存到 ~/.cache/verify-mcp/downloads/protect,只返回路径、大小、sha256 和响应元数据
    • 可传 outputPath 指定目录或完整文件路径;仅 includeBase64=true 时返回 Base64
  • delete_protect_task

  • get_context

  • list_configs

  • list_runtime_crashes

    • 查询崩溃问题组;支持 incidentType、attribution、query、days 和分页
    • ACCOUNT 级 Token 必须传 appId;APP/CONFIG 级 Token 可省略
  • get_runtime_crash_events

    • 按 64 位 fingerprint 读取组内事件详情和脱敏栈
  • download_runtime_crash_report

    • type=raw 下载单事件原始报告,type=event 下载事件 JSON,type=group 下载问题组 ZIP
    • 默认保存到 ~/.cache/verify-mcp/downloads/runtime-crashes;支持 outputPath,Base64 需显式开启
  • get_app_credentials

  • get_verification_examples

  • unbind_card

    • 参数:code、machine;ACCOUNT 级 Token 还需传 appId
    • 自动读取应用 apiKey/effectiveSecret/secure/encryptionAlg
    • 普通模式签名源为 code + "\n" + machine
    • 安全模式自动生成 RC4/AES-CBC payload,并校验、解密加密响应
  • consume_count_card

    • 参数:code;可选 requestId;ACCOUNT 级 Token 还需传 appId
    • 普通模式签名源为 code + "\n" + requestId
    • 安全模式自动加密 {code,requestId},并校验、解密加密响应
    • 同一次业务消费的所有重试必须复用相同 requestId
  • download_menupro_java_ui_template

    • 下载 MenuPro 纯 Java 悬浮菜单 UI 模板源码 zip 到 targetDir 并解压,临时压缩包会自动清理
    • zip 默认包含 com/xy/menupro/...,通常把 targetDir 指到 app/src/main/java 或 Verify 云代码 workspace/src
    • Verify 云代码接入时建议传 profile="verify-cloud",工具会移除演示 Activity/Service,只保留可复用 UI、控件、主题、验证和悬浮宿主代码
  • prepare_ithook_apk

    • 检查并触发指定 Xposed 应用的专属 ITHook.apk 构建;只做预处理,不下载
    • 需要 ACCOUNT 或 APP 级 VERIFY_API_TOKEN;CONFIG 级 Token 不允许下载应用级 APK
  • download_ithook_apk

    • 先执行 prepare;默认等待构建完成后下载指定 Xposed 应用的专属 ITHook.apk
    • 默认保存到 ~/.cache/verify-mcp/downloads/ithook-apk;可传 outputPath 指定位置
    • 仅 includeBase64=true 时返回 Base64
  • update_app_redeem_extra

    • 设置应用级 /api/redeem 全局回参,支持 redeemExtraMode=ALWAYS/SUCCESS_ONLY/FAILURE_ONLY
  • update_card_extra

    • 设置单卡密验证成功回参,写入 extra 并控制 returnExtra
  • get_config

  • create_config

    • 可传本地 dexPath/zipPath,自动计算 sha256 和 Base64 后创建配置;不再需要手动准备 Base64
    • 可传 vmDetectionEnabled / packetCaptureDetectionEnabled / fridaDetectionEnabled;不传时默认开启
  • update_config

    • 可更新基础字段和三项配置级安全检测开关;不传则保留已有值
  • delete_config

  • get_config_files

    • 默认 includeData=false,只返回文件存在状态、大小与哈希;需要原始内容时再显式开启
  • update_config_files

    • 只更新 dex 时建议传 updateDexOnly=true 或 preserveExistingZip=true
    • 传本地 dexPath/zipPath,自动计算 sha256 和 Base64 后更新配置文件;不再需要手动准备 Base64
  • install_shadowhook

    • 固定校验 ShadowHook 2.0.1 官方 AAR 和内置 host bridge digest
    • 保留现有 resource zip 与云代码,生成包装入口后完成编译、ZIP 更新和 Dex 应用
    • 支持 xposed / inject、双 ABI、可选 Hook SO、workspacePath、dryRun 和回滚产物
  • inspect_patched_apk

    • 判断 APK 或已安装应用是否被 Verify 本地 Patch,以及是否绑定当前账号的应用
    • 已安装应用传 packageName,走 dumpsys package 读 xyz.patch.owner 哈希;本地文件传 apkPath
    • 归属哈希为 SHA-256(appId + NUL + appKey),对得上才返回 appId
  • patch_local_apk

    • 用已安装并登录的 Verify APP,在连接设备上对本地 APK 做 Patch,再拉回 outputDir
    • 必填 apkPath / appId / outputDir;只支持 Xposed 应用
    • dryRun=true 只检查 token、应用类型、设备和 APP 安装
    • 多设备时必须传 serial;可选 hookEngine、runtimeAbis、sigBypassLevel
    • embedOwnerHash 默认 false;为 true 时才写入 xyz.patch.owner 归属哈希
  • install_wifi_adb_module

    • 省略 serials 时批量处理 adb devices 中全部在线设备;也可指定最多 20 个 serial
    • 支持 Magisk、Magisk Alpha、Kitsune Mask/Delta、KernelSU、KernelSU Next、SukiSU Ultra 与 APatch
    • 默认端口 5555、并发数 3、不重启;安装后热激活、自动重连并逐台健康检查
    • dryRun=true 只检查 Root、管理器、Android API、IP 和已有版本,不下载或写入模块
  • get_cloud_code

  • push_cloud_code

    • 严格要求同时传 files、fileTree、currentFilePath
    • 不会自动补树;布局不对会直接拒绝
  • update_compile_settings

  • compile_config

  • list_compile_tasks

  • get_compile_task

  • download_compile_task

    • 默认保存到 ~/.cache/verify-mcp/downloads/compile;支持 outputPath,Base64 需显式开启
  • delete_compile_task

  • get_compile_quota

  • wait_compile_result

    • includeDownload=true 时产物保存到本地,返回中不内联 Base64
  • publish_cloud_code

    • 严格要求同时传 files、fileTree、currentFilePath
    • 会先校验编辑器兼容布局,再推送与编译
    • 传 applyToConfig=true 时,编译成功后自动写回配置 dex,并返回 appliedToConfig=true
  • publish_cloud_code_from_workspace

    • 传本地目录,自动扫描 .java 并生成 files/fileTree/currentFilePath
    • 适合大文件或多文件项目,避免手工拼 JSON 漏字段
  • create_module_config

  • list_module_configs

  • get_source_workspace

  • push_source_workspace

  • submit_build_task

  • wait_build_task

    • includeDownload=true 时 Artifact 保存到本地,返回中不内联 Base64
  • download_artifact

    • 默认保存到 ~/.cache/verify-mcp/downloads/artifacts;支持 outputPath,Base64 需显式开启
  • delete_build_task

  • publish_native_workspace

    • 传本地 Native/C++ 工作区目录,自动扫描并归一化到 src/native/...
    • 自动推送源码工作区、提交构建任务,并可选等待构建完成
    • 构建成功后返回 artifact 与 artifactLayout
    • .so 不会直接写入 Hook 配置;它先成为 Native Artifact,产物包内运行时路径通常是 payload/lib/{abi}/libxxx.so
  • apply_compile_task_to_config

  • apply_compile_task_to_configs

    • 把已成功编译任务写入配置
    • 默认只更新 dex,不触碰已有 zip
    • 写入后逐配置复核 dexHash,单个配置的复核读取失败会重试并记入 verificationFailures,不会把已提交的写入误报成整批失败
    • 读取 verified 判断是否 10 个配置全部复核通过;snapshots 与 configIds 顺序对齐
  • get_full_config_snapshot

    • 默认轻量返回,不含 dex/zip base64,也不含云端源码内容
    • 需要云端源码内容时传 includeCloudCodeFiles=true

MCP 公开解绑教程

应用级 ApiToken 已经绑定唯一应用时,直接调用:

{
  "name": "unbind_card",
  "arguments": {
    "code": "CARD-XXXX-XXXX",
    "machine": "DEVICE_ID_001"
  }
}

账号级 ApiToken 可以访问多个应用,必须指定 appId:

{
  "name": "unbind_card",
  "arguments": {
    "appId": 60,
    "code": "CARD-XXXX-XXXX",
    "machine": "DEVICE_ID_001"
  }
}

工具执行流程:

  1. 调用 get_app_credentials 获取目标应用的 apiKey、effectiveSecret、secure、encryptionAlg。
  2. 生成当前 Unix 秒时间戳。
  3. 普通模式签名 md5(secret + timestamp + code + "\n" + machine)。
  4. 安全模式将 {code,machine} 按 RC4 或 AES-CBC 加密为 payload,签名 md5(secret + timestamp + payload)。
  5. 调用 /api/unbind,安全模式下继续校验响应签名并解密响应 payload。

典型返回:

{
  "success": true,
  "message": "解绑成功",
  "httpStatus": 200,
  "secure": true,
  "encryptionAlg": "AES-256-CBC"
}

需要查看手工调用代码时,使用 get_verification_examples;返回结果的 examples.unbind 包含 curl、JavaScript 和 Python 示例。

MCP 次数卡消费教程

调用应用级 ApiToken 时可以省略 requestId,MCP 会自动生成 UUID:

{
  "name": "consume_count_card",
  "arguments": {
    "code": "COUNT-XXXX-XXXX"
  }
}

账号级 ApiToken 还需要指定 appId;也可以显式传入幂等 ID:

{
  "name": "consume_count_card",
  "arguments": {
    "appId": 60,
    "code": "COUNT-XXXX-XXXX",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
}

典型返回:

{
  "success": true,
  "code": 0,
  "message": "消费成功",
  "cardType": "COUNT",
  "totalCount": 10,
  "remainingCount": 9,
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "replayed": false,
  "httpStatus": 200,
  "secure": true,
  "encryptionAlg": "AES-256-CBC"
}

正常结果始终包含实际使用的 requestId。如果调用超时或网络中断,MCP 错误信息也会包含本次生成的 ID;重试时把它作为 requestId 显式传回。服务端识别重放后返回同一次消费结果和 replayed=true,不会再次扣次。只有下一次真实消费才能省略或改用新的 requestId。手工调用示例位于 get_verification_examples 返回的 examples.consume。

ShadowHook 完整安装

已有云代码快照的配置只需提供配置 ID 和运行时:

{
  "name": "install_shadowhook",
  "arguments": {
    "configId": 44,
    "runtime": "xposed"
  }
}

工具会依次完成:

  1. 下载或读取 ShadowHook 2.0.1 官方 AAR,并核对固定 SHA-256。
  2. 读取配置现有 resource zip,保留原条目并写入两种 ABI 的 ShadowHook、nothing 库和 host bridge。
  3. 保留已有云代码,新增 ShadowHookBootstrap 与包装入口 ShadowHookEntry.main()。
  4. 云 loader 创建时绑定私有 native 目录;资源就绪后复制 SO、追加只读 host bridge Jar,并校验二者 loader 身份一致。
  5. 包装入口调用原来的无参静态入口,重复安装不会形成递归包装。
  6. 云代码编译成功后上传合并 ZIP,再应用 Dex,并复核最终 zipHash。
  7. 在本地输出合并 ZIP、安装前 ZIP 和完整云代码工作区,便于检查与回滚。

同时安装自定义 Hook SO 时,每个库必须覆盖所有选择的 ABI:

{
  "name": "install_shadowhook",
  "arguments": {
    "configId": 44,
    "runtime": "inject",
    "abis": ["arm64-v8a", "armeabi-v7a"],
    "hookLibraries": [
      {"abi": "arm64-v8a", "path": "/absolute/arm64-v8a/libdemo_hook.so"},
      {"abi": "armeabi-v7a", "path": "/absolute/armeabi-v7a/libdemo_hook.so"}
    ],
    "recordable": true,
    "debuggable": false
  }
}

hookLibraries 会由云端 ClassLoader 中的 host bridge 按数组中的逻辑库顺序执行 System.load()。自定义 SO 应在 JNI_OnLoad 中完成 Hook 注册,或自行提供后续 Java 调用入口;native 侧通过 dlopen("libshadowhook.so", RTLD_NOW | RTLD_NOLOAD) 复用已由官方 Java loader 初始化的 ShadowHook。

libshadowhook_nothing.so 必须复制到云 loader 构造时绑定的 native 目录,但 Bridge 不得主动加载它。 ShadowHook 初始化会首次 dlopen 该探针 SO,用它的构造回调扫描 linker soinfo;提前加载会使初始化返回 SHADOWHOOK_ERRNO_INIT_LINKER (12)。

配置已经绑定 Dex、但服务端没有云代码编辑快照时,传入原项目源码目录:

{
  "name": "install_shadowhook",
  "arguments": {
    "configId": 44,
    "runtime": "xposed",
    "workspacePath": "/absolute/project/cloud/src"
  }
}

先检查产物且不修改配置时传 dryRun=true。结果中的 localArtifacts.resourceZipPath、 localArtifacts.previousZipPath 和 localArtifacts.cloudWorkspacePath 分别对应合并 ZIP、回滚 ZIP 和生成后的完整源码目录。

持久化 WiFi ADB 模块批量安装

先检查所有在线设备,不下载或写入模块:

{
  "name": "install_wifi_adb_module",
  "arguments": {
    "dryRun": true,
    "concurrency": 3
  }
}

确认后批量安装并立即切换到固定端口:

{
  "name": "install_wifi_adb_module",
  "arguments": {
    "port": 5555,
    "concurrency": 3,
    "reboot": false
  }
}

工具只下载一次服务端 ZIP,然后为每台设备独立检测 Root、Android API、IPv4 和管理器发行版。 单台失败会记录在 devices[].error 并继续其他设备。完成时重点检查 devices[].installed、activated、verified、targetAddress 和 rebootRequired。

MCP 主机默认从 PATH 查找 adb,也可用 VERIFY_ADB_PATH 指定路径。模块服务端制品目录由 ROOT_MODULE_STORAGE_DIR 配置,使用 root_modules/wifi-adbd/publish.sh 发布新版本时,ZIP 和版本 清单先落盘,最后原子切换 latest.txt。

运行时文档工具

为了让智能体准确区分 Xposed HookHelper 和 DEX InjectHelper 的真实能力,MCP 里额外提供了两类本地文档工具:

  • list_runtime_api_classes
    • 列出 xposed / inject 各自有哪些运行时工具类
    • 返回每个类的常用方法名和框架内部公开方法名摘要
  • get_runtime_api_doc
    • 支持按 runtime、className、methodName 精确查询
    • 例如可查 HookHelper.getModuleContext
    • 也可查 InjectHelper 全类说明,确认它并不提供 getModuleContext

除此之外,又补了一组“迁移知识层 / 运行时语义层”工具:

  • get_runtime_migration_guide
    • 说明入口类/入口方法写法
    • 说明当前云端代码支持 files[] 多文件上传
    • 说明 Xposed / Inject 在 Helper 能力上的差异
  • get_runtime_lifecycle_guide
    • 说明初始化时机
    • 说明 main() 不等于资源已就绪
    • 说明 ActivityTask / ResourceTask 的晚提交兜底语义
  • get_resource_and_native_rules
    • 说明 resHook.zip 固定命名、解压目录、缓存行为
    • 说明 findFileInUnzipDir* 的真实搜索语义
    • 说明 native 建议如何结合 ResourceTaskManager
  • get_compile_semantics
    • 说明 hasDexFile
    • 说明 cloudCode.exists
    • 说明编译任务 SUCCESS
    • 说明 downloaded
  • get_card_verification_guide
    • 说明 requireCardVerification / exitOnVerificationFailure
    • 说明平台卡密门禁与业务自带卡密逻辑如何共存
    • 说明次数卡消费、requestId 幂等重试和公开解绑协议
  • validate_cloud_runtime
    • 在编译前静态检查入口方法、运行时 API 混用、资源/native 风险
  • simulate_resource_layout
    • 根据 resHook.zip 内部条目模拟 findFileInUnzipDir* 会命中什么
  • validate_cloud_code_layout
    • 校验 files / fileTree / currentFilePath 是否满足编辑器恢复要求
    • 只做检查,不会自动补任何字段

推荐调用顺序:

  1. 不确定某个运行时有哪些工具类时,先调用 list_runtime_api_classes
  2. 确认目标类存在后,再调用 get_runtime_api_doc
  3. 需要确认“用户代码能不能直接调”时,get_runtime_api_doc 建议加 includeInternal=false
  4. 真正开始迁移项目时,再调用 get_runtime_migration_guide / get_runtime_lifecycle_guide
  5. 涉及图片、配置、.so 时,再调用 get_resource_and_native_rules
  6. 提交编译前,先调用 validate_cloud_runtime
  7. 推送云端代码前,先调用 validate_cloud_code_layout

典型调用示例:

  1. 列出 DEX Inject 运行时有哪些工具类
{
  "name": "list_runtime_api_classes",
  "arguments": {
    "runtime": "inject"
  }
}
  1. 同时查看 xposed 和 inject 两边的工具类摘要
{
  "name": "list_runtime_api_classes",
  "arguments": {}
}
  1. 查询 Xposed 下 HookHelper.getModuleContext() 是否存在
{
  "name": "get_runtime_api_doc",
  "arguments": {
    "runtime": "xposed",
    "className": "HookHelper",
    "methodName": "getModuleContext"
  }
}
  1. 查询 DEX 下 InjectHelper 的可直接调用方法,并排除框架内部回填方法
{
  "name": "get_runtime_api_doc",
  "arguments": {
    "runtime": "inject",
    "className": "InjectHelper",
    "includeInternal": false
  }
}
  1. 查询 ActivityTaskManager 的整类说明,确认 submitTask(...) 等能力
{
  "name": "get_runtime_api_doc",
  "arguments": {
    "runtime": "inject",
    "className": "ActivityTaskManager"
  }
}
  1. 使用完整包名查询也可以
{
  "name": "get_runtime_api_doc",
  "arguments": {
    "runtime": "inject",
    "className": "com.xy.verfiy_inject.Util.InjectHelper",
    "methodName": "getHostContext"
  }
}
  1. 读取 DEX Inject 的迁移指南
{
  "name": "get_runtime_migration_guide",
  "arguments": {
    "runtime": "inject"
  }
}
  1. 读取 Xposed 的生命周期说明
{
  "name": "get_runtime_lifecycle_guide",
  "arguments": {
    "runtime": "xposed"
  }
}
  1. 编译前静态校验云端入口和资源风险
{
  "name": "validate_cloud_runtime",
  "arguments": {
    "runtime": "inject",
    "dexClassName": "com.example.cloud.Entry",
    "dexMethodName": "main",
    "files": [
      {
        "path": "src/com/example/cloud/Entry.java",
        "content": "package com.example.cloud;\\npublic final class Entry {\\n  public static void main() {}\\n}"
      },
      {
        "path": "src/com/example/cloud/Helper.java",
        "content": "package com.example.cloud;\\npublic final class Helper {}"
      }
    ],
    "resourceEntries": [
      "lib/arm64-v8a/libdemo.so",
      "images/logo.png"
    ],
    "requireCardVerification": false
  }
}
  1. 模拟 resHook.zip 解压后查找 libdemo.so
{
  "name": "simulate_resource_layout",
  "arguments": {
    "entries": [
      "lib/arm64-v8a/libdemo.so",
      "images/logo.png",
      "config/app.json"
    ],
    "exactFileNames": ["libdemo.so"],
    "containsFileNames": ["logo"]
  }
}
  1. 推送前先校验编辑器布局是否完整
{
  "name": "validate_cloud_code_layout",
  "arguments": {
    "files": [
      {
        "path": "src/com/example/cloud/Entry.java",
        "content": "package com.example.cloud;\\npublic final class Entry {\\n  public static void main() {}\\n}"
      },
      {
        "path": "src/com/example/cloud/Helper.java",
        "content": "package com.example.cloud;\\npublic final class Helper {}"
      }
    ],
    "fileTree": {
      "name": "root",
      "type": "folder",
      "path": "",
      "children": [
        {
          "name": "src",
          "type": "folder",
          "path": "src",
          "children": [
            {
              "name": "com",
              "type": "folder",
              "path": "src/com",
              "children": [
                {
                  "name": "example",
                  "type": "folder",
                  "path": "src/com/example",
                  "children": [
                    {
                      "name": "cloud",
                      "type": "folder",
                      "path": "src/com/example/cloud",
                      "children": [
                        {
                          "name": "Entry.java",
                          "type": "file",
                          "path": "src/com/example/cloud/Entry.java"
                        },
                        {
                          "name": "Helper.java",
                          "type": "file",
                          "path": "src/com/example/cloud/Helper.java"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    "currentFilePath": "src/com/example/cloud/Entry.java"
  }
}
  1. 通过校验后再推送/发布;如果 fileTree 缺失、currentFilePath 不命中真实文件,工具会直接拒绝

推荐方式:从本地工作区目录一键推送、编译并写回配置。

{
  "name": "publish_cloud_code_from_workspace",
  "arguments": {
    "configId": 39,
    "workspacePath": "/Users/me/verify_cloud_mg/src",
    "currentFilePath": "src/com/example/cloud/Entry.java",
    "cacheKey": "verify_cloud_mg",
    "compileSettings": {
      "dexClassName": "com.example.cloud.Entry",
      "dexMethodName": "main",
      "dexMethodParamTypes": []
    },
    "waitForResult": true,
    "applyToConfig": true,
    "deleteTaskAfterDownload": true
  }
}

返回里重点看:

  • compiled=true:编译任务成功。
  • appliedToConfig=true:dex 已写回配置。
  • hasDexFile=true、dexSize>0、dexHash:配置侧已经能读到 dex。

如果已经有成功任务,也可以单独应用:

{
  "name": "apply_compile_task_to_config",
  "arguments": {
    "configId": 39,
    "taskId": "compile-task-id",
    "deleteTaskAfterApply": true
  }
}

同一套产物需要发布到多个配置时,使用完整产物批量应用:

{
  "name": "apply_compile_task_to_configs",
  "arguments": {
    "configIds": [39, 40, 41],
    "taskId": "compile-task-id",
    "deleteTaskAfterApply": true
  }
}

该工具要求目标配置属于编译任务对应的同一应用。它会保留各配置已有资源 ZIP,并在 VMP 开启时将同一个 DEX、bundleId 和 bundleHash 一起绑定到所有目标配置。

只确认配置状态时使用轻量快照:

{
  "name": "get_full_config_snapshot",
  "arguments": {
    "configId": 39,
    "includeFileData": false,
    "includeCloudCodeFiles": false
  }
}
{
  "name": "publish_cloud_code",
  "arguments": {
    "configId": 39,
    "cacheKey": "verify_mcp_example",
    "files": [
      {
        "path": "src/com/example/cloud/Entry.java",
        "content": "package com.example.cloud;\\npublic final class Entry {\\n  public static void main() {}\\n}"
      }
    ],
    "fileTree": {
      "name": "root",
      "type": "folder",
      "path": "",
      "children": [
        {
          "name": "src",
          "type": "folder",
          "path": "src",
          "children": [
            {
              "name": "com",
              "type": "folder",
              "path": "src/com",
              "children": [
                {
                  "name": "example",
                  "type": "folder",
                  "path": "src/com/example",
                  "children": [
                    {
                      "name": "cloud",
                      "type": "folder",
                      "path": "src/com/example/cloud",
                      "children": [
                        {
                          "name": "Entry.java",
                          "type": "file",
                          "path": "src/com/example/cloud/Entry.java"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    "currentFilePath": "src/com/example/cloud/Entry.java",
    "compileSettings": {
      "dexClassName": "com.example.cloud.Entry",
      "dexMethodName": "main",
      "dexMethodParamTypes": []
    },
    "waitForResult": false
  }
}

AI 调用建议:

  • 写 DEX 代码前,优先查 inject
  • 写 Xposed 代码前,优先查 xposed
  • 如果 AI 不确定 InjectHelper.getModuleContext() 这类方法是否真实存在,应先调用 get_runtime_api_doc,不要只凭补全文案猜测
  • 开始迁移旧项目前,优先查 get_runtime_migration_guide
  • 涉及 main() 时序、Activity 可见阶段、native 资源回调时,优先查 get_runtime_lifecycle_guide 与 get_resource_and_native_rules
  • 编译前先跑 validate_cloud_runtime,比等到运行时再猜问题更稳
  • 推送前先跑 validate_cloud_code_layout,确保“能编译”和“能完整拉回编辑器树”同时成立
  • 多文件或大文件项目优先用 publish_cloud_code_from_workspace,不要手工在 MCP 参数里塞完整源码树
  • 编译成功后需要应用到单个线上配置时,使用 applyToConfig=true 或 apply_compile_task_to_config
  • 同一产物需要推送到多个配置时,使用 apply_compile_task_to_configs,不要逐配置重新编译
  • 只确认配置是否已有 dex 时,get_full_config_snapshot 保持 includeCloudCodeFiles=false
  • 不要只传 files;push_cloud_code / publish_cloud_code 现在会把缺失的 fileTree、错误的 currentFilePath 直接判错

MCP 客户端配置示例

以本地 npx 方式为例,客户端配置通常类似:

{
  "mcpServers": {
    "verify": {
      "command": "npx",
      "args": [
        "-y",
        "@ktbtw/verify-mcp"
      ],
      "env": {
        "VERIFY_BASE_URL": "https://www.xyapi.top/verfiy",
        "VERIFY_API_TOKEN": "vat_xxx_replace_me",
        "VERIFY_TIMEOUT_MS": "30000"
      }
    }
  }
}

如果你已经把仓库拉到本地,也可以直接指向构建产物:

{
  "mcpServers": {
    "verify": {
      "command": "node",
      "args": [
        "/Users/yuminghao/Downloads/verfiy/verify_mcp/dist/index.js"
      ],
      "env": {
        "VERIFY_BASE_URL": "https://www.xyapi.top/verfiy",
        "VERIFY_API_TOKEN": "vat_xxx_replace_me",
        "VERIFY_TIMEOUT_MS": "30000"
      }
    }
  }
}