Skip to main content
Glama
Nam0101

android-mcp-toolkit

Manage ADB Logcat

manage-logcat

Read Android logcat logs, capture crash dumps, check ANR traces, and clear log buffers with filters for package, PID, tag, priority, and line count.

Instructions

Unified tool to read logs, capture crashes, check ANRs, and clear buffers.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionNoAction to perform: read logs, get crash buffer, check ANR, or clear buffer.read
packageNameNoAndroid package name; resolves pid via adb shell pidof
pidNoExplicit process id for logcat --pid
tagNoLogcat tag to include (uses -s tag)
priorityNoMinimum priority (e.g. D for debug).V
maxLinesNoTail line count (logcat -t).
timeoutMsNoTimeout per adb call in milliseconds

Implementation Reference

  • The main handler function for the 'manage-logcat' tool. Executes the tool logic: clear logcat buffers, check ANR state, capture crash buffer, or read logs based on the 'action' parameter. Resolves PID from packageName if needed.
    async (params) => {
      const { action, timeoutMs } = params;
    
      if (action === 'clear') {
        await runAdbCommand(['logcat', '-c'], timeoutMs);
        return { content: [{ type: 'text', text: 'Cleared logcat buffers.' }] };
      }
    
      // Resolve PID if packageName is provided
      let pid = params.pid;
      if (!pid && params.packageName) {
        pid = await resolvePid(params.packageName, timeoutMs);
      }
    
      // 1. ANR Check
      if (action === 'anr') {
        const sections = [];
        try {
           const logArgs = ['logcat', '-d', '-t', String(params.maxLines), 'ActivityManager:E', '*:S'];
           const amLogs = await runAdbCommand(logArgs, timeoutMs);
           sections.push('ActivityManager (recent):\n' + (amLogs || 'No entries.'));
        } catch (e) { sections.push('ActivityManager error: ' + e.message); }
    
        try {
           const tail = await runAdbCommand(['shell', 'tail', '-n', '200', '/data/anr/traces.txt'], timeoutMs);
           sections.push('traces.txt tail (200 lines):\n' + (tail || 'Empty.'));
        } catch (e) { sections.push('traces.txt error: ' + e.message); }
        
        return { content: [{ type: 'text', text: sections.join('\n\n') }] };
      }
    
      // 2. Crash Buffer
      if (action === 'crash') {
        const args = ['logcat', '-b', 'crash', '-d', '-t', String(params.maxLines)];
        if (pid) args.push(`--pid=${pid}`);
        const output = await runAdbCommand(args, timeoutMs);
        return { content: [{ type: 'text', text: output || 'No crash entries found.' }] };
      }
    
      // 3. Normal Read (Default)
      const args = ['logcat', '-d', '-t', String(params.maxLines)];
      if (pid) args.push(`--pid=${pid}`);
      if (params.tag) {
         args.push('-s', `${params.tag}:${params.priority}`);
      }
      
      const output = await runAdbCommand(args, timeoutMs);
      return { content: [{ type: 'text', text: output || 'Logcat returned no lines.' }] };
    }
  • Input schema for the 'manage-logcat' tool defined with Zod. Validates/describes parameters: action (enum: read/crash/anr/clear), packageName, pid, tag, priority, maxLines, and timeoutMs.
    const manageLogcatSchema = z.object({
      action: z.enum(['read', 'crash', 'anr', 'clear']).default('read').describe('Action to perform: read logs, get crash buffer, check ANR, or clear buffer.'),
      packageName: z.string().min(1).describe('Android package name; resolves pid via adb shell pidof').optional(),
      pid: z.string().min(1).describe('Explicit process id for logcat --pid').optional(),
      tag: z.string().min(1).describe('Logcat tag to include (uses -s tag)').optional(),
      priority: z.enum(['V', 'D', 'I', 'W', 'E', 'F', 'S']).default('V').describe('Minimum priority (e.g. D for debug).'),
      maxLines: z.number().int().min(1).max(2000).default(200).describe('Tail line count (logcat -t).'),
      timeoutMs: z.number().int().min(1000).max(15000).default(5000).describe('Timeout per adb call in milliseconds')
    });
  • The 'registerLogcatTool' function registers the 'manage-logcat' tool with the MCP server, including its metadata (title, description, inputSchema) and handler.
    function registerLogcatTool(server) {
      server.registerTool(
        'manage-logcat',
        {
          title: 'Manage ADB Logcat',
          description: 'Unified tool to read logs, capture crashes, check ANRs, and clear buffers.',
          inputSchema: manageLogcatSchema
        },
        async (params) => {
          const { action, timeoutMs } = params;
    
          if (action === 'clear') {
            await runAdbCommand(['logcat', '-c'], timeoutMs);
            return { content: [{ type: 'text', text: 'Cleared logcat buffers.' }] };
          }
    
          // Resolve PID if packageName is provided
          let pid = params.pid;
          if (!pid && params.packageName) {
            pid = await resolvePid(params.packageName, timeoutMs);
          }
    
          // 1. ANR Check
          if (action === 'anr') {
            const sections = [];
            try {
               const logArgs = ['logcat', '-d', '-t', String(params.maxLines), 'ActivityManager:E', '*:S'];
               const amLogs = await runAdbCommand(logArgs, timeoutMs);
               sections.push('ActivityManager (recent):\n' + (amLogs || 'No entries.'));
            } catch (e) { sections.push('ActivityManager error: ' + e.message); }
    
            try {
               const tail = await runAdbCommand(['shell', 'tail', '-n', '200', '/data/anr/traces.txt'], timeoutMs);
               sections.push('traces.txt tail (200 lines):\n' + (tail || 'Empty.'));
            } catch (e) { sections.push('traces.txt error: ' + e.message); }
            
            return { content: [{ type: 'text', text: sections.join('\n\n') }] };
          }
    
          // 2. Crash Buffer
          if (action === 'crash') {
            const args = ['logcat', '-b', 'crash', '-d', '-t', String(params.maxLines)];
            if (pid) args.push(`--pid=${pid}`);
            const output = await runAdbCommand(args, timeoutMs);
            return { content: [{ type: 'text', text: output || 'No crash entries found.' }] };
          }
    
          // 3. Normal Read (Default)
          const args = ['logcat', '-d', '-t', String(params.maxLines)];
          if (pid) args.push(`--pid=${pid}`);
          if (params.tag) {
             args.push('-s', `${params.tag}:${params.priority}`);
          }
          
          const output = await runAdbCommand(args, timeoutMs);
          return { content: [{ type: 'text', text: output || 'Logcat returned no lines.' }] };
        }
      );
  • src/index.js:27-29 (registration)
    The top-level registration of the logcat tool in the MCP server entry point. Calls registerLogcatTool(server) to wire up the tool.
    registerSvgTool(server);
    registerLogcatTool(server);
    registerTextLengthTool(server);
  • Helper function 'resolvePid' that resolves an Android package name to a PID using 'adb shell pidof -s'. Returns null if not found.
    async function resolvePid(packageName, timeoutMs) {
      try {
        const output = await runAdbCommand(['shell', 'pidof', '-s', packageName], timeoutMs);
        const pid = output.split(/\s+/).find(Boolean);
        return pid || null;
      } catch (e) {
        return null; // Return null if pidof failed or not found
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry the full burden. It hints at different behaviors (reading vs clearing) but does not disclose side effects (e.g., clearing buffers loses data) or performance implications. For a tool with multiple actions, more transparency is needed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, well-formed sentence that front-loads the purpose and lists capabilities concisely. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity (7 parameters, multiple actions) and no output schema, the description should explain what the tool returns (e.g., log text, crash dump). It does not, leaving the return format unclear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage for all 7 parameters. The description adds no further parameter-specific context beyond 'log management', so a baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('manage logs') and explicitly lists distinct capabilities ('read logs, capture crashes, check ANRs, and clear buffers'). It clearly distinguishes from sibling tools which focus on UI hierarchy, screenshots, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is the go-to tool for all log-related tasks ('Unified tool') but does not explicitly state when to use it versus alternatives or mention any exclusion criteria. Sibling tools are different domains, so no conflict, but guidance is minimal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nam0101/android-mcp-toolkit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server