DEV Community

Cover image for Experimenting with Gemini, MCP, Agentic AI and Android
Thomas Ezan
Thomas Ezan

Posted on • Edited on

Experimenting with Gemini, MCP, Agentic AI and Android

The views and opinions expressed on this blog are my own and do not reflect those of my employer.

MCP has been the craze in the past few months, and we've seen an explosion of MCP servers for every possible use case (see this MCP server to flip a coin 🤔).,, Similarly, Agentic AI, while lacking a universally clear definition, has been a major topic of discussion in the industry for the past 12 months.

Some define Agentic AI behavior as “using AI to do something for you”. This definition is too broad for me. I prefer Yoshua Bengio’s definition: “understand context, set objectives, and execute multi-step plans with robustness.”

In this blog post, I will describe how to:

  1. Create a simple MCP server leveraging Android Debug Bridge (ADB)
  2. Create a basic AI Agent leveraging our MCP server to find and launch an Android app

Here is a diagram of what we will build:

Architecture diagram

Creating an ADB MCP server

What is MCP?
For a comprehensive introduction to MCP, take a look at the project documentation. You can also read Philip Schmidt overview blog post.

You can think of MCP as a universal adapter for your AI application to interact with the real world. The documentation describes MCP as “a USB-C port for AI applications”. I like to think of MCP servers as drivers that connect the real world to your AI application. Writing a hardware driver is a bit of a pain, but once it is available your computer can talk to your hardware.

However, let me reassure you: writing an MCP server is significantly easier than developing a hardware driver for an operating system 😅. Also, there are a lot of MCP servers and what you need might already exist. Here are few places to search:

MCP + ADB

For this project, I decided to build a very simple MCP service using the following 3 tools:

  • get_devices: retrieves a list of Android devices connected to the laptop,
  • get_apps: retrieves the package name of all the apps installed on the device,
  • open_app: opens the app with the matching package name.

If you're familiar with ADB, you likely already have an idea of the implementation and the commands we'll use.

MCP servers provide their functionalities through 3 core building blocks:

  • Tools: called directly by the LLM, these are essentially an abstraction over function calling capabilities.
  • Resources: a standardized way to expose resources such as files, databases, etc…
  • Prompts: a list templatized messages and instructions that can be used as prompts for the LLM

There are also more advanced features such as sampling and elicitation. Interestingly, most of MCP hosts don’t support all the MCP features. As a consequence, you'll notice that MCP servers often leverage only Tools, which is the most common MCP feature.

If you want to implement an MCP server, there's already a rich ecosystem with libraries and reference implementations.

In my case I used the MCP Python SDK:

from mcp.server.fastmcp import FastMCP
import subprocess

mcp = FastMCP("ADB MCP")

@mcp.tool()
def get_devices() -> str:
    """Get the list of Android devices connected to the laptop"""
    result = subprocess.run(['adb', 'devices'], capture_output=True, text=True)
    return result.stdout

@mcp.tool()
def get_apps() -> str:
    """Use ADB to get the list of all the apps installed on a specific Android devices connected to the laptop. 
    Search through the output of this list to confirm if an app is installed."""
    result = subprocess.run(['adb', 'shell', 'pm', 'list', 'packages'], capture_output=True, text=True)
    if result.returncode != 0:
        return f"Error: {result.stderr}"
    return result.stdout


@mcp.tool()
def open_app(package_name: str) -> str:
    """Open an app on the connected Android device using its package name via ADB."""
    # The command to launch the main activity of the app
    cmd = [
        'adb', 'shell', 'monkey', '-p', package_name, '-c', 'android.intent.category.LAUNCHER', '1'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        return f"Error opening app: {result.stderr.strip()}"
    return f"App '{package_name}' launched successfully."


if __name__ == "__main__":
    mcp.run()
Enter fullscreen mode Exit fullscreen mode

I was curious about the inner workings of MCP and how the protocol and ADB would work together. But you don’t have to follow this route. There is already an ADB MCP server ready to use if you have a more complex project in mind: minhalvp/android-mcp-server.

Additionally, if you want to experiment with running the server directly in your Android app, take a look at kaeawc/android-mcp-sdk.

Creating an AI Agent

mcp-use library
The AI Agent component of this project could have been implemented in various ways. I chose the mcp-use library because it offered a relatively easy method for implementing an AI Agent that leverages an MCP server.

import asyncio
import os
from mcp_use import MCPAgent, MCPClient
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI
from langchain_google_genai import ChatGoogleGenerativeAI

async def main():
    print("hello!")
    config = {
        "mcpServers": {
            "demo": {
                "command": "/path/to/venv/bin/uv",
                "args": [
                    "run",
                    "--with",
                    "mcp[cli]",
                    "mcp",
                    "run",
                    "/path/to/server.py"
                ]
            }
        }
    }


    client = MCPClient.from_config_file(
        os.path.join(os.path.dirname(__file__), "android_mcp.json")
    )

    agent = MCPAgent(
        llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro"),
        client=client
    )

    result = await agent.run("Fetch the list of app installed to the android device connected to the laptop and review the list of packages to check if the New York Time app installed on the device and if it is, open the app")
    print("--------------------------------")
    print(result)

if __name__ == "__main__":
    asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

Conclusion

If you weren’t familiar with MCP, you probably learned new concepts! 😀

The goal of this project was to build a fun demo and test out different APIs and SDKs I came across in the past few weeks. It's not meant to be an endorsement of these tools or a suggested way to build production features for real products. Don't hesitate to reach out if you've also experimented with MCP and Android!

Top comments (1)

Collapse
 
jamey_h66 profile image
Jamey H

Nice posting, I'd like to talk to you, could you share your email address?