From 4f0664bdfa2c53727d206d2ace12963f9f8bbf80 Mon Sep 17 00:00:00 2001 From: Jonathan Flatt Date: Sun, 18 May 2025 10:48:41 -0500 Subject: [PATCH 1/2] Make AutoHotkey the default provider and update documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change default provider from keysender to autohotkey - Update environment variable examples to PowerShell syntax - Move keysender to optionalDependencies - Update documentation to reflect keysender as optional - Clarify that build tools are only needed for keysender provider 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 28 ++++++++++++++-------------- package.json | 4 +++- src/config.ts | 5 +++-- src/index.ts | 2 +- src/providers/factory.ts | 10 +++++----- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index e9fd7ae..52fd698 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ To launch MCPControl locally with SSE transport: First, start the MCPControl server on your VM or local machine: -```bash +```powershell mcp-control --sse ``` @@ -238,30 +238,30 @@ By using this software, you acknowledge and accept that: MCPControl supports multiple automation providers for different use cases: -- **keysender** (default) - Native Windows automation with high reliability +- **autohotkey** (default) - AutoHotkey v2 scripting for advanced automation needs +- **keysender** - Native Windows automation with high reliability (optional) - **powershell** - Windows PowerShell-based automation for simpler operations -- **autohotkey** - AutoHotkey v2 scripting for advanced automation needs ### Provider Configuration You can configure the automation provider using environment variables: -```bash +```powershell # Use a specific provider for all operations -export AUTOMATION_PROVIDER=autohotkey +$env:AUTOMATION_PROVIDER = "autohotkey" # Configure AutoHotkey executable path (if not in PATH) -export AUTOHOTKEY_PATH="C:\Program Files\AutoHotkey\v2\AutoHotkey.exe" +$env:AUTOHOTKEY_PATH = "C:\Program Files\AutoHotkey\v2\AutoHotkey.exe" ``` Or use modular configuration for specific operations: -```bash +```powershell # Mix and match providers for different operations -export AUTOMATION_KEYBOARD_PROVIDER=autohotkey -export AUTOMATION_MOUSE_PROVIDER=keysender -export AUTOMATION_SCREEN_PROVIDER=keysender -export AUTOMATION_CLIPBOARD_PROVIDER=powershell +$env:AUTOMATION_KEYBOARD_PROVIDER = "autohotkey" +$env:AUTOMATION_MOUSE_PROVIDER = "autohotkey" +$env:AUTOMATION_SCREEN_PROVIDER = "autohotkey" +$env:AUTOMATION_CLIPBOARD_PROVIDER = "powershell" ``` See provider-specific documentation: @@ -275,14 +275,14 @@ If you're interested in contributing or building from source, please see [CONTRI To build this project for development, you'll need: -1. Windows operating system (required for the keysender dependency) +1. Windows operating system 2. Node.js 18 or later (install using the official Windows installer which includes build tools) 3. npm package manager -4. Native build tools: +4. Native build tools (optional, only needed if using the keysender provider): - node-gyp: `npm install -g node-gyp` - cmake-js: `npm install -g cmake-js` -The keysender dependency relies on Windows-specific native modules that require these build tools. +The keysender provider is optional and relies on Windows-specific native modules that require these build tools. If you don't need keysender, you can skip installing the build tools. ## 📋 Project Structure diff --git a/package.json b/package.json index 1a009d2..50c2171 100644 --- a/package.json +++ b/package.json @@ -23,12 +23,14 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.11.2", "clipboardy": "^4.0.0", - "keysender": "^2.3.0", "sharp": "^0.34.1", "ulid": "^3.0.0", "uuid": "^11.1.0", "zod": "^3.24.4" }, + "optionalDependencies": { + "keysender": "^2.3.0" + }, "devDependencies": { "@eslint/js": "^9.25.0", "@types/express": "^5.0.1", diff --git a/src/config.ts b/src/config.ts index edaf473..e140de2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,7 +4,8 @@ export interface AutomationConfig { /** * Legacy: The provider to use for all automation - * Currently supported: 'keysender' + * Currently supported: 'keysender', 'autohotkey' + * Default: 'autohotkey' */ provider?: string; @@ -43,6 +44,6 @@ export function loadConfig(): AutomationConfig { // Fall back to legacy configuration return { - provider: process.env.AUTOMATION_PROVIDER || 'keysender', + provider: process.env.AUTOMATION_PROVIDER || 'autohotkey', }; } diff --git a/src/index.ts b/src/index.ts index 74cf1a2..13e00f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,7 +49,7 @@ class MCPControlServer { } // Validate that the provider is supported - const supportedProviders = ['keysender']; // add others as they become available + const supportedProviders = ['keysender', 'autohotkey']; // add others as they become available if (!supportedProviders.includes(config.provider.toLowerCase())) { throw new Error( `Unsupported provider: ${config.provider}. Supported providers: ${supportedProviders.join(', ')}`, diff --git a/src/providers/factory.ts b/src/providers/factory.ts index 6ff7976..bf3e2fa 100644 --- a/src/providers/factory.ts +++ b/src/providers/factory.ts @@ -72,7 +72,7 @@ export function createAutomationProvider(config?: AutomationConfig): AutomationP if (!config || !config.providers) { // Legacy behavior: use monolithic provider - const type = config?.provider || 'keysender'; + const type = config?.provider || 'autohotkey'; const providerType = type.toLowerCase(); // Return cached instance if available @@ -106,19 +106,19 @@ export function createAutomationProvider(config?: AutomationConfig): AutomationP // Get individual components from the registry const keyboardProvider = config.providers.keyboard ? registry.getKeyboard(config.providers.keyboard) - : new KeysenderProvider().keyboard; + : new AutoHotkeyProvider().keyboard; const mouseProvider = config.providers.mouse ? registry.getMouse(config.providers.mouse) - : new KeysenderProvider().mouse; + : new AutoHotkeyProvider().mouse; const screenProvider = config.providers.screen ? registry.getScreen(config.providers.screen) - : new KeysenderProvider().screen; + : new AutoHotkeyProvider().screen; const clipboardProvider = config.providers.clipboard ? registry.getClipboard(config.providers.clipboard) - : new KeysenderProvider().clipboard; + : new AutoHotkeyProvider().clipboard; if (!keyboardProvider || !mouseProvider || !screenProvider || !clipboardProvider) { throw new Error('Failed to resolve all provider components'); From deb5e73e2ce7947f88a914e9cd35c5e7269780ca Mon Sep 17 00:00:00 2001 From: Jonathan Flatt Date: Sun, 18 May 2025 11:27:25 -0500 Subject: [PATCH 2/2] fix: Update factory tests to reflect AutoHotkey as default provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated provider factory tests to expect AutoHotkey as the default provider instead of Keysender. Added necessary mocks and test cases for AutoHotkey provider to ensure test suite passes with the new default. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/providers/factory.test.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/providers/factory.test.ts b/src/providers/factory.test.ts index 2b07c4d..ef1885e 100644 --- a/src/providers/factory.test.ts +++ b/src/providers/factory.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, vi } from 'vitest'; import { createAutomationProvider } from './factory.js'; import { KeysenderProvider } from './keysender/index.js'; +import { AutoHotkeyProvider } from './autohotkey/index.js'; // Mock the providers vi.mock('./keysender/index.js', () => { @@ -14,10 +15,21 @@ vi.mock('./keysender/index.js', () => { }; }); +vi.mock('./autohotkey/index.js', () => { + return { + AutoHotkeyProvider: vi.fn().mockImplementation(() => ({ + keyboard: {}, + mouse: {}, + screen: {}, + clipboard: {}, + })), + }; +}); + describe('createAutomationProvider', () => { - it('should create KeysenderProvider by default', () => { + it('should create AutoHotkeyProvider by default', () => { const provider = createAutomationProvider(); - expect(KeysenderProvider).toHaveBeenCalled(); + expect(AutoHotkeyProvider).toHaveBeenCalled(); expect(provider).toBeDefined(); }); @@ -27,12 +39,24 @@ describe('createAutomationProvider', () => { expect(provider).toBeDefined(); }); + it('should create AutoHotkeyProvider when explicitly specified', () => { + const provider = createAutomationProvider({ provider: 'autohotkey' }); + expect(AutoHotkeyProvider).toHaveBeenCalled(); + expect(provider).toBeDefined(); + }); + it('should be case insensitive for KeysenderProvider', () => { const provider = createAutomationProvider({ provider: 'KeYsEnDeR' }); expect(KeysenderProvider).toHaveBeenCalled(); expect(provider).toBeDefined(); }); + it('should be case insensitive for AutoHotkeyProvider', () => { + const provider = createAutomationProvider({ provider: 'AuToHoTkEy' }); + expect(AutoHotkeyProvider).toHaveBeenCalled(); + expect(provider).toBeDefined(); + }); + it('should throw error for unknown provider type', () => { expect(() => createAutomationProvider({ provider: 'unknown' })).toThrow( 'Unknown provider type: unknown',