Skip to main content
Glama

XC-MCP: XCode CLI wrapper

by conorluddy
pbcopy.ts7.85 kB
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { executeCommand } from '../../utils/command.js'; import { simulatorCache } from '../../state/simulator-cache.js'; interface SimctlPbcopyToolArgs { udid: string; text: string; } /** * Copy text to the clipboard of a simulator (simulated UIPasteboard) * * Examples: * - Copy text: udid: "device-123", text: "Hello World" * - Copy URL: udid: "device-123", text: "https://example.com" * - Copy JSON: udid: "device-123", text: '{"key":"value"}' * * This simulates the pasteboard in the simulator, allowing apps to access * the pasted content via UIPasteboard.general.string * * **Full documentation:** See simctl/pbcopy.md for detailed parameters and examples */ export async function simctlPbcopyTool(args: any) { const { udid, text } = args as SimctlPbcopyToolArgs; try { // Validate inputs if (!udid || udid.trim().length === 0) { throw new McpError(ErrorCode.InvalidRequest, 'UDID is required and cannot be empty'); } if (!text || text.trim().length === 0) { throw new McpError(ErrorCode.InvalidRequest, 'Text is required and cannot be empty'); } // Validate simulator exists const simulator = await simulatorCache.findSimulatorByUdid(udid); if (!simulator) { throw new McpError( ErrorCode.InvalidRequest, `Simulator with UDID "${udid}" not found. Use simctl-list to see available simulators.` ); } // Write text to temp file const tempFile = `/tmp/pbcopy_${Date.now()}.txt`; const fs = await import('fs/promises'); await fs.writeFile(tempFile, text, 'utf8'); try { // Execute pbcopy command const command = `cat "${tempFile}" | xcrun simctl pbcopy "${udid}"`; console.error(`[simctl-pbcopy] Executing: xcrun simctl pbcopy "${udid}"`); const result = await executeCommand(command, { timeout: 10000, }); const success = result.code === 0; // Build guidance messages const guidanceMessages: string[] = []; if (success) { guidanceMessages.push( `✅ Text copied to clipboard on "${simulator.name}"`, `Text length: ${text.length} characters`, `App can access via: UIPasteboard.general.string`, `Test paste in app: simctl-launch ${udid} com.example.app` ); } else { guidanceMessages.push( `❌ Failed to copy to clipboard: ${result.stderr || 'Unknown error'}`, `Check simulator is available: simctl-health-check`, `Verify text format: ${text.substring(0, 50)}...` ); } // Add warnings for simulator state regardless of success if (simulator.state !== 'Booted') { guidanceMessages.push( `⚠️ Warning: Simulator is in ${simulator.state} state. Boot the simulator for optimal functionality: simctl-boot ${udid}` ); } if (simulator.isAvailable === false) { guidanceMessages.push( `⚠️ Warning: Simulator is marked as unavailable. This may cause issues with operations.` ); } const responseData = { success, udid, textLength: text.length, textPreview: text.length > 100 ? text.substring(0, 100) + '...' : text, simulatorInfo: { name: simulator.name, udid: simulator.udid, state: simulator.state, isAvailable: simulator.isAvailable, }, command, output: result.stdout, error: result.stderr || undefined, exitCode: result.code, guidance: guidanceMessages, }; const responseText = JSON.stringify(responseData, null, 2); return { content: [ { type: 'text' as const, text: responseText, }, ], isError: !success, }; } finally { // Clean up temp file try { await fs.unlink(tempFile); } catch { // Ignore cleanup errors } } } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `simctl-pbcopy failed: ${error instanceof Error ? error.message : String(error)}` ); } } export const SIMCTL_PBCOPY_DOCS = ` # simctl-pbcopy Copy text to simulator's clipboard for testing paste operations and UIPasteboard APIs. ## What it does Copies text to the simulator's pasteboard (UIPasteboard.general), making it available for apps to access via standard pasteboard APIs. Useful for testing paste functionality without manual interaction. ## Parameters - **udid** (string, required): Simulator UDID (from simctl-list) - **text** (string, required): Text to copy to clipboard ## Returns JSON response with: - Copy operation status - Text length and preview - Guidance for accessing pasteboard in app ## Examples ### Copy simple text \`\`\`typescript await simctlPbcopyTool({ udid: 'device-123', text: 'Hello World' }) \`\`\` ### Copy URL \`\`\`typescript await simctlPbcopyTool({ udid: 'device-123', text: 'https://example.com/path?param=value' }) \`\`\` ### Copy JSON data \`\`\`typescript await simctlPbcopyTool({ udid: 'device-123', text: JSON.stringify({ key: 'value', number: 123 }) }) \`\`\` ## Common Use Cases 1. **Paste testing**: Test text field paste functionality 2. **URL handling**: Test app URL detection from clipboard 3. **Data import**: Test importing data via clipboard 4. **Share functionality**: Test receiving shared text content 5. **Clipboard monitoring**: Test apps that monitor pasteboard changes ## How Apps Access the Text Apps can access the clipboard text using: \`\`\`swift if let text = UIPasteboard.general.string { // Use the pasted text } \`\`\` Or for URLs: \`\`\`swift if let url = UIPasteboard.general.url { // Handle the URL } \`\`\` ## Important Notes - **Immediate availability**: Text is available on pasteboard immediately - **Simulator-specific**: Each simulator has its own separate pasteboard - **String only**: Only supports string data (no images, files, or custom types) - **Persistent**: Clipboard content persists until overwritten or simulator resets ## Error Handling - **Empty text**: Error if text string is empty - **Simulator not found**: Validates simulator exists in cache - **Write failure**: Reports if clipboard operation fails ## Testing Workflow 1. **Copy text**: \`simctl-pbcopy <udid> "Test text to paste"\` 2. **Launch app**: \`simctl-launch <udid> <bundleId>\` 3. **Navigate to input**: Use app to navigate to text field 4. **Test paste**: App should detect clipboard content 5. **Take screenshot**: \`simctl-io <udid> screenshot\` to verify paste ## Use Cases by Category ### Authentication Testing - Copy and paste email addresses - Copy and paste passwords (for test accounts only!) - Copy verification codes from clipboard ### URL Handling - Copy URLs and test app deep link detection - Test universal link handling from clipboard - Verify URL parameter parsing ### Data Import - Copy JSON/CSV data for import testing - Test clipboard-based data transfer - Verify data format validation ### UX Testing - Test long-press paste menu appearance - Verify paste button states - Test clipboard change notifications ## Clipboard Monitoring Some apps monitor clipboard changes. To test this: 1. Launch app first 2. Copy text to clipboard 3. App should detect and respond to clipboard change 4. Take screenshot to verify UI update ## Limitations - **String data only**: Cannot copy images, files, or custom types - **No rich text**: Only plain text is supported - **No pasteboard metadata**: Cannot set pasteboard change count or other metadata - **Simulator scope**: Clipboard is not shared with host macOS clipboard `;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/conorluddy/xc-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server