sweetspot-remote-agent 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mcp-server.js +119 -106
- package/package.json +1 -1
package/mcp-server.js
CHANGED
|
@@ -17,109 +17,116 @@ import { click, doubleClick, typeText, pressKey, hotkey, scroll } from "./lib/in
|
|
|
17
17
|
import { openApp, openUrl, listApps, closeApp, focusApp, getClipboard, setClipboard } from "./lib/apps.mjs";
|
|
18
18
|
import { runCommand, getSystemInfo } from "./lib/shell.mjs";
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
scroll
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
20
|
+
/**
|
|
21
|
+
* 도구를 등록한 McpServer 인스턴스를 생성
|
|
22
|
+
*/
|
|
23
|
+
function createServer() {
|
|
24
|
+
const srv = new McpServer({
|
|
25
|
+
name: "sweetspot-remote-agent",
|
|
26
|
+
version: "1.0.0",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// ── 스크린샷 ──
|
|
30
|
+
srv.tool("screenshot", "화면 스크린샷을 찍어 base64 PNG로 반환", {}, async () => {
|
|
31
|
+
const buf = await screenshot({ format: "png" });
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "image", data: buf.toString("base64"), mimeType: "image/png" }],
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// ── 마우스 ──
|
|
38
|
+
srv.tool("click", "마우스 클릭", { x: z.number().describe("X 좌표"), y: z.number().describe("Y 좌표") }, async ({ x, y }) => {
|
|
39
|
+
click(x, y);
|
|
40
|
+
return { content: [{ type: "text", text: `클릭 (${x}, ${y}) 완료` }] };
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
srv.tool("doubleclick", "마우스 더블 클릭", { x: z.number(), y: z.number() }, async ({ x, y }) => {
|
|
44
|
+
doubleClick(x, y);
|
|
45
|
+
return { content: [{ type: "text", text: `더블클릭 (${x}, ${y}) 완료` }] };
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
srv.tool("scroll", "마우스 스크롤", {
|
|
49
|
+
direction: z.enum(["up", "down"]).describe("방향"),
|
|
50
|
+
amount: z.number().default(3).describe("스크롤 양"),
|
|
51
|
+
}, async ({ direction, amount }) => {
|
|
52
|
+
scroll(direction, amount);
|
|
53
|
+
return { content: [{ type: "text", text: `스크롤 ${direction} ${amount} 완료` }] };
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ── 키보드 ──
|
|
57
|
+
srv.tool("type", "텍스트 입력 (키보드 타이핑)", { text: z.string().describe("입력할 텍스트") }, async ({ text }) => {
|
|
58
|
+
typeText(text);
|
|
59
|
+
return { content: [{ type: "text", text: `입력 완료: "${text}"` }] };
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
srv.tool("key", "특수키 입력 (enter, tab, escape, backspace, delete, up, down, left, right, space)", {
|
|
63
|
+
key: z.string().describe("키 이름"),
|
|
64
|
+
}, async ({ key }) => {
|
|
65
|
+
pressKey(key);
|
|
66
|
+
return { content: [{ type: "text", text: `키 ${key} 완료` }] };
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
srv.tool("hotkey", "단축키 실행 (예: cmd+c, ctrl+v, alt+tab)", {
|
|
70
|
+
keys: z.string().describe("단축키 조합 (예: cmd+c)"),
|
|
71
|
+
}, async ({ keys }) => {
|
|
72
|
+
hotkey(keys);
|
|
73
|
+
return { content: [{ type: "text", text: `단축키 ${keys} 완료` }] };
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// ── 앱 제어 ──
|
|
77
|
+
srv.tool("open_app", "앱 실행", { app: z.string().describe("앱 이름 (예: Chrome, Slack, Excel)") }, async ({ app }) => {
|
|
78
|
+
openApp(app);
|
|
79
|
+
return { content: [{ type: "text", text: `${app} 실행 완료` }] };
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
srv.tool("close_app", "앱 종료", { app: z.string().describe("앱 이름") }, async ({ app }) => {
|
|
83
|
+
closeApp(app);
|
|
84
|
+
return { content: [{ type: "text", text: `${app} 종료 완료` }] };
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
srv.tool("focus_app", "앱으로 포커스 전환", { app: z.string().describe("앱 이름") }, async ({ app }) => {
|
|
88
|
+
focusApp(app);
|
|
89
|
+
return { content: [{ type: "text", text: `${app} 포커스 완료` }] };
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
srv.tool("list_apps", "실행 중인 앱 목록 조회", {}, async () => {
|
|
93
|
+
const apps = listApps();
|
|
94
|
+
return { content: [{ type: "text", text: apps }] };
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
srv.tool("open_url", "URL을 기본 브라우저로 열기", { url: z.string().describe("URL") }, async ({ url }) => {
|
|
98
|
+
openUrl(url);
|
|
99
|
+
return { content: [{ type: "text", text: `${url} 열기 완료` }] };
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ── 클립보드 ──
|
|
103
|
+
srv.tool("get_clipboard", "클립보드 내용 읽기", {}, async () => {
|
|
104
|
+
const text = getClipboard();
|
|
105
|
+
return { content: [{ type: "text", text: text || "(빈 클립보드)" }] };
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
srv.tool("set_clipboard", "클립보드에 텍스트 복사", { text: z.string() }, async ({ text }) => {
|
|
109
|
+
setClipboard(text);
|
|
110
|
+
return { content: [{ type: "text", text: "클립보드에 복사 완료" }] };
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// ── 셸 명령 ──
|
|
114
|
+
srv.tool("shell", "셸 명령 실행 (보안 필터링 적용)", {
|
|
115
|
+
cmd: z.string().describe("실행할 명령어"),
|
|
116
|
+
timeout: z.number().default(30000).describe("타임아웃 (ms)"),
|
|
117
|
+
}, async ({ cmd, timeout }) => {
|
|
118
|
+
const output = runCommand(cmd, timeout);
|
|
119
|
+
return { content: [{ type: "text", text: output || "(출력 없음)" }] };
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ── 시스템 정보 ──
|
|
123
|
+
srv.tool("sysinfo", "시스템 정보 조회 (OS, CPU, 메모리 등)", {}, async () => {
|
|
124
|
+
const info = getSystemInfo();
|
|
125
|
+
return { content: [{ type: "text", text: JSON.stringify(info, null, 2) }] };
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return srv;
|
|
129
|
+
}
|
|
123
130
|
|
|
124
131
|
// ── 서버 시작 ──
|
|
125
132
|
const args = process.argv.slice(2);
|
|
@@ -169,7 +176,10 @@ async function autoRegister() {
|
|
|
169
176
|
try {
|
|
170
177
|
const res = await fetch(`${BOT_SERVER}/register`, {
|
|
171
178
|
method: "POST",
|
|
172
|
-
headers: {
|
|
179
|
+
headers: {
|
|
180
|
+
"Content-Type": "application/json",
|
|
181
|
+
"ngrok-skip-browser-warning": "true",
|
|
182
|
+
},
|
|
173
183
|
body: JSON.stringify({ name: regName, agentUrl }),
|
|
174
184
|
});
|
|
175
185
|
const data = await res.json();
|
|
@@ -200,10 +210,12 @@ async function main() {
|
|
|
200
210
|
const transport = new StreamableHTTPServerTransport({
|
|
201
211
|
sessionIdGenerator: () => crypto.randomUUID(),
|
|
202
212
|
});
|
|
213
|
+
// 세션마다 새 McpServer 인스턴스 생성 (멀티세션 지원)
|
|
214
|
+
const sessionServer = createServer();
|
|
203
215
|
transport.onclose = () => {
|
|
204
216
|
if (transport.sessionId) transports.delete(transport.sessionId);
|
|
205
217
|
};
|
|
206
|
-
await
|
|
218
|
+
await sessionServer.connect(transport);
|
|
207
219
|
await transport.handleRequest(req, res, req.body);
|
|
208
220
|
if (transport.sessionId) transports.set(transport.sessionId, transport);
|
|
209
221
|
return;
|
|
@@ -225,8 +237,9 @@ async function main() {
|
|
|
225
237
|
});
|
|
226
238
|
} else {
|
|
227
239
|
// stdio 모드: 로컬 사용
|
|
240
|
+
const stdioServer = createServer();
|
|
228
241
|
const transport = new StdioServerTransport();
|
|
229
|
-
await
|
|
242
|
+
await stdioServer.connect(transport);
|
|
230
243
|
console.error("[remote-agent] MCP 서버 시작 (stdio)");
|
|
231
244
|
}
|
|
232
245
|
}
|