Skip to content

Conversation

@nirukk52
Copy link
Owner

@nirukk52 nirukk52 commented Nov 11, 2025

Integrate mobile-mcp as a new Encore microservice to replace direct Appium integration and resolve persistent device connection issues.

The existing Appium integration was causing reliability issues, such as shell stalls (BUG-011) and agent stalls on privacy consent dialogs (BUG-015). mobile-mcp offers a more robust and battle-tested solution for device I/O, providing better error handling, cross-platform abstraction, and a foundation for improved observability and future scalability. This PR establishes the new backend/mobile service with 25+ typed APIs, session management, and an audit log to address these problems.


Open in Cursor Open in Web


Note

Adds comprehensive Mobile-MCP integration documentation (spec, plan, tasks, test plan, decisions, summaries) and updates handoff notes.

  • Docs (specs/002-integrate-mobile-mcp/):
    • Specification & Plan: Add spec.md, plan.md, and analysis.md defining requirements, phases, and rationale.
    • Execution Artifacts: Add tasks.md, PHASE_2_OPERATIONS_TASKS.md, and TASK_CREATION_TEMPLATE.md with detailed task breakdowns and exit criteria.
    • Status & Summaries: Add EXECUTIVE_SUMMARY.md, COMPLETION_SUMMARY.md, ALIGNMENT_CHECKPOINT.md, and recommendation.md summarizing progress, alignment, and next steps.
    • Quality & Validation: Add bugs.md (fixed/known issues) and test-plan.md (unit/integration/E2E, benchmarks).
    • Decision Records: Add decision.md capturing incremental integration approach.
  • Handoff:
    • Update specs/003-coding-agent-optimization/BACKEND_HANDOFF_DEPRECATED.md with a new handoff entry describing the Mobile-MCP microservice work and pending integration steps.

Written by Cursor Bugbot for commit 7525bab. This will update automatically on new commits. Configure here.

nirukk52 and others added 4 commits November 10, 2025 20:21
- Fixed E2E test hangs by racing navigation + API calls with Promise.all()
- Replaced 3-test suite with single deterministic run-validation test
- Added data-testid attributes to run-events and discovered-screens
- Updated frontend development + debugging skills with E2E patterns
- Integrated spec-kit as submodule for spec-driven development
- Added Appium startup script for automated mobile testing

Test result: ✅ 1 passed (5.7s)
Resolves: BUG-015, BUG-014 validation
Replaces direct Appium integration with a dedicated microservice for mobile device automation. This improves reliability and provides a typed API for mobile operations.

Co-authored-by: niranjankurambhatti <niranjankurambhatti@gmail.com>
@cursor
Copy link

cursor bot commented Nov 11, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@vercel
Copy link

vercel bot commented Nov 11, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
screengraph Ready Ready Preview Comment Nov 14, 2025 6:39pm

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 210 to 227
const whereClause = conditions.join(" AND ");

const result = await db.queryRow<{
device_id: string;
name: string;
platform: "android" | "ios";
device_type: "real" | "emulator" | "simulator";
version: string;
screen_width: number | null;
screen_height: number | null;
orientation: "portrait" | "landscape" | null;
}>`
SELECT device_id, name, platform, device_type, version,
screen_width, screen_height, orientation
FROM device_info
WHERE ${whereClause}
ORDER BY last_seen_at DESC
LIMIT 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind parameters when filtering devices

The allocation lookup builds a whereClause containing placeholders like $1 and collects the values in a local params array, but the array is never passed to db.queryRow. When createSession supplies a platform, device type, or provider, Postgres receives a query that references $1/$2 without any bound values and fails with a parameter-mismatch error before any device is returned. The query needs to be constructed with tagged template literals (e.g. composing SQL`` fragments) or otherwise supply the collected parameters to db.queryRow`.

Useful? React with 👍 / 👎.

Comment on lines +675 to +694
/**
* Create a new device session.
*/
export const createSession = api(
{ expose: true, method: "POST", path: "/mobile/sessions/create" },
async (req: CreateSessionRequest): Promise<CreateSessionResponse> => {
logger.info("creating device session", { allocation: req.allocation });

const sessionRepo = getDeviceSessionRepository();

// For now, find first available device matching criteria
// In future, implement smart allocation with AWS Device Farm integration
const device = await sessionRepo.findAvailableDevice(req.allocation);

if (!device) {
throw new Error(`No available device matching criteria: ${JSON.stringify(req.allocation)}`);
}

const session = await sessionRepo.createSession(device.id, {
allocation: req.allocation,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not keep allocated devices flagged as available

Device selection filters on available = TRUE, but createSession only inserts a row in device_sessions and never updates device_info.available when a device is allocated (nor when a session closes). As a result every call to createSession can return the same physical device even while an earlier session is active, because the availability flag is never cleared. The allocation path should mark the chosen device unavailable and restore it when the session ends to avoid concurrent sessions contending for the same hardware.

Useful? React with 👍 / 👎.

- Add mobile MCP client and session management
- Implement mobile session repository with database persistence
- Create mobile service with WebDriver session lifecycle
- Add mobile session adapter for agent integration
- Update agent state and device setup nodes for mobile support
- Add database migration for mobile sessions table
- Update environment config for mobile MCP settings
- Add comprehensive mobile integration tests
- Update package.json with mobile service dependencies
- Create detailed implementation documentation and status tracking
screenWidth: result.screen_width || undefined,
screenHeight: result.screen_height || undefined,
orientation: result.orientation || undefined,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Unreachable Code: A Ghost in the Machine

The findAvailableDevice method contains unreachable dead code after an early return statement. Lines 284-297 will never execute because the function returns at line 282 within the for await loop. This dead code appears to be a duplicate/leftover implementation that contradicts the working loop-based logic above it.

Fix in Cursor Fix in Web

retryable: isRetryable,
humanReadableFailureSummary: errorMessage,
mobileSessionId: null,
mobileDeviceId: null,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Device Identity Lost During Failures

In the failure path, mobileDeviceId is set to null but should preserve the device name from deviceConfiguration.deviceName like in the success path. This loses device identification information when failures occur, making debugging harder since the device ID won't be tracked in failure outputs.

Fix in Cursor Fix in Web


# Expected Run Metrics (for deterministic testing)
EXPECTED_UNIQUE_SCREENS_DISCOVERED=1
ENABLE_MOBILE_MCP=true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Experimental Feature Flag Enabled By Default

The feature flag ENABLE_MOBILE_MCP=true is enabled by default in the committed .env file. According to the PR description, the mobile-mcp integration is intended to replace Appium integration, but the implementation shows it's still experimental with pending agent adapter migration and end-to-end testing. Enabling this by default could break existing functionality since the agent integration is incomplete, and the .env file header explicitly states it's committed to git, affecting all developers.

Fix in Cursor Fix in Web

- Updated dependencies for mobile-mcp and modelcontextprotocol/sdk to specific versions.
- Added mobile session management with new session.adapter.ts for lifecycle coordination.
- Enhanced agent state to track mobile session and device IDs.
- Implemented device session repository for managing active sessions and logging operations.
- Created comprehensive mobile service with 25+ REST API endpoints for device management.
- Added database migrations for mobile session tracking.
- Introduced feature flag `ENABLE_MOBILE_MCP` for conditional integration.
- Completed integration tests and ensured all backend tests are passing.

This commit establishes a robust mobile device automation service, replacing direct Appium integration and improving reliability.
@openhands-ai
Copy link

openhands-ai bot commented Nov 14, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • CI

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #17 at branch `cursor/integrate-mobile-mcp-as-microservice-46cf`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

AND (${request.provider !== undefined} = FALSE OR provider = ${request.provider || null})
ORDER BY last_seen_at DESC
LIMIT 1
`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Boolean String Injection Breaks SQL Queries

The WHERE clause injects boolean values into SQL template literals, converting them to string literals "true" or "false" rather than SQL boolean expressions. This produces invalid SQL syntax like "false" = FALSE when optional fields (deviceType, provider, version) are undefined. The logic should evaluate these conditionals outside the template literal or use proper SQL conditional expressions to correctly skip optional filters when not provided.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants