Skip to main content
Glama

Cursor MCP Server

by Buga-luga
natural-command-test.ts5.97 kB
import robot from 'robotjs' import { spawn } from 'child_process' import path from 'path' import { windowManager } from 'node-window-manager' import { parseNaturalLanguage } from '../commands/cursor-commands.js' const DEFAULT_CURSOR_PATH = path.join(process.env.LOCALAPPDATA || '', 'Programs', 'cursor', 'Cursor.exe') async function findCursorWindow(): Promise<any> { const windows = windowManager.getWindows() return windows.find(w => w.getTitle().includes('Cursor')) } async function ensureCursorFocus(cursorWindow: any): Promise<boolean> { // Get currently active window const windows = windowManager.getWindows() const activeWindow = windows.find(w => w.getTitle().includes('Cursor')) // Check if Cursor is already focused if (activeWindow) { return true } // If not focused, try to restore focus console.log('Restoring Cursor window focus...') cursorWindow.bringToTop() cursorWindow.show() cursorWindow.restore() // Wait for focus change await new Promise(resolve => setTimeout(resolve, 500)) // Verify focus was restored const newWindows = windowManager.getWindows() const newActiveWindow = newWindows.find(w => w.getTitle().includes('Cursor')) return !!newActiveWindow } async function typeText(text: string, cursorWindow: any) { for (const char of text) { // Ensure focus before each keystroke if (!await ensureCursorFocus(cursorWindow)) { console.log('Failed to maintain Cursor window focus') throw new Error('Lost window focus') } // Handle uppercase letters if (char >= 'A' && char <= 'Z') { robot.keyToggle('shift', 'down') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyTap(char.toLowerCase()) await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('shift', 'up') await new Promise(resolve => setTimeout(resolve, 50)) } // Handle special characters else if (char === ':') { robot.keyToggle('shift', 'down') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyTap(';') // On most keyboards, shift+; gives : await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('shift', 'up') await new Promise(resolve => setTimeout(resolve, 50)) } // Handle spaces else if (char === ' ') { robot.keyTap('space') await new Promise(resolve => setTimeout(resolve, 50)) } // Handle normal lowercase letters else { robot.keyTap(char) await new Promise(resolve => setTimeout(resolve, 50)) } } } async function executeCommand(naturalCommand: string) { try { console.log('Launching Cursor...') const cursorProcess = spawn(DEFAULT_CURSOR_PATH, [], { detached: false, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: false }) // Wait for Cursor to start console.log('Waiting for Cursor to initialize...') await new Promise(resolve => setTimeout(resolve, 3000)) // Find the Cursor window const cursorWindow = await findCursorWindow() if (!cursorWindow) { throw new Error('Could not find Cursor window') } // Parse the natural language command const commandRequest = parseNaturalLanguage(naturalCommand) if (!commandRequest) { throw new Error(`Could not understand command: ${naturalCommand}`) } // Initial focus console.log('Focusing Cursor window...') if (!await ensureCursorFocus(cursorWindow)) { throw new Error('Failed to focus Cursor window') } console.log('Sending Ctrl+Shift+P...') // Press Ctrl+Shift+P using robotjs robot.keyToggle('control', 'down') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('shift', 'down') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('p', 'down') await new Promise(resolve => setTimeout(resolve, 50)) // Release in reverse order with delays robot.keyToggle('p', 'up') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('shift', 'up') await new Promise(resolve => setTimeout(resolve, 50)) robot.keyToggle('control', 'up') await new Promise(resolve => setTimeout(resolve, 50)) console.log('Command palette shortcut sent!') // Wait for command palette to appear await new Promise(resolve => setTimeout(resolve, 500)) // Type the command with focus checks console.log('Typing command:', commandRequest.command) await typeText(commandRequest.command, cursorWindow) // Wait briefly after typing await new Promise(resolve => setTimeout(resolve, 500)) // Ensure focus before Enter if (!await ensureCursorFocus(cursorWindow)) { throw new Error('Lost window focus before pressing Enter') } // Press Enter console.log('Pressing Enter...') robot.keyTap('enter') // Keep process alive briefly to observe result await new Promise(resolve => setTimeout(resolve, 2000)) // Cleanup console.log('Cleaning up...') cursorProcess.kill() } catch (error) { console.error('Test failed:', error) process.exit(1) } } // Example usage const command = process.argv[2] || 'open cline' console.log('Executing natural language command:', command) executeCommand(command).catch(error => { console.error('Unhandled error:', error) process.exit(1) })

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/Buga-luga/cursor-mcp'

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