@beeos-ai/device-mcp-server 0.2.3
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/LICENSE +201 -0
- package/dist/backends/android-adb-runner.d.ts +32 -0
- package/dist/backends/android-adb-runner.js +15 -0
- package/dist/backends/android-adb-runner.js.map +1 -0
- package/dist/backends/android-adb.d.ts +153 -0
- package/dist/backends/android-adb.js +723 -0
- package/dist/backends/android-adb.js.map +1 -0
- package/dist/backends/base.d.ts +150 -0
- package/dist/backends/base.js +116 -0
- package/dist/backends/base.js.map +1 -0
- package/dist/backends/desktop.d.ts +62 -0
- package/dist/backends/desktop.js +176 -0
- package/dist/backends/desktop.js.map +1 -0
- package/dist/backends/index.d.ts +63 -0
- package/dist/backends/index.js +105 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/linux.d.ts +69 -0
- package/dist/backends/linux.js +230 -0
- package/dist/backends/linux.js.map +1 -0
- package/dist/backends/mac.d.ts +154 -0
- package/dist/backends/mac.js +881 -0
- package/dist/backends/mac.js.map +1 -0
- package/dist/backends/stubs/ios.d.ts +17 -0
- package/dist/backends/stubs/ios.js +32 -0
- package/dist/backends/stubs/ios.js.map +1 -0
- package/dist/backends/stubs/macos.d.ts +13 -0
- package/dist/backends/stubs/macos.js +27 -0
- package/dist/backends/stubs/macos.js.map +1 -0
- package/dist/backends/stubs/windows.d.ts +69 -0
- package/dist/backends/stubs/windows.js +191 -0
- package/dist/backends/stubs/windows.js.map +1 -0
- package/dist/cli.d.ts +37 -0
- package/dist/cli.js +177 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/server/action-mapping.d.ts +21 -0
- package/dist/server/action-mapping.js +153 -0
- package/dist/server/action-mapping.js.map +1 -0
- package/dist/server/app.d.ts +23 -0
- package/dist/server/app.js +157 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/tool-registry.d.ts +50 -0
- package/dist/server/tool-registry.js +504 -0
- package/dist/server/tool-registry.js.map +1 -0
- package/dist/util/adb-files.d.ts +92 -0
- package/dist/util/adb-files.js +221 -0
- package/dist/util/adb-files.js.map +1 -0
- package/dist/util/adb-shell.d.ts +80 -0
- package/dist/util/adb-shell.js +102 -0
- package/dist/util/adb-shell.js.map +1 -0
- package/dist/util/android-apps.d.ts +10 -0
- package/dist/util/android-apps.js +103 -0
- package/dist/util/android-apps.js.map +1 -0
- package/dist/util/image-dim.d.ts +27 -0
- package/dist/util/image-dim.js +37 -0
- package/dist/util/image-dim.js.map +1 -0
- package/dist/util/ui-xml.d.ts +20 -0
- package/dist/util/ui-xml.js +184 -0
- package/dist/util/ui-xml.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool registry — verbs exposed by the device sandbox.
|
|
3
|
+
*
|
|
4
|
+
* Each tool entry carries:
|
|
5
|
+
* - a name (the MCP tool identifier, e.g. `click`)
|
|
6
|
+
* - a JSON schema describing the expected `arguments` payload
|
|
7
|
+
* - a `handler` that maps `arguments` → `SandboxBackend` method call.
|
|
8
|
+
*
|
|
9
|
+
* Filtering is driven entirely by `backend.tools` (a flat
|
|
10
|
+
* `ReadonlySet<string>` declared on each backend). The registry is
|
|
11
|
+
* purely a name → schema/handler lookup table; it does not encode
|
|
12
|
+
* support gates of its own. `listToolDescriptorsFor(backend)` filters
|
|
13
|
+
* via `backend.tools.has(name)`; `getToolFor(name, backend)` mirrors
|
|
14
|
+
* the same gate so `/mcp/tools/call` returns 404 (instead of 200 +
|
|
15
|
+
* runtime `unsupported`) for any tool the active backend doesn't
|
|
16
|
+
* advertise.
|
|
17
|
+
*
|
|
18
|
+
* Inspired by the Python `mcp_tools/registry.py` reference; verbs are kept
|
|
19
|
+
* verbatim for cross-runtime compatibility.
|
|
20
|
+
*/
|
|
21
|
+
import { formatUiXmlToolOutput } from "../util/ui-xml.js";
|
|
22
|
+
/* ----------------------------------------------------------------------- */
|
|
23
|
+
/* Helpers */
|
|
24
|
+
/* ----------------------------------------------------------------------- */
|
|
25
|
+
function n(args, key) {
|
|
26
|
+
const v = args[key];
|
|
27
|
+
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
28
|
+
throw new TypeError(`argument '${key}' must be a finite number`);
|
|
29
|
+
}
|
|
30
|
+
return v;
|
|
31
|
+
}
|
|
32
|
+
function s(args, key) {
|
|
33
|
+
const v = args[key];
|
|
34
|
+
if (typeof v !== "string") {
|
|
35
|
+
throw new TypeError(`argument '${key}' must be a string`);
|
|
36
|
+
}
|
|
37
|
+
return v;
|
|
38
|
+
}
|
|
39
|
+
function optS(args, key) {
|
|
40
|
+
const v = args[key];
|
|
41
|
+
if (v === undefined || v === null)
|
|
42
|
+
return undefined;
|
|
43
|
+
if (typeof v !== "string")
|
|
44
|
+
throw new TypeError(`argument '${key}' must be a string`);
|
|
45
|
+
return v;
|
|
46
|
+
}
|
|
47
|
+
function optN(args, key) {
|
|
48
|
+
const v = args[key];
|
|
49
|
+
if (v === undefined || v === null)
|
|
50
|
+
return undefined;
|
|
51
|
+
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
52
|
+
throw new TypeError(`argument '${key}' must be a finite number`);
|
|
53
|
+
}
|
|
54
|
+
return v;
|
|
55
|
+
}
|
|
56
|
+
const xy = {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
x: { type: "number" },
|
|
60
|
+
y: { type: "number" },
|
|
61
|
+
},
|
|
62
|
+
required: ["x", "y"],
|
|
63
|
+
};
|
|
64
|
+
/* ----------------------------------------------------------------------- */
|
|
65
|
+
/* Tool definitions */
|
|
66
|
+
/* ----------------------------------------------------------------------- */
|
|
67
|
+
export const TOOLS = {
|
|
68
|
+
/* — observation — */
|
|
69
|
+
screenshot: {
|
|
70
|
+
descriptor: {
|
|
71
|
+
name: "screenshot",
|
|
72
|
+
description: "Capture a screenshot. Returns base64 image bytes plus actual " +
|
|
73
|
+
"image dimensions (width/height) and click coordinate-system " +
|
|
74
|
+
"dimensions (deviceWidth/deviceHeight).",
|
|
75
|
+
inputSchema: { type: "object", properties: {} },
|
|
76
|
+
},
|
|
77
|
+
handler: async (_args, { backend }) => {
|
|
78
|
+
// 0.2.3 split: `width/height` reflect the actual encoded bytes
|
|
79
|
+
// (so an agent that decodes `b64` always agrees with these
|
|
80
|
+
// numbers), while `deviceWidth/deviceHeight` carry the click
|
|
81
|
+
// coordinate-system size used by `tap(x, y)` / `click(x, y)`.
|
|
82
|
+
const shot = await backend.screenshot();
|
|
83
|
+
const size = await backend
|
|
84
|
+
.screenSize()
|
|
85
|
+
.catch(() => ({ w: shot.width, h: shot.height }));
|
|
86
|
+
return {
|
|
87
|
+
b64: shot.data.toString("base64"),
|
|
88
|
+
format: shot.format,
|
|
89
|
+
width: shot.width,
|
|
90
|
+
height: shot.height,
|
|
91
|
+
deviceWidth: size.w,
|
|
92
|
+
deviceHeight: size.h,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
ui_dump: {
|
|
97
|
+
descriptor: {
|
|
98
|
+
name: "ui_dump",
|
|
99
|
+
description: "Dump the active UI hierarchy. Optional `query` filters nodes server-side.",
|
|
100
|
+
inputSchema: {
|
|
101
|
+
type: "object",
|
|
102
|
+
properties: {
|
|
103
|
+
query: { type: "string" },
|
|
104
|
+
format: { type: "string", enum: ["compact", "raw"] },
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
handler: async (args, { backend }) => {
|
|
109
|
+
const out = await backend.uiDump();
|
|
110
|
+
if (!out.supported)
|
|
111
|
+
return { supported: false };
|
|
112
|
+
const fmt = optS(args, "format") ?? "compact";
|
|
113
|
+
const query = optS(args, "query");
|
|
114
|
+
if (fmt === "raw")
|
|
115
|
+
return { supported: true, content: out.content ?? "" };
|
|
116
|
+
const compact = formatUiXmlToolOutput(out.content ?? "", query);
|
|
117
|
+
return { supported: true, content: compact };
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
device_info: {
|
|
121
|
+
descriptor: {
|
|
122
|
+
name: "device_info",
|
|
123
|
+
description: "Return DeviceInfo (type, name, screen size, capabilities, metadata).",
|
|
124
|
+
inputSchema: { type: "object", properties: {} },
|
|
125
|
+
},
|
|
126
|
+
// Always available — every backend has `info()` (platform metadata
|
|
127
|
+
// is the one thing even a stub backend can report). Backends still
|
|
128
|
+
// need to include `device_info` in their `tools` set to advertise
|
|
129
|
+
// it; the iOS stub uses this as its single advertised tool so the
|
|
130
|
+
// health check has something to call.
|
|
131
|
+
handler: async (_args, { backend }) => backend.info(),
|
|
132
|
+
},
|
|
133
|
+
screen_size: {
|
|
134
|
+
descriptor: {
|
|
135
|
+
name: "screen_size",
|
|
136
|
+
description: "Return current screen size (w, h).",
|
|
137
|
+
inputSchema: { type: "object", properties: {} },
|
|
138
|
+
},
|
|
139
|
+
handler: async (_args, { backend }) => backend.screenSize(),
|
|
140
|
+
},
|
|
141
|
+
/* — pointer / gesture — */
|
|
142
|
+
click: {
|
|
143
|
+
descriptor: {
|
|
144
|
+
name: "click",
|
|
145
|
+
description: "Mouse click at (x, y). Equivalent to tap on touch backends.",
|
|
146
|
+
inputSchema: {
|
|
147
|
+
type: "object",
|
|
148
|
+
properties: {
|
|
149
|
+
...xy.properties,
|
|
150
|
+
button: { type: "string", enum: ["left", "right", "middle"] },
|
|
151
|
+
clicks: { type: "number" },
|
|
152
|
+
},
|
|
153
|
+
required: ["x", "y"],
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
handler: async (args, { backend }) => {
|
|
157
|
+
await backend.click(n(args, "x"), n(args, "y"), optS(args, "button") ?? "left", optN(args, "clicks") ?? 1);
|
|
158
|
+
return { ok: true };
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
double_click: {
|
|
162
|
+
descriptor: {
|
|
163
|
+
name: "double_click",
|
|
164
|
+
description: "Double click at (x, y).",
|
|
165
|
+
inputSchema: { ...xy },
|
|
166
|
+
},
|
|
167
|
+
handler: async (args, { backend }) => {
|
|
168
|
+
await backend.doubleClick(n(args, "x"), n(args, "y"));
|
|
169
|
+
return { ok: true };
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
right_click: {
|
|
173
|
+
descriptor: {
|
|
174
|
+
name: "right_click",
|
|
175
|
+
description: "Right click at (x, y).",
|
|
176
|
+
inputSchema: { ...xy },
|
|
177
|
+
},
|
|
178
|
+
handler: async (args, { backend }) => {
|
|
179
|
+
await backend.rightClick(n(args, "x"), n(args, "y"));
|
|
180
|
+
return { ok: true };
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
tap: {
|
|
184
|
+
descriptor: {
|
|
185
|
+
name: "tap",
|
|
186
|
+
description: "Tap at (x, y) on a touch device.",
|
|
187
|
+
inputSchema: { ...xy },
|
|
188
|
+
},
|
|
189
|
+
handler: async (args, { backend }) => {
|
|
190
|
+
await backend.tap(n(args, "x"), n(args, "y"));
|
|
191
|
+
return { ok: true };
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
long_press: {
|
|
195
|
+
descriptor: {
|
|
196
|
+
name: "long_press",
|
|
197
|
+
description: "Long-press at (x, y) for `durationMs` (default 3000).",
|
|
198
|
+
inputSchema: {
|
|
199
|
+
type: "object",
|
|
200
|
+
properties: {
|
|
201
|
+
...xy.properties,
|
|
202
|
+
durationMs: { type: "number" },
|
|
203
|
+
},
|
|
204
|
+
required: ["x", "y"],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
handler: async (args, { backend }) => {
|
|
208
|
+
await backend.longPress(n(args, "x"), n(args, "y"), optN(args, "durationMs"));
|
|
209
|
+
return { ok: true };
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
drag: {
|
|
213
|
+
descriptor: {
|
|
214
|
+
name: "drag",
|
|
215
|
+
description: "Drag from (x1, y1) to (x2, y2).",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
type: "object",
|
|
218
|
+
properties: {
|
|
219
|
+
x1: { type: "number" },
|
|
220
|
+
y1: { type: "number" },
|
|
221
|
+
x2: { type: "number" },
|
|
222
|
+
y2: { type: "number" },
|
|
223
|
+
durationMs: { type: "number" },
|
|
224
|
+
},
|
|
225
|
+
required: ["x1", "y1", "x2", "y2"],
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
handler: async (args, { backend }) => {
|
|
229
|
+
await backend.drag(n(args, "x1"), n(args, "y1"), n(args, "x2"), n(args, "y2"), optN(args, "durationMs"));
|
|
230
|
+
return { ok: true };
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
swipe: {
|
|
234
|
+
descriptor: {
|
|
235
|
+
name: "swipe",
|
|
236
|
+
description: "Swipe from (x1, y1) to (x2, y2).",
|
|
237
|
+
inputSchema: {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
x1: { type: "number" },
|
|
241
|
+
y1: { type: "number" },
|
|
242
|
+
x2: { type: "number" },
|
|
243
|
+
y2: { type: "number" },
|
|
244
|
+
durationMs: { type: "number" },
|
|
245
|
+
},
|
|
246
|
+
required: ["x1", "y1", "x2", "y2"],
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
handler: async (args, { backend }) => {
|
|
250
|
+
await backend.swipe(n(args, "x1"), n(args, "y1"), n(args, "x2"), n(args, "y2"), optN(args, "durationMs"));
|
|
251
|
+
return { ok: true };
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
scroll: {
|
|
255
|
+
descriptor: {
|
|
256
|
+
name: "scroll",
|
|
257
|
+
description: "Scroll at (x, y) in `direction` (up | down | left | right).",
|
|
258
|
+
inputSchema: {
|
|
259
|
+
type: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
x: { type: "number" },
|
|
262
|
+
y: { type: "number" },
|
|
263
|
+
direction: { type: "string", enum: ["up", "down", "left", "right"] },
|
|
264
|
+
amount: { type: "number" },
|
|
265
|
+
},
|
|
266
|
+
required: ["direction"],
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
handler: async (args, { backend }) => {
|
|
270
|
+
await backend.scroll(optN(args, "x") ?? 0, optN(args, "y") ?? 0, s(args, "direction"), optN(args, "amount"));
|
|
271
|
+
return { ok: true };
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
/* — keyboard — */
|
|
275
|
+
type: {
|
|
276
|
+
descriptor: {
|
|
277
|
+
name: "type",
|
|
278
|
+
description: "Type the given Unicode `text` into the focused field.",
|
|
279
|
+
inputSchema: {
|
|
280
|
+
type: "object",
|
|
281
|
+
properties: { text: { type: "string" } },
|
|
282
|
+
required: ["text"],
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
handler: async (args, { backend }) => {
|
|
286
|
+
await backend.typeText(s(args, "text"));
|
|
287
|
+
return { ok: true };
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
key: {
|
|
291
|
+
descriptor: {
|
|
292
|
+
name: "key",
|
|
293
|
+
description: "Press a single named key (e.g. `KEYCODE_HOME`, `Escape`).",
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: "object",
|
|
296
|
+
properties: { key: { type: "string" } },
|
|
297
|
+
required: ["key"],
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
handler: async (args, { backend }) => {
|
|
301
|
+
await backend.pressKey(s(args, "key"));
|
|
302
|
+
return { ok: true };
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
hotkey: {
|
|
306
|
+
descriptor: {
|
|
307
|
+
name: "hotkey",
|
|
308
|
+
description: "Press a hotkey combo, e.g. ['Cmd', 'Shift', 'P'].",
|
|
309
|
+
inputSchema: {
|
|
310
|
+
type: "object",
|
|
311
|
+
properties: {
|
|
312
|
+
keys: { type: "array", items: { type: "string" } },
|
|
313
|
+
},
|
|
314
|
+
required: ["keys"],
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
handler: async (args, { backend }) => {
|
|
318
|
+
const keys = args.keys;
|
|
319
|
+
if (!Array.isArray(keys) || keys.some((k) => typeof k !== "string")) {
|
|
320
|
+
throw new TypeError("argument 'keys' must be a string[]");
|
|
321
|
+
}
|
|
322
|
+
await backend.hotkey(...keys);
|
|
323
|
+
return { ok: true };
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
/* — system nav — */
|
|
327
|
+
back: {
|
|
328
|
+
descriptor: {
|
|
329
|
+
name: "back",
|
|
330
|
+
description: "Press the system back button (Android) / browser back.",
|
|
331
|
+
inputSchema: { type: "object", properties: {} },
|
|
332
|
+
},
|
|
333
|
+
handler: async (_args, { backend }) => {
|
|
334
|
+
await backend.back();
|
|
335
|
+
return { ok: true };
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
home: {
|
|
339
|
+
descriptor: {
|
|
340
|
+
name: "home",
|
|
341
|
+
description: "Press the system home button (Android).",
|
|
342
|
+
inputSchema: { type: "object", properties: {} },
|
|
343
|
+
},
|
|
344
|
+
handler: async (_args, { backend }) => {
|
|
345
|
+
await backend.home();
|
|
346
|
+
return { ok: true };
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
/* — app — */
|
|
350
|
+
launch_app: {
|
|
351
|
+
descriptor: {
|
|
352
|
+
name: "launch_app",
|
|
353
|
+
description: "Launch app by package or display name.",
|
|
354
|
+
inputSchema: {
|
|
355
|
+
type: "object",
|
|
356
|
+
properties: {
|
|
357
|
+
pkg: { type: "string" },
|
|
358
|
+
activity: { type: "string" },
|
|
359
|
+
},
|
|
360
|
+
required: ["pkg"],
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
handler: async (args, { backend }) => {
|
|
364
|
+
await backend.launchApp(s(args, "pkg"), optS(args, "activity"));
|
|
365
|
+
return { ok: true };
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
/* — shell / files — */
|
|
369
|
+
execute_command: {
|
|
370
|
+
descriptor: {
|
|
371
|
+
name: "execute_command",
|
|
372
|
+
description: "Run a shell command on the sandbox. Returns stdout/stderr/exitCode.",
|
|
373
|
+
inputSchema: {
|
|
374
|
+
type: "object",
|
|
375
|
+
properties: {
|
|
376
|
+
body: { type: "string" },
|
|
377
|
+
timeoutS: { type: "number" },
|
|
378
|
+
cwd: { type: "string" },
|
|
379
|
+
},
|
|
380
|
+
required: ["body"],
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
handler: async (args, { backend }) => backend.executeCommand(s(args, "body"), {
|
|
384
|
+
timeoutS: optN(args, "timeoutS"),
|
|
385
|
+
cwd: optS(args, "cwd"),
|
|
386
|
+
}),
|
|
387
|
+
},
|
|
388
|
+
file_read: {
|
|
389
|
+
descriptor: {
|
|
390
|
+
name: "file_read",
|
|
391
|
+
description: "Read a file from the sandbox. Returns base64 content.",
|
|
392
|
+
inputSchema: {
|
|
393
|
+
type: "object",
|
|
394
|
+
properties: { path: { type: "string" } },
|
|
395
|
+
required: ["path"],
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
handler: async (args, { backend }) => {
|
|
399
|
+
const buf = await backend.fileRead(s(args, "path"));
|
|
400
|
+
return { contentB64: buf.toString("base64"), bytes: buf.length };
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
file_write: {
|
|
404
|
+
descriptor: {
|
|
405
|
+
name: "file_write",
|
|
406
|
+
description: "Write base64 content to a file in the sandbox.",
|
|
407
|
+
inputSchema: {
|
|
408
|
+
type: "object",
|
|
409
|
+
properties: {
|
|
410
|
+
path: { type: "string" },
|
|
411
|
+
contentB64: { type: "string" },
|
|
412
|
+
},
|
|
413
|
+
required: ["path", "contentB64"],
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
handler: async (args, { backend }) => {
|
|
417
|
+
const buf = Buffer.from(s(args, "contentB64"), "base64");
|
|
418
|
+
await backend.fileWrite(s(args, "path"), buf);
|
|
419
|
+
return { ok: true, bytes: buf.length };
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
list_directory: {
|
|
423
|
+
descriptor: {
|
|
424
|
+
name: "list_directory",
|
|
425
|
+
description: "List directory entries.",
|
|
426
|
+
inputSchema: {
|
|
427
|
+
type: "object",
|
|
428
|
+
properties: { path: { type: "string" } },
|
|
429
|
+
required: ["path"],
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
handler: async (args, { backend }) => {
|
|
433
|
+
const entries = await backend.listDirectory(s(args, "path"));
|
|
434
|
+
return { entries };
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
/**
|
|
438
|
+
* `install_package` — backend-agnostic native-package install.
|
|
439
|
+
*
|
|
440
|
+
* Dispatches to whichever installer the backend implements (APK on
|
|
441
|
+
* Android, DMG/PKG on macOS, MSI/EXE on Windows, DEB/RPM on Linux).
|
|
442
|
+
* Wire-compatible alias `install_apk` is kept registered for
|
|
443
|
+
* existing agents that still hardcode the Android verb name.
|
|
444
|
+
*
|
|
445
|
+
* Reference: plan §3.4 — "工具命名上,去掉 backend 私有词".
|
|
446
|
+
*/
|
|
447
|
+
install_package: installToolEntry("install_package"),
|
|
448
|
+
install_apk: installToolEntry("install_apk"),
|
|
449
|
+
};
|
|
450
|
+
function installToolEntry(name) {
|
|
451
|
+
return {
|
|
452
|
+
descriptor: {
|
|
453
|
+
name,
|
|
454
|
+
description: name === "install_package"
|
|
455
|
+
? "Install a native package at `path`. Backend-agnostic — dispatches " +
|
|
456
|
+
"to APK / DMG / MSI / DEB based on the active backend."
|
|
457
|
+
: "Install an APK at `path` (Android only). Alias for `install_package`.",
|
|
458
|
+
inputSchema: {
|
|
459
|
+
type: "object",
|
|
460
|
+
properties: { path: { type: "string" } },
|
|
461
|
+
required: ["path"],
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
handler: async (args, { backend }) => {
|
|
465
|
+
await backend.install(s(args, "path"));
|
|
466
|
+
return { ok: true };
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
/* ----------------------------------------------------------------------- */
|
|
471
|
+
/* Public API */
|
|
472
|
+
/* ----------------------------------------------------------------------- */
|
|
473
|
+
/**
|
|
474
|
+
* Return ALL registered tool descriptors regardless of backend support.
|
|
475
|
+
*
|
|
476
|
+
* Useful for documentation / tests that want to enumerate the catalog.
|
|
477
|
+
* Wire callers SHOULD use `listToolDescriptorsFor(backend)` so the list
|
|
478
|
+
* only contains tools the active backend can actually execute.
|
|
479
|
+
*/
|
|
480
|
+
export function listToolDescriptors() {
|
|
481
|
+
return Object.values(TOOLS).map((t) => t.descriptor);
|
|
482
|
+
}
|
|
483
|
+
/** Return tool descriptors filtered by the backend's advertised tool set. */
|
|
484
|
+
export function listToolDescriptorsFor(backend) {
|
|
485
|
+
return Object.values(TOOLS)
|
|
486
|
+
.filter((t) => backend.tools.has(t.descriptor.name))
|
|
487
|
+
.map((t) => t.descriptor);
|
|
488
|
+
}
|
|
489
|
+
/** Look up a tool by name, ignoring backend tool-set gates. */
|
|
490
|
+
export function getTool(name) {
|
|
491
|
+
return TOOLS[name];
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Look up a tool by name, **gated** on the backend's advertised tool
|
|
495
|
+
* set. Returns `undefined` for tools the active backend cannot
|
|
496
|
+
* satisfy — the `/mcp/tools/call` route uses this and returns 404,
|
|
497
|
+
* mirroring the filtering applied at `/mcp/tools/list`.
|
|
498
|
+
*/
|
|
499
|
+
export function getToolFor(name, backend) {
|
|
500
|
+
if (!backend.tools.has(name))
|
|
501
|
+
return undefined;
|
|
502
|
+
return TOOLS[name];
|
|
503
|
+
}
|
|
504
|
+
//# sourceMappingURL=tool-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-registry.js","sourceRoot":"","sources":["../../src/server/tool-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adb-files — file-IO and listing primitives over the native `adb`
|
|
3
|
+
* `pull` / `push` / `shell ls` protocols.
|
|
4
|
+
*
|
|
5
|
+
* # Why this module exists
|
|
6
|
+
*
|
|
7
|
+
* Earlier versions of the Android backend did file IO with two ad-hoc
|
|
8
|
+
* tricks:
|
|
9
|
+
*
|
|
10
|
+
* - `fileRead` → `adb exec-out cat <path>` and decoded the bytes from
|
|
11
|
+
* stdout. This silently swallowed device-side `cat` errors because
|
|
12
|
+
* `adb exec-out` does NOT propagate the remote command's exit code
|
|
13
|
+
* back to the host adb client (the host always exits 0 when the
|
|
14
|
+
* channel closes cleanly), so reading a non-existent path returned
|
|
15
|
+
* `cat`'s stderr text base64-encoded as if it were file content.
|
|
16
|
+
*
|
|
17
|
+
* - `fileWrite` → `adb shell sh -c "echo <b64> | base64 -d > <path>"`.
|
|
18
|
+
* Because `adb shell` joins argv with spaces and re-evaluates through
|
|
19
|
+
* `sh -c`, the shell saw `sh -c sh -c echo <b64> | base64 -d > path`,
|
|
20
|
+
* which dropped the pipeline body, ran `sh -c echo` with no args, and
|
|
21
|
+
* left an empty file on the device. The bug went undetected because
|
|
22
|
+
* the host-side `adb` still returned exit 0.
|
|
23
|
+
*
|
|
24
|
+
* The right tools for this job are `adb pull` and `adb push`: they speak
|
|
25
|
+
* the file-sync protocol designed for binary transfer, the host-side
|
|
26
|
+
* `adb` exits with a non-zero code when the device-side path is missing
|
|
27
|
+
* or unwritable, and they side-step the shell tokeniser entirely. This
|
|
28
|
+
* module wraps those primitives in async-friendly helpers and routes
|
|
29
|
+
* every error through `wrapAdbFailure` so callers see the familiar
|
|
30
|
+
* `DeviceError` shape.
|
|
31
|
+
*
|
|
32
|
+
* `adbListDir` exists in this module rather than in the backend so the
|
|
33
|
+
* "use `ls -laL` to dereference symlinks" rule has a single home. The
|
|
34
|
+
* raw `ls -la` form does not deref symlinks (so listing `/sdcard` returns
|
|
35
|
+
* the symlink itself instead of the contents of `/storage/self/primary`,
|
|
36
|
+
* which is almost never what callers want).
|
|
37
|
+
*/
|
|
38
|
+
import type { AdbRunner } from "../backends/android-adb-runner.js";
|
|
39
|
+
import type { ListDirectoryEntry } from "../backends/base.js";
|
|
40
|
+
export interface AdbFileOpOptions {
|
|
41
|
+
/** Hard timeout for the underlying `adb` invocation. */
|
|
42
|
+
timeoutMs: number;
|
|
43
|
+
/** Optional override for the host-side temp directory (tests). */
|
|
44
|
+
tmpdir?: () => string;
|
|
45
|
+
/** Cap stdout buffer for pull (defaults to 64 MiB). */
|
|
46
|
+
maxBufferBytes?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Prepend `["-s", serial]` when a serial is set. Mirrors the private
|
|
50
|
+
* `adbArgs()` helper in the backend so the helpers here can build their
|
|
51
|
+
* own argv without leaking the backend's internal state.
|
|
52
|
+
*/
|
|
53
|
+
export declare function withSerial(serial: string | undefined, args: readonly string[]): string[];
|
|
54
|
+
/**
|
|
55
|
+
* `adb pull <remote> <hostTmp>` followed by an in-memory read of the
|
|
56
|
+
* temp file. Throws `DeviceError(file_not_found)` when the device path
|
|
57
|
+
* does not exist (host-side adb exits with code 1 and prints
|
|
58
|
+
* `adb: error: failed to stat remote object ... No such file or directory`),
|
|
59
|
+
* and the generic `adb_failed` shape for everything else.
|
|
60
|
+
*/
|
|
61
|
+
export declare function adbPull(runner: AdbRunner, serial: string | undefined, remote: string, opts: AdbFileOpOptions): Promise<Buffer>;
|
|
62
|
+
/**
|
|
63
|
+
* `adb push <hostTmp> <remote>`. The buffer is written to a temp file
|
|
64
|
+
* first because `adb push` reads from disk; piping into stdin is not
|
|
65
|
+
* supported by the file-sync protocol.
|
|
66
|
+
*/
|
|
67
|
+
export declare function adbPush(runner: AdbRunner, serial: string | undefined, remote: string, content: Buffer, opts: AdbFileOpOptions): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* `ls -laL <path>` over `adb shell` (single-string command, properly
|
|
70
|
+
* quoted via `sh\`...\``). The `-L` flag dereferences symlinks so callers
|
|
71
|
+
* who pass `/sdcard` (a symlink to `/storage/self/primary` on stock AOSP)
|
|
72
|
+
* see the contents of the linked directory rather than a single
|
|
73
|
+
* `lrwxrwxrwx ... /sdcard -> /storage/self/primary` row.
|
|
74
|
+
*
|
|
75
|
+
* The runner contract is: throws on non-zero adb exit (the call site
|
|
76
|
+
* handles that with `wrapAdbFailure`); on success, parses the textual
|
|
77
|
+
* output via `parseLsOutput`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function adbListDir(runner: AdbRunner, serial: string | undefined, pathArg: string, opts: AdbFileOpOptions): Promise<ListDirectoryEntry[]>;
|
|
80
|
+
/**
|
|
81
|
+
* Parse the output of `ls -la` / `ls -laL` from Android's toybox `ls`
|
|
82
|
+
* into structured entries. Tolerates header lines (`total 12`) and skips
|
|
83
|
+
* the canonical `.` / `..` entries.
|
|
84
|
+
*
|
|
85
|
+
* Entry layout (toybox): `perms links owner group size month day time name`.
|
|
86
|
+
* We index by whitespace-split position rather than parsing each column
|
|
87
|
+
* type-by-type because Android's `ls` output is stable across releases.
|
|
88
|
+
*
|
|
89
|
+
* Exported here (not in the backend) so the symlink-dereferencing rule
|
|
90
|
+
* lives next to the `ls -laL` invocation it depends on.
|
|
91
|
+
*/
|
|
92
|
+
export declare function parseLsOutput(out: string): ListDirectoryEntry[];
|