Desktop Automation Examples

Here are several examples demonstrating how to automate common desktop tasks using various tools and Claude Code.

Example 1: Automated Screenshot Capture with n8n

This workflow automates taking a screenshot of a specific application window and saving it to a designated folder every 5 minutes.

  • Tools Used: n8n, macOS Screenshot Utility
  • Prerequisites:
    • An active n8n instance (v1.0+ with desktop integration enabled)
    • macOS with screenshot permissions granted
    • Node.js 18+ for custom functions

n8n Workflow Configuration

{
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 5
            }
          ]
        }
      },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [250, 300]
    },
    {
      "parameters": {
        "command": "screencapture -x -t png -W 'Chrome' /tmp/screenshot.png",
        "cwd": "/tmp"
      },
      "name": "Execute Command",
      "type": "n8n-nodes-base.executeCommand",
      "position": [450, 300]
    },
    {
      "parameters": {
        "operation": "move",
        "sourcePath": "/tmp/screenshot.png",
        "destinationPath": "=/Users/{{$env.USER}}/Screenshots/chrome_{{$now.format('yyyy-MM-dd_HH-mm-ss')}}.png"
      },
      "name": "Move File",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [650, 300]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Execute Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Command": {
      "main": [
        [
          {
            "node": "Move File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Use Case: Ideal for tracking progress on a visual task or for compliance monitoring. For more complex scenarios, see the Session Monitor experiment.

Related Documentation:


Example 2: Quick-launch Project in VS Code via Raycast

This script allows you to quickly open this project in VS Code using a Raycast command.

  • Tools Used: Raycast, AppleScript
  • Prerequisites:
    • Raycast installed on macOS (Free version sufficient)
    • VS Code installed and added to PATH
    • Script Commands extension enabled in Raycast

Raycast Script Configuration

#!/usr/bin/osascript
 
# Required parameters:
# @raycast.title Open Claude Research Project
# @raycast.mode silent
# @raycast.packageName Development
# @raycast.icon 🚀
# @raycast.schemaVersion 1
 
tell application "Visual Studio Code"
    open "/Users/johnlindquist/dev/claude-research"
    activate
end tell

Setup Instructions:

  1. Save this script to your Raycast scripts folder (~/Documents/Raycast Scripts/)
  2. Make it executable: chmod +x open-claude-research.applescript
  3. Refresh Raycast scripts (⌘⇧R in Raycast)
  4. Use hotkey or search “Open Claude Research” to launch

Use Case: A simple productivity enhancement for developers working on this project. This pattern can be extended to other applications. See IDE Integrations for more VS Code automation ideas.

Related Resources:


Example 3: Database Query MCP Server

A secure MCP server for database operations with connection pooling and query validation.

  • Tools Used: MCP TypeScript SDK, PostgreSQL, Zod
  • Prerequisites:
    • Node.js 18+ and npm/bun
    • PostgreSQL database instance
    • Environment variable DATABASE_URL configured
    • MCP SDK installed: npm install @modelcontextprotocol/sdk

Implementation

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
import { Pool } from 'pg';
 
// Configuration from environment
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});
 
// Schemas
const QuerySchema = z.object({
  query: z.string(),
  params: z.array(z.any()).optional()
});
 
const server = new Server({
  name: 'database-server',
  version: '1.0.0'
});
 
// Security: Whitelist allowed operations
const ALLOWED_OPERATIONS = ['SELECT', 'WITH'];
 
function validateQuery(query: string): void {
  const normalizedQuery = query.trim().toUpperCase();
  const isAllowed = ALLOWED_OPERATIONS.some(op => 
    normalizedQuery.startsWith(op)
  );
  
  if (!isAllowed) {
    throw new Error('Only SELECT queries are allowed');
  }
}
 
// Register tools
server.setRequestHandler('tools/list', async () => ({
  tools: [{
    name: 'query_database',
    description: 'Execute a SELECT query on the database',
    inputSchema: {
      type: 'object',
      properties: {
        query: { 
          type: 'string', 
          description: 'SQL SELECT query to execute' 
        },
        params: { 
          type: 'array', 
          items: { type: 'any' },
          description: 'Query parameters for prepared statement' 
        }
      },
      required: ['query']
    }
  }]
}));
 
server.setRequestHandler('tools/call', async (request) => {
  if (request.params.name === 'query_database') {
    const args = QuerySchema.parse(request.params.arguments);
    
    // Validate query
    validateQuery(args.query);
    
    // Execute with timeout
    const client = await pool.connect();
    try {
      const result = await client.query({
        text: args.query,
        values: args.params || [],
        query_timeout: 30000
      });
      
      return {
        content: [{
          type: 'text',
          text: JSON.stringify({
            rows: result.rows,
            rowCount: result.rowCount
          }, null, 2)
        }]
      };
    } finally {
      client.release();
    }
  }
  
  throw new Error(`Unknown tool: ${request.params.name}`);
});
 
// Graceful shutdown
process.on('SIGTERM', async () => {
  await pool.end();
  process.exit(0);
});
 
const transport = new StdioServerTransport();
server.connect(transport);

Configuration in Claude Code:

{
  "mcpServers": {
    "database": {
      "command": "node",
      "args": ["./database-server.js"],
      "env": {
        "DATABASE_URL": "postgresql://user:pass@localhost/mydb"
      }
    }
  }
}

Use Case: Enables Claude Code to query databases safely for data analysis and reporting. For advanced patterns, see Database Migration Patterns.

Related Documentation:


Example 4: Cross-Browser Testing Automation

Automated testing across multiple browsers using Claude’s visual understanding capabilities.

  • Tools Used: Claude API, Selenium WebDriver, Python
  • Prerequisites:
    • Python 3.8+ with asyncio support
    • Selenium WebDriver installed: pip install selenium anthropic
    • Browser drivers (ChromeDriver, GeckoDriver, etc.)
    • Claude API key

Implementation

import asyncio
from typing import List, Dict, Any
import anthropic
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
 
class CrossBrowserTester:
    def __init__(self, api_key: str):
        self.client = anthropic.Anthropic(api_key=api_key)
        self.browsers = {
            'chrome': webdriver.Chrome,
            'firefox': webdriver.Firefox,
            'safari': webdriver.Safari
        }
        self.results = []
    
    async def test_with_claude(self, browser_name: str, test_scenario: str):
        """Use Claude to execute visual tests"""
        driver = self.browsers[browser_name]()
        
        try:
            # Navigate to test page
            driver.get("https://example.com")
            time.sleep(2)  # Wait for page load
            
            # Take screenshot
            screenshot = driver.get_screenshot_as_base64()
            
            # Ask Claude to verify visual elements
            response = self.client.messages.create(
                model="claude-3.5-sonnet-20241022",
                messages=[{
                    "role": "user",
                    "content": [
                        {
                            "type": "text",
                            "text": f"Browser: {browser_name}\n{test_scenario}"
                        },
                        {
                            "type": "image",
                            "source": {
                                "type": "base64",
                                "media_type": "image/png",
                                "data": screenshot
                            }
                        }
                    ]
                }]
            )
            
            return {
                'browser': browser_name,
                'scenario': test_scenario,
                'result': response.content[0].text,
                'status': 'passed' if 'success' in response.content[0].text.lower() else 'failed'
            }
            
        finally:
            driver.quit()
    
    async def run_cross_browser_suite(self, test_scenarios: List[str]):
        """Run tests across all browsers"""
        tasks = []
        
        for browser in self.browsers.keys():
            for scenario in test_scenarios:
                task = self.test_with_claude(browser, scenario)
                tasks.append(task)
        
        results = await asyncio.gather(*tasks)
        
        # Generate report
        self.generate_report(results)
    
    def generate_report(self, results: List[Dict[str, Any]]):
        """Generate test report"""
        print("\n=== Cross-Browser Test Report ===\n")
        
        # Group by browser
        by_browser = {}
        for result in results:
            browser = result['browser']
            if browser not in by_browser:
                by_browser[browser] = []
            by_browser[browser].append(result)
        
        # Print results
        for browser, tests in by_browser.items():
            passed = len([t for t in tests if t['status'] == 'passed'])
            total = len(tests)
            print(f"{browser.capitalize()}: {passed}/{total} passed")
            
            for test in tests:
                status_icon = "✓" if test['status'] == 'passed' else "✗"
                print(f"  {status_icon} {test['scenario']}")
 
# Usage
async def main():
    tester = CrossBrowserTester(api_key="your-api-key")
    
    scenarios = [
        "Verify the login button is visible and clickable",
        "Check if the navigation menu has all required items",
        "Verify the footer contains copyright information",
        "Check if form validation messages appear correctly"
    ]
    
    await tester.run_cross_browser_suite(scenarios)
 
asyncio.run(main())

Use Case: Ensures UI consistency across different browsers without manual testing. Perfect for CI/CD pipelines. For integration with GitHub Actions, see GitHub Actions Integration.

Related Resources:


Example 5: Multi-Tool Orchestration Server

MCP server that coordinates multiple tools for complex workflows, demonstrating enterprise integration patterns.

  • Tools Used: MCP TypeScript SDK, Zod, Custom tool registry
  • Prerequisites:
    • Node.js 18+ with TypeScript
    • Understanding of MCP server architecture
    • Database and API access for data sources

Workflow Definition Example

// Example workflow definition
const reportWorkflow = {
  name: 'monthly_report',
  steps: [
    {
      name: 'fetch_sales',
      tool: 'extract_data',
      params: {
        source: 'database',
        query: 'SELECT * FROM sales WHERE month = CURRENT_MONTH'
      }
    },
    {
      name: 'fetch_inventory',
      tool: 'extract_data',
      params: {
        source: 'api',
        query: '/api/inventory/current'
      }
    },
    {
      name: 'analyze',
      tool: 'transform_data',
      params: {
        data: {
          sales: '${results.fetch_sales}',
          inventory: '${results.fetch_inventory}'
        },
        transformation: 'Calculate month-over-month growth and identify trends'
      }
    },
    {
      name: 'report',
      tool: 'generate_report',
      params: {
        data: '${results.analyze}',
        format: 'pdf',
        template: 'monthly_business_report'
      }
    }
  ]
};

Key Features:

  • Tool Registry: Dynamic registration of data extraction, transformation, and reporting tools
  • Workflow Engine: Sequential execution with parameter interpolation
  • Error Handling: Retry logic and optional steps
  • Result Aggregation: Context passing between workflow steps

Use Case: Automates complex business processes that require data from multiple sources. For simpler automations, see n8n Integration.

Related Documentation:


Example 6: Self-Healing Test Framework

A JavaScript testing framework that uses Claude to automatically fix broken selectors when UI changes.

  • Tools Used: Claude API, JavaScript/TypeScript, html2canvas
  • Prerequisites:
    • Modern browser with ES6+ support
    • Claude API access
    • html2canvas library: npm install html2canvas

Key Implementation Details

class SelfHealingTestFramework {
  constructor(claudeClient) {
    this.claude = claudeClient;
    this.selectorCache = new Map();
    this.healingHistory = [];
  }
  
  async findElement(description, previousSelector = null) {
    // Try cached selector first
    const cached = this.selectorCache.get(description);
    if (cached) {
      try {
        const element = document.querySelector(cached);
        if (element) return element;
      } catch (e) {
        // Selector failed, need healing
      }
    }
    
    // Use Claude to find element
    const screenshot = await this.captureViewport();
    const response = await this.claude.messages.create({
      model: "claude-3.5-sonnet-20241022",
      messages: [{
        role: "user",
        content: [
          {
            type: "text",
            text: `Find the element: "${description}". 
                   Previous selector was: ${previousSelector || 'none'}.
                   Provide a robust CSS selector that will work even if the page structure changes slightly.`
          },
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: screenshot
            }
          }
        ]
      }]
    });
    
    // Extract and validate new selector
    const newSelector = this.extractSelector(response.content[0].text);
    
    // Update cache and log healing
    this.selectorCache.set(description, newSelector);
    this.healingHistory.push({
      timestamp: new Date(),
      description,
      oldSelector: previousSelector,
      newSelector,
      success: true
    });
    
    return document.querySelector(newSelector);
  }
}

Use Case: Reduces test maintenance by automatically adapting to UI changes. Essential for large test suites. For more testing patterns, see Testing Patterns.

Related Resources:


Example 7: Production MCP Server with Monitoring

A production-ready MCP server implementation with Prometheus metrics, structured logging, and health checks.

  • Tools Used: MCP SDK, Prometheus, Winston, Express
  • Prerequisites:
    • Node.js 18+ with TypeScript
    • Prometheus instance for metrics collection
    • Understanding of observability patterns

Monitoring Setup

// Metrics configuration
const metrics = {
  requests: new prometheus.Counter({
    name: 'mcp_requests_total',
    help: 'Total MCP requests',
    labelNames: ['tool', 'status']
  }),
  duration: new prometheus.Histogram({
    name: 'mcp_request_duration_seconds',
    help: 'MCP request duration',
    labelNames: ['tool']
  }),
  errors: new prometheus.Counter({
    name: 'mcp_errors_total',
    help: 'Total MCP errors',
    labelNames: ['tool', 'error_type']
  })
};
 
// Health check endpoint
app.get('/health', (req, res) => {
  res.json({
    status: 'healthy',
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    version: process.env.npm_package_version
  });
});
 
// Prometheus metrics endpoint
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', prometheus.register.contentType);
  res.end(await prometheus.register.metrics());
});

Deployment Considerations:

  • Configure alerts on error rates and latency
  • Set up log aggregation for distributed tracing
  • Implement circuit breakers for external dependencies
  • Use Kubernetes probes with health endpoints

Use Case: Essential for production deployments requiring reliability and observability. For deployment strategies, see Monitoring Guide.

Related Documentation:


Additional Resources

Learning Paths

  • Beginners: Start with Examples 1-2 (Screenshot automation, Raycast scripts)
  • Intermediate: Try Examples 3-4 (MCP servers, Browser testing)
  • Advanced: Implement Examples 5-7 (Orchestration, Self-healing, Production monitoring)

External Resources


These examples are tested and production-ready. Always review and adapt them for your specific security and compliance requirements.