Mobile MCP servers: set up Appium MCP, Maestro MCP and mobile-mcp
---
title: "Mobile MCP servers: set up Appium MCP, Maestro MCP and mobile-mcp"
published: true
published_at: "2026-11-03T16:00:00Z"
description: "Install commands and config for Appium MCP, Maestro MCP and mobile-mcp in Claude Code, Cursor and Codex."
tags: testing,mcp,mobile,ai
canonical_url: momentic.ai
---
Originally published on the Momentic blog.
TL;DR
- mobile-mcp lets a coding agent inspect and control a mobile app during a live session. Reach for it when you need to explore the UI.
- Appium MCP gives the agent access through an Appium session. Reach for it when your mobile setup already uses Appium drivers.
- Maestro MCP lets the agent work with Maestro’s mobile testing tools. Reach for it when you already use Maestro flows.
- All three can help an agent inspect and drive an app, but an MCP session alone does not leave behind a test that runs in CI.
- For a versioned test, use Momentic’s MCP server to write and run YAML tests. Install the mobile skills with npx momentic-mobile skills --yes.
Appium MCP, Maestro MCP and mobile-mcp compared
All three run as local stdio servers that your coding agent starts with one command. They differ in what they drive and what they leave behind.
| Server | Install | Platforms and targets | What the agent works with | Leaves a test behind? |
| --- | --- | --- | --- | --- |
| <a href="mobile-next/mobile-mcp">mobile-mcp</a> | npx -y @mobilenext/mobile-mcp@latest | iOS and Android: simulators, emulators and real devices | The native accessibility tree, with screenshots and coordinates as a fallback | No. The session lives in the agent's conversation |
| <a href="appium/appium-mcp">Appium MCP</a> | npx -y appium-mcp@latest | Android (UiAutomator2) and iOS (XCUITest): simulators, emulators and real devices | An Appium session: find elements, tap, type, gestures, screenshots | It can generate Java/TestNG test code from a description |
| <a href="docs.maestro.dev">Maestro MCP</a> | maestro mcp (needs the Maestro CLI) | iOS and Android apps, plus web | Maestro commands, so the agent can write, run and debug flows | Yes, when the agent saves the flow as a YAML file |
Pick the one that matches the tooling you already run. If your team has Appium capabilities and drivers set up, Appium MCP reuses them. If you write Maestro flows, Maestro MCP lets the agent write more of them. If you want an agent to poke at an app with no framework at all, mobile-mcp has the least setup.
Setting up mobile-mcp
Boot an iOS simulator (xcrun simctl boot "iPhone 16") or start an Android emulator first. The project's installer finds the MCP clients on your machine and configures them:
npx @mobilenext/mobile-mcp@latest install
To configure each client by hand:
# Claude Code
claude mcp add mobile-mcp -- npx -y @mobilenext/mobile-mcp@latest
# Codex
codex mcp add mobile-mcp npx "@mobilenext/mobile-mcp@latest"
For Cursor, add the server to ~/.cursor/mcp.json or a project-level .cursor/mcp.json:
{
"mcpServers": {
"mobile-mcp": {
"command": "npx",
"args": ["-y", "@mobilenext/mobile-mcp@latest"]
}
}
}
mobile-mcp drives the app from the native accessibility tree first, so the agent reads element labels instead of spending image tokens on screenshots. It falls back to a screenshot and coordinate taps when an element has no accessible label. It also installs, launches and terminates apps, opens deep links and records the screen.
Setting up Appium MCP
Appium MCP bundles the UiAutomator2 and XCUITest drivers for local sessions. You still need the platform toolchains: ANDROID_HOME, Java and the Android SDK tools for Android, and Xcode with an installed simulator for iOS (macOS only).
# Claude Code
claude mcp add appium-mcp -- npx -y appium-mcp@latest
For Cursor, and for other clients that take a JSON config:
{
"mcpServers": {
"appium-mcp": {
"type": "stdio",
"command": "npx",
"args": ["appium-mcp@latest"],
"env": {
"ANDROID_HOME": "/path/to/android/sdk",
"CAPABILITIES_CONFIG": "/path/to/your/capabilities.json"
}
}
}
}
For Codex, the same server goes in ~/.codex/config.toml:
[mcp_servers.appium-mcp]
command = "npx"
args = ["-y", "appium-mcp@latest"]
env = { ANDROID_HOME = "/path/to/android/sdk" }
CAPABILITIES_CONFIG points at a JSON file of Appium capabilities, such as platformName, appium:deviceName and appium:app. The agent opens a session with appium_session_management, then uses tools such as appium_find_element, appium_gesture and appium_set_value. For a device farm or CI, pass a remoteServerUrl and explicit capabilities when the session is created instead of using the local drivers.
Setting up Maestro MCP
Install the Maestro CLI first. The MCP server is a subcommand of it, so there is no separate package.
# Claude Code
claude mcp add maestro -- maestro mcp
# Codex
codex mcp add maestro -- maestro mcp
Or add it to ~/.codex/config.toml by hand:
[mcp_servers.maestro]
command = "maestro"
args = ["mcp"]
For Cursor, merge this into ~/.cursor/mcp.json:
{
"mcpServers": {
"maestro": {
"command": "maestro",
"args": ["mcp"]
}
}
}
This assumes maestro is on your PATH. If the client starts from a minimal shell, use the full path from which maestro. Maestro MCP is the only one of the three that writes into a test format you already run: when the agent saves its work as a flow file, maestro test can run it again in CI.
Where an MCP session stops and a repeatable test starts
A live MCP session can help a coding agent inspect a mobile app and try a user journey, but the session alone does not give CI a test to run. The agent’s observations and next steps remain in its conversation unless the agent writes them into a file. A PR cannot review or rerun a conversation as a test.
For example, an agent might open an order screen and confirm that the latest order appears. To check that behavior after every change, you need a saved test with an assertion and a repeatable run command. Appium and Maestro can support persistent tests, but access through their MCP servers does not, by itself, save the agent’s exploration as one.
Momentic’s MCP server gives a coding agent a way to write, run, and fix tests while keeping the test definition as YAML in your repository. Install the mobile skills and the MCP server for your agent:
npx momentic-mobile skills --yes
npx momentic-mobile install-mcp
The command equips the agent to work on mobile tests. The agent still needs to turn the behavior it explored into a YAML test and run it. Once you commit that file, reviewers can diff the test in a PR, and CI can invoke it without asking the agent to explore the app again. The MCP server handles the agent interaction. The test file and CI invocation make the check repeatable.
Running the resulting test in CI
Run npx momentic-mobile skills --yes in your project, then use your coding agent and the Momentic MCP server to write and run the mobile test. Review the resulting YAML test and commit it to your repository. CI needs that file, not the agent’s chat history.
Add a pull-request job that builds the app and runs the committed test with the Momentic CLI. Give the job the credentials and simulator or emulator access it needs, then make the job a required status check so a failed test blocks the merge. The CI job runs the committed tests with npx momentic-mobile run --upload-results, with MOMENTIC_API_KEY set as a CI secret. See the CLI reference for device and sharding flags.
Related reading
- How to set up the Momentic MCP server
- Best MCP servers for testing
- Playwright MCP vs. a testing MCP server
- Testing mobile apps in Cursor
- Appium vs. Maestro vs. AI testing
Frequently asked questions
Can these servers use physical devices?
Appium can drive physical iOS and Android devices when you configure the appropriate drivers and devices. Maestro supports physical devices as well as simulators and emulators. Check the mobile-mcp project’s README before assuming its server supports your device setup. Momentic’s mobile testing uses simulators and emulators, not physical devices.
Can one MCP configuration drive both iOS and Android?
You can register one server, but that does not make both platforms ready to use. You still need the devices and platform-specific tooling that the server requires. With Appium, you also need the appropriate driver for each platform.
How is Momentic’s MCP server different?
The device-control servers let an agent interact with a running app. Momentic’s MCP server lets an agent write, run, and fix end-to-end tests that remain as YAML files in your repository. The separate npx momentic-mobile skills --yes command installs mobile testing skills. Check the Momentic documentation for the current setup.
Must I abandon an existing Appium or Maestro suite?
No. You can keep that suite in CI while adding Momentic tests for behavior you want to cover separately. Do not assume existing test files will run unchanged in Momentic.
MCP Shouldn't Require a Desktop: Designing a One-Tap Mobile MCP App
Thanks for support..
Release: "Sentinel-IR-MCP v0.2.2 on GitLab" (gitlab.com)
Package: "sentinel-ir-mcp@0.2.2 on npm" (npmjs.com)
!Image description
Somewhere between “I found a useful MCP tool” and “I can use it from my phone,” a simple idea can turn into a side quest through runtimes, JSON files, credentials, server URLs and settings screens.
I want to explore a simpler path: a mobile-first app that makes connecting to useful tools feel understandable, safe and close to one tap. Not by hiding the permissions, but by removing the setup archaeology.
This article has three levels: 30 seconds for the scroll crowd, 10 minutes for curious humans, and a deeper technical tour for developers.
Project status, before the marketing goblin gets near the keyboard: the Mobile MCP 0.1.0 source draft exists, and nine focused unit tests passed in the authoring environment. A DNS failure blocked npm dependency installation, so a normal dependency-backed build has not been verified. Google OAuth, a real Drive search, PostgreSQL integration and a deployment have not been tested live. The source draft is also not yet a general MCP client or MCP server. This is an engineering direction with an initial codebase, not a launched product.
The 30-second version
MCP, the Model Context Protocol, gives AI applications a common way to discover and use tools. But connecting tools can still feel like assembling furniture with instructions written for someone who already owns a screwdriver factory.
Mobile MCP is an attempt to make that connection mobile-first. Open an app on your phone, choose a connector, authorize it with the provider, understand what it can access, and use it without starting from a terminal and a configuration file.
The first planned slice uses Google Drive to search file names and show basic metadata. It is designed not to read document contents or modify files. The code draft exists, but the full build and live flow still need verification. It does not yet expose or consume the MCP protocol end-to-end.
The principle is simple: one tap should remove setup friction, not remove user consent.
The 10-minute guide for non-experts
1. First, imagine a toolbox
Imagine you buy a new cordless drill.
You do not want to build the electric motor, manufacture the battery, solder a charger and write a driver before drilling one hole. You want to choose the tool, connect it safely, and get on with your day.
AI tools have a similar problem.
An AI assistant becomes more useful when it can work with things outside the chat: files, calendars, repositories, databases, issue trackers or other services. But the connection between an AI app and those tools needs a common interface, permissions and somewhere for the tool to run.
That is where MCP enters the picture.
2. What MCP is, without the acronym fog
MCP stands for Model Context Protocol. Think of it as a standard connection language between an AI application and external tools or data sources.
The AI model is not MCP. Google Drive is not MCP. A button labelled “Connect” is not MCP either.
A useful mental model is:
The AI application or client asks what tools are available and calls them.
The MCP server exposes tools or other capabilities through the protocol.
The underlying service does the actual work, such as searching files or looking up an issue.
MCP helps standardize the conversation between the client and the server. It does not automatically make a tool secure, reliable or useful. A standard plug does not make every appliance safe to leave running overnight.
The official project documentation is here: modelcontextprotocol.io.
3. So why focus on phones?
A lot of developer tooling assumes that the user is sitting at a computer. That makes sense for many development workflows. It is less comfortable when you are using a phone as your main device.
Depending on the tool and client, connecting an MCP server may involve installing a runtime, creating a JSON configuration, entering an endpoint, managing credentials, restarting an application, and then figuring out why nothing appears in the tool list.
A developer may consider that a five-minute setup. For someone who does not live in terminals, it can be a locked door with a very technical doormat.
And mobile makes the friction more visible: typing long paths on a touchscreen is not exactly a premium user experience. Copying a JSON block from one app to another is possible, but so is eating soup with a fork.
The problem is not that MCP is inherently desktop-only. Remote MCP services can be accessed over HTTP by compatible clients. The problem we want to tackle is the product experience around connecting, authorizing and using tools from a phone.
4. The idea: a mobile-first connection desk
The aim is to make the first steps feel like this:
Open the app from a phone browser or install it as a PWA where supported.
Choose a connector, for example Google Drive.
Sign in with the provider and review the requested permissions.
See a clear list of what that connector can and cannot do.
Use the capability through a simple interface, without manually editing configuration files.
Disconnect it when it is no longer needed.
That is the experience we are aiming for, not a claim that every step is already live.
For the first vertical slice, I chose Google Drive metadata search. It is concrete and easy to check: search for a file you know exists, see its name and type, and open the real Drive link. The first slice is not supposed to read your documents, rewrite them, share them or delete them.
Why start small? Because “connect everything with one click” sounds wonderful until the first click grants a tool more access than it needs. A tiny, verifiable capability is a better foundation than a giant dashboard full of green connection badges.
5. What the current source draft contains
The project has a mobile-oriented React and TypeScript interface, a Node.js/Fastify API, PostgreSQL session and OAuth-account storage, a Google OAuth flow, a Drive metadata-search connector, security helpers, deployment configuration and test instructions.
The current code is designed around a single configured owner account for a private test, not public multi-user onboarding. That keeps the first authorization boundary narrow while the flow is being checked.
There are also important limits:
It is not yet a general MCP client that can connect to arbitrary MCP servers.
It is not yet an MCP server that exposes the connector through the MCP protocol.
There is no AI model or chat-based tool selection in this first slice.
No paid hosting has been provisioned and nothing has been deployed.
Google authorization and real Drive requests have not been verified live.
Why call it Mobile MCP, then? Because the intended product is a mobile-first way to connect and use MCP-compatible capabilities. The current connector hub is the first foundation to validate, not the final protocol surface.
6. A phone-first interface does not mean a phone-only backend
The mobile app should be the simple front door. It does not need to hold every secret or do every job itself.
The planned boundary looks like this:
Phone browser / installable PWA
|
HTTPS request
|
Authenticated API
|
Connector registry
|
Google Drive API
The phone gets a usable interface. The server handles provider credentials and provider calls. Later, a protocol adapter can expose approved capabilities to compatible MCP clients.
This separation matters. A mobile browser is not a secure place to paste a long-lived Google client secret, and a user should not have to understand refresh-token rotation to search for a project plan.
7. “One click” cannot mean “trust us with everything”
There is a difference between removing friction and removing control.
For a real product, users should be able to see which account is connected, what the connector can access, whether it can write anything, and how to disconnect it. The server should enforce these limits even if an AI model asks for something outside them.
The source draft includes several security mechanisms: an OAuth state check, verified Google identity, an owner-account allowlist, HTTP-only browser sessions, hashed session identifiers in PostgreSQL, token encryption at rest, request-origin checks, rate limits, API no-cache headers and basic log redaction.
Those are design and implementation choices visible in the source. They are not a third-party security audit, and they do not prove the deployed system is safe. They still need normal integration tests and live checks.
There is also an important permission decision ahead. The current broad Drive metadata-search design requests drive.metadata.readonly. Google classifies that scope as restricted. A public release must account for Google's applicable verification and data-handling requirements. A narrower drive.file flow combined with the Google Picker can give users more per-file control, but it does not provide the same unrestricted search across all Drive metadata. The convenient product requirement and the least-privilege permission model need to be considered together, not after launch.
Google's scope guidance: Choose Google Drive API scopes.
8. What would count as real progress?
Not a screenshot. Not a successful-looking mock result. Not “the code seems fine.”
The first meaningful acceptance test should be boring in the best possible way:
Open the actual HTTPS app on a phone.
Connect a real Google test account through OAuth.
Search for a known file in that account.
Confirm the real file name, metadata and Drive link.
Try an unknown name and get an honest empty result.
Deny or cancel authorization and confirm the app does not pretend to be connected.
Disconnect and confirm protected search calls stop working.
Before that test, the dependency installation, lockfile, type checking, full build and PostgreSQL integration test must be completed. The authoring environment hit EAI_AGAIN while resolving the npm registry, so those dependency-backed checks are still blocked. Nine focused unit tests did pass, but they are only one part of the evidence.
9. What is the potential payoff?
If the product works, the value is not “MCP, but with a smaller screen.” It is a different entry point.
For non-developers, it could make useful tool connections less intimidating. For developers, it could provide a simpler way to configure approved connectors, test permissions and use remote tools while away from a workstation. For teams, a curated catalogue could make the allowed capabilities easier to discover and explain.
That does not automatically make it faster, cheaper or safer than every existing MCP setup. Those are claims to measure after there is a working product. The first hypothesis is narrower: a mobile-first setup flow can remove unnecessary configuration work without hiding important permissions.
That is worth testing.
The 20-minute developer guide
This section goes from the product idea to the source-level design. It is intentionally specific about what exists today and what remains future work.
1. Start by separating three roles
“MCP app” can refer to several different things, so let us avoid building one acronym-shaped ball of confusion.
A. Mobile control surface
The React PWA is the phone-friendly interface. It handles user interaction, account status, connector selection and search results.
B. Connector backend
The Fastify server handles sessions, OAuth credentials and provider API calls. The current first-party connector uses the Google Drive API directly.
C. MCP protocol integration, planned
A future MCP client capability would connect to remote MCP servers and discover/call their tools. A future MCP server capability would expose selected first-party tools, such as a permitted Drive search, to other MCP-compatible applications. These are separate capabilities. The current 0.1.0 source draft does not yet implement a general-purpose client or server.
That distinction is architectural, not cosmetic. A React button calling /api/drive/search is an ordinary application API call. It does not magically become an MCP tool because the repository name contains “MCP.”
2. Current stack and data flow
The source draft uses:
React, TypeScript and Vite for the responsive PWA.
Node.js and Fastify for HTTP routes.
PostgreSQL for sessions and OAuth-account records.
Google's OAuth client and Drive API libraries.
AES-256-GCM for encrypting stored OAuth tokens.
Unit tests plus opt-in PostgreSQL and live-health tests.
Current request flow:
Browser / PWA
|
| POST /api/drive/search
| HTTP-only session cookie
v
Fastify route
| validate origin and input
| resolve authenticated owner
v
DriveClient
| load encrypted credentials
| decrypt server-side
| refresh if needed
v
Google Drive API
| files.list(q, fields, pageSize)
v
Metadata only: id, name, mimeType,
modifiedTime, webViewLink
There is no LLM call in that path. The user query is validated and used to build a Drive search expression. The server asks Google for limited metadata and returns it to the interface.
3. Input validation before the provider call
The current helper checks the query length, rejects control characters and escapes backslashes and quotes before building the Drive expression. A simplified excerpt from src/connectors/google-drive/search-files.ts:
export function escapeDriveQueryLiteral(input: string): string {
return input.replace(/\/g, '\\').replace(/'/g, "\'");
}
export function buildDriveNameQuery(searchTerm: string): string {
const trimmed = searchTerm.trim();
if (trimmed.length < 2 || trimmed.length > 120) {
throw new Error('Search term must be between 2 and 120 characters.');
}
if (/[\u0000-\u001F\u007F]/.test(trimmed)) {
throw new Error('Search term cannot contain control characters.');
}
return name contains '${escapeDriveQueryLiteral(trimmed)}' and trashed = false;
}
The point is not that string escaping solves every security concern. It is that input length, control characters and query quoting should be handled in one narrow function and tested independently, rather than scattered through route handlers.
The current Drive request uses a limited field selection and a capped result count:
const result = await drive.files.list({
q: query,
pageSize: 25,
orderBy: 'modifiedTime desc',
fields: 'nextPageToken,files(id,name,mimeType,modifiedTime,webViewLink)',
spaces: 'drive'
});
That is a deliberate boundary: metadata, not document content. A webViewLink is a link to Drive, not a grant of extra access. Google still enforces the user's file permissions and the OAuth scope.
4. Protect the route, not just the button
Frontend controls are convenience, not authorization. Someone can call an HTTP endpoint without using the UI, so the route itself checks the request origin, validates the body, and requires the configured owner account.
A shortened excerpt of the current route's shape:
app.post('/api/drive/search', {
config: { rateLimit: { max: 30, timeWindow: '1 minute' } }
}, async (request, reply) => {
if (!requestHasAllowedOrigin(request)) {
return reply.code(403).send({ error: 'ORIGIN_NOT_ALLOWED' });
}
const email = await requireOwner(request, reply);
if (!email) return reply;
const parsed = searchSchema.safeParse(request.body);
if (!parsed.success) {
return reply.code(400).send({ error: 'INVALID_QUERY' });
}
const result = await driveClient.searchByName(email, parsed.data.q);
return reply.code(200).send(result);
});
This excerpt omits the error mapping found in the full route. The implementation uses a narrow, generic error response for unexpected failures instead of returning raw provider details to the client.
The same principle will matter even more when MCP tools are added. A model should not be able to choose an arbitrary account ID and access another person's connector. The server should resolve the identity from the authenticated session, validate every tool argument and enforce permissions independently of the model's instructions.
5. OAuth state, sessions and token storage
The authorization-code flow is server-side. The callback validates a short-lived OAuth state value against the session, verifies the returned Google identity and checks that the verified email matches the configured owner allowlist. After a successful login, the session identifier is rotated to reduce session-fixation risk.
The browser session cookie is HTTP-only and uses Secure in production. PostgreSQL stores a SHA-256 hash of the opaque session identifier instead of the raw identifier. OAuth access and refresh tokens are encrypted before they are stored.
The token-encryption helper uses authenticated encryption:
const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 12;
const TAG_LENGTH = 16;
Each encryption call generates a fresh random IV and stores the IV, authentication tag and ciphertext in a versioned envelope. Decryption verifies the authentication tag, so tampering causes failure rather than returning modified token bytes.
The encryption key belongs in the server environment, not in the Vite frontend, Git history, the database alongside the ciphertext, or logs. Encrypting a token at rest helps protect database contents, but it does not protect a compromised application process that can read the key. Key access, backup handling, rotation and incident response remain operational concerns.
The API also applies no-store headers to /api/ responses. Authentication is not a license to let private search results sit in a shared cache.
6. The Google scope is a product decision
The current source requests:
export const DRIVE_METADATA_SCOPE =
'googleapis.com';
This scope is read-only for metadata, but Google classifies it as a restricted Drive scope. That has consequences for a public release. Depending on the app's usage and how restricted-scope data is stored or transmitted, Google verification and a security assessment may be required. This should be checked against Google's current requirements before inviting public users.
An alternative is to use the narrower drive.file scope with Google Picker, letting the user select files they want to authorize for the app. That reduces the scope of access, but it does not provide identical behavior to searching metadata across all of a user's Drive. The product needs to decide what matters more for the first release: broad name search or a narrower per-file consent experience.
Do not silently request a broader scope because it is easier to code. Make the trade-off visible, document it, and test it with actual Google Cloud configuration.
Reference: Google Drive API scope guidance.
7. Where the MCP protocol should enter
The existing connector service should not be entangled with one protocol. A clean next step is to treat provider operations as capabilities and add a separate protocol adapter around only those operations that should be exposed.
Conceptually:
+----------------------+
Phone PWA ------> | App API | ------> Google Drive
+----------------------+
^
|
+----------------------+
MCP client -----> | MCP adapter (future) | ------> approved capability
+----------------------+
There are two possible product features here:
Use remote MCP servers from the mobile app. The app becomes an MCP client. It needs server discovery/configuration, transport handling, authorization, a tool catalogue and a safe way to invoke selected tools.
Expose Mobile MCP connectors to other AI clients. The backend becomes an MCP server. It needs protocol endpoints, tool discovery, schemas, per-user authorization and execution policies.
They should not be implemented as one vague feature called “MCP support.” They have different trust boundaries and acceptance tests.
For remote server access, the official TypeScript SDK documents Streamable HTTP as the recommended transport for remote MCP servers, while stdio is primarily suited to local process integrations. A phone cannot always spawn a local server process as a desktop client can, so a remote transport is a natural direction for a hosted mobile experience.
Official references: MCP TypeScript SDK server guide and MCP specification.
8. Design the connector interface before the protocol adapter
The existing registry is intentionally small. It describes a connector and its capabilities rather than making the UI responsible for provider-specific logic. As additional connectors arrive, keep the provider operation separate from how it is called.
A future capability could be described conceptually like this:
interface ToolCapability<Input, Output> {
name: string;
description: string;
inputSchema: unknown;
requiredPermission: string;
execute(input: Input, actor: AuthenticatedActor): Promise<Output>;
}
This is a design sketch, not an interface that currently ships in the source draft. Its purpose is to make a few rules explicit:
Each capability has a stable name and input schema.
The authenticated actor is supplied by the backend, not invented by the model.
Required permissions are declared and checked before execution.
The output type is narrow and documented.
The transport adapter does not become the source of authorization truth.
A future MCP adapter can map approved capabilities to MCP tools. A mobile UI can call a first-party API. Both can reuse the same policy-checked service without copying Google API logic into two routes.
9. The safety boundary for future MCP tools
MCP tools are code execution entry points, even when the tool itself only calls a web API. Before allowing arbitrary server configuration or broader actions, the system needs to handle at least these concerns:
Per-user isolation: a user must never inherit another user's connector credentials or data.
Least privilege: a tool gets only the provider scope and operation it needs.
Argument validation: tool inputs are untrusted, even when generated by a model.
No arbitrary URL fetches by default: accepting arbitrary MCP URLs can create server-side request forgery and network-boundary problems.
No shell execution in the connector path: do not turn tool configuration into an arbitrary command runner.
Visible side effects: write, share and delete operations should be separate capabilities with clear confirmation and authorization rules.
Time and size limits: cap result counts, request duration and response size.
Redacted observability: record enough structured events to troubleshoot without logging tokens or private file contents.
Revocation: disconnecting a provider should make subsequent calls fail and should remove or invalidate stored credentials according to the product's retention policy.
MCP tool descriptions and annotations can help a client understand a tool, but they are not an access-control system. Authorization must be enforced by the server.
For the first version, I would not allow users to paste an arbitrary remote MCP endpoint and immediately grant it network access. Start with a curated connector list, known transport behavior and explicit account boundaries. Extensibility can come after we have evidence that the first connector behaves correctly.
10. PWA is a delivery choice, not a magic trick
A Progressive Web App is attractive because one responsive web app can run in a mobile browser and can be installed from supported browsers over HTTPS. It reduces the need to maintain separate native apps just to test the first flow.
But a PWA is not identical to a native app. Browser capabilities, background execution, notifications and installation behavior vary. The service worker should cache static interface assets only. Authentication callbacks, API responses, tokens and private search results must not be placed in a shared offline cache.
This MVP is not an offline Drive search engine. It needs a network connection to call Google Drive, and a server connection for the hosted API. The interface should say so rather than inventing a spinner that works as a substitute for connectivity.
11. Test gates: what is known and what is not
The checks completed while preparing the source archive were:
JSON configuration files parsed.
YAML deployment and CI files parsed.
TypeScript and TSX files passed a source-syntax transpilation check. This was not a full semantic typecheck.
Nine focused unit tests passed for token encryption and tamper rejection, Drive query escaping and limits, log redaction, and same-origin comparison.
The checks that remain blocked or unperformed are just as important:
npm install could not reach the npm registry because the environment returned EAI_AGAIN during DNS resolution.
No package-lock.json was generated. It must be created on a network-enabled machine and reviewed, not fabricated.
A normal dependency-backed typecheck and full production build have not passed.
PostgreSQL integration has not been run against a live test database.
Google OAuth, refresh-token behavior, real Drive search, disconnect behavior, phone installation and deployment have not been tested live.
No Render service was provisioned. No production user data was accessed. That is the evidence boundary for this source draft.
12. The first release should pass a boring acceptance checklist
Before adding an AI model, a marketplace or generic remote-server support, the first vertical slice should pass these gates:
Install dependencies and generate a committed lockfile.
Pass dependency-backed type checking, all unit and integration tests, and the production build.
Run the database migration on a disposable test database.
Configure a real Google Cloud OAuth client and exact HTTPS redirect URI.
From the target phone, complete real sign-in and search for a file that is known to exist.
Verify the returned metadata and Drive link against the actual file.
Check cancelled consent, invalid state, revoked credentials, unknown results, logout, disconnect and unauthorized requests.
Revisit the Google scope and verification requirements before a public beta.
Only after those gates pass, add and test a real MCP protocol adapter.
That order may look less exciting than a dashboard full of connectors. It is also less likely to produce a dashboard full of connectors that do not work.
13. What I want to learn from this experiment
The main hypothesis is not that one mobile interface magically makes every integration simple. It is that we can move complexity out of the user's path without moving their permissions out of view.
For developers, that means a clean service boundary, reusable connector capabilities, explicit schemas and testable authorization rules. For everyone else, it means they should not need to learn what a refresh token is just to find a document they already have permission to see.
The current draft is an early step, not proof that the whole idea has succeeded. The build still needs dependency-backed verification, the Google flow needs a real end-to-end test, and the MCP protocol layer still has to be implemented. Those are concrete tasks, not footnotes to hide under a launch graphic.
If this works, the phone is not a tiny desktop pretending to be comfortable. It becomes a first-class way to connect useful tools, review permissions and use approved capabilities.
And if the first thing we simplify is setup, not security, we might finally make the connection feel like a button instead of a weekend project.
mobile-next/mobile-mcp
Question for the community: what would you want as the first genuinely useful one-tap connector on mobile: Google Drive, GitHub, Notion, a calendar, or something else? And where would you draw the line between convenience and access control?
1 reaction
Mentions
Mobile MCP servers: set up Appium MCP, Maestro MCP and mobile-mcp --- title: "Mobile MCP servers: set up Appium MCP, Maestro MCP and mobile-mcp" published: true published_at: "2026-11-03T16:00:00Z" description: "Install commands and config for Appium MCP, Maestro MCP and mobile-mcp in Claude Code, Cursor and Codex." tags: testing,mcp,mobile,ai canonical_url: momentic.ai --- Originally published on the Momentic blog. TL;DR - mobile-mcp lets a coding agent inspect and control a mobile app during a live session. Reach for it when you need to explore the UI. - Appium MCP gives the agent access through an Appium session. Reach for it when your mobile setup already uses Appium drivers. - Maestro MCP lets the agent work with Maestro’s mobile testing tools. Reach for it when you already use Maestro flows. - All three can help an agent inspect and drive an app, but an MCP session alone does not leave behind a test that runs in CI. - For a versioned test, use Momentic’s MCP server to write and run YAML tests. Install the mobile skills with npx momentic-mobile skills --yes. Appium MCP, Maestro MCP and mobile-mcp compared All three run as local stdio servers that your coding agent starts with one command. They differ in what they drive and what they leave behind. | Server | Install | Platforms and targets | What the agent works with | Leaves a test behind? | | --- | --- | --- | --- | --- | | <a href="mobile-next/mobile-mcp">mobile-mcp</a> | npx -y @mobilenext/mobile-mcp@latest | iOS and Android: simulators, emulators and real devices | The native accessibility tree, with screenshots and coordinates as a fallback | No. The session lives in the agent's conversation | | <a href="appium/appium-mcp">Appium MCP</a> | npx -y appium-mcp@latest | Android (UiAutomator2) and iOS (XCUITest): simulators, emulators and real devices | An Appium session: find elements, tap, type, gestures, screenshots | It can generate Java/TestNG test code from a description | | <a href="docs.maestro.dev">Maestro MCP</a> | maestro mcp (needs the Maestro CLI) | iOS and Android apps, plus web | Maestro commands, so the agent can write, run and debug flows | Yes, when the agent saves the flow as a YAML file | Pick the one that matches the tooling you already run. If your team has Appium capabilities and drivers set up, Appium MCP reuses them. If you write Maestro flows, Maestro MCP lets the agent write more of them. If you want an agent to poke at an app with no framework at all, mobile-mcp has the least setup. Setting up mobile-mcp Boot an iOS simulator (xcrun simctl boot "iPhone 16") or start an Android emulator first. The project's installer finds the MCP clients on your machine and configures them: npx @mobilenext/mobile-mcp@latest install To configure each client by hand: # Claude Code claude mcp add mobile-mcp -- npx -y @mobilenext/mobile-mcp@latest # Codex codex mcp add mobile-mcp npx "@mobilenext/mobile-mcp@latest" For Cursor, add the server to ~/.cursor/mcp.json or a project-level .cursor/mcp.json: { "mcpServers": { "mobile-mcp": { "command": "npx", "args": ["-y", "@mobilenext/mobile-mcp@latest"] } } } mobile-mcp drives the app from the native accessibility tree first, so the agent reads element labels instead of spending image tokens on screenshots. It falls back to a screenshot and coordinate taps when an element has no accessible label. It also installs, launches and terminates apps, opens deep links and records the screen. Setting up Appium MCP Appium MCP bundles the UiAutomator2 and XCUITest drivers for local sessions. You still need the platform toolchains: ANDROID_HOME, Java and the Android SDK tools for Android, and Xcode with an installed simulator for iOS (macOS only). # Claude Code claude mcp add appium-mcp -- npx -y appium-mcp@latest For Cursor, and for other clients that take a JSON config: { "mcpServers": { "appium-mcp": { "type": "stdio", "command": "npx", "args": ["appium-mcp@latest"], "env": { "ANDROID_HOME": "/path/to/android/sdk", "CAPABILITIES_CONFIG": "/path/to/your/capabilities.json" } } } } For Codex, the same server goes in ~/.codex/config.toml: [mcp_servers.appium-mcp] command = "npx" args = ["-y", "appium-mcp@latest"] env = { ANDROID_HOME = "/path/to/android/sdk" } CAPABILITIES_CONFIG points at a JSON file of Appium capabilities, such as platformName, appium:deviceName and appium:app. The agent opens a session with appium_session_management, then uses tools such as appium_find_element, appium_gesture and appium_set_value. For a device farm or CI, pass a remoteServerUrl and explicit capabilities when the session is created instead of using the local drivers. Setting up Maestro MCP Install the Maestro CLI first. The MCP server is a subcommand of it, so there is no separate package. # Claude Code claude mcp add maestro -- maestro mcp # Codex codex mcp add maestro -- maestro mcp Or add it to ~/.codex/config.toml by hand: [mcp_servers.maestro] command = "maestro" args = ["mcp"] For Cursor, merge this into ~/.cursor/mcp.json: { "mcpServers": { "maestro": { "command": "maestro", "args": ["mcp"] } } } This assumes maestro is on your PATH. If the client starts from a minimal shell, use the full path from which maestro. Maestro MCP is the only one of the three that writes into a test format you already run: when the agent saves its work as a flow file, maestro test can run it again in CI. Where an MCP session stops and a repeatable test starts A live MCP session can help a coding agent inspect a mobile app and try a user journey, but the session alone does not give CI a test to run. The agent’s observations and next steps remain in its conversation unless the agent writes them into a file. A PR cannot review or rerun a conversation as a test. For example, an agent might open an order screen and confirm that the latest order appears. To check that behavior after every change, you need a saved test with an assertion and a repeatable run command. Appium and Maestro can support persistent tests, but access through their MCP servers does not, by itself, save the agent’s exploration as one. Momentic’s MCP server gives a coding agent a way to write, run, and fix tests while keeping the test definition as YAML in your repository. Install the mobile skills and the MCP server for your agent: npx momentic-mobile skills --yes npx momentic-mobile install-mcp The command equips the agent to work on mobile tests. The agent still needs to turn the behavior it explored into a YAML test and run it. Once you commit that file, reviewers can diff the test in a PR, and CI can invoke it without asking the agent to explore the app again. The MCP server handles the agent interaction. The test file and CI invocation make the check repeatable. Running the resulting test in CI Run npx momentic-mobile skills --yes in your project, then use your coding agent and the Momentic MCP server to write and run the mobile test. Review the resulting YAML test and commit it to your repository. CI needs that file, not the agent’s chat history. Add a pull-request job that builds the app and runs the committed test with the Momentic CLI. Give the job the credentials and simulator or emulator access it needs, then make the job a required status check so a failed test blocks the merge. The CI job runs the committed tests with npx momentic-mobile run --upload-results, with MOMENTIC_API_KEY set as a CI secret. See the CLI reference for device and sharding flags. Related reading - How to set up the Momentic MCP server - Best MCP servers for testing - Playwright MCP vs. a testing MCP server - Testing mobile apps in Cursor - Appium vs. Maestro vs. AI testing Frequently asked questions Can these servers use physical devices? Appium can drive physical iOS and Android devices when you configure the appropriate drivers and devices. Maestro supports physical devices as well as simulators and emulators. Check the mobile-mcp project’s README before assuming its server supports your device setup. Momentic’s mobile testing uses simulators and emulators, not physical devices. Can one MCP configuration drive both iOS and Android? You can register one server, but that does not make both platforms ready to use. You still need the devices and platform-specific tooling that the server requires. With Appium, you also need the appropriate driver for each platform. How is Momentic’s MCP server different? The device-control servers let an agent interact with a running app. Momentic’s MCP server lets an agent write, run, and fix end-to-end tests that remain as YAML files in your repository. The separate npx momentic-mobile skills --yes command installs mobile testing skills. Check the Momentic documentation for the current setup. Must I abandon an existing Appium or Maestro suite? No. You can keep that suite in CI while adding Momentic tests for behavior you want to cover separately. Do not assume existing test files will run unchanged in Momentic.
Mobile Next. Tem mais de 10 mil estrelas no GitHub e cerca de 56 mil downloads só na semana passada, foi atualizado ontem e tem licença aberta (Apache): mobile-next/mobile-mcp
Claude Code に React Native アプリを触らせるなら agent-device の CLI はじめに AI に React Native のバグを直させると、コードはそれらしく直してくれます。ただ、シミュレータで本当に直ったかを確かめさせようとすると、何かツールを入れる必要があります。React Native の有名どころの会社からも、Callstack が agent-device、Software Mansion が Argent を出していて、ほかに mobile-mcp もあります。 どれを入れればいいのか。比べた記事を探したら、英語でも日本語でも機能表の比較しか見つかりませんでした。Expo 自身もブログで「検証ツールの比較は今後の実験」と書いています。そこで、Bluesky の公式アプリで実際に直されたバグを使って、180回測りました。 ! 検証環境は Claude Code 2.1.310、Opus 5.5、Xcode 27.1、iOS 26.5 のシミュレータ (iPhone 17) です。アプリは Bluesky の公式アプリ (コミット 61c7cad、Expo SDK 57) を使い、計測は2026年10月に行いました。ほかのアプリやエージェント、Android では試していません。 React Native なら agent-device の CLI を入れればいい 比べたのは、Callstack の agent-device、Software Mansion の Argent、Mobile Next の mobile-mcp の3つです。3つとも CLI と MCP の両方の入口があるので、6通りで測り、1回あたりの費用と、画面で再現から確認までやり切れたかを見ました。作業時間も参考に測っています。 早速結論ですが、自分のアプリに入れるなら agent-device の CLI を選びます。理由は2つです。 一番安い。1回あたり $0.70 で、mobilecli (mobile-mcp の CLI) と並んで最安。同じ agent-device の MCP より3割近く安い React Native 向けの機能がある。コンポーネントの props や state を調べる React DevTools や、Metro の再読み込みをコマンドで使える。mobilecli には無い 費用だけなら mobilecli も同じくらい安く済みます。React Native のアプリなら、機能の分だけ agent-device の CLI が上だと判断しました。 MCP しか使えない環境なら、mobile-mcp を選びます。タップや入力をまとめて1回で送れ、画面を読んだ結果も短いので、MCP の3つの中で一番安く済みました。 速さを重視する場合は、Argent の MCP が選択肢になります。6通りの中で作業時間が一番短く済みました。ただし費用は一番高く、agent-device の CLI の1.6倍かかります。タップするたびにスクショが返ってくるので、やり取りは少なく済む一方、受け取る画像が多くなるためです。 Bluesky の実バグで180回測った 比べた3つのツール どれも、エージェントにシミュレータの画面を読ませ、タップや入力をさせるためのツールです。違いは、画面をエージェントにどう渡すかにあります。 ツール 開発元 画面の渡し方 agent-device Callstack ボタンや文字を @e2 [button] "Add" のような参照の一覧で返す。操作のあとは、変わった部分だけを差分で返す Argent Software Mansion タップなどの操作のたびに、結果のスクショを自動で返す。画面の要素の一覧も別に取れる mobile-mcp Mobile Next 画面の要素を1行1個の一覧で返し、座標を指定してタップする。複数の操作をまとめて1回で送れる CLI はエージェントがシェルでコマンドを打って使い、MCP は Claude Code にツールとして登録して使います。mobile-mcp の CLI は、中で動いている mobilecli というエンジンをそのまま使う形です。この画面の渡し方の違いが、あとで見る費用の差になって表れます。 比べた6つの条件 3つのツールの CLI と MCP で6条件です。ツールはどれも公式ドキュメントが勧める入れ方にしました。 条件 入れたもの agent-device CLI CLI 0.21.31、公式の skill 4つ、公式が勧めるプロジェクトのルール文 agent-device MCP agent-device mcp、同じルール文 Argent MCP argent init が入れるもの一式 (MCP、skill 18個、rules) 0.30.1 Argent CLI 上から MCP の設定だけを外したもの mobile-mcp MCP @mobilenext/mobile-mcp 1.0.13 mobile-mcp CLI 中のエンジンの mobilecli 1.0.21 と公式の skill xcrun simctl の起動・スクショ・URL を開く操作は、どの条件でも使えるようにしました。テレメトリは全ツールで切っています。 この6条件に、次のお題5問 × testID とアクセシビリティのラベルの有無 × 3回を掛けて、全部で180回測りました。 お題は Bluesky で実際に直された5件 Bluesky の公式アプリは Expo SDK 57 のアプリで、E2E テスト用のモックサーバーが付いています。毎回同じデータでアプリを立ち上げられるので、計測に向いています。 お題は、Bluesky で実際にマージされた PR を戻して作りました。選んだのは、モックサーバーで症状を出せて、直ったかを Maestro で判定できる PR です。比べるツールを一度も動かす前に決めたので、結果を見てお題を選び直してはいません。 お題 症状 症状を出すのに必要な操作 #10132 画像に ALT を付けても案内が消えない 画像の添付、ALT の入力と保存 #10163 モデレーションリストが開けない URL でリストを開く #11503 存在しないユーザーのプロフィールが読み込み中のまま止まる URL でプロフィールを開く #8502 引用を禁止した投稿でも、リポストの長押しで引用の作成画面が開く 別のアカウントで引用禁止の投稿を作り、リポストを長押し #11820 (機能追加) 新規登録の生年月日を入力必須にする 新規登録のフォームに入力して Next を押す エージェントには、バグの症状と環境を伝えたうえで「シミュレータで再現して、直して、直ったことを確かめて」と頼みました。条件ごとに変えたのは、使うツールを指定する1文だけです。ALT の案内のバグだけは、Bluesky の issue の英文をそのまま貼っています。「このバグを直して」とだけ頼んだときに、エージェントが自分から画面で確かめに行くかは測っていません。 実際に渡した指示の例このリポジトリは Bluesky の公式アプリです。次のバグに対応してください。 存在しないハンドルのプロフィール (例: bluesky://profile/nobody.test) を開くと、エラー画面にならず、読み込み中の表示のまま止まってしまう。 アプリは iOS シミュレータ「BlueskyLab iPhone 17」(UDID 2B6D50B9-95B8-4FD8-8EFB-37FFE605ACF2) で起動していて、Metro (localhost:8081) とローカルのテストサーバー (localhost) につながっています。alice でサインインしています。このシミュレータ以外は別の作業で使っているので、触らないでください。ファイルを保存すると、Metro がアプリを自動で再読み込みします。 シミュレータの操作には agent-device の CLI を使ってください。 シミュレータでバグを再現し、コードを直して、直ったことをシミュレータで確かめてください。Web 検索はしないでください。終わったら、原因と直した内容を短く報告してください。 バグが直ったかどうかは、エージェントの作業が終わったあとに、アプリが Bluesky の修正と同じ動きになるかを Maestro のフローで確かめました。エージェントが画面で確かめたかどうかは、ログを Sonnet 5.5 に読ませて判定し、食い違った箇所はコードとログを自分で読んで確認しています。それでも見落としはありえます。 エージェントに答えを見せない仕掛け Bluesky は公開リポジトリなので、直し方がエージェントの手の届くところに残っています。答えを見て直せてしまうと、画面で再現する前に作業が終わり、ツールの差を測れません。比べたいツールを通らずに画面を操作できる道も同じです。そこで、次のように塞ぎました。 git の履歴と差分には、修正そのものが残っている。バグを入れた状態を1コミットだけのリポジトリにして、回ごとに作り直した 公式の E2E テストには、どの testID を押せばいいかが書いてある。テストのフォルダを外した アプリには E2E テスト用に、ログインや画面の移動を1回で済ませる隠しボタンがある。描画しないようにした Maestro が入っていると、比べたいツールを使わずに画面を操作できる。Maestro をコマンドとして呼べなくした Web で検索すると、元の PR が見つかる。Web 検索を禁止した 実際の開発ではエージェントが git の履歴や E2E テストも読めるので、費用や時間はこの記事の数字より軽く済むかもしれません。外したものはどの条件でも同じなので、ツールどうしの順位には響かないと見ています。 agent-device の CLI を選ぶ2つの理由 再現から確認までは、6条件すべてが30回中30回やり切りました。差が出たのは費用です。agent-device の CLI を選ぶ理由は、一番安いことと、React Native 向けの機能があることの2つです。 CLI は画面を読む量が少ないので一番安い 条件 1回の費用 (平均) 作業時間 (平均) 再現・確認まで終えた agent-device CLI $0.70 2分05秒 30 mobile-mcp CLI (mobilecli) $0.70 2分08秒 30 mobile-mcp MCP $0.80 1分53秒 30 Argent CLI $0.91 3分04秒 30 agent-device MCP $0.95 1分53秒 30 Argent MCP $1.11 1分41秒 30 agent-device の CLI は、mobilecli と並んで一番安く、Argent の MCP の6割ほどで済みました。同じお題・ラベル・回の組で比べると、agent-device の MCP には30組中29組、Argent の MCP には30組すべてで安くなっています。mobilecli とは30組中18組で、差はありません。 費用は API の料金に換算した値です。トークンの96%はキャッシュの読み込みで、1回平均142万トークンでも費用は $1 前後に収まりました。計測の順番によっては前の回のキャッシュを使えて安く出るので、どの回もキャッシュが空の状態から始めたとして計算し直しています。同じ組み合わせ3回の間のばらつきは、どの条件も6〜14%でした。 作業時間は参考にとどめてください。計測の途中に、同じ Mac で別の作業をしていた時間帯があります。 安さのわけは、画面を読む量にあります。CLI はシェルで動くので、エージェントが | grep や | head で必要な部分だけを読めます。同じツールの CLI と MCP を比べると、3つとも CLI の方が安くなりました。agent-device で3割近く、Argent で2割弱、mobile-mcp で1割強です。 画面を読む量の内訳 agent-device の2つをログで比べると、差は画面を読み取る量から来ていました。 条件 やり取り 画面を1回読んだ結果の長さ 受け取った画像 agent-device CLI 26回 約580文字 3.5枚 agent-device MCP 26回 約5,300文字 2.5枚 やり取りの回数は同じで、1回に読む画面の長さが9倍ほど違います。MCP は、ツールが返したものを丸ごと受け取るしかありません。mobile-mcp でも、CLI の約620文字に対して MCP は約2,300文字でした。 Argent の MCP が1回の作業で受け取った画像は平均9.5枚で、agent-device の CLI (3.5枚) の3倍近くでした。画像は文字よりトークンが重いので、そのぶん費用がかさみます。 なお、「画面を読み取った回」はツールの名前やコマンドの文字で拾う簡易な数え方です。傾向は見えますが、厳密な内訳ではありません。 React Native 向けの機能がある 費用で並んだ mobilecli との違いは、React Native 向けの機能です。agent-device には、React Native のアプリを調べるためのコマンドがあります。 できること コマンドの例 コンポーネントの木、props、state、hooks を見る agent-device react-devtools tree / inspect 遅い描画や再描画の原因を調べる agent-device react-devtools profile start JS だけの変更を Metro で読み込み直す agent-device metro reload LogBox や RedBox の表示を閉じる agent-device react-native dismiss-overlay React DevTools は、Metro につながった開発ビルド (React Native 0.74 以上) なら、アプリに手を入れずに使えます。mobilecli のコマンドは画面の操作と端末の管理が中心で、React Native に特化したものはありません。 ただし、今回の計測ではこの差は測れていません。お題はどれも画面に症状が出るバグで、agent-device の CLI の回でも、ログや通信を見るコマンドが数回使われただけでした。再描画が多すぎて重い、のように画面だけでは原因が分からないバグでどれだけ効くかは、試していません。 作りから予想できたことと、外れたこと ここまでの結果のうち2つは、ツールの作りから予想がつきます。Argent の MCP はタップのたびにスクショを返すので、受け取る画像が増えて高くなります。CLI はエージェントが要る部分だけを読めるので、ツールの返すものを丸ごと受け取る MCP より安くなります。予想と違ったのは、次の2つでした。 testID やラベルを外しても、費用も時間も変わらない testID とアクセシビリティのラベルをアプリから全部外した版でも測りました。アイコンだけのボタンが、名前の無いただの「Button」になる状態です。エージェントがボタンを探しにくくなり、費用がかさむと予想していました。 条件 1回の費用 (ラベルあり → 無し) 無しの方が安かった組 agent-device CLI $0.71 → $0.69 8/15 mobile-mcp CLI $0.71 → $0.69 8/15 mobile-mcp MCP $0.83 → $0.76 8/15 Argent CLI $1.01 → $0.82 11/15 agent-device MCP $0.94 → $0.97 7/15 Argent MCP $1.15 → $1.07 8/15 どの条件も、ラベル無しの方が安かった組は半分前後で、差は3回のばらつきの範囲に収まりました。Argent の CLI だけ2割安くなっていますが、ばらつきと区別しきれません。全条件を合わせた90組で見ても、トークンが少なかったのは41組、時間が短かったのは39組でした。 アイコンだけのリポストのボタンを長押しする #8502 でも、差は出ていません。エージェントは、名前の無いボタンをスクショや並び順から見つけていました。 なお、今回のお題はどれも、たどる画面が少ないものです。何画面もたどる操作では、結果が変わるかもしれません。また、Bluesky は testID とラベルが丁寧に付いたアプリで、ここで測ったのはそれを「外した」状態です。最初から付いていないアプリでは、画面の作りが違うかもしれません。 一番高い Argent の MCP が一番速い 作業時間は平均1分41秒で、6条件の中で一番短くなりました。同じお題どうしで並べると、30組中25組で agent-device の CLI より早く、平均で24秒の差です。 速さのわけは、やり取りの少なさです。タップのたびにスクショが返ってくるので、画面を見るためだけの呼び出しがほとんど要りません。やり取りは平均22回で、agent-device の CLI (26回) より4回少なく済みました。 その代わり、1回のやり取りの費用は agent-device の CLI の倍近く ($0.053 と $0.028) かかります。 まとめ 差が出たのは、バグを直せるかどうかではなく、画面をエージェントにどう渡すかでした。CLI で画面を短く読める agent-device と mobilecli は安く、操作のたびにスクショを返す Argent の MCP は高くつきました。新しいツールを入れるときも、CLI があるか、画面を何で返すか (文字の一覧か、スクショか) を見れば、費用の当たりはつけられます。testID やラベルは、少なくとも費用のためには足さなくて構いません。 まだエージェントの操作ツールを使ったことのない React Native の開発者は、まずは agent-device の CLI を試してみてください。 参考リンク callstack/agent-device (GitHub) software-mansion/argent (GitHub) mobile-next/mobile-mcp (GitHub) bluesky-social/social-app (GitHub)
MCP Shouldn't Require a Desktop: Designing a One-Tap Mobile MCP App Thanks for support.. Release: "Sentinel-IR-MCP v0.2.2 on GitLab" (gitlab.com) Package: "sentinel-ir-mcp@0.2.2 on npm" (npmjs.com) !Image description Somewhere between “I found a useful MCP tool” and “I can use it from my phone,” a simple idea can turn into a side quest through runtimes, JSON files, credentials, server URLs and settings screens. I want to explore a simpler path: a mobile-first app that makes connecting to useful tools feel understandable, safe and close to one tap. Not by hiding the permissions, but by removing the setup archaeology. This article has three levels: 30 seconds for the scroll crowd, 10 minutes for curious humans, and a deeper technical tour for developers. Project status, before the marketing goblin gets near the keyboard: the Mobile MCP 0.1.0 source draft exists, and nine focused unit tests passed in the authoring environment. A DNS failure blocked npm dependency installation, so a normal dependency-backed build has not been verified. Google OAuth, a real Drive search, PostgreSQL integration and a deployment have not been tested live. The source draft is also not yet a general MCP client or MCP server. This is an engineering direction with an initial codebase, not a launched product. The 30-second version MCP, the Model Context Protocol, gives AI applications a common way to discover and use tools. But connecting tools can still feel like assembling furniture with instructions written for someone who already owns a screwdriver factory. Mobile MCP is an attempt to make that connection mobile-first. Open an app on your phone, choose a connector, authorize it with the provider, understand what it can access, and use it without starting from a terminal and a configuration file. The first planned slice uses Google Drive to search file names and show basic metadata. It is designed not to read document contents or modify files. The code draft exists, but the full build and live flow still need verification. It does not yet expose or consume the MCP protocol end-to-end. The principle is simple: one tap should remove setup friction, not remove user consent. The 10-minute guide for non-experts 1. First, imagine a toolbox Imagine you buy a new cordless drill. You do not want to build the electric motor, manufacture the battery, solder a charger and write a driver before drilling one hole. You want to choose the tool, connect it safely, and get on with your day. AI tools have a similar problem. An AI assistant becomes more useful when it can work with things outside the chat: files, calendars, repositories, databases, issue trackers or other services. But the connection between an AI app and those tools needs a common interface, permissions and somewhere for the tool to run. That is where MCP enters the picture. 2. What MCP is, without the acronym fog MCP stands for Model Context Protocol. Think of it as a standard connection language between an AI application and external tools or data sources. The AI model is not MCP. Google Drive is not MCP. A button labelled “Connect” is not MCP either. A useful mental model is: The AI application or client asks what tools are available and calls them. The MCP server exposes tools or other capabilities through the protocol. The underlying service does the actual work, such as searching files or looking up an issue. MCP helps standardize the conversation between the client and the server. It does not automatically make a tool secure, reliable or useful. A standard plug does not make every appliance safe to leave running overnight. The official project documentation is here: modelcontextprotocol.io. 3. So why focus on phones? A lot of developer tooling assumes that the user is sitting at a computer. That makes sense for many development workflows. It is less comfortable when you are using a phone as your main device. Depending on the tool and client, connecting an MCP server may involve installing a runtime, creating a JSON configuration, entering an endpoint, managing credentials, restarting an application, and then figuring out why nothing appears in the tool list. A developer may consider that a five-minute setup. For someone who does not live in terminals, it can be a locked door with a very technical doormat. And mobile makes the friction more visible: typing long paths on a touchscreen is not exactly a premium user experience. Copying a JSON block from one app to another is possible, but so is eating soup with a fork. The problem is not that MCP is inherently desktop-only. Remote MCP services can be accessed over HTTP by compatible clients. The problem we want to tackle is the product experience around connecting, authorizing and using tools from a phone. 4. The idea: a mobile-first connection desk The aim is to make the first steps feel like this: Open the app from a phone browser or install it as a PWA where supported. Choose a connector, for example Google Drive. Sign in with the provider and review the requested permissions. See a clear list of what that connector can and cannot do. Use the capability through a simple interface, without manually editing configuration files. Disconnect it when it is no longer needed. That is the experience we are aiming for, not a claim that every step is already live. For the first vertical slice, I chose Google Drive metadata search. It is concrete and easy to check: search for a file you know exists, see its name and type, and open the real Drive link. The first slice is not supposed to read your documents, rewrite them, share them or delete them. Why start small? Because “connect everything with one click” sounds wonderful until the first click grants a tool more access than it needs. A tiny, verifiable capability is a better foundation than a giant dashboard full of green connection badges. 5. What the current source draft contains The project has a mobile-oriented React and TypeScript interface, a Node.js/Fastify API, PostgreSQL session and OAuth-account storage, a Google OAuth flow, a Drive metadata-search connector, security helpers, deployment configuration and test instructions. The current code is designed around a single configured owner account for a private test, not public multi-user onboarding. That keeps the first authorization boundary narrow while the flow is being checked. There are also important limits: It is not yet a general MCP client that can connect to arbitrary MCP servers. It is not yet an MCP server that exposes the connector through the MCP protocol. There is no AI model or chat-based tool selection in this first slice. No paid hosting has been provisioned and nothing has been deployed. Google authorization and real Drive requests have not been verified live. Why call it Mobile MCP, then? Because the intended product is a mobile-first way to connect and use MCP-compatible capabilities. The current connector hub is the first foundation to validate, not the final protocol surface. 6. A phone-first interface does not mean a phone-only backend The mobile app should be the simple front door. It does not need to hold every secret or do every job itself. The planned boundary looks like this: Phone browser / installable PWA | HTTPS request | Authenticated API | Connector registry | Google Drive API The phone gets a usable interface. The server handles provider credentials and provider calls. Later, a protocol adapter can expose approved capabilities to compatible MCP clients. This separation matters. A mobile browser is not a secure place to paste a long-lived Google client secret, and a user should not have to understand refresh-token rotation to search for a project plan. 7. “One click” cannot mean “trust us with everything” There is a difference between removing friction and removing control. For a real product, users should be able to see which account is connected, what the connector can access, whether it can write anything, and how to disconnect it. The server should enforce these limits even if an AI model asks for something outside them. The source draft includes several security mechanisms: an OAuth state check, verified Google identity, an owner-account allowlist, HTTP-only browser sessions, hashed session identifiers in PostgreSQL, token encryption at rest, request-origin checks, rate limits, API no-cache headers and basic log redaction. Those are design and implementation choices visible in the source. They are not a third-party security audit, and they do not prove the deployed system is safe. They still need normal integration tests and live checks. There is also an important permission decision ahead. The current broad Drive metadata-search design requests drive.metadata.readonly. Google classifies that scope as restricted. A public release must account for Google's applicable verification and data-handling requirements. A narrower drive.file flow combined with the Google Picker can give users more per-file control, but it does not provide the same unrestricted search across all Drive metadata. The convenient product requirement and the least-privilege permission model need to be considered together, not after launch. Google's scope guidance: Choose Google Drive API scopes. 8. What would count as real progress? Not a screenshot. Not a successful-looking mock result. Not “the code seems fine.” The first meaningful acceptance test should be boring in the best possible way: Open the actual HTTPS app on a phone. Connect a real Google test account through OAuth. Search for a known file in that account. Confirm the real file name, metadata and Drive link. Try an unknown name and get an honest empty result. Deny or cancel authorization and confirm the app does not pretend to be connected. Disconnect and confirm protected search calls stop working. Before that test, the dependency installation, lockfile, type checking, full build and PostgreSQL integration test must be completed. The authoring environment hit EAI_AGAIN while resolving the npm registry, so those dependency-backed checks are still blocked. Nine focused unit tests did pass, but they are only one part of the evidence. 9. What is the potential payoff? If the product works, the value is not “MCP, but with a smaller screen.” It is a different entry point. For non-developers, it could make useful tool connections less intimidating. For developers, it could provide a simpler way to configure approved connectors, test permissions and use remote tools while away from a workstation. For teams, a curated catalogue could make the allowed capabilities easier to discover and explain. That does not automatically make it faster, cheaper or safer than every existing MCP setup. Those are claims to measure after there is a working product. The first hypothesis is narrower: a mobile-first setup flow can remove unnecessary configuration work without hiding important permissions. That is worth testing. The 20-minute developer guide This section goes from the product idea to the source-level design. It is intentionally specific about what exists today and what remains future work. 1. Start by separating three roles “MCP app” can refer to several different things, so let us avoid building one acronym-shaped ball of confusion. A. Mobile control surface The React PWA is the phone-friendly interface. It handles user interaction, account status, connector selection and search results. B. Connector backend The Fastify server handles sessions, OAuth credentials and provider API calls. The current first-party connector uses the Google Drive API directly. C. MCP protocol integration, planned A future MCP client capability would connect to remote MCP servers and discover/call their tools. A future MCP server capability would expose selected first-party tools, such as a permitted Drive search, to other MCP-compatible applications. These are separate capabilities. The current 0.1.0 source draft does not yet implement a general-purpose client or server. That distinction is architectural, not cosmetic. A React button calling /api/drive/search is an ordinary application API call. It does not magically become an MCP tool because the repository name contains “MCP.” 2. Current stack and data flow The source draft uses: React, TypeScript and Vite for the responsive PWA. Node.js and Fastify for HTTP routes. PostgreSQL for sessions and OAuth-account records. Google's OAuth client and Drive API libraries. AES-256-GCM for encrypting stored OAuth tokens. Unit tests plus opt-in PostgreSQL and live-health tests. Current request flow: Browser / PWA | | POST /api/drive/search | HTTP-only session cookie v Fastify route | validate origin and input | resolve authenticated owner v DriveClient | load encrypted credentials | decrypt server-side | refresh if needed v Google Drive API | files.list(q, fields, pageSize) v Metadata only: id, name, mimeType, modifiedTime, webViewLink There is no LLM call in that path. The user query is validated and used to build a Drive search expression. The server asks Google for limited metadata and returns it to the interface. 3. Input validation before the provider call The current helper checks the query length, rejects control characters and escapes backslashes and quotes before building the Drive expression. A simplified excerpt from src/connectors/google-drive/search-files.ts: export function escapeDriveQueryLiteral(input: string): string { return input.replace(/\/g, '\\').replace(/'/g, "\'"); } export function buildDriveNameQuery(searchTerm: string): string { const trimmed = searchTerm.trim(); if (trimmed.length < 2 || trimmed.length > 120) { throw new Error('Search term must be between 2 and 120 characters.'); } if (/[\u0000-\u001F\u007F]/.test(trimmed)) { throw new Error('Search term cannot contain control characters.'); } return name contains '${escapeDriveQueryLiteral(trimmed)}' and trashed = false; } The point is not that string escaping solves every security concern. It is that input length, control characters and query quoting should be handled in one narrow function and tested independently, rather than scattered through route handlers. The current Drive request uses a limited field selection and a capped result count: const result = await drive.files.list({ q: query, pageSize: 25, orderBy: 'modifiedTime desc', fields: 'nextPageToken,files(id,name,mimeType,modifiedTime,webViewLink)', spaces: 'drive' }); That is a deliberate boundary: metadata, not document content. A webViewLink is a link to Drive, not a grant of extra access. Google still enforces the user's file permissions and the OAuth scope. 4. Protect the route, not just the button Frontend controls are convenience, not authorization. Someone can call an HTTP endpoint without using the UI, so the route itself checks the request origin, validates the body, and requires the configured owner account. A shortened excerpt of the current route's shape: app.post('/api/drive/search', { config: { rateLimit: { max: 30, timeWindow: '1 minute' } } }, async (request, reply) => { if (!requestHasAllowedOrigin(request)) { return reply.code(403).send({ error: 'ORIGIN_NOT_ALLOWED' }); } const email = await requireOwner(request, reply); if (!email) return reply; const parsed = searchSchema.safeParse(request.body); if (!parsed.success) { return reply.code(400).send({ error: 'INVALID_QUERY' }); } const result = await driveClient.searchByName(email, parsed.data.q); return reply.code(200).send(result); }); This excerpt omits the error mapping found in the full route. The implementation uses a narrow, generic error response for unexpected failures instead of returning raw provider details to the client. The same principle will matter even more when MCP tools are added. A model should not be able to choose an arbitrary account ID and access another person's connector. The server should resolve the identity from the authenticated session, validate every tool argument and enforce permissions independently of the model's instructions. 5. OAuth state, sessions and token storage The authorization-code flow is server-side. The callback validates a short-lived OAuth state value against the session, verifies the returned Google identity and checks that the verified email matches the configured owner allowlist. After a successful login, the session identifier is rotated to reduce session-fixation risk. The browser session cookie is HTTP-only and uses Secure in production. PostgreSQL stores a SHA-256 hash of the opaque session identifier instead of the raw identifier. OAuth access and refresh tokens are encrypted before they are stored. The token-encryption helper uses authenticated encryption: const ALGORITHM = 'aes-256-gcm'; const IV_LENGTH = 12; const TAG_LENGTH = 16; Each encryption call generates a fresh random IV and stores the IV, authentication tag and ciphertext in a versioned envelope. Decryption verifies the authentication tag, so tampering causes failure rather than returning modified token bytes. The encryption key belongs in the server environment, not in the Vite frontend, Git history, the database alongside the ciphertext, or logs. Encrypting a token at rest helps protect database contents, but it does not protect a compromised application process that can read the key. Key access, backup handling, rotation and incident response remain operational concerns. The API also applies no-store headers to /api/ responses. Authentication is not a license to let private search results sit in a shared cache. 6. The Google scope is a product decision The current source requests: export const DRIVE_METADATA_SCOPE = 'googleapis.com'; This scope is read-only for metadata, but Google classifies it as a restricted Drive scope. That has consequences for a public release. Depending on the app's usage and how restricted-scope data is stored or transmitted, Google verification and a security assessment may be required. This should be checked against Google's current requirements before inviting public users. An alternative is to use the narrower drive.file scope with Google Picker, letting the user select files they want to authorize for the app. That reduces the scope of access, but it does not provide identical behavior to searching metadata across all of a user's Drive. The product needs to decide what matters more for the first release: broad name search or a narrower per-file consent experience. Do not silently request a broader scope because it is easier to code. Make the trade-off visible, document it, and test it with actual Google Cloud configuration. Reference: Google Drive API scope guidance. 7. Where the MCP protocol should enter The existing connector service should not be entangled with one protocol. A clean next step is to treat provider operations as capabilities and add a separate protocol adapter around only those operations that should be exposed. Conceptually: +----------------------+ Phone PWA ------> | App API | ------> Google Drive +----------------------+ ^ | +----------------------+ MCP client -----> | MCP adapter (future) | ------> approved capability +----------------------+ There are two possible product features here: Use remote MCP servers from the mobile app. The app becomes an MCP client. It needs server discovery/configuration, transport handling, authorization, a tool catalogue and a safe way to invoke selected tools. Expose Mobile MCP connectors to other AI clients. The backend becomes an MCP server. It needs protocol endpoints, tool discovery, schemas, per-user authorization and execution policies. They should not be implemented as one vague feature called “MCP support.” They have different trust boundaries and acceptance tests. For remote server access, the official TypeScript SDK documents Streamable HTTP as the recommended transport for remote MCP servers, while stdio is primarily suited to local process integrations. A phone cannot always spawn a local server process as a desktop client can, so a remote transport is a natural direction for a hosted mobile experience. Official references: MCP TypeScript SDK server guide and MCP specification. 8. Design the connector interface before the protocol adapter The existing registry is intentionally small. It describes a connector and its capabilities rather than making the UI responsible for provider-specific logic. As additional connectors arrive, keep the provider operation separate from how it is called. A future capability could be described conceptually like this: interface ToolCapability<Input, Output> { name: string; description: string; inputSchema: unknown; requiredPermission: string; execute(input: Input, actor: AuthenticatedActor): Promise<Output>; } This is a design sketch, not an interface that currently ships in the source draft. Its purpose is to make a few rules explicit: Each capability has a stable name and input schema. The authenticated actor is supplied by the backend, not invented by the model. Required permissions are declared and checked before execution. The output type is narrow and documented. The transport adapter does not become the source of authorization truth. A future MCP adapter can map approved capabilities to MCP tools. A mobile UI can call a first-party API. Both can reuse the same policy-checked service without copying Google API logic into two routes. 9. The safety boundary for future MCP tools MCP tools are code execution entry points, even when the tool itself only calls a web API. Before allowing arbitrary server configuration or broader actions, the system needs to handle at least these concerns: Per-user isolation: a user must never inherit another user's connector credentials or data. Least privilege: a tool gets only the provider scope and operation it needs. Argument validation: tool inputs are untrusted, even when generated by a model. No arbitrary URL fetches by default: accepting arbitrary MCP URLs can create server-side request forgery and network-boundary problems. No shell execution in the connector path: do not turn tool configuration into an arbitrary command runner. Visible side effects: write, share and delete operations should be separate capabilities with clear confirmation and authorization rules. Time and size limits: cap result counts, request duration and response size. Redacted observability: record enough structured events to troubleshoot without logging tokens or private file contents. Revocation: disconnecting a provider should make subsequent calls fail and should remove or invalidate stored credentials according to the product's retention policy. MCP tool descriptions and annotations can help a client understand a tool, but they are not an access-control system. Authorization must be enforced by the server. For the first version, I would not allow users to paste an arbitrary remote MCP endpoint and immediately grant it network access. Start with a curated connector list, known transport behavior and explicit account boundaries. Extensibility can come after we have evidence that the first connector behaves correctly. 10. PWA is a delivery choice, not a magic trick A Progressive Web App is attractive because one responsive web app can run in a mobile browser and can be installed from supported browsers over HTTPS. It reduces the need to maintain separate native apps just to test the first flow. But a PWA is not identical to a native app. Browser capabilities, background execution, notifications and installation behavior vary. The service worker should cache static interface assets only. Authentication callbacks, API responses, tokens and private search results must not be placed in a shared offline cache. This MVP is not an offline Drive search engine. It needs a network connection to call Google Drive, and a server connection for the hosted API. The interface should say so rather than inventing a spinner that works as a substitute for connectivity. 11. Test gates: what is known and what is not The checks completed while preparing the source archive were: JSON configuration files parsed. YAML deployment and CI files parsed. TypeScript and TSX files passed a source-syntax transpilation check. This was not a full semantic typecheck. Nine focused unit tests passed for token encryption and tamper rejection, Drive query escaping and limits, log redaction, and same-origin comparison. The checks that remain blocked or unperformed are just as important: npm install could not reach the npm registry because the environment returned EAI_AGAIN during DNS resolution. No package-lock.json was generated. It must be created on a network-enabled machine and reviewed, not fabricated. A normal dependency-backed typecheck and full production build have not passed. PostgreSQL integration has not been run against a live test database. Google OAuth, refresh-token behavior, real Drive search, disconnect behavior, phone installation and deployment have not been tested live. No Render service was provisioned. No production user data was accessed. That is the evidence boundary for this source draft. 12. The first release should pass a boring acceptance checklist Before adding an AI model, a marketplace or generic remote-server support, the first vertical slice should pass these gates: Install dependencies and generate a committed lockfile. Pass dependency-backed type checking, all unit and integration tests, and the production build. Run the database migration on a disposable test database. Configure a real Google Cloud OAuth client and exact HTTPS redirect URI. From the target phone, complete real sign-in and search for a file that is known to exist. Verify the returned metadata and Drive link against the actual file. Check cancelled consent, invalid state, revoked credentials, unknown results, logout, disconnect and unauthorized requests. Revisit the Google scope and verification requirements before a public beta. Only after those gates pass, add and test a real MCP protocol adapter. That order may look less exciting than a dashboard full of connectors. It is also less likely to produce a dashboard full of connectors that do not work. 13. What I want to learn from this experiment The main hypothesis is not that one mobile interface magically makes every integration simple. It is that we can move complexity out of the user's path without moving their permissions out of view. For developers, that means a clean service boundary, reusable connector capabilities, explicit schemas and testable authorization rules. For everyone else, it means they should not need to learn what a refresh token is just to find a document they already have permission to see. The current draft is an early step, not proof that the whole idea has succeeded. The build still needs dependency-backed verification, the Google flow needs a real end-to-end test, and the MCP protocol layer still has to be implemented. Those are concrete tasks, not footnotes to hide under a launch graphic. If this works, the phone is not a tiny desktop pretending to be comfortable. It becomes a first-class way to connect useful tools, review permissions and use approved capabilities. And if the first thing we simplify is setup, not security, we might finally make the connection feel like a button instead of a weekend project. mobile-next/mobile-mcp Question for the community: what would you want as the first genuinely useful one-tap connector on mobile: Google Drive, GitHub, Notion, a calendar, or something else? And where would you draw the line between convenience and access control?
@_smontlouis les tool call de mobile-next/mobile-mcp sont bien plus rapide que ceux d'argent je trouve
卧槽,AI 现在连手机都能自己操作了! 开源项目 Mobile MCP,让 Claude Code、Cursor 直接操控 iPhone 和安卓真机。 自动点击、滑动、输入、截图、安装 App,还能自己测试找 Bug! AI 写代码,AI 操作手机,AI 自己测试。 GitHub 已获 9.1k Star,赶紧收藏!🔥 mobile-next/mobile-mcp
想让 Agent 直接点手机测 App,我核验了两个开源项目: 1. mobile-mcp:iOS、Android、模拟器、真机都支持,Apache-2.0,8.9k star,35 个贡献者 2. iPhone-use:只做 iPhone 真机,MIT,2.4k star,目前 1 个贡献者 进团队测试流程我选前者,个人玩 iPhone 可以试后者。 mobile-next/mobile-mcp
@gursuyaman Beraberinde bunu da kullanırsanız çok daha iyi performans alırsınız: mobile-next/mobile-mcp