Skip to main content
Glama

Cursor MCP Server

by johnneerdael
windows-manager.ts5.6 kB
import { WindowManager, WindowInfo, WindowEvent } from './types.js' import { windowManager } from 'node-window-manager' import robot from 'robotjs' import { EventEmitter } from 'events' export class WindowsWindowManager implements WindowManager { private eventEmitter = new EventEmitter() private windowCache = new Map<number, WindowInfo>() private convertToWindowInfo(nativeWindow: any): WindowInfo { const cached = this.windowCache.get(nativeWindow.processId) if (cached) return cached const windowInfo: WindowInfo = { id: nativeWindow.handle, title: nativeWindow.getTitle(), processId: nativeWindow.processId, bounds: { x: nativeWindow.getBounds().x, y: nativeWindow.getBounds().y, width: nativeWindow.getBounds().width, height: nativeWindow.getBounds().height } } this.windowCache.set(nativeWindow.processId, windowInfo) return windowInfo } async getActiveWindow(): Promise<WindowInfo | null> { try { const windows = windowManager.getWindows() const activeWindow = windows.find(w => w.getTitle() === windowManager.getActiveWindow()?.getTitle()) return activeWindow ? this.convertToWindowInfo(activeWindow) : null } catch (error) { console.error('Error getting active window:', error) return null } } async getAllWindows(): Promise<WindowInfo[]> { try { const windows = windowManager.getWindows() return windows.map(w => this.convertToWindowInfo(w)) } catch (error) { console.error('Error getting all windows:', error) return [] } } async findWindowByTitle(title: string): Promise<WindowInfo | null> { try { const windows = windowManager.getWindows() const window = windows.find(w => w.getTitle().includes(title)) return window ? this.convertToWindowInfo(window) : null } catch (error) { console.error('Error finding window by title:', error) return null } } async findWindowByProcessId(processId: number): Promise<WindowInfo | null> { try { const windows = windowManager.getWindows() const window = windows.find(w => w.processId === processId) return window ? this.convertToWindowInfo(window) : null } catch (error) { console.error('Error finding window by process ID:', error) return null } } async focusWindow(windowInfo: WindowInfo): Promise<boolean> { try { const windows = windowManager.getWindows() const window = windows.find(w => w.processId === windowInfo.processId) if (!window) return false window.bringToTop() window.show() window.restore() // Wait for focus change await new Promise(resolve => setTimeout(resolve, 500)) // Verify focus const activeWindow = await this.getActiveWindow() return activeWindow?.processId === windowInfo.processId } catch (error) { console.error('Error focusing window:', error) return false } } async closeWindow(windowInfo: WindowInfo): Promise<boolean> { try { const windows = windowManager.getWindows() const window = windows.find(w => w.processId === windowInfo.processId) if (!window) return false // Send Alt+F4 to close the window since there's no direct close method await this.sendKeys(windowInfo, ['alt', 'f4']) return true } catch (error) { console.error('Error closing window:', error) return false } } async isWindowResponding(windowInfo: WindowInfo): Promise<boolean> { try { const windows = windowManager.getWindows() const window = windows.find(w => w.processId === windowInfo.processId) return !!window && window.getTitle().length > 0 } catch (error) { console.error('Error checking window response:', error) return false } } on(event: WindowEvent['type'], callback: (event: WindowEvent) => void): void { this.eventEmitter.on(event, callback) } off(event: WindowEvent['type'], callback: (event: WindowEvent) => void): void { this.eventEmitter.off(event, callback) } async sendKeys(windowInfo: WindowInfo, keys: string[]): Promise<void> { try { await this.focusWindow(windowInfo) for (const key of keys) { robot.keyToggle(key.toLowerCase(), 'down') await new Promise(resolve => setTimeout(resolve, 30)) robot.keyToggle(key.toLowerCase(), 'up') await new Promise(resolve => setTimeout(resolve, 30)) } } catch (error) { console.error('Error sending keys:', error) throw error } } async sendMouseClick(x: number, y: number, button: 'left' | 'right' = 'left'): Promise<void> { try { robot.moveMouse(x, y) robot.mouseClick(button) } catch (error) { console.error('Error sending mouse click:', error) throw error } } getPlatformSpecificApi(): any { return windowManager } }

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/johnneerdael/multiplatform-cursor-mcp'

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