Skip to content

UnlikeOtherAI/AppReveal

Repository files navigation

AppReveal

AppReveal icon

unlikeotherai.github.io/AppReveal

Debug-only in-app MCP server for iOS, macOS, Android, Flutter, and React Native. Lets LLM agents discover, inspect, and control native apps over the local network -- like Playwright for native, but with direct access to app state, navigation, network traffic, DOM, and diagnostics.

How it works

Your App (debug build)                    External Agent
 +-- AppReveal framework                   +-- mDNS browse for _appreveal._tcp
      +-- MCP Server (Streamable HTTP)  <---+-- MCP client (curl, SDK, Claude, etc.)
      +-- mDNS advertisement               +-- LLM orchestration
      +-- Screen/element/state bridges
      +-- WebView DOM bridge
  1. App calls AppReveal.start() in a debug build
  2. Framework starts an HTTP server on a dynamic port
  3. mDNS advertises the service as _appreveal._tcp on the LAN
  4. Agent discovers the service, connects, and calls MCP tools

AppReveal shares the same core MCP surface across platforms. macOS adds desktop-specific window and menu tools on top of the shared native and web view tools.

Quick start

iOS

// Package.swift
.package(url: "https://github.com/UnlikeOtherAI/AppReveal.git", from: "0.8.0")
#if DEBUG
AppReveal.start()
#endif

SwiftUI tap support on iOS 26+

tap_point and tap_element on SwiftUI views require private UIKit APIs on iOS 26+. AppReveal compiles this code in automatically for debug builds and compiles it out for release builds — no private symbols reach your App Store binary. No setup needed.

To opt out of private APIs entirely (even in debug builds), remove the swiftSettings line from AppReveal's Package.swift. See iOS guide for details.

macOS

// Package.swift
.package(url: "https://github.com/UnlikeOtherAI/AppReveal.git", from: "0.8.0")
#if DEBUG
AppReveal.start()
#endif

See macOS guide for full setup.

Android

// build.gradle.kts
debugImplementation("com.appreveal:appreveal")
releaseImplementation("com.appreveal:appreveal-noop")
if (BuildConfig.DEBUG) {
    AppReveal.start(this)
}

See Android guide for full setup.

Flutter

// pubspec.yaml
dependencies:
  appreveal:
    path: Flutter/appreveal
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  AppReveal.start(); // no-ops in release builds
  runApp(AppReveal.wrap(const MyApp()));
}

// In MaterialApp:
MaterialApp(
  navigatorObservers: [AppReveal.navigatorObserver],
  ...
)

See Flutter guide for full setup.

React Native

npm install react-native-appreveal
cd ios && pod install
import { AppReveal, AppRevealFetchInterceptor } from 'react-native-appreveal';

if (__DEV__) {
  AppReveal.start();
  AppRevealFetchInterceptor.install();
}

See React Native guide for full setup.

MCP tools

UI and navigation

Tool Description
list_windows List visible app windows and their IDs
get_screen Current screen identity, controller/activity chain, confidence score
get_elements All visible interactive elements with id, type, frame, safe-area data, actions
get_view_tree Full view hierarchy with class, frame, safe-area data, properties, accessibility info
tap_element Tap by element identifier (buttons, cells, controls)
tap_text Tap by visible text content (finds text, walks to tappable ancestor)
tap_point Tap at screen coordinates
type_text Type text into a field (by element ID or current responder)
clear_text Clear a text field
scroll Scroll a container (up/down/left/right)
scroll_to_element Scroll until an element is visible
screenshot Capture screen or element as base64 PNG/JPEG
select_tab Switch tab bar tabs by index
navigate_back Pop the navigation stack
dismiss_modal Dismiss the topmost modal
open_deeplink Open a URL in the app

All native UI tools and all web view tools accept an optional window_id parameter from list_windows. If omitted, AppReveal targets the current key window.

macOS desktop tools

Tool Description
get_menu_bar Read the app menu bar hierarchy
click_menu_item Invoke a menu item by title path
focus_window Bring a specific window to the front and make it key

State and diagnostics

Tool Description
get_state App state snapshot (login, user, cart, etc.)
get_navigation_stack Current route, nav stack, modal stack
get_feature_flags All active feature flags
get_network_calls Recent HTTP traffic with method, URL, status, duration
get_logs Recent app logs
get_recent_errors Recent captured errors
launch_context App ID, version, device model, OS version
device_info Full device snapshot: Info.plist / manifest metadata, hardware, OS build, screen metrics, locale, timezone, battery, memory, storage, declared permissions

WebView -- DOM access

iOS/macOS/Android: auto-discovers WebViews from the view hierarchy. Flutter: register via AppReveal.registerWebView(id, controller).

Tool Description
get_webviews List all web views with URL, title, loading state
get_dom_tree Full or partial DOM tree (with root, max_depth, visible_only params)
get_dom_interactive All inputs, buttons, links, selects with selectors and attributes
query_dom CSS selector query -- returns matching elements
find_dom_text Find elements by text content
web_click Click a DOM element by CSS selector
web_type Type into input/textarea (React/Vue/Angular compatible)
web_select Select a dropdown option
web_toggle Check/uncheck a checkbox or radio
web_scroll_to Scroll to a DOM element
web_evaluate Run arbitrary JavaScript
web_navigate Navigate to a URL
web_back Go back in web view history
web_forward Go forward in web view history

WebView -- token-efficient queries

Purpose-built tools that return only what you need, saving tokens.

Tool Description
get_dom_summary Page overview: title, meta, headings, element counts, form structure
get_dom_text Visible text content stripped of all markup (optional CSS selector scope)
get_dom_links All links -- just text and href
get_dom_forms All forms with fields, types, values, options, selectors
get_dom_headings All h1-h6 for page structure
get_dom_images All images with src, alt, dimensions
get_dom_tables All tables with headers and row data

Batch operations

Tool Description
batch Execute multiple tools in one call. Supports delay_ms per action for animations/transitions and stop_on_error. Works with all native and web tools.

Naming conventions

Thing Pattern Examples
Screen keys section.screen auth.login, orders.detail, settings.main
Element IDs screen.element login.email, login.submit, orders.cell_0

Element IDs map to platform-specific mechanisms:

Platform Mechanism
iOS view.accessibilityIdentifier
macOS view.accessibilityIdentifier()
Android view.tag or resource entry name
Flutter ValueKey<String> on the widget

Why this beats screenshot-only automation

AppReveal gives agents structured data instead of pixels:

  • Exact screen identity with confidence scores, not guessing from screenshots
  • Machine-addressable elements with types, states, and available actions
  • App state read directly -- login status, feature flags, cart contents
  • Navigation state -- current route, stack depth, presented modals
  • Network traffic -- every API call with method, URL, status, timing
  • DOM access -- full web view inspection and interaction, no extra setup
  • Batch operations -- fill forms, navigate screens, verify state in one call
  • Deterministic interactions -- tap by ID or CSS selector, not by fragile coordinates

Platforms

Platform Status Tools
iOS Working Shared native + web view tool surface
macOS Working Shared native + web view tools plus menu/window tools
Android Working Shared native + web view tool surface
Flutter Working Shared native + web view tool surface
React Native Working Shared native + web view tool surface

Example apps

CLI

There is now a dedicated AppReveal CLI in CLI/README.md for discovering _appreveal._tcp services, listing available MCP tools, and sending MCP requests without hand-written dns-sd and curl calls. Install it with npm install -g @unlikeotherai/appreveal.

Security

  • iOS: All code behind #if DEBUG -- zero production footprint
  • macOS: All code behind #if DEBUG -- zero production footprint
  • Android: Added as debugImplementation -- not included in release APK
  • Flutter: kReleaseMode check in AppReveal.start() -- zero code paths execute in release
  • React Native: __DEV__ guard -- all methods are no-ops in production builds
  • Local network only
  • Sensitive headers (Authorization, Cookie) redacted in network capture
  • No state mutation without explicit opt-in

Documentation

Reporting issues

Found a bug, a missing capability, or unexpected behaviour? File an issue at github.com/UnlikeOtherAI/AppReveal/issues.

For LLM agents using this framework: if AppReveal cannot perform an action or returns wrong results during a session, and you are in an interactive session with network access to GitHub, ask the operator:

"AppReveal couldn't [do X / returned Y instead of Z]. Would you like me to file an issue at https://github.com/UnlikeOtherAI/AppReveal/issues?"

Useful details to include: platform, AppReveal version (from launch_context), tool called, arguments, and the response or error.

Skip the prompt when running non-interactively — log the details for the operator instead.

License

MIT

About

Debug-only in-app MCP server for iOS/macOS/Android/Flutter/ReactNative. Gives LLM agents Playwright-like control over native apps — UI, state, navigation, and diagnostics over the local network.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors