Labsco
appium logo

appium-mcp

β˜… 416

from appium

MCP server for Mobile Development and Automation | iOS, Android, Simulator, Emulator, and Real Devices

πŸ”₯πŸ”₯πŸ”₯πŸ”₯βœ“ VerifiedFreeQuick setup

MCP Appium - MCP server for Mobile Development and Automation | iOS, Android, Simulator, Emulator, and Real Devices

npm version

License

MCP Appium is an intelligent MCP (Model Context Protocol) server designed to empower AI assistants with a robust suite of tools for mobile automation. It streamlines mobile app testing by enabling natural language interactions, intelligent locator generation, and automated test creation for both Android and iOS platforms.

Table of Contents

πŸš€ Features

  • Cross-Platform Support: Automate tests for both Android (UiAutomator2) and iOS (XCUITest).
  • AI-Powered Element Finding: Locate UI elements using natural language descriptions powered by vision models - no need for complex XPath or selectors.
  • Intelligent Locator Generation: AI-powered element identification using priority-based strategies.
  • Interactive Session Management: Easily create and manage sessions on local mobile devices.
  • Smart Element Interactions: Perform actions like clicks, text input, screenshots, and element finding.
  • Automated Test Generation: Generate Java/TestNG test code from natural language descriptions.
  • Page Object Model Support: Utilize built-in templates that follow industry best practices.
  • Flexible Configuration: Customize capabilities and settings for different environments.
  • Multilingual Support: Use your native language - AI handles all interactions naturally in any language (English, Spanish, Chinese, Japanese, Korean, etc.).

πŸ”Œ Plugin API

Use appium-mcp/core to compose the default Appium MCP server with custom business logic without maintaining a fork. Plugins can register MCP tools, prompts, resources, and resource templates, and can wrap tool execution with lifecycle hooks. Call hooks are tool-only: prompts, resources, and resource templates are registered with FastMCP but are not wrapped by beforeCall or afterCall.

createAppiumMcpServer({ policy }) can also hide nonmatching tools and resources from MCP discovery. The factory is async, so await it before starting the returned server. Policy rules are regular expressions matched against tool and resource names exactly as registered. The policy is applied at registration time to both single and batch registration methods. Resource policy matches the resource name only; resources or resource templates without a string name cannot match a non-empty allowResources list.

Copy & paste β€” that's it
import { createAppiumMcpServer } from 'appium-mcp/core';
import type {
  AppiumMcpPlugin,
  McpRegistry,
  ToolCallContext,
} from 'appium-mcp/core';
import { z } from 'zod';

class CheckoutPlugin implements AppiumMcpPlugin {
  readonly name = 'checkout-plugin';
  readonly version = '1.0.0';

  register(registry: McpRegistry): void {
    const parameters = z.object({ orderId: z.string() });
    registry.addTool({
      name: 'assert_checkout_summary',
      description:
        'Assert that the checkout summary screen shows an expected order ID.',
      parameters,
      execute: async (args) => {
        const { orderId } = parameters.parse(args);
        return {
          content: [
            { type: 'text', text: `Assert checkout order ${orderId}` },
          ],
        };
      },
    });
  }

  async beforeCall(ctx: ToolCallContext): Promise<void> {
    if (ctx.toolName === 'appium_gesture') {
      console.error(`[checkout-plugin] about to call ${ctx.toolName}`);
    }
  }
}

const server = await createAppiumMcpServer({
  plugins: [new CheckoutPlugin()],
  additionalInstructions: 'Custom checkout policies are active.',
  policy: {
    allowTools: [/^appium_session_management$/, /^assert_checkout_summary$/],
    allowResources: [/^Generate Code With Locators$/],
  },
});

await server.start({ transportType: 'stdio' });

Plugin lifecycle:

  • register(registry, core): called during server construction. Register custom tools, prompts, resources, and resource templates here.
  • initialize(ctx): called lazily on the first MCP client connection. Use it for async setup such as artifact storage or internal service clients.
  • beforeCall(ctx): called before a registered MCP tool executes. Return a ToolCallResult to short-circuit the tool. This hook only applies to tools, not prompts, resources, or resource templates.
  • afterCall(ctx, result): called after a registered MCP tool executes. Return a modified ToolCallResult to decorate or replace the response. This hook only applies to tools, not prompts, resources, or resource templates.
  • destroy(): called after the last MCP client disconnects.

Safe plugin surface

The supported plugin API is intentionally small:

SurfaceSafe methods
McpRegistryaddTool, addTools, addPrompt, addPrompts, addResource, addResources, addResourceTemplate, addResourceTemplates
AppiumMcpCoregetSessionId(), getSessionInfo(sessionId?), getDriver(sessionId?), listSessions()
ToolCallContext.sessiongetSessionId(), getSessionInfo(sessionId?), getDriver(sessionId?), listSessions()
PluginContextcore, plugins

McpRegistry methods delegate to the matching FastMCP registration APIs, so their object shapes follow FastMCP's documented tool, prompt, resource, and resource-template definitions. Appium MCP wraps registered tools with plugin call hooks, but prompts and resources are registered directly with FastMCP.

Each plugin name should be unique within the server. If two plugins use the same name, Appium MCP keeps the first plugin registered for that name and skips later plugins with a warning. Use a stable, package-style or organization-prefixed name, such as acme-checkout-plugin, to avoid collisions when composing plugins from multiple teams.

Each tool name should also be unique across all plugins and the core server. Tool names follow FastMCP behavior, not plugin-name behavior: when a tool is registered with the same name as an existing tool, FastMCP replaces the earlier tool definition with the later one. Appium MCP registers built-in tools before plugin tools, which means a plugin tool that uses the same name as a built-in tool replaces the built-in tool. Appium MCP tools usually have an appium_ prefix, so plugin tool names should use that pattern only when they intentionally override a core tool.

Verify plugin and tool names

Use verifyAppiumMcpNames before publishing or deploying a custom plugin setup. It registers your plugin capabilities into a lightweight collector, registers the Appium MCP core tools, and reports duplicate plugin names, duplicate tool names, and registration errors without starting the MCP server.

The recommended approach is to verify the same plugin array you pass to createAppiumMcpServer({ plugins }). This preserves your real plugin instances and order:

Copy & paste β€” that's it
import {
  formatVerificationReport,
  verifyAppiumMcpNames,
} from 'appium-mcp/core';
import { plugins } from './plugins.js';

const report = verifyAppiumMcpNames({ plugins });

console.log(formatVerificationReport(report));
process.exit(report.ok ? 0 : 1);

When you provide multiple plugins, order is preserved. Plugins are verified in array order after the appium-mcp core tools. This matters because Appium MCP keeps the first plugin for a duplicate plugin name and skips later plugins with the same name, while duplicate tool names follow FastMCP's later-registration-wins behavior. Tool names still need to be unique across all loaded plugins and appium-mcp core; the verifier reports any collisions it finds.

The report labels this package's own shipped tools as appium-mcp core. Plugin sources are labeled as plugin:<name> with the plugin version.

Treat anything outside appium-mcp/core as internal. In particular, plugins should not rely on private server internals, internal session-store modules, tool implementation files, or the raw FastMCP server instance. If a plugin needs another stable primitive, open an issue so it can be added to AppiumMcpCore or McpRegistry deliberately.

See examples/plugin-example.ts for a fuller cookbook with tools, prompts, resources, resource templates, call hooks, and lifecycle setup.

🎯 Available Tools

MCP Appium provides a comprehensive set of tools organized into the following categories:

Platform & Device Setup

ToolDescription
select_deviceREQUIRED FIRST: Discover available devices and select one. Auto-selects if only one device found
prepare_ios_simulatorBoot an iOS/tvOS simulator, download WDA (if not cached), and install/launch WDA in a single call. Each step is skipped if already satisfied (iOS/tvOS only). Set APPIUM_MCP_WDA_APP_PATH to skip all downloads and use a local .app bundle instead.
appium_prepare_ios_real_devicePrepare a real iOS device for Appium testing. Two-step flow: (1) call without provisioningProfileUuid to list available .mobileprovision profiles; (2) call again with the chosen UUID and isFreeAccount to download the matching WDA release, package it as an IPA, and resign with the profile. Results are cached per WDA version and profile, so repeat runs are fast. Pass the returned capabilitiesHint to create_session so Appium installs and launches WDA. macOS + Xcode 16+ required.

Session Management

ToolDescription
appium_session_managementUnified session management. action=create: start a new session for Android, iOS, or general capabilities (see 'general' mode above); forwards capabilities to a remote server via WebDriver newSession when remoteServerUrl is provided. action=attach: connect MCP Appium to an already-running remote Appium session without taking ownership. action=detach: forget an attached session without deleting the real remote session. action=delete: stop and clean up an owned session (defaults to active). action=list: show all active sessions, including ownership. action=select: switch the active session by sessionId.
appium_mobile_device_controlControl device behavior: lock/unlock the screen, shake the device, or open the notifications panel (action: lock | unlock | shake | open_notifications). shake is iOS only; open_notifications is Android only; seconds is optional for timed lock.
appium_driver_settingsRead or update Appium driver session settings in one tool. action=get returns current settings as JSON; action=update merges a settings map (driver-specific keys; use action=get first to inspect).

The remote server URL in appium_session_management (action=create or action=attach) can be set via the remoteServerUrl parameter. When remoteServerUrl is omitted, action=create starts an embedded local UiAutomator2 or XCUITest driver for platform=android or platform=ios. platform=general requires remoteServerUrl. When remoteServerUrl is present, action=create calls WebDriver newSession on the remote server, and action=attach connects MCP Appium to an existing remote session without owning its lifecycle. If REMOTE_SERVER_URL_ALLOW_REGEX is set, the URL must match the provided regex pattern for security reasons. This allows you to restrict which remote servers can be used with your MCP Appium instance, preventing unauthorized connections. The default regex pattern allows any URL that starts with http:// or https://.

Context Management

ToolDescription
appium_contextManage contexts in one tool. action=list gets all available contexts including NATIVEAPP and WEBVIEW* entries. action=switch switches to a target context (context required).

Element Discovery & Interaction

ToolDescription
appium_find_elementFind a specific element using traditional locator strategies. Strategy priority: accessibility id > id > platform-native (-ios predicate string / -ios class chain on iOS, -android uiautomator on Android) > xpath (last resort β€” slow & brittle). To scroll until an element appears, use appium_gesture with action=scroll_to_element (same strategy / selector as find).
appium_aiOpt-in (gated by AI_VISION_ENABLED=true). Vision-based element finding β€” fallback for when traditional locators don't work. action=find_element takes a natural-language instruction (e.g., "yellow search button at bottom") and returns a coordinate UUID consumable by appium_gesture (tap / double_tap / long_press). See AI Vision Element Finding for setup.
appium_gesturePerform a touch gesture. action = back, tap, double_tap, long_press, scroll, swipe, pinch_zoom, or scroll_to_element. scroll_to_element scrolls vertically (direction = up | down) until the locator matches, page source stops changing after a scroll (end of list), or maxScrollAttempts (default 10, max 80). Optional scrollDistance (0.05–1) or scrollDistancePreset = small | medium | large. Supports element UUIDs and raw coordinates for other actions. For swipe, use speed = slow | normal | fast (fast for pull-to-refresh).
appium_drag_and_dropPerform a drag and drop gesture from a source location to a target location (supports element-to-element, element-to-coordinates, coordinates-to-element, and coordinates-to-coordinates)
appium_perform_actionsExecute raw W3C Actions API sequences for custom multi-touch gestures (rotate, three-finger swipe, edge swipes, precise timing). Prefer appium_gesture for standard gestures.
appium_set_valueEnter text into an input field
appium_mobile_keyboardHide the on-screen keyboard or query visibility. action=hide | is_shown (keys optional for hide).
appium_get_textGet text content from an element
appium_mobile_clipboardRead or set device clipboard plain text. action=get | set (content required for set).
appium_alertHandle alerts with action = accept, dismiss, or get_text (optional buttonLabel)

Screen & Navigation

ToolDescription
appium_screenshotTake a screenshot and save as PNG. Optionally provide elementUUID to capture a specific element. Pass returnRawBase64: true (default false) to return the raw base64 PNG inline instead of saving to disk β€” useful when the server runs on a remote machine where the saved file is not accessible. Intended for manual use only; an LLM should keep this false.
appium_get_window_sizeGet the width and height of the device screen in pixels
appium_get_page_sourceGet the page source (XML) from the current screen
appium_orientationGet or set device/screen orientation with action = get or set (requires orientation for set).
appium_geolocationGet, set, or reset the device GPS coordinates with action = get, set, or reset. For set, provide latitude and longitude (and optional altitude on Android). Not supported on Android emulators for reset.
appium_screen_recordingStart or stop screen recording with action = start or stop. On stop, returns the saved MP4 path.
appium_mobile_device_infoGet device information, battery status, or current device time. Use action = info (model, OS version, locale, timezone, screen density, etc.), battery (level as percentage and charging state), or time (current device time; accepts an optional format moment.js string, defaults to ISO 8601). Works on both iOS and Android.

App Management

ToolActionDescription
appium_app_lifecycleactivateActivate (launch/bring to foreground) a specified app by bundle ID or name
appium_app_lifecycleterminateTerminate (close) a specified app
appium_app_lifecycleinstallInstall an app on the device from a file path
appium_app_lifecycleuninstallUninstall an app from the device by bundle ID or name
appium_app_lifecyclelistList all installed apps on the device (Android and iOS)
appium_app_lifecycleis_installedCheck whether an app is installed. Package name for Android, bundle ID for iOS.
appium_app_lifecyclequery_stateQuery the current state of an app: 0=not installed, 1=not running, 2=background suspended, 3=background, 4=foreground
appium_app_lifecyclebackgroundBackground the current app for a duration (optional; defaults to 5 seconds)
appium_app_lifecycleclearClear app data and cache without uninstalling (mobile: clearApp). Android: stop the app first when possible. iOS: Simulator only; not supported on real devices.
appium_app_lifecycledeep_linkOpen a deep link URL with the default or a specified app
appium_mobile_permissionsGet, update, or reset app permissions in one tool (action: get / update / reset)Android: list or change runtime permissions. iOS Simulator: get/set privacy via bundle id; reset (action=reset) applies to the AUT on sim and device.

Test Generation & Documentation

ToolDescription
generate_locatorsGenerate intelligent locators for all interactive elements on the current screen
appium_generate_testsGenerate automated test code from natural language scenarios
appium_documentation_queryOpt-in (gated by APPIUM_MCP_DOCS_ENABLED). Query Appium documentation using RAG for help and guidance
appium_skillsOpt-in (gated by APPIUM_MCP_DOCS_ENABLED). Return ordered setup or troubleshooting skills from appium/skills for local Appium environments

πŸ€– Client Support

MCP Appium is designed to be compatible with any MCP-compliant client.

πŸ™Œ Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue to discuss any changes.

πŸ“„ License

This project is licensed under the Apache-2.0. See the LICENSE file for details.