pcloudy 0.1.0
pCloudy MCP Server: Category-based FastMCP tools for device, app, session, Appium automation, and analytics management.
Requires Python: >=3.10

# pCloudy MCP Server (Simplified Action-Based Architecture)

This project implements a streamlined MCP server for managing Android and iOS devices on the pCloudy platform. It features a **simplified action-based tool architecture** with clean, intuitive tool names that replace complex naming conventions. The server includes Appium SDK integration, QPilot automation, and comprehensive device management capabilities.

**Author**: Rishav Raj

## 🎯 Simplified Action-Based Tool Architecture

### 📱 Device Management (`device_management`)

**Actions**: `list`, `book`, `release`, `detect_platform`, `set_location`

- **list**: List available devices (`platform="android"`/`"ios"`)
- **book**: Book device (`device_name="GalaxyS10"`, `platform="android"`, `auto_start_services=True`)
- **release**: Release device (`rid="device_id"`)
- **detect_platform**: Auto-detect device platform (`rid="device_id"`)
- **set_location**: Set GPS coordinates (`rid="device_id"`, `latitude=48.8566`, `longitude=2.3522`)

### � Device Services (`device_services`)

**Actions**: `screenshot`, `get_url`, `start_services`, `adb`

- **screenshot**: Capture device screenshot (`rid="device_id"`, `skin=True`)
- **get_url**: Get device page URL and open in browser (`rid="device_id"`)
- **start_services**: Start device services (`rid="device_id"`, `start_device_logs=True`, `start_performance_data=True`, `start_session_recording=True`)
- **adb**: Execute ADB command on Android (`rid="device_id"`, `adb_command="logcat"`, `platform="auto"`)

### 📦 Files (`files`)

**Actions**: `upload`, `list_apps`, `install`, `resign`, `download_cloud`

- **upload**: Upload APK/IPA file (`file_path="/path/to/app.apk"`, `force_upload=False`)
- **list_apps**: List cloud apps (`limit=10`, `filter_type="all"`)
- **install**: Install and launch app (`rid="device_id"`, `filename="app.apk"`, `grant_all_permissions=True`, `platform="android"`, `app_package_name="com.example.app"`)
- **resign**: Resign iOS IPA file (`filename="app.ipa"`, `force_resign=False`)
- **download_cloud**: Download file from cloud (`filename="app.apk"`)

### 📊 Session Data (`session_data`)

**Actions**: `download_file`, `list_performance`

- **download_file**: Download session data (`rid="device_id"`, `filename="optional_specific_file"`, `save_to_disk=True`, `custom_path="optional_directory"`)
- **list_performance**: List performance data files (`rid="device_id"`)

### 🤖 Appium SDK (`appium_sdk`)

**Actions**: `get_capabilities`, `setup_appium`

- **get_capabilities**: Generate Appium capabilities boilerplate (`language="python"`, `device_name="optional"`)
- **setup_appium**: Setup Appium environment with capabilities (`language="java"`, `device_name="GalaxyS10"`)

### 🚀 QPilot Tools

#### QPilot Credits (`qpilotcredit`)

- Get remaining QPilot credits for code generation

#### Test Project (`test_project`)

**Actions**: `create`, `list`

- **create**: Create new test project (`project_name="MyProject"`)
- **list**: List all test projects

#### Test Suite (`test_suite`)

**Actions**: `create`, `list`

- **create**: Create new test suite (`suite_name="MySuite"`)
- **list**: List all test suites

#### Test Case (`test_case`)

**Actions**: `create`, `list`

- **create**: Create new test case (`testSuiteId="123"`, `testCaseName="MyTest"`, `platform="android"`)
- **list**: List all test cases

#### QPilot Code Generation (`qpilot`)

- Generate QPilot automation code steps (`rid="device_id"`, `description="Test description"`, `steps="Step instructions"`)

#### Get Code (`get_code`)

- Retrieve generated QPilot script code (`hostname="device.pcloudy.com"`, `testCaseId="123"`, `testSuiteId="456"`, `scriptType="pcloudy_appium-js"`)

## 📋 Usage Examples

### 🔄 Complete Testing Workflow

```python
# 1. List available devices
device_management(action="list", platform="android")

# 2. Book a device
device_management(action="book", device_name="GalaxyS10") 

# 3. Set GPS location for location-based testing
device_management(action="set_location", rid="123", latitude=48.8566, longitude=2.3522)

# 4. Install and launch app (auto-opens device in browser)
files(action="install", rid="123", filename="MyApp.apk")

# 5. Take a screenshot
device_services(action="screenshot", rid="123")

# 6. Download session data
session_data(action="download_file", rid="123")

# 7. Release device
device_management(action="release", rid="123")
```

### 📱 iOS App Testing

```python
# 1. Upload iOS app
files(action="upload", file_path="MyApp.ipa")

# 2. Resign the IPA for deployment
files(action="resign", filename="MyApp.ipa") 

# 3. Book iOS device
device_management(action="book", device_name="iPhone", platform="ios")

# 4. Install resigned app
files(action="install", rid="123", filename="MyApp_resign.ipa")
```

### 🐛 Android Debugging

```python
# 1. Book Android device
device_management(action="book", device_name="Pixel")

# 2. Execute ADB commands
device_services(action="adb", rid="123", adb_command="logcat")

# 3. List performance data
session_data(action="list_performance", rid="123")

# 4. Download specific log files
session_data(action="download_file", rid="123", filename="specific_log.txt")
```

### 🤖 Appium SDK Integration

```python
# Generate Appium capabilities for a booked device and uploaded app
appium_sdk(action="get_capabilities", language="python")

# Setup Appium environment
appium_sdk(action="setup_appium", language="java", device_name="GalaxyS10")
```

### 🚀 QPilot Automation Workflow

```python
# 1. Check QPilot credits
qpilotcredit()

# 2. Create test project
test_project(action="create", project_name="MyAutomationProject")

# 3. Create test suite
test_suite(action="create", suite_name="LoginTestSuite")

# 4. Create test case
test_case(action="create", testSuiteId="456", testCaseName="ValidLogin", platform="android")

# 5. Generate QPilot automation code
qpilot(rid="123", description="Login test automation", steps="Open app, enter credentials, tap login")

# 6. Get generated code
get_code(hostname="device.pcloudy.com", testCaseId="789", testSuiteId="456", scriptType="pcloudy_appium-js")
```

## Setup

1. **Clone the repository:**

   ```powershell
   git clone <repository_url>
   cd <repository_directory>
   ```

2. **Create a virtual environment:**

   ```powershell
   python3.13 -m venv .venv
   ```

3. **Activate the virtual environment:**
   - **Windows (PowerShell):**

     ```powershell
     .venv\Scripts\Activate.ps1
     ```

   - **Linux/macOS:**

     ```bash
     source .venv/bin/activate
     ```

4. **Install dependencies:**
   The project requires the following Python packages (see `pyproject.toml`):
   - `aiofiles`
   - `fastapi`
   - `fastmcp`
   - `python-dotenv`

   Install them using pip:

   ```powershell
   pip install aiofiles fastapi fastmcp python-dotenv
   ```

   Or, if you use Poetry or uv:

   ```powershell
   poetry install
   # OR
   uv sync
   ```

5. **pCloudy API Credentials:**
   - Copy `.env.template` to `.env` and fill in your credentials.
   - The server uses a browser-based authentication flow. You'll be prompted to enter your pCloudy `username` and `api_key` when running any tool if not set in `.env`.

## Running the MCP Server

### 🚀 **Universal Startup (Recommended)**

The easiest way to start the server on **any platform** (Windows, macOS, Linux):

```bash
python start_server.py
```

This script automatically:

- Detects your operating system and Python installation
- Tries multiple methods: uv → direct python → pip install + run
- Installs missing dependencies automatically
- Provides helpful error messages and guidance

### ⚙️ **Manual Methods (Advanced)**

If you prefer to run the server manually:

#### Using uv (recommended if installed)

```bash
uv run --with fastmcp fastmcp run src/mcp_server/server_main.py
```

#### Using FastMCP directly

```bash
fastmcp dev src/mcp_server/server_main.py
```

#### Direct Python execution

```bash
python src/mcp_server/server_main.py
```

The server will listen on `http://localhost:8000` by default (port can be changed via the `PORT` environment variable).

## ✅ Enhanced Features

### 🎯 Category-Based Architecture Benefits

- **Simplified Interface**: 4 meta-tools instead of 17 individual tools
- **Logical Grouping**: Related operations organized under single tools
- **Intelligent Routing**: System automatically selects correct method based on action
- **Cleaner Documentation**: Easier to understand and maintain
- **Better User Experience**: Less tool discovery, more focused workflows

### 🚀 Smart Automation

- **Auto-Authentication**: Seamless authentication across all operations
- **Auto-Service Startup**: Device booking automatically starts logs, performance data, and session recording
- **Auto-Browser Opening**: App installation and device URL requests automatically open in browser
- **Auto-Platform Detection**: ADB commands automatically detect device platform
- **Auto-Session Discovery**: Device release automatically prompts for session data download

### 🔧 Advanced Capabilities

- **GPS Location Setting**: Simulate location-based testing with precise coordinates
- **Unified Download System**: Single function handles both individual files and bulk session downloads
- **iOS App Resigning**: Automatic IPA resigning for iOS deployment
- **Performance Monitoring**: Real-time performance data collection during app testing
- **ADB Command Execution**: Full Android debugging capabilities with safety checks
- **Appium Capabilities Generation**: Instantly generate Appium capabilities for your automation scripts

### 🛡️ Security & Validation

- **Input Validation**: Comprehensive validation for all parameters
- **Path Security**: Download directory validation prevents security issues
- **Platform Compatibility**: Automatic platform detection prevents incompatible operations
- **Error Handling**: Detailed error messages and graceful failure handling

## 📁 Project File Structure

The project is organized as follows:

```text
Pcloudy/
├── .env                  # Your pCloudy credentials (not committed)
├── .env.template         # Example template for .env
├── pcloudy_mcp_server.log # Log file for server activity
├── pyproject.toml        # Project metadata and dependencies
├── README.md             # Project documentation
├── uv.lock               # UV lock file for dependency management
├── src/                  # All source code
│   ├── __init__.py       # Package initialization
│   ├── config.py         # Configuration and logging setup
│   ├── security.py       # Security utilities
│   ├── utils.py          # General utility functions
│   ├── api/              # API classes for pCloudy endpoints
│   │   ├── __init__.py   # API package initialization
│   │   ├── auth.py       # Authentication logic (Auth class)
│   │   ├── device.py     # Device management (Device class)
│   │   ├── adb.py        # ADB command handling (Adb class)
│   │   ├── app_management.py # App installation and management (AppManagement class)
│   │   ├── device_control.py # Device control operations (DeviceControl class)
│   │   ├── file_management.py # File upload/download (FileManagement class)
│   │   ├── platform.py   # Platform detection (Platform class)
│   │   ├── services.py   # Device services management (Services class)
│   │   ├── session.py    # Session data handling (Session class)
│   │   └── qpilot_*.py   # QPilot-related API classes
│   └── mcp_server/       # Main server and tool definitions
│       ├── __init__.py   # MCP server package initialization
│       ├── server_main.py    # Main entry point for FastMCP server
│       ├── shared_mcp.py     # Shared FastMCP instance
│       └── tools/            # Simplified action-based tool implementations
│           ├── device_management.py     # Device management operations
│           ├── device_services.py       # Device control and monitoring
│           ├── files.py                 # File and app management
│           ├── session_data.py          # Session data operations
│           ├── appium_sdk.py            # Appium SDK integration
│           ├── qpilotcredit.py          # QPilot credits
│           ├── test_project.py          # Test project management
│           ├── test_suite.py            # Test suite management
│           ├── test_cases.py            # Test case management
│           ├── qpilot.py                # QPilot code generation
│           └── get_code.py              # QPilot script retrieval
```

- **.env**: Your pCloudy credentials and environment variables. Use `.env.template` as a starting point.
- **src/api/**: Contains clean API classes for each pCloudy API area (no more "Mixin" suffixes).
- **src/mcp_server/tools/**: Each simplified tool with action-based operations.
- **Token Persistence**: Authentication tokens are automatically saved to `Downloads/pCloudy_Downloads/` with base64 encoding.
- **src/mcp_server/server_main.py**: The main entry point that registers all tools and starts the FastMCP server.
- **config.py, utils.py, security.py**: Shared configuration, utility, and security logic.
- **pcloudy_mcp_server.log**: All logs are written here for debugging and audit.

This structure keeps configuration, API logic, and tool implementations modular and easy to maintain.

## Notes

- **Python Version**: Requires Python 3.13.
  On Ubuntu, you might use:

  ```bash
  sudo apt install python3.13 python3.13-venv python3.13-dev
  ```

- **Logs**: Log messages are saved in `pcloudy_mcp_server.log`. Check this file for detailed error messages if issues occur.
- **Environment**: Place your `.env` file in the project root. Use `.env.template` as a starting point.
- **Security**: Ensure you secure your credentials. The server runs a local HTTP server on `localhost` for authentication, which shuts down after use. For production, consider using HTTPS and additional security measures.
- **Troubleshooting**:
  - **Import Errors**: If you encounter "ModuleNotFoundError", ensure you're running the server from the project root directory.
  - **Python Path Issues**: The project includes automatic path resolution for module imports.
  - Verify your network access to `https://device.pcloudy.com/api`.
  - Ensure your pCloudy `username` and `api_key` are correct when prompted during authentication.
  - If authentication fails, check `pcloudy_mcp_server.log` for the raw API response to diagnose the issue (e.g., invalid credentials or API errors).
  - If you encounter port conflicts (e.g., on port 8080 used for authentication), the server will automatically retry with the next available port.
  - For performance data issues, ensure the package name is correct and the app is installed and running.
  - Use `device_management(action="detect_platform", rid="device_id")` if unsure about device platform compatibility.
  - **Windows Users**: Use PowerShell commands as shown in the setup instructions.

## Migration from Previous Version

If upgrading from the previous complex naming architecture:

**Old Approach:**

```python
list_available_devices(platform="android")
book_device_by_name(device_name="GalaxyS10")
capture_device_screenshot(rid="123")
file_app_management(action="upload", file_path="app.apk")
session_analytics(action="download_session", rid="123")
appium_capabilities(language="python")
```

**New Simplified Approach:**

```python
device_management(action="list", platform="android")
device_management(action="book", device_name="GalaxyS10")
device_services(action="screenshot", rid="123")
files(action="upload", file_path="app.apk")
session_data(action="download_file", rid="123")
appium_sdk(action="get_capabilities", language="python")
```

The new approach provides the same functionality with cleaner, more intuitive tool names.

---

## 🔄 Recent Updates (July 9, 2025)

### ✅ Major Refactoring & Simplification

- **Simplified Tool Names**: Removed complex suffixes and adopted clean, action-based naming
  - `device_control_tool` → `device_services`
  - `file_app_management_tool` → `files`
  - `session_analytics_tool` → `session_data`
  - `appium_capabilities_tool` → `appium_sdk`
  - And many more...

- **Removed "Mixin" Suffixes**: All API classes now have clean names
  - `AuthMixin` → `Auth`
  - `DeviceMixin` → `Device`
  - `FileManagementMixin` → `FileManagement`
  - All 16 API classes simplified

- **Enhanced Token Persistence**: Authentication tokens now persist in Downloads/pCloudy_Downloads/ with base64 encoding
- **Cache Prevention**: Added `sys.dont_write_bytecode = True` to prevent `__pycache__` directories
- **QPilot Integration**: Complete QPilot workflow support with dedicated tools
- **Appium SDK Actions**: Enhanced Appium integration with `get_capabilities` and `setup_appium` actions

### 🏗️ Architecture Improvements

- **Action-Based Design**: All tools follow consistent action parameter patterns
- **Simplified Imports**: Clean, organized import structure in server_main.py
- **No Functional Changes**: All features work exactly the same with better names
- **Improved Documentation**: Updated examples and usage patterns throughout

### 🛡️ Enhanced Features

- **Token Persistence**: Automatic token saving/loading from disk
- **Better Error Handling**: Improved error messages and validation
- **Cross-Platform Support**: Enhanced Windows PowerShell compatibility
- **Modular Design**: Clean separation between API logic and MCP tools

---

## Updated: July 9, 2025

Major refactoring with simplified action-based architecture, removed "Mixin" suffixes, enhanced QPilot integration, and improved token persistence for better developer experience.