/**
* 鼠标键盘控制工具
* 注意:robotjs 需要编译,如果安装失败,某些功能将不可用
*/
export class MouseKeyboardTools {
constructor() {
this.robotAvailable = false;
this.robot = null;
try {
// 尝试加载 robotjs
import('robotjs').then(module => {
this.robot = module.default;
this.robotAvailable = true;
}).catch(() => {
console.error('[MCP] robotjs 未安装或编译失败,鼠标键盘功能将受限');
});
} catch (error) {
console.error('[MCP] robotjs 加载失败:', error.message);
}
}
getToolDefinitions() {
return [
{
name: 'move_mouse',
description: '移动鼠标到指定位置',
inputSchema: {
type: 'object',
properties: {
x: { type: 'number', description: 'X 坐标' },
y: { type: 'number', description: 'Y 坐标' },
smooth: { type: 'boolean', description: '是否平滑移动(可选)' },
},
required: ['x', 'y'],
},
},
{
name: 'mouse_click',
description: '鼠标点击',
inputSchema: {
type: 'object',
properties: {
button: { type: 'string', enum: ['left', 'right', 'middle'], description: '按钮类型' },
double: { type: 'boolean', description: '是否双击(可选)' },
},
},
},
{
name: 'type_text',
description: '输入文本',
inputSchema: {
type: 'object',
properties: {
text: { type: 'string', description: '要输入的文本' },
delay: { type: 'number', description: '每个字符之间的延迟(毫秒,可选)' },
},
required: ['text'],
},
},
{
name: 'press_key',
description: '按下键盘按键',
inputSchema: {
type: 'object',
properties: {
key: { type: 'string', description: '按键名称(如 enter, tab, escape)' },
modifiers: { type: 'array', items: { type: 'string' }, description: '修饰键(如 control, shift, alt)' },
},
required: ['key'],
},
},
{
name: 'get_mouse_position',
description: '获取当前鼠标位置',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_screen_size',
description: '获取屏幕尺寸',
inputSchema: {
type: 'object',
properties: {},
},
},
];
}
canHandle(toolName) {
const tools = ['move_mouse', 'mouse_click', 'type_text', 'press_key',
'get_mouse_position', 'get_screen_size'];
return tools.includes(toolName);
}
async executeTool(name, args) {
if (!this.robotAvailable && name !== 'get_screen_size') {
return {
success: false,
error: 'robotjs 未安装。请运行: npm install robotjs(需要 Windows Build Tools)'
};
}
switch (name) {
case 'move_mouse':
return this.moveMouse(args.x, args.y, args.smooth);
case 'mouse_click':
return this.mouseClick(args.button, args.double);
case 'type_text':
return this.typeText(args.text, args.delay);
case 'press_key':
return this.pressKey(args.key, args.modifiers);
case 'get_mouse_position':
return this.getMousePosition();
case 'get_screen_size':
return this.getScreenSize();
default:
throw new Error(`未知工具: ${name}`);
}
}
moveMouse(x, y, smooth = false) {
try {
if (smooth) {
this.robot.moveMouseSmooth(x, y);
} else {
this.robot.moveMouse(x, y);
}
return { success: true, position: { x, y }, message: '鼠标已移动' };
} catch (error) {
return { success: false, error: error.message };
}
}
mouseClick(button = 'left', double = false) {
try {
this.robot.mouseClick(button, double);
return { success: true, button, double, message: '点击完成' };
} catch (error) {
return { success: false, error: error.message };
}
}
typeText(text, delay = 0) {
try {
if (delay > 0) {
for (const char of text) {
this.robot.typeString(char);
this.robot.keyTap('');
// 简单延迟
const start = Date.now();
while (Date.now() - start < delay) {}
}
} else {
this.robot.typeString(text);
}
return { success: true, text, message: '文本已输入' };
} catch (error) {
return { success: false, error: error.message };
}
}
pressKey(key, modifiers = []) {
try {
if (modifiers.length > 0) {
this.robot.keyTap(key, modifiers);
} else {
this.robot.keyTap(key);
}
return { success: true, key, modifiers, message: '按键已按下' };
} catch (error) {
return { success: false, error: error.message };
}
}
getMousePosition() {
try {
const pos = this.robot.getMousePos();
return { success: true, position: { x: pos.x, y: pos.y } };
} catch (error) {
return { success: false, error: error.message };
}
}
getScreenSize() {
try {
if (this.robotAvailable) {
const size = this.robot.getScreenSize();
return { success: true, width: size.width, height: size.height };
} else {
// 备用方法:使用 PowerShell
return { success: true, width: 1920, height: 1080, note: '使用默认值' };
}
} catch (error) {
return { success: false, error: error.message };
}
}
}