从零搭建 Android ADB MCP Server:让 AI 助手直接操控你的 Android 设备

通过 MCP (Model Context Protocol) 让 AI 助手直接调用 ADB 命令操作 Android 设备,实现日志查看、应用安装、性能分析等自动化操作。

MCP 协议说明

MCP 是 Anthropic 推出的开放协议,用于连接 AI 助手与外部工具。MCP Server 将特定工具包装成标准化接口,让 AI 能够理解和调用。

架构如下:

go 复制代码
Claude Desktop/API → MCP Server → ADB Commands → Android Device

实现步骤

初始化项目

go 复制代码
mkdir adb_mcp
cd adb_mcp
npm init -y
npm install @modelcontextprotocol/sdk

配置 package.json

go 复制代码
{
  "name":"adb-mcp-server",
"version":"1.0.0",
"description":"MCP Server for Android Debug Bridge (ADB) operations",
"main":"adb-mcp-server.js",
"bin":{
    "adb-mcp-server":"./adb-mcp-server.js"
},
"scripts":{
    "start":"node adb-mcp-server.js"
},
"keywords":["mcp","adb","android","debug"],
"author":"",
"license":"MIT",
"dependencies":{
    "@modelcontextprotocol/sdk":"^1.0.0"
}
}

核心代码实现

创建 adb-mcp-server.js

go 复制代码
#!/usr/bin/env node
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
const { exec } = require('child_process');
const { promisify } = require('util');

const execPromise = promisify(exec);

// 创建 MCP Server 实例
const server = newServer(
  {
    name: 'adb-server',
    version: '1.0.0'
  },
  {
    capabilities: {
      tools: {}
    }
  }
);

// 定义工具列表
const tools = [
  {
    name: 'adb-logcat',
    description: 'Get Android device logs',
    inputSchema: {
      type: 'object',
      properties: {
        lines: {
          type: 'number',
          description: 'Number of log lines to retrieve',
          default: 100
        }
      }
    }
  },
  {
    name: 'adb-devices',
    description: 'List connected Android devices',
    inputSchema: {
      type: 'object',
      properties: {}
    }
  },
  {
    name: 'adb-install',
    description: 'Install APK on connected device',
    inputSchema: {
      type: 'object',
      properties: {
        apkPath: {
          type: 'string',
          description: 'Path to the APK file to install'
        }
      },
      required: ['apkPath']
    }
  },
  {
    name: 'adb-app-info',
    description: 'Get app package information',
    inputSchema: {
      type: 'object',
      properties: {
        packageName: {
          type: 'string',
          description: 'Android package name (e.g., com.example.app)'
        }
      },
      required: ['packageName']
    }
  },
  {
    name: 'adb-meminfo',
    description: 'Get app memory usage information',
    inputSchema: {
      type: 'object',
      properties: {
        packageName: {
          type: 'string',
          description: 'Android package name (e.g., com.example.app)'
        }
      },
      required: ['packageName']
    }
  },
  {
    name: 'adb-clear-data',
    description: 'Clear app data and cache',
    inputSchema: {
      type: 'object',
      properties: {
        packageName: {
          type: 'string',
          description: 'Android package name (e.g., com.example.app)'
        }
      },
      required: ['packageName']
    }
  }
];

// 处理工具列表请求
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools };
});

// 处理工具执行请求
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;

try {
    let result;

    switch (name) {
      case'adb-logcat': {
        const lines = args.lines || 100;
        const { stdout } = awaitexecPromise(`adb logcat -d -t ${lines}`);
        result = stdout;
        break;
      }

      case'adb-devices': {
        const { stdout } = awaitexecPromise('adb devices -l');
        result = stdout;
        break;
      }

      case'adb-install': {
        if (!args.apkPath) {
          thrownewError('apkPath is required');
        }
        const { stdout } = awaitexecPromise(`adb install -r "${args.apkPath}"`);
        result = stdout;
        break;
      }

      case'adb-app-info': {
        if (!args.packageName) {
          thrownewError('packageName is required');
        }
        const { stdout } = awaitexecPromise(`adb shell dumpsys package ${args.packageName}`);
        result = stdout;
        break;
      }

      case'adb-meminfo': {
        if (!args.packageName) {
          thrownewError('packageName is required');
        }
        const { stdout } = awaitexecPromise(`adb shell dumpsys meminfo ${args.packageName}`);
        result = stdout;
        break;
      }

      case'adb-clear-data': {
        if (!args.packageName) {
          thrownewError('packageName is required');
        }
        const { stdout } = awaitexecPromise(`adb shell pm clear ${args.packageName}`);
        result = stdout;
        break;
      }

      default:
        thrownewError(`Unknown tool: ${name}`);
    }

    return {
      content: [
        {
          type: 'text',
          text: result
        }
      ]
    };
  } catch (error) {
    return {
      content: [
        {
          type: 'text',
          text: `Error executing ${name}: ${error.message}`
        }
      ],
      isError: true
    };
  }
});

// 启动服务器
asyncfunctionmain() {
const transport = newStdioServerTransport();
await server.connect(transport);
console.error('ADB MCP Server running on stdio');
}

main().catch((error) => {
console.error('Server error:', error);
  process.exit(1);
});

赋予执行权限:

go 复制代码
chmod +x adb-mcp-server.js

关键实现说明

Server 初始化

go 复制代码
const server = new Server(
  { name: 'adb-server', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

声明服务器名称、版本和支持的能力类型。

工具定义

每个工具包含三个部分:

  • name: 唯一标识符

  • description: 功能描述,AI 根据此判断调用时机

  • inputSchema: JSON Schema 格式的参数定义

示例:

go 复制代码
{
  name: 'adb-install',
  description: 'Install APK on connected device',
  inputSchema: {
    type: 'object',
    properties: {
      apkPath: { type: 'string', description: 'Path to the APK file' }
    },
    required: ['apkPath']
  }
}

请求处理

MCP 定义两种请求类型:

ListToolsRequest - 列出所有可用工具:

go 复制代码
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return { tools };
});

CallToolRequest - 执行具体工具:

go 复制代码
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  // 根据 name 执行相应 ADB 命令
});

命令执行

使用 child_process 执行 ADB 命令:

go 复制代码
const { stdout } = await execPromise(`adb devices -l`);

配置方式

Claude Desktop 配置

编辑 ~/Library/Application Support/Claude/claude_desktop_config.json

go 复制代码
{
  "mcpServers": {
    "adb": {
      "command": "node",
      "args": ["/Users/你的用户名/Documents/self_host/adb_mcp/adb-mcp-server.js"]
    }
  }
}

配置完成后重启 Claude Desktop。

Claude Code CLI 配置

使用 Claude Code 命令行工具添加 MCP Server:

go 复制代码
claude -p mcp add adb node /Users/xxxx/Documents/sxxx/adb_mcp/adb-mcp-server.js

参数说明:

  • adb: MCP Server 名称

  • node: 运行命令

  • • 最后是 adb-mcp-server.js 的完整路径

Gemini CLI 配置

编辑 Gemini CLI 配置文件 ~/.gemini/mcp_config.json

go 复制代码
{
  "mcpServers": {
    "adb": {
      "command": "node",
      "args": ["/Users/xxxx/Documents/sxxx/adb_mcp/adb-mcp-server.js"]
    }
  }
}

:Gemini CLI 的 MCP 配置可能因版本而异,建议以官方文档为准。

Copilot CLI 配置

编辑 Copilot CLI 配置文件 ~/.github-copilot/mcp_servers.json

go 复制代码
{
  "adb": {
    "command": "node",
    "args": ["/Users/xxxx/Documents/sxxx/adb_mcp/adb-mcp-server.js"]
  }
}

:Copilot CLI 的 MCP 配置可能因版本而异,建议以官方文档为准。


使用示例

在 Claude 中直接使用自然语言:

go 复制代码
查看连接的 Android 设备
go 复制代码
获取最近 50 行 logcat 日志
go 复制代码
查看 com.android.chrome 的内存使用情况
go 复制代码
清除 com.example.app 的数据

Claude 会自动调用对应的 MCP 工具执行操作。


应用场景

日志分析

传统方式:

go 复制代码
adb logcat -d > log.txt
# 手动搜索错误信息

使用 MCP:

go 复制代码
获取最近的 logcat 日志,找出所有 ERROR 级别信息

Claude 自动执行并分析结果。

性能监控

传统方式:

go 复制代码
adb shell dumpsys meminfo com.example.app
# 手动分析输出数据

使用 MCP:

go 复制代码
查看 com.example.app 的内存使用,分析是否有内存泄漏

批量操作

go 复制代码
列出所有连接的设备,在每个设备上安装 /path/to/app.apk

Claude 自动处理设备列表和批量安装。


扩展功能

添加截图

go 复制代码
{
  name: 'adb-screenshot',
  description: 'Take a screenshot',
  inputSchema: {
    type: 'object',
    properties: {
      savePath: { type: 'string', description: 'Path to save screenshot' }
    },
    required: ['savePath']
  }
}

执行命令:

go 复制代码
await execPromise(`adb exec-out screencap -p > ${args.savePath}`);

添加性能监控

go 复制代码
{
  name: 'adb-top',
  description: 'Get CPU usage',
  inputSchema: { type: 'object', properties: {} }
}

添加文件传输

go 复制代码
{
  name: 'adb-push',
  description: 'Push file to device',
  inputSchema: {
    type: 'object',
    properties: {
      localPath: { type: 'string' },
      remotePath: { type: 'string' }
    },
    required: ['localPath', 'remotePath']
  }
}

注意事项

权限检查

确保 ADB 已添加到系统 PATH:

go 复制代码
which adb
adb version

设备授权

使用前确认设备已连接并授权:

go 复制代码
adb devices

如果显示 unauthorized,需在设备上确认 USB 调试授权。

错误处理

生产环境应添加:

  • • 详细日志记录

  • • 设备断开连接处理

  • • 命令超时机制

安全性

  • • 避免在不信任的环境使用

  • • 注意 APK 路径注入风险

  • • 考虑添加命令白名单

相关推荐
2501_915921433 小时前
iOS混淆与IPA加固实战手记,如何构建苹果应用防反编译体系
android·macos·ios·小程序·uni-app·cocoa·iphone
Jeled4 小时前
Android 集成指南:Google 登录、Facebook 登录 与 Firebase 深入接入(实战)
android·kotlin·android studio·memcached·facebook
用户094 小时前
Android唤醒锁优化指南
android·面试·kotlin
aqi005 小时前
FFmpeg开发笔记(八十三)国产的视频裁剪框架AndroidVideoTrimmer
android·ffmpeg·音视频·流媒体
困到晕阙5 小时前
[Zer0pts2020]Can you guess it?
android
写点啥呢6 小时前
android取消每次u盘插入创建无用(媒体)文件夹
android·u盘·车机·aosp
杨筱毅6 小时前
【Android】RecyclerView LayoutManager 重写方法详解
android
shaominjin1236 小时前
Android 中 Padding 与 Margin 的深度解析:从概念到实战区分
android