-
Notifications
You must be signed in to change notification settings - Fork 751
feat(mcp): simplify MCP tool architecture and unify platform tools #1507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v1
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for midscene ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors the MCP (Model Context Protocol) server architecture to use a unified, dynamic tool generation pattern across all platforms (Web, Android, iOS), significantly reducing code duplication and improving maintainability.
Key Changes
- Introduced shared base classes (
BaseMCPServerandBaseMidsceneTools) in@midscene/shared/mcpto provide common infrastructure for all platform MCP servers - Implemented dynamic tool generation from
agent.getActionSpace()instead of hardcoded tool definitions, making the architecture more flexible - Created platform-specific MCP packages:
@midscene/android-mcpfor Android automation and@midscene/ios-mcpfor iOS automation, plus@midscene/web-mcpas an alias for the existing@midscene/mcp
Reviewed changes
Copilot reviewed 38 out of 39 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/mcp/base-server.ts | New base MCP server class providing common launch() API and lifecycle management |
| packages/shared/src/mcp/base-tools.ts | New base tools manager with dynamic tool initialization from action space |
| packages/shared/src/mcp/tool-generator.ts | Core tool generation logic converting action space to MCP tool definitions |
| packages/shared/src/mcp/types.ts | Type definitions for tool architecture |
| packages/shared/src/mcp/index.ts | Export aggregation for shared MCP infrastructure |
| packages/shared/package.json | Added MCP module export path and SDK dependency |
| packages/mcp/src/server.ts | Refactored Web MCP server to extend BaseMCPServer |
| packages/mcp/src/web-tools.ts | New Web-specific tools manager extending BaseMidsceneTools |
| packages/mcp/src/index.ts | Simplified CLI entry to use new server architecture |
| packages/mcp/src/tools.ts | Removed (replaced by dynamic tool generation) |
| packages/mcp/src/midscene.ts | Removed (logic moved to base classes and web-tools) |
| packages/mcp/package.json | Added exports field for server module |
| packages/mcp/tests/index.test.ts | Removed obsolete tool snapshot tests |
| packages/android-mcp/* | New Android MCP server package with android_connect tool |
| packages/ios-mcp/* | New iOS MCP server package with ios_connect tool |
| packages/web-mcp/* | New alias package re-exporting @midscene/mcp for naming consistency |
| pnpm-lock.yaml | Updated dependencies for new packages |
| package.json | Added new packages to test script |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (4)
packages/android-mcp/rslib.config.ts:1
- Unused import path.
import path from 'node:path';
packages/ios-mcp/rslib.config.ts:1
- Unused import path.
import path from 'node:path';
packages/ios-mcp/src/ios-tools.ts:5
- Unused import z.
import { z } from 'zod';
packages/shared/src/mcp/tool-generator.ts:29
- Unused variable result.
const result = await agent.action(`Use the action "${action.name}"`, {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
9535f2f to
4613d05
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 39 out of 40 changed files in this pull request and generated 7 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ff57aac to
9cfd87e
Compare
bec2957 to
8f47ac4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 41 out of 45 changed files in this pull request and generated 6 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
packages/mcp/tests/index.test.ts:7
- The test file imports
deepMerge,getChromePathFromEnv, andgetSystemChromePathfrom../src/utils, but this file no longer exists in thepackages/mcppackage. These utilities have been moved topackages/web-mcp/src/utils.tsas part of the refactoring.
Since @midscene/mcp is now just a wrapper for @midscene/web-mcp, these tests should either be:
- Moved to the
packages/web-mcppackage where the actual implementation now lives, or - Updated to import from
@midscene/web-mcpif testing the wrapper functionality
The current import path will cause test failures.
import {
deepMerge,
getChromePathFromEnv,
getSystemChromePath,
} from '../src/utils';
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
0d4a373 to
25fb2ee
Compare
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
d380d75 to
870fe07
Compare
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
870fe07 to
2fb6bab
Compare
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2fb6bab to
1c23d4e
Compare
…Web tools; enhance action space retrieval
… and Web tools; streamline temporary device creation
…ers; enhance command line argument parsing
…gic for Android, iOS, and Web MCP servers
… MCP server and tools
… for unified HTTP support and argument parsing
- Improve error handling in base-tools.ts for bridge mode initialization - Add specific detection for bridge mode URL requirement errors - Provide friendly logging messages instead of generic failure messages - Clarify that deferred initialization is expected behavior - Improve comments in web-tools.ts - Remove misleading "deferred until first tool use" comment - Add clear explanations for bridge vs puppeteer mode behavior - Clarify that bridge mode requires URL while puppeteer can auto-start - Move tests from @midscene/mcp to @midscene/web-mcp - Relocate utils and puppeteer tests to correct package location - Update mcp package.json to remove obsolete test scripts - All 22 tests passing in new location 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Fix invalid planType parameter in tool-generator.ts - Add missing isError field to wait_for tool - Remove unused @midscene/android dependency from web-mcp - Add externals configuration to android-mcp and ios-mcp - Unify version handling using __VERSION__ constant - Improve error handling in base-tools.ts wait_for Resolves 8 review comments from GitHub Copilot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Type Safety & Documentation: - Add aiAction and aiWaitFor optional methods to BaseAgent interface - Add comprehensive JSDoc for ensureAgent abstract method - Remove complex type assertions in favor of optional method calls Code Organization: - Extract magic numbers to named constants (defaultAppLoadingTimeoutMs, defaultAppLoadingCheckIntervalMs) - Add buildScreenshotContent helper method to reduce code duplication - Unify method naming: initAgentByBridgeMode → initBridgeModeAgent Error Handling & Logging: - Add debug logging to all catch blocks instead of silent failures - Replace error variable 'e' with descriptive 'error' Code Style: - Use optional chaining (?.) for cleaner agent.destroy calls - Simplify verbose comments (require usage explanations) - Improve comment clarity for temporary device creation All changes follow conventional commits and maintain backward compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…kage Extract Constants: - Move defaultAppLoadingTimeoutMs (10000) to @midscene/shared/mcp/types - Move defaultAppLoadingCheckIntervalMs (2000) to @midscene/shared/mcp/types - Remove duplicate constant definitions from android-mcp and ios-mcp Type Safety: - Add BaseAgent import to android-tools.ts - Use double type assertion (as unknown as) for agent type conversion - Fix spelling: temp-for-actionspace → temp-for-action-space This follows DRY principle by maintaining constants in a single location and improves type safety with proper imports and assertions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
4280717 to
88698d3
Compare
bd1d89d to
5c2fddb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 60 out of 63 changed files in this pull request and generated 5 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "nx": "21.1.2", | ||
| "prettier": "^3.7.4", | ||
| "nx": "22.1.3", | ||
| "prettier": "^3.6.2", |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prettier version specifier in package.json has been downgraded from ^3.7.4 to ^3.6.2, but the lock file shows version 3.7.4 is still being used. This mismatch could cause confusion. Either update the specifier to match the actual version used (^3.7.4) or ensure the lock file reflects the intended version (^3.6.2).
| "prettier": "^3.6.2", | |
| "prettier": "^3.7.4", |
| if (this.agent && openNewTabWithUrl) { | ||
| try { | ||
| await this.agent?.destroy?.(); | ||
| } catch (error) { | ||
| console.debug('Failed to destroy agent during re-init:', error); | ||
| } |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling in ensureAgent uses try-catch to suppress errors during agent destruction, but the error is only logged via debug(). Consider using console.error() or a more visible logging mechanism for destruction failures, as these could indicate resource leaks or other serious issues that should not be silently ignored.
| // Close the HTTP server | ||
| if (httpServer) { | ||
| await new Promise<void>((resolve) => { | ||
| httpServer!.close(() => resolve()); |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The base expression of this property access is always null or undefined.
|
|
||
| try { | ||
| // Start server in background | ||
| const serverPromise = server.launchHttp({ |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable serverPromise.
| const conflictServer = new WebMCPServer(); | ||
|
|
||
| // This should fail because the port is already in use | ||
| const launchPromise = conflictServer.launchHttp({ |
Copilot
AI
Dec 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable launchPromise.
…tion across Android, iOS, and Web packages
55e3380 to
34df6ec
Compare
82bffa2 to
eabb1f0
Compare
Summary
This PR refactors the MCP packages to use a simplified, consistent tool architecture across all platforms (Web, Android, iOS).
Key Changes
🏗️ Shared Infrastructure (
@midscene/shared/mcp)BaseMCPServerandBaseMidsceneToolsbase classes for code reuseagent.getActionSpace()take_screenshotandwait_for(removedassert)tool-generator.ts📦 Platform-Specific Packages
android_connecttoolios_connecttool🎯 Simplified Tool Architecture
Each platform now provides exactly 3 types of tools:
agent.getActionSpace()take_screenshot: Capture current page/screenwait_for: Wait until condition becomes trueweb_connect: Connect to web page (Puppeteer) or browser (Bridge mode)android_connect: Connect to Android device (optionaldeviceIdanduri)ios_connect: Connect to iOS device (optionaluri)🔧 Recent Improvements
Bridge Mode Enhancement (d56be2d):
base-tools.tsBuild & Type Fixes (0d4a373):
planTypeparameter in tool-generator.tsisErrorfield to wait_for tool response@midscene/androiddependency from web-mcp__VERSION__constant across all MCP packages🧪 Testing & Quality
Migration Notes
Tools have been consolidated:
→open_newweb_connect→ Removed (useandroid_list_devicesandroid_connectwithout deviceId)→ Merged intoandroid_launchandroid_connect(useuriparameter)→ Removed (just useios_check_environmentios_connect)→ Removed from common toolsassertPackage rename:
@midscene/mcp→@midscene/web-mcpRelated Issues
Part of MCP architecture refactoring to support multiple platforms with consistent patterns.
Addresses GitHub Copilot review comments for improved code quality and type safety.
🤖 Generated with Claude Code