An Android application that runs as an MCP (Model Context Protocol) server, enabling AI models to fully control an Android device remotely using accessibility services and screenshot capture.
> /plugin marketplace add danielealbano/android-remote-control-mcp> /plugin install android-remote-control@android-remote-control-mcp
Repo: danielealbano/android-remote-control-mcp
What's inside
An Android application that runs as an MCP (Model Context Protocol) server, enabling AI models to fully control an Android device remotely using accessibility services and screenshot capture.
The app runs directly on your Android device (or emulator) and exposes an HTTP server (with optional HTTPS) implementing the MCP protocol. AI models like Claude can connect to it and interact with any app on the device โ reading UI elements, tapping buttons, typing text, swiping, capturing screenshots, managing files, launching apps, and more.
Warning: This software is provided "as-is" without warranty of any kind, for research and educational purposes only. The authors do not condone the use of this tool for any illegal, unauthorized, or unethical activities. Users are solely responsible for ensuring their use complies with all applicable laws and regulations. By using this software, you agree to use it responsibly and at your own risk.
/mcp (MCP specification compliant, JSON-only, no SSE)Screen introspection, system actions, touch actions, gestures, node actions, text input, utilities, file operations, app management, camera, intents, notifications, location, and sharing.
All tool names use the android_ prefix by default (e.g., android_tap). When a device slug is configured (e.g., pixel7), the prefix becomes android_pixel7_ (e.g., android_pixel7_tap).
See docs/MCP_TOOLS.md for the full tool reference with input/output schemas and examples.
| Feature | This project | mobile-mcp | Android-MCP | android-mcp-server | adb-mcp | droidrun-mcp |
|---|---|---|---|---|---|---|
| MCP tools | 57 | 21 | 11 | 5 | 10 | 11 |
| Runs on the phone (no ADB) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
| Action latency | 10-100 ms | 1-4 s | 1-4 s | 1-4 s | 1-4 s | 1-4 s |
| Works over the internet | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
| Token-efficient screen state | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: |
| Annotated screenshots | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: |
| Configurable screenshot resolution/quality | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
| Per-tool enable/disable | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
| Multi-device support | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: |
| Camera, clipboard, files, downloads | :white_check_mark: | :x: | :x: | :x: | :x: | :x: |
| iOS support | :x: | :white_check_mark: | :x: | :x: | :x: | :x: |
Most alternatives rely on ADB running on a host machine, which means a USB cable or local network connection and a computer sitting next to the phone. This project runs entirely on the device itself, so you can expose the MCP endpoint through a tunnel and control your phone from anywhere.
On the token efficiency side, ADB-based tools typically return raw uiautomator XML dumps which can easily be 10-50x more verbose than the compact representation used here. Combined with numbered screenshot annotations, configurable image quality, and the ability to disable tools you don't need (every tool definition costs tokens on every turn), this significantly reduces the per-interaction cost in agentic loops.
Each release provides two flavors of the APK โ pick the one that matches your device:
โฆ-gms-release.apk) โ the full build. Requires Google Mobile Services (Google Play Services) installed on the phone. Choose this on standard devices/emulators that ship with Google services.โฆ-foss-release.apk) โ a Google-free build with no dependency on Google Mobile Services. Works on any Android phone, including de-Googled ROMs and devices where Google services are unavailable.If unsure, the GMS build is the right choice for a typical phone with the Play Store.
adb install android-remote-control-mcp-<version>-gms-release.apk
git clone https://github.com/danielealbano/android-remote-control-mcp.git
cd android-remote-control-mcp
make build
make install # installs on connected device/emulator
See CONTRIBUTING.md for full build requirements and instructions.
Open the app. The Server tab shows a permission warning banner; grant permissions from there or via Settings > Permissions.
Grant permissions:
Start the server. Go back to the Server tab and tap Start.
The server starts on http://127.0.0.1:8080 by default. The connection info (IP, port, token, URL) is displayed on the Server tab.
Note:
127.0.0.1refers to the phone's localhost, not your computer. To connect from your computer, use adb port forwarding, bind to0.0.0.0(network mode), or enable a remote access tunnel.
Privacy Mode detects and hides personal data โ emails, credit cards and IBANs, credentials, phone
numbers, national IDs, addresses, and names โ in everything the MCP tools return (screen content,
notifications, clipboard, files, โฆ) before it leaves the device for the AI provider. Detection
runs fully on-device: fast rule-based checks (checksums, formats, field context) combined with a
local NER model โ no cloud calls. Detected values are either pseudonymized with consistent
placeholders (EMAIL#a1b2c, so AI tools keep working across screens) or fully redacted. Detection
is best-effort mitigation, not a guarantee.
The model is the Ai4Privacy multilingual anonymiser (MIT license, Built with Llama), downloaded once on first enable (~150 MB) directly from the pinned Hugging Face revision and checksum-verified on device.
Share of personal data items detected per category by the full pipeline, measured with the in-repo
effectiveness benchmark (make privacy-benchmark) on realistic UI-style content across 8 languages:
| Category | Detected |
|---|---|
| Addresses | 77.9% |
| Cards & IBANs | 75.3% |
| Credentials | 90.9% |
| Emails | 100.0% |
| Names | 0.8% |
| National IDs | 93.0% |
| Phone numbers | 84.4% |
Names are the on-device model's known weak spot (it recognizes common Western names far better than the globally diverse names in the benchmark); improving name detection with a fine-tuned model is on the roadmap. Actual results vary with content and language.
Add the server to your .mcp.json configuration file:
{
"mcpServers": {
"android-phone": {
"type": "http",
"url": "http://DEVICE_IP:PORT/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
Replace DEVICE_IP, PORT, and YOUR_TOKEN with the values shown in the app's Server tab. If the server is bound to localhost (default), you'll need adb port forwarding or a remote access tunnel to connect.
Note for clients without custom-header support: if your MCP client cannot send an
Authorizationheader and does not support OAuth, you can turn off both auth methods in the app (Settings โ Access โ disable Bearer token and OAuth). The app warns and asks you to confirm, because the server is then open: anyone who can reach it has full control. Only do this on a network you trust.
Claude.ai (web) and Claude Desktop connect as a custom connector (remote MCP) using OAuth 2.1 โ the app is its own OAuth Authorization Server, so no external account or pre-registration is needed. This requires the server to be reachable over a public HTTPS URL, so you must first enable a remote access tunnel โ a localhost/LAN address or adb port-forward will not work.
https://โฆ URL from the Server tab and append /mcp (e.g. https://your-tunnel.trycloudflare.com/mcp).https://โฆ/mcp URL, and leave the OAuth Client ID and Client Secret blank (the app uses Dynamic Client Registration). Click Add.Public URL override (optional): if your tunnel/host topology needs a fixed public host (or you bind to
0.0.0.0without a trusted proxy), set a Public URL override in Settings โ Access so OAuth metadata and links use a stable host.
Custom connectors are available on the Free (1 connector), Pro, Max, Team, and Enterprise plans (currently in beta).
โ ๏ธ Security: treat the public tunnel URL as sensitive, approve only connections you initiated (verify the 2-digit code), revoke clients you no longer use, and stop the tunnel and server when you are done. Never point it at a device holding sensitive data.
ChatGPT connects to the server as a custom MCP connector using the same self-contained OAuth 2.1 flow. As with Claude, the server must be reachable over a public HTTPS URL, so enable a remote access tunnel first โ a localhost/LAN address or adb port-forward will not work. Custom connectors require a paid plan (Plus, Pro, Business, Enterprise, or Edu โ not Free) and are set up from the ChatGPT web app.
https://โฆ/mcp URL from the Server tab.https://โฆ/mcp URL, select OAuth as the authentication method, and leave any Client ID / Client Secret blank (the app self-registers clients via Dynamic Client Registration).โ ๏ธ Security: the same cautions apply โ treat the tunnel URL as sensitive, approve only connections you initiated (verify the code), revoke unused clients, and stop the tunnel and server when you are done.
The MCP server exposes a standard Streamable HTTP endpoint at /mcp with combined authentication (static bearer token and/or OAuth 2.1). Any MCP-compatible client can connect to it โ refer to your client's documentation for the specific configuration format.
MCP Inspector is the official visual testing tool for MCP servers. It provides a browser-based UI to connect, list tools, fill parameters, and see responses:
npx @modelcontextprotocol/inspector
This opens a UI at http://localhost:6274 where you can connect to your server and test tools interactively.
All requests are sent as JSON-RPC 2.0 via POST /mcp (Streamable HTTP transport). The server requires a session initialization handshake before tool calls:
# Initialize a session (required before any tool call)
# Capture the mcp-session-id from the response headers
curl -s -D- -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl-client","version":"1.0.0"}}}'
# Use the mcp-session-id from the response headers in all subsequent requests
# List available tools
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: SESSION_ID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# Get the current screen state (UI nodes + optional screenshot)
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: SESSION_ID" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"android_get_screen_state","arguments":{}}}'
# Tap at coordinates
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: SESSION_ID" \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"android_tap","arguments":{"x":540,"y":1200}}}'
Replace SESSION_ID with the mcp-session-id value from the initialize response headers.
The bearer token is shown in the app's connection info and can be copied directly. Bearer authentication is controlled by the Bearer token toggle in Settings โ Access (not by clearing the value): with it enabled, every /mcp request must present the token (or a valid OAuth access token). The server accepts unauthenticated requests only when both the Bearer token and OAuth are disabled.
| Setting | Default | Description |
|---|---|---|
| Port | 8080 | HTTP/HTTPS server port |
| Binding Address | 127.0.0.1 | 127.0.0.1 (localhost, use with adb port forwarding) or 0.0.0.0 (network, all interfaces) |
| Bearer Token | Enabled, auto-generated UUID | Static token for MCP requests (Settings โ Access). Enforcement is set by the Bearer toggle, not by clearing the value. |
| OAuth | Enabled | Self-contained OAuth 2.1 server for Claude.ai / Claude Desktop custom connectors (Settings โ Access). |
| Public URL override | Empty (auto-detect) | Pin the public host used for OAuth metadata and share links. |
| HTTPS | Disabled | Enable HTTPS with auto-generated self-signed certificate (configurable hostname) or upload custom .p12/.pfx |
| Auto-start on Boot | Disabled | Start MCP server automatically when device boots |
| Device Slug | Empty | Optional device identifier for tool name prefix (e.g., pixel7 makes tools android_pixel7_tap) |
| Remote Access Tunnel | Disabled | Expose server via public HTTPS URL (Cloudflare Quick Tunnels or ngrok) |
| Tool Permissions | All enabled | Per-tool and per-parameter enable/disable (Settings > MCP Tools) |
| File Size Limit | 50 MB | Maximum file size for file operations (range 1-500 MB) |
| Allow HTTP Downloads | Disabled | Allow non-HTTPS downloads via android_download_from_url |
| Download Timeout | 60 seconds | Timeout for file downloads (range 10-300 seconds) |
When the server is bound to 127.0.0.1 (default, most secure):
# Forward device port to host
adb forward tcp:8080 tcp:8080
# Test connection from host
curl -X POST http://localhost:8080/mcp \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
When the server is bound to 0.0.0.0:
POST http://DEVICE_IP:8080/mcp with bearer tokenWarning: Binding to 0.0.0.0 exposes the server to all devices on the same network. Only use on trusted private networks.
For connecting from outside the local network without port forwarding:
*.trycloudflare.com HTTPS URL.Enable the tunnel in the app's "Remote Access" section. The public URL is displayed in the connection info and server logs.
The app can be fully configured and controlled from the command line without opening the UI. This is useful for automated setups, CI pipelines, or headless devices.
Replace <app-id> with the application ID for your build:
com.danielealbano.androidremotecontrolmcp.debugcom.danielealbano.androidremotecontrolmcp# Enable Accessibility Service (required for UI introspection, actions, and screenshots)
adb shell settings put secure enabled_accessibility_services \
<app-id>/com.danielealbano.androidremotecontrolmcp.services.accessibility.McpAccessibilityService
# Enable Notification Listener Service (required for notification tools)
adb shell cmd notification allow_listener \
<app-id>/com.danielealbano.androidremotecontrolmcp.services.notifications.McpNotificationListenerService
# Grant notification permission (Android 13+)
adb shell pm grant <app-id> android.permission.POST_NOTIFICATIONS
# Grant camera permission
adb shell pm grant <app-id> android.permission.CAMERA
# Grant microphone permission
adb shell pm grant <app-id> android.permission.RECORD_AUDIO
# Grant location permissions
adb shell pm grant <app-id> android.permission.ACCESS_FINE_LOCATION
adb shell pm grant <app-id> android.permission.ACCESS_COARSE_LOCATION
adb shell pm grant <app-id> android.permission.ACCESS_BACKGROUND_LOCATION
# Grant nearby WiFi devices permission (Android 13+)
adb shell pm grant <app-id> android.permission.NEARBY_WIFI_DEVICES
# Grant media read permissions (Android 13+)
adb shell pm grant <app-id> android.permission.READ_MEDIA_IMAGES
adb shell pm grant <app-id> android.permission.READ_MEDIA_VIDEO
adb shell pm grant <app-id> android.permission.READ_MEDIA_AUDIO
See docs/PERMISSIONS.md for the full reference and a copy-paste script that grants everything in one go.
All extras are optional โ only the ones provided are updated. The app does not need to be open.
Requires adb. The configuration receiver and the service trampoline are gated on
android.permission.DUMP, which the adb shell UID holds but ordinary apps cannot obtain. The commands below work unchanged fromadb shell; an app on the device cannot use them to reconfigure the server. See the Security section.
adb shell am broadcast \
-a com.danielealbano.androidremotecontrolmcp.ADB_CONFIGURE \
-n <app-id>/com.danielealbano.androidremotecontrolmcp.services.mcp.AdbConfigReceiver \
--es bearer_token "my-secret-token" \
--es binding_address "0.0.0.0" \
--ei port 8080 \
--ez auto_start_on_boot true \
--ez https_enabled false \
--es certificate_source "AUTO_GENERATED" \
--es certificate_hostname "mcp.local" \
--ez tunnel_enabled false \
--es tunnel_provider "CLOUDFLARE" \
--es ngrok_authtoken "your-ngrok-token" \
--es ngrok_domain "your-domain.ngrok-free.app" \
--ei file_size_limit_mb 50 \
--ez allow_http_downloads false \
--ez allow_unverified_https_certs false \
--ei download_timeout_seconds 60 \
--es device_slug "pixel8" \
--es tool_permissions '{"disabled_tools":["tap"],"disabled_params":{"swipe":["duration_ms"]}}'
# Disable bearer authentication (use only on trusted networks; the server is open
# only if OAuth is also disabled โ see the Security section)
adb shell am broadcast \
-a com.danielealbano.androidremotecontrolmcp.ADB_CONFIGURE \
-n <app-id>/com.danielealbano.androidremotecontrolmcp.services.mcp.AdbConfigReceiver \
--ez bearer_token_enabled false
Bearer enforcement is controlled by --ez bearer_token_enabled <bool>, NOT by clearing the value. Clearing the value (--es bearer_token "") while bearer_token_enabled=true makes /mcp fail CLOSED (401) โ it does NOT open the server. The server accepts unauthenticated requests only when BOTH bearer_token_enabled and oauth_enabled are false.
| Extra | Type | Description |
|---|---|---|
bearer_token | string | Static bearer-token value (clearing it while bearer_token_enabled=true fails closed, it does NOT disable auth) |
bearer_token_enabled | boolean | Enable/disable bearer-token authentication (controls enforcement, independent of the value) |
oauth_enabled | boolean | Enable/disable the self-contained OAuth 2.1 server (Claude.ai / Claude Desktop connectors) |
public_url_override | string | Pin the public host used for OAuth metadata and share links (empty = auto-detect from the request) |
binding_address | string | 127.0.0.1 (localhost) or 0.0.0.0 (network) |
port | int | HTTP/HTTPS server port (1-65535) |
auto_start_on_boot | boolean | Start MCP server when device boots |
https_enabled | boolean | Enable HTTPS with TLS |
certificate_source | string | AUTO_GENERATED or CUSTOM |
certificate_hostname | string | Hostname for auto-generated certificate |
tunnel_enabled | boolean | Enable remote access tunnel |
tunnel_provider | string | CLOUDFLARE or NGROK |
ngrok_authtoken | string | ngrok authentication token |
ngrok_domain | string | ngrok custom domain (optional) |
file_size_limit_mb | int | Max file size for file operations (1-500) |
allow_http_downloads | boolean | Allow non-HTTPS downloads |
allow_unverified_https_certs | boolean | Allow unverified HTTPS certificates for downloads |
download_timeout_seconds | int | Download timeout (10-300) |
device_slug | string | Device identifier for tool name prefix |
tool_permissions | string (JSON) | Per-tool and per-parameter permissions: {"disabled_tools":["tool_name"],"disabled_params":{"tool_name":["param"]}} |
The server must be started via a trampoline Activity (required on Android 12+ to gain foreground service exemption). This works even when the app is force-stopped.
adb shell am start \
-n <app-id>/com.danielealbano.androidremotecontrolmcp.services.mcp.AdbServiceTrampolineActivity \
--es action start
adb shell am start \
-n <app-id>/com.danielealbano.androidremotecontrolmcp.services.mcp.AdbServiceTrampolineActivity \
--es action stop
The app declares the permissions below. Normal permissions are granted automatically at install. Runtime permissions and Special access require explicit user action (via the app's Settings > Permissions tab, or programmatically โ see Granting Permissions Programmatically). All runtime permissions are optional: the app works without them, but the features that depend on them are disabled until granted.
| Permission | Type | Used for |
|---|---|---|
INTERNET | Normal | HTTP/HTTPS server and remote access tunnels |
ACCESS_NETWORK_STATE | Normal | Detect network connectivity |
FOREGROUND_SERVICE | Normal | Run the MCP server as a foreground service |
FOREGROUND_SERVICE_SPECIAL_USE | Normal | Foreground service type for the MCP server |
FOREGROUND_SERVICE_LOCATION | Normal | Foreground service type for the Event Channel (geofence/WiFi) |
RECEIVE_BOOT_COMPLETED | Normal | Auto-start the server on device boot |
QUERY_ALL_PACKAGES | Normal | Enumerate installed apps for app-management tools |
KILL_BACKGROUND_PROCESSES | Normal | Stop background apps via app-management tools |
ACCESS_WIFI_STATE | Normal | Read WiFi state for the Event Channel |
CHANGE_WIFI_STATE | Normal | Manage WiFi for the Event Channel |
POST_NOTIFICATIONS | Runtime | Show the foreground service notification (Android 13+) |
CAMERA | Runtime | Camera photo/video MCP tools |
RECORD_AUDIO | Runtime | Audio capture for camera video tools |
ACCESS_FINE_LOCATION | Runtime | Location tools and geofence events |
ACCESS_COARSE_LOCATION | Runtime | Approximate location |
ACCESS_BACKGROUND_LOCATION | Runtime | Location/geofence events while the app is in the background |
NEARBY_WIFI_DEVICES | Runtime | WiFi scanning for the Event Channel (Android 13+) |
READ_MEDIA_IMAGES | Runtime | "All files" mode for built-in image storage locations (Android 13+) |
READ_MEDIA_VIDEO | Runtime | "All files" mode for built-in video storage locations (Android 13+) |
READ_MEDIA_AUDIO | Runtime | "All files" mode for built-in audio storage locations (Android 13+) |
| Accessibility Service | Special access | UI introspection, action execution, and screenshots โ required for core functionality |
| Notification Listener | Special access | Reading and managing notifications via notification tools |
The application runs entirely within Android's standard permission model. No root access, no unlocked bootloader, no custom ROM required.
Authentication is combined (dual-accept): a /mcp request is authorized by a valid static bearer token OR a valid issued OAuth access token. Enforcement is controlled by two independent toggles in Settings โ Access โ bearer_token_enabled (default on) and oauth_enabled (default on) โ not by the token value. The bearer token is auto-generated once on first launch (UUID, preserved across app upgrades) and can be viewed, copied, or regenerated in the app. Clearing the value while bearer is enabled makes the server fail CLOSED (401). The server accepts unauthenticated requests only when BOTH toggles are off (the app shows a warning and a confirmation before that happens) โ see the security note in the Connect section.
127.0.0.1: Only accessible via adb port forwarding or tunnels (most secure)0.0.0.0: Accessible over network (use only on trusted networks; security warning displayed when enabling)All permissions are managed from the app's Settings > Permissions tab. Every sensitive permission requires explicit user action โ nothing is granted silently.
Storage locations are configured in Settings > Storage, which includes automatic locations (e.g., Downloads) and custom locations authorized via the system file picker.
See CONTRIBUTING.md for build requirements, testing, architecture, and development conventions.
This project is licensed under the MIT License. See LICENSE.md for details.
.claude/
.claude-plugin/
marketplace.json
agents/
code-reviewer.md
plan-reviewer.md
.editorconfig
.env.example
.github/
workflows/
ci.yml
release.yml
.gitignore
.gitmodules
app/
build.gradle.kts
proguard-rules.pro
src/
debug/
AndroidManifest.xml
kotlin/
com/
danielealbano/
androidremotecontrolmcp/
debug/
E2EConfigReceiver.kt
OAuthApprovalTestReceiver.kt
foss/
kotlin/
com/
danielealbano/
androidremotecontrolmcp/
di/
FossBatteryModule.kt
FossGeofenceModule.kt
FossLocationModule.kt
services/
channel/
NoOpGeofenceChannelController.kt
location/
FossLocationProviderImpl.kt
power/
FossBatteryOptimizationManagerImpl.kt
startup/
FlavorStartup.kt
ui/
screens/
settings/
BackgroundLocationPermissionRow.kt
GeofenceDestinations.kt
GeofenceEventSourceItem.kt
gms/
AndroidManifest.xml
kotlin/
com/
danielealbano/
androidremotecontrolmcp/
data/
model/
GeofenceChannelEventFactory.kt
GeofenceConfig.kt
repository/
GeofenceConfigRepository.kt
GeofenceConfigRepositoryImpl.kt
di/
GmsBatteryModule.kt
GmsGeofenceConfigModule.kt
GmsGeofenceModule.kt
GmsLocationModule.kt
services/
channel/
geofence/
GeofenceManager.kt
GeofenceManagerImpl.kt
GeofenceTransitionReceiver.kt
GeofenceChannelControllerImpl.kt
listeners/
GeofenceEventListener.kt
location/
LocationProviderImpl.kt
power/
GmsBatteryOptimizationManagerImpl.kt
startup/
FlavorStartup.kt
ui/
navigation/
GeofenceRoutes.kt
screens/
settings/
BackgroundLocationPermissionRow.kt
GeofenceDestinations.kt
GeofenceEventSourceItem.kt
GeofenceListScreen.kt
GeofenceMapScreen.kt
viewmodels/
GeofenceSettingsViewModel.kt
res/
values/
strings.xml
main/
AndroidManifest.xml
kotlin/
com/
danielealbano/
androidremotecontrolmcp/
data/
model/
AppFilter.kt
AppInfo.kt
BindingAddress.kt
BuiltinPermissions.kt
BuiltinStorageLocation.kt
CameraInfo.kt
CameraResolution.kt
CertificateSource.kt
ChannelConnectionStatus.kt
ChannelEvent.kt
ChannelEventFactory.kt
CloudflareTunnelMode.kt
EventChannelConfig.kt
FileInfo.kt
LocationData.kt
NotificationChangeEvent.kt
OptionalToolPermission.kt
ScreenshotData.kt
ServerConfig.kt
ServerLogEntry.kt
ServerStatus.kt
StorageBackend.kt
StorageLocation.kt
ToolPermissionsConfig.kt
TunnelProviderType.kt
TunnelStatus.kt
repository/
EventChannelSettings.kt
EventChannelSettingsImpl.kt
OAuthClientRepository.kt
OAuthClientRepositoryImpl.kt
ServerLogRepository.kt
ServerLogRepositoryImpl.kt
ServerLogSegmentedStore.kt
SettingsChangeLogger.kt
SettingsJsonCodec.kt
SettingsRepository.kt
SettingsRepositoryImpl.kt
di/
AppModule.kt
geo/
CountryDisplay.kt
DbIpGeoResolver.kt
GeoIpResolver.kt
LocationDb.kt
mcp/
auth/
BearerTokenAuth.kt
CertificateManager.kt
ContentTypeUtil.kt
Cors.kt
McpApplicationPlugins.kt
McpServer.kt
McpStreamableHttpExtension.kt
McpToolException.kt
oauth/
AuthorizationCodeStore.kt
AuthorizationCodeStoreImpl.kt
ClientIconUrl.kt
ConsentPageData.kt
JwtTokenService.kt
JwtTokenServiceImpl.kt
LogoUrlPolicy.kt
OAuthAccessValidator.kt
OAuthApprovalCoordinator.kt
OAuthApprovalCoordinatorImpl.kt
OAuthClient.kt
OAuthConsentPage.kt
OAuthMetadata.kt
OAuthPolicy.kt
OAuthRoutes.kt
OAuthRouteSupport.kt
OAuthServerDeps.kt
OAuthTokenGrants.kt
Pkce.kt
RequestBaseUrl.kt
tools/
AppManagementTools.kt
CameraTools.kt
FileTools.kt
GestureTools.kt
IntentTools.kt
LocationTools.kt
LoggedToolRegistration.kt
McpToolUtils.kt
NodeActionTools.kt
NotificationTools.kt
ScreenIntrospectionTools.kt
SharingTools.kt
SystemActionTools.kt
TextInputTools.kt
TouchActionTools.kt
TreeFingerprint.kt
UtilityTools.kt
McpApplication.kt
privacy/
model/
PrivacyModelDownloader.kt
PrivacyModeManager.kt
PrivacyModeStatus.kt
PrivacyPipeline.kt
PrivacyPipelineImpl.kt
PrivacyToolGate.kt
services/
accessibility/
AccessibilityNodeCache.kt
AccessibilityNodeCacheImpl.kt
AccessibilityServiceProvider.kt
AccessibilityServiceProviderImpl.kt
AccessibilityTreeLock.kt
AccessibilityTreeParser.kt
ActionExecutor.kt
ActionExecutorImpl.kt
CacheInvalidationDebouncer.kt
CompactTreeFormatter.kt
ElementFinder.kt
McpAccessibilityService.kt
ScreenInfo.kt
ScreenStateSnapshotCache.kt
ScreenStateSnapshotCacheImpl.kt
TypeInputController.kt
TypeInputControllerImpl.kt
WebViewNodeMerger.kt
apps/
AppIconCache.kt
AppManager.kt
AppManagerImpl.kt
camera/
CameraProvider.kt
CameraProviderImpl.kt
ServiceLifecycleOwner.kt
channel/
EventChannelService.kt
EventDispatcher.kt
EventDispatcherImpl.kt
GeofenceChannelController.kt
listeners/
NotificationEventListener.kt
WifiEventListener.kt
intents/
IntentDispatcher.kt
IntentDispatcherImpl.kt
location/
LocationProvider.kt
ReverseGeocoder.kt
mcp/
AdbConfigHandler.kt
AdbConfigReceiver.kt
AdbServiceTrampolineActivity.kt
BootCompletedReceiver.kt
McpServerRestart.kt
McpServerService.kt
OAuthApprovalNotifier.kt
PackageReplacedReceiver.kt
notifications/
McpNotificationListenerService.kt
NotificationDataExtractor.kt
NotificationProvider.kt
NotificationProviderImpl.kt
power/
BatteryOptimizationManager.kt
BatteryOptimizationState.kt
screencapture/
ApiLevelProvider.kt
ScreenCaptureProvider.kt
ScreenCaptureProviderImpl.kt
ScreenshotAnnotator.kt
ScreenshotEncoder.kt
ScreenshotRedactor.kt
sharing/
CapabilityToken.kt
EphemeralFileLinkService.kt
EphemeralFileLinkServiceImpl.kt
SharedContentClassifier.kt
SharedContentInbox.kt
SharedContentInboxImpl.kt
SharedStreamReader.kt
storage/
DownloadUrlValidator.kt
FileOperationProvider.kt
FileOperationProviderImpl.kt
MediaStoreFileOperations.kt
MediaStoreFileOperationsImpl.kt
MimeTypeUtils.kt
PermissionChecker.kt
PermissionCheckerImpl.kt
SslUtils.kt
StorageLocationProvider.kt
StorageLocationProviderImpl.kt
StorageStreamUtils.kt
tunnel/
AndroidCloudflareBinaryResolver.kt
CloudflaredBinaryResolver.kt
CloudflareTunnelProvider.kt
NgrokTunnelProvider.kt
TunnelManager.kt
TunnelProvider.kt
ui/
ApprovalActivity.kt
components/
BatteryOptimizationCard.kt
CalloutCard.kt
ConnectionInfoCard.kt
PrivacyModeCard.kt
ServerLogsSection.kt
ServerStatusCard.kt
MainActivity.kt
navigation/
Routes.kt
screens/
AboutScreen.kt
ApprovalScreen.kt
LogsScreen.kt
MainScreen.kt
ServerScreen.kt
ServerTabScreen.kt
settings/
AccessSettingsScreen.kt
ChannelSettingsScreen.kt
GeneralSettingsScreen.kt
McpToolsSettingsScreen.kt
NotificationFilterScreen.kt
OAuthClientsScreen.kt
PermissionsSettingsScreen.kt
PrivacySettingsScreen.kt
SecuritySettingsScreen.kt
SettingsIndexScreen.kt
StorageSettingsScreen.kt
TunnelSettingsScreen.kt
WifiMonitorScreen.kt
SettingsScreen.kt
ShareReceiverActivity.kt
theme/
Color.kt
Theme.kt
Type.kt
viewmodels/
AccessViewModel.kt
ApprovalViewModel.kt
ChannelViewModel.kt
LogsViewModel.kt
MainViewModel.kt
OAuthClientsViewModel.kt
PrivacyViewModel.kt
utils/
Logger.kt
NetworkUtils.kt
PermissionUtils.kt
res/
drawable/
ic_launcher_foreground.xml
ic_notification.xml
mipmap-anydpi-v26/
ic_launcher_round.xml
ic_launcher.xml
values/
ic_launcher_background.xml
strings.xml
themes.xml
xml/
accessibility_service_config.xml
resources/
native.properties
test/
kotlin/
com/
danielealbano/
androidremotecontrolmcp/
data/
model/
BuiltinStorageLocationTest.kt
ChannelEventFactoryTest.kt
EventChannelConfigTest.kt
OptionalToolPermissionTest.kt
PrivacyModeConfigTest.kt
ServerConfigTest.kt
ServerLogEntryTypeTest.kt
ServerStatusTest.kt
ToolPermissionsConfigTest.kt
TunnelStatusTest.kt
repository/
EventChannelSettingsTest.kt
ServerLogRepositoryImplTest.kt
ServerLogSegmentedStoreTest.kt
SettingsChangeLoggerTest.kt
SettingsRepositoryImplTest.kt
SettingsRepositoryLoggingTest.kt
SettingsRepositoryServerRunningTest.kt
geo/
CountryDisplayTest.kt
DbIpGeoResolverTest.kt
LocationDbTest.kt
integration/
... 478 moreFAQ
android-remote-control-mcp is a Claude Code plugin with hand-picked skills for automation work, indexed on Flowy. Install it with the command on its page. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.