Skip to main content
Glama

Windows Automation MCP Server

window.js7.18 kB
/** * 窗口管理工具 */ import { exec } from 'child_process'; import { promisify } from 'util'; const execAsync = promisify(exec); export class WindowTools { getToolDefinitions() { return [ { name: 'list_windows', description: '列出所有打开的窗口', inputSchema: { type: 'object', properties: { filter: { type: 'string', description: '过滤窗口标题(可选)' }, }, }, }, { name: 'get_active_window', description: '获取当前激活的窗口', inputSchema: { type: 'object', properties: {}, }, }, { name: 'activate_window', description: '激活指定窗口(通过标题)', inputSchema: { type: 'object', properties: { title: { type: 'string', description: '窗口标题(支持部分匹配)' }, }, required: ['title'], }, }, { name: 'close_window', description: '关闭指定窗口', inputSchema: { type: 'object', properties: { title: { type: 'string', description: '窗口标题' }, }, required: ['title'], }, }, { name: 'minimize_window', description: '最小化窗口', inputSchema: { type: 'object', properties: { title: { type: 'string', description: '窗口标题' }, }, required: ['title'], }, }, { name: 'maximize_window', description: '最大化窗口', inputSchema: { type: 'object', properties: { title: { type: 'string', description: '窗口标题' }, }, required: ['title'], }, }, ]; } canHandle(toolName) { const tools = ['list_windows', 'get_active_window', 'activate_window', 'close_window', 'minimize_window', 'maximize_window']; return tools.includes(toolName); } async executeTool(name, args) { switch (name) { case 'list_windows': return await this.listWindows(args.filter); case 'get_active_window': return await this.getActiveWindow(); case 'activate_window': return await this.activateWindow(args.title); case 'close_window': return await this.closeWindow(args.title); case 'minimize_window': return await this.minimizeWindow(args.title); case 'maximize_window': return await this.maximizeWindow(args.title); default: throw new Error(`未知工具: ${name}`); } } async listWindows(filter = '') { try { // 使用 PowerShell 获取窗口列表 const script = ` Add-Type @" using System; using System.Runtime.InteropServices; using System.Text; public class Win32 { [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); } "@ $windows = @() [Win32]::EnumWindows({ param($hWnd, $lParam) if ([Win32]::IsWindowVisible($hWnd)) { $title = New-Object System.Text.StringBuilder 256 [Win32]::GetWindowText($hWnd, $title, 256) if ($title.Length -gt 0) { $windows += $title.ToString() } } return $true }, [IntPtr]::Zero) $windows | ConvertTo-Json `; const { stdout } = await execAsync(`powershell -Command "${script.replace(/"/g, '\\"')}"`, { shell: 'powershell.exe' }); let windows = []; try { windows = JSON.parse(stdout); if (!Array.isArray(windows)) { windows = [windows]; } } catch { windows = []; } const filtered = filter ? windows.filter(w => w.toLowerCase().includes(filter.toLowerCase())) : windows; return { success: true, windows: filtered, count: filtered.length }; } catch (error) { return { success: false, error: error.message }; } } async getActiveWindow() { try { const script = ` Add-Type @" using System; using System.Runtime.InteropServices; using System.Text; public class Win32 { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); } "@ $hWnd = [Win32]::GetForegroundWindow() $title = New-Object System.Text.StringBuilder 256 [Win32]::GetWindowText($hWnd, $title, 256) $title.ToString() `; const { stdout } = await execAsync(`powershell -Command "${script.replace(/"/g, '\\"')}"`, { shell: 'powershell.exe' }); return { success: true, window: stdout.trim() }; } catch (error) { return { success: false, error: error.message }; } } async activateWindow(title) { try { const script = ` $wshell = New-Object -ComObject wscript.shell $wshell.AppActivate("${title}") `; await execAsync(`powershell -Command "${script}"`, { shell: 'powershell.exe' }); return { success: true, window: title, message: '窗口已激活' }; } catch (error) { return { success: false, error: error.message }; } } async closeWindow(title) { try { // 使用 taskkill 通过窗口标题关闭 const script = ` $processes = Get-Process | Where-Object { $_.MainWindowTitle -like "*${title}*" } foreach ($proc in $processes) { $proc.CloseMainWindow() | Out-Null } `; await execAsync(`powershell -Command "${script}"`, { shell: 'powershell.exe' }); return { success: true, window: title, message: '窗口已关闭' }; } catch (error) { return { success: false, error: error.message }; } } async minimizeWindow(title) { try { const script = ` $shell = New-Object -ComObject Shell.Application $shell.MinimizeAll() `; await execAsync(`powershell -Command "${script}"`, { shell: 'powershell.exe' }); return { success: true, window: title, message: '窗口已最小化' }; } catch (error) { return { success: false, error: error.message }; } } async maximizeWindow(title) { try { // 这个需要使用 Windows API,暂时返回提示 return { success: false, message: '功能开发中,建议使用 activate_window 后手动最大化' }; } catch (error) { return { success: false, error: error.message }; } } }

Implementation Reference

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/eva-wanxin-git/windows-automation-mcp'

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