@ddqd/droid-mcp 2.0.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/CLAUDE.md +124 -0
- package/EXAMPLES.md +471 -0
- package/LICENSE +21 -0
- package/README.md +354 -0
- package/dist/adb.d.ts +110 -0
- package/dist/adb.d.ts.map +1 -0
- package/dist/adb.js +579 -0
- package/dist/adb.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +366 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { execAdb, AdbError, captureLogcatUntil, getPidsForPackages, listThirdPartyPackages, scanGradleForPackageId, dumpViewHierarchy, parseViewHierarchyXml, captureScreenshot, setOutputDir, } from "./adb.js";
|
|
4
|
+
import { GetLogcatSchema, CaptureSessionSchema, InspectAppSchema, ViewHierarchySchema, CaptureScreenshotSchema, } from "./types.js";
|
|
5
|
+
// Debug logging utility
|
|
6
|
+
const DEBUG = process.env.DROID_MCP_DEBUG === "true" || process.env.DEBUG === "1";
|
|
7
|
+
function debugLog(message, data) {
|
|
8
|
+
if (DEBUG) {
|
|
9
|
+
const timestamp = new Date().toISOString();
|
|
10
|
+
const dataStr = data ? JSON.stringify(data, null, 2) : "";
|
|
11
|
+
console.error(`[${timestamp}] [DEBUG] ${message}${dataStr ? "\n" + dataStr : ""}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
// Create the MCP server
|
|
15
|
+
const server = new McpServer({
|
|
16
|
+
name: "droid-mcp",
|
|
17
|
+
version: "0.1.0",
|
|
18
|
+
});
|
|
19
|
+
// Глобальный фильтр по package ID из переменной окружения
|
|
20
|
+
// Поддерживает список через запятую или пробел: "com.app1,com.app2" или "com.app1 com.app2"
|
|
21
|
+
function getGlobalPackageIds() {
|
|
22
|
+
const envValue = process.env.ANDROID_APP_IDS;
|
|
23
|
+
if (!envValue) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
// Разделяем по запятой или пробелу, убираем пустые строки
|
|
27
|
+
return envValue
|
|
28
|
+
.split(/[,\s]+/)
|
|
29
|
+
.map((id) => id.trim())
|
|
30
|
+
.filter((id) => id.length > 0);
|
|
31
|
+
}
|
|
32
|
+
// Парсинг аргументов командной строки
|
|
33
|
+
function parseArgs() {
|
|
34
|
+
const args = process.argv.slice(2);
|
|
35
|
+
let outputDir;
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
if (args[i] === "--output-dir" && i + 1 < args.length) {
|
|
38
|
+
outputDir = args[i + 1];
|
|
39
|
+
i++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Также проверяем переменную окружения
|
|
43
|
+
if (!outputDir && process.env.DROID_MCP_OUTPUT_DIR) {
|
|
44
|
+
outputDir = process.env.DROID_MCP_OUTPUT_DIR;
|
|
45
|
+
}
|
|
46
|
+
return { outputDir };
|
|
47
|
+
}
|
|
48
|
+
// Register tool: get_logcat
|
|
49
|
+
server.registerTool("get_logcat", {
|
|
50
|
+
description: "Fetches historical logcat logs from Android device. Returns the last N lines (default: 200, max: 2000) with optional filtering by tag. Automatically filters by process ID (PID) if ANDROID_APP_IDS environment variable is set, showing only logs from specified app packages. Useful for reviewing recent log history or debugging past events.",
|
|
51
|
+
inputSchema: GetLogcatSchema.shape,
|
|
52
|
+
}, async (params) => {
|
|
53
|
+
debugLog("get_logcat invoked", { params });
|
|
54
|
+
const lines = params.lines ?? 200;
|
|
55
|
+
const command = ["logcat", "-d", "-t", lines.toString()];
|
|
56
|
+
// Применяем глобальный фильтр по PID, если задан ANDROID_APP_IDS
|
|
57
|
+
const globalPackageIds = getGlobalPackageIds();
|
|
58
|
+
let appPids = [];
|
|
59
|
+
if (globalPackageIds.length > 0) {
|
|
60
|
+
debugLog("Filtering by package IDs", { globalPackageIds });
|
|
61
|
+
appPids = await getPidsForPackages(globalPackageIds);
|
|
62
|
+
debugLog("Found PIDs for packages", { appPids });
|
|
63
|
+
if (appPids.length === 0) {
|
|
64
|
+
console.error(`[MCP] Warning: No running processes found for package IDs: ${globalPackageIds.join(", ")}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Добавляем фильтры по PID
|
|
68
|
+
for (const pid of appPids) {
|
|
69
|
+
command.push(`--pid=${pid}`);
|
|
70
|
+
}
|
|
71
|
+
// Add tag filter if provided
|
|
72
|
+
if (params.tag) {
|
|
73
|
+
command.push(`${params.tag}:*`);
|
|
74
|
+
}
|
|
75
|
+
debugLog("Executing ADB command", { command: command.join(" ") });
|
|
76
|
+
try {
|
|
77
|
+
const result = await execAdb(command);
|
|
78
|
+
debugLog("get_logcat completed successfully", { outputLength: result.stdout?.length || 0 });
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
text: result.stdout || "(no output)",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
debugLog("get_logcat error", {
|
|
90
|
+
error: error instanceof Error ? error.message : String(error),
|
|
91
|
+
isAdbError: error instanceof AdbError,
|
|
92
|
+
adbErrorDetails: error instanceof AdbError ? { code: error.code, stderr: error.stderr } : undefined
|
|
93
|
+
});
|
|
94
|
+
if (error instanceof AdbError) {
|
|
95
|
+
throw new Error(`ADB error: ${error.message}. ${error.stderr}`);
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Register tool: capture_session
|
|
101
|
+
server.registerTool("capture_session", {
|
|
102
|
+
description: "Captures logcat logs in real-time until a stop pattern (regex) is found or timeout is reached. Automatically filters by process ID (PID) if ANDROID_APP_IDS environment variable is set. Supports filtering by tag, priority level, and log buffer. Ideal for interactive debugging when reproducing specific user scenarios. Default timeout: 30 seconds (max: 300). Can optionally clear buffer before starting to capture only fresh logs.",
|
|
103
|
+
inputSchema: CaptureSessionSchema.shape,
|
|
104
|
+
}, async (params) => {
|
|
105
|
+
debugLog("capture_session invoked", { params });
|
|
106
|
+
const timeoutSeconds = Math.min(Math.max(params.timeout_seconds ?? 30, 1), 300);
|
|
107
|
+
const timeoutMs = timeoutSeconds * 1000;
|
|
108
|
+
// Применяем глобальный фильтр по PID, если задан ANDROID_APP_IDS
|
|
109
|
+
const globalPackageIds = getGlobalPackageIds();
|
|
110
|
+
let appPids = [];
|
|
111
|
+
if (globalPackageIds.length > 0) {
|
|
112
|
+
debugLog("Filtering by package IDs", { globalPackageIds });
|
|
113
|
+
appPids = await getPidsForPackages(globalPackageIds);
|
|
114
|
+
debugLog("Found PIDs for packages", { appPids });
|
|
115
|
+
if (appPids.length === 0) {
|
|
116
|
+
console.error(`[MCP] Warning: No running processes found for package IDs: ${globalPackageIds.join(", ")}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
debugLog("Starting logcat capture", {
|
|
120
|
+
stopPattern: params.stop_pattern,
|
|
121
|
+
timeoutMs,
|
|
122
|
+
pids: appPids
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
const logs = await captureLogcatUntil({
|
|
126
|
+
stopPattern: params.stop_pattern,
|
|
127
|
+
timeoutMs,
|
|
128
|
+
clearBuffer: params.clear_buffer ?? false,
|
|
129
|
+
tag: params.tag,
|
|
130
|
+
priority: params.priority,
|
|
131
|
+
buffer: params.buffer,
|
|
132
|
+
pids: appPids.length > 0 ? appPids : undefined,
|
|
133
|
+
});
|
|
134
|
+
debugLog("capture_session completed", { logsLength: logs?.length || 0 });
|
|
135
|
+
return {
|
|
136
|
+
content: [
|
|
137
|
+
{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: logs || "(no output)",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
debugLog("capture_session error", {
|
|
146
|
+
error: error instanceof Error ? error.message : String(error),
|
|
147
|
+
isAdbError: error instanceof AdbError,
|
|
148
|
+
adbErrorDetails: error instanceof AdbError ? { code: error.code, stderr: error.stderr } : undefined
|
|
149
|
+
});
|
|
150
|
+
if (error instanceof AdbError) {
|
|
151
|
+
throw new Error(`ADB error: ${error.message}. ${error.stderr}`);
|
|
152
|
+
}
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// Register tool: inspect_app_identity
|
|
157
|
+
server.registerTool("inspect_app_identity", {
|
|
158
|
+
description: "Scans the project directory and connected Android device to automatically detect package IDs (applicationId) for log filtering. Searches build.gradle files for applicationId and lists all third-party packages installed on the device. Shows matches between project and device, helping you configure ANDROID_APP_IDS environment variable. No parameters required. Useful for initial setup or when working with multiple apps.",
|
|
159
|
+
inputSchema: InspectAppSchema.shape,
|
|
160
|
+
}, async () => {
|
|
161
|
+
try {
|
|
162
|
+
// Параллельно получаем данные из gradle и с устройства
|
|
163
|
+
const [gradlePackageId, installedPackages] = await Promise.all([
|
|
164
|
+
scanGradleForPackageId(),
|
|
165
|
+
listThirdPartyPackages()
|
|
166
|
+
]);
|
|
167
|
+
let resultText = "=== Package ID Inspection ===\n\n";
|
|
168
|
+
// Результаты сканирования gradle
|
|
169
|
+
if (gradlePackageId) {
|
|
170
|
+
resultText += `[Project Source] Found in build.gradle: ${gradlePackageId}\n`;
|
|
171
|
+
const isInstalled = installedPackages.includes(gradlePackageId);
|
|
172
|
+
if (isInstalled) {
|
|
173
|
+
resultText += ` ✓ Currently installed on device\n`;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
resultText += ` ✗ NOT found on device (may need to install)\n`;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
resultText += `[Project Source] Could not find applicationId in build.gradle files.\n`;
|
|
181
|
+
resultText += ` Searched paths: app/build.gradle, app/build.gradle.kts, build.gradle, build.gradle.kts\n`;
|
|
182
|
+
}
|
|
183
|
+
resultText += `\n[Device] Third-party packages installed (${installedPackages.length} total):\n`;
|
|
184
|
+
if (installedPackages.length > 0) {
|
|
185
|
+
// Показываем первые 50 пакетов, чтобы не перегружать вывод
|
|
186
|
+
const displayPackages = installedPackages.slice(0, 50);
|
|
187
|
+
displayPackages.forEach((pkg) => {
|
|
188
|
+
const isMatch = pkg === gradlePackageId;
|
|
189
|
+
resultText += ` ${isMatch ? "→ " : " "}${pkg}${isMatch ? " (matches gradle)" : ""}\n`;
|
|
190
|
+
});
|
|
191
|
+
if (installedPackages.length > 50) {
|
|
192
|
+
resultText += ` ... and ${installedPackages.length - 50} more packages\n`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
resultText += ` (None found or device not connected)\n`;
|
|
197
|
+
}
|
|
198
|
+
resultText += `\n[Usage] Set ANDROID_APP_IDS environment variable to filter logs:\n`;
|
|
199
|
+
resultText += ` Example: ANDROID_APP_IDS="${gradlePackageId || "com.example.app"}"\n`;
|
|
200
|
+
if (installedPackages.length > 0) {
|
|
201
|
+
resultText += ` Or multiple: ANDROID_APP_IDS="${installedPackages.slice(0, 2).join(",")}"\n`;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: resultText,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (error instanceof AdbError) {
|
|
214
|
+
throw new Error(`ADB error: ${error.message}. ${error.stderr}`);
|
|
215
|
+
}
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
// Register tool: dump_view_hierarchy
|
|
220
|
+
server.registerTool("dump_view_hierarchy", {
|
|
221
|
+
description: "Dumps the current screen UI hierarchy from Android device using uiautomator. Returns view structure with bounds, text, resource-id, content-desc, and clickable attributes. Optimized for AI analysis with compact JSON format (default) that filters empty containers to save tokens. Supports raw XML output for debugging. Useful for UI understanding, test automation, and AI agents that need to interact with Android apps.",
|
|
222
|
+
inputSchema: ViewHierarchySchema.shape,
|
|
223
|
+
}, async (params) => {
|
|
224
|
+
debugLog("dump_view_hierarchy invoked", { params });
|
|
225
|
+
try {
|
|
226
|
+
// Получаем XML через uiautomator dump
|
|
227
|
+
const xml = await dumpViewHierarchy();
|
|
228
|
+
debugLog("dump_view_hierarchy xml received", { xmlLength: xml.length });
|
|
229
|
+
// Определяем формат вывода
|
|
230
|
+
const format = params.format ?? "compact";
|
|
231
|
+
const includeInvisible = params.include_invisible ?? false;
|
|
232
|
+
let output;
|
|
233
|
+
if (format === "xml") {
|
|
234
|
+
// Сырой XML
|
|
235
|
+
output = xml;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Парсим в JSON
|
|
239
|
+
const parsed = parseViewHierarchyXml(xml, {
|
|
240
|
+
includeInvisible,
|
|
241
|
+
compact: format === "compact",
|
|
242
|
+
});
|
|
243
|
+
output = JSON.stringify(parsed, null, 2);
|
|
244
|
+
}
|
|
245
|
+
debugLog("dump_view_hierarchy completed", {
|
|
246
|
+
format,
|
|
247
|
+
outputLength: output.length,
|
|
248
|
+
});
|
|
249
|
+
return {
|
|
250
|
+
content: [
|
|
251
|
+
{
|
|
252
|
+
type: "text",
|
|
253
|
+
text: output,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
debugLog("dump_view_hierarchy error", {
|
|
260
|
+
error: error instanceof Error ? error.message : String(error),
|
|
261
|
+
isAdbError: error instanceof AdbError,
|
|
262
|
+
adbErrorDetails: error instanceof AdbError ? { code: error.code, stderr: error.stderr } : undefined
|
|
263
|
+
});
|
|
264
|
+
if (error instanceof AdbError) {
|
|
265
|
+
throw new Error(`ADB error: ${error.message}. ${error.stderr}`);
|
|
266
|
+
}
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
// Register tool: capture_screenshot
|
|
271
|
+
server.registerTool("capture_screenshot", {
|
|
272
|
+
description: "Captures screenshot from Android device. By default saves to file and returns absolute path. Supports WebP format (default, AI-optimized, smaller size) and PNG (lossless). Automatically scales down to reduce token usage while maintaining AI readability. Ideal for visual debugging, UI verification, and documenting issues.",
|
|
273
|
+
inputSchema: CaptureScreenshotSchema.shape,
|
|
274
|
+
}, async (params) => {
|
|
275
|
+
debugLog("capture_screenshot invoked", { params });
|
|
276
|
+
try {
|
|
277
|
+
const result = await captureScreenshot({
|
|
278
|
+
output: params.output ?? "file",
|
|
279
|
+
format: params.format ?? "webp",
|
|
280
|
+
scale: params.scale ?? 0.5,
|
|
281
|
+
quality: params.quality ?? 85,
|
|
282
|
+
});
|
|
283
|
+
debugLog("capture_screenshot completed", {
|
|
284
|
+
format: result.format,
|
|
285
|
+
sizeKb: result.sizeKb,
|
|
286
|
+
dimensions: `${result.width}x${result.height}`,
|
|
287
|
+
output: params.output ?? "file"
|
|
288
|
+
});
|
|
289
|
+
if (params.output === "base64") {
|
|
290
|
+
// Возвращаем data URL для base64 режима
|
|
291
|
+
const mimeType = result.format === "webp" ? "image/webp" : "image/png";
|
|
292
|
+
const dataUrl = `${mimeType};base64,${result.data}`;
|
|
293
|
+
return {
|
|
294
|
+
content: [
|
|
295
|
+
{
|
|
296
|
+
type: "text",
|
|
297
|
+
text: JSON.stringify({
|
|
298
|
+
dataUrl,
|
|
299
|
+
format: result.format,
|
|
300
|
+
sizeKb: result.sizeKb,
|
|
301
|
+
width: result.width,
|
|
302
|
+
height: result.height,
|
|
303
|
+
originalWidth: result.originalWidth,
|
|
304
|
+
originalHeight: result.originalHeight,
|
|
305
|
+
scaled: result.scaled,
|
|
306
|
+
}, null, 2),
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// Возвращаем путь к файлу
|
|
312
|
+
return {
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: "text",
|
|
316
|
+
text: JSON.stringify({
|
|
317
|
+
filePath: result.filePath,
|
|
318
|
+
relativePath: result.relativePath,
|
|
319
|
+
format: result.format,
|
|
320
|
+
sizeKb: result.sizeKb,
|
|
321
|
+
width: result.width,
|
|
322
|
+
height: result.height,
|
|
323
|
+
originalWidth: result.originalWidth,
|
|
324
|
+
originalHeight: result.originalHeight,
|
|
325
|
+
scaled: result.scaled,
|
|
326
|
+
message: `Screenshot saved to ${result.filePath}`,
|
|
327
|
+
}, null, 2),
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
debugLog("capture_screenshot error", {
|
|
334
|
+
error: error instanceof Error ? error.message : String(error)
|
|
335
|
+
});
|
|
336
|
+
if (error instanceof AdbError) {
|
|
337
|
+
throw new Error(`ADB error: ${error.message}. ${error.stderr}`);
|
|
338
|
+
}
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
// Start the server
|
|
343
|
+
async function main() {
|
|
344
|
+
// Парсим и устанавливаем output директорию
|
|
345
|
+
const { outputDir } = parseArgs();
|
|
346
|
+
if (outputDir) {
|
|
347
|
+
setOutputDir(outputDir);
|
|
348
|
+
}
|
|
349
|
+
debugLog("Server starting", {
|
|
350
|
+
debugMode: DEBUG,
|
|
351
|
+
nodeVersion: process.version,
|
|
352
|
+
cwd: process.cwd(),
|
|
353
|
+
outputDir: outputDir || "(default: .droid-mcp/screenshots)"
|
|
354
|
+
});
|
|
355
|
+
const transport = new StdioServerTransport();
|
|
356
|
+
const startupPackageIds = getGlobalPackageIds();
|
|
357
|
+
debugLog("Global package IDs", { startupPackageIds });
|
|
358
|
+
await server.connect(transport);
|
|
359
|
+
console.error("droid-mcp server running on stdio");
|
|
360
|
+
debugLog("Server connected and ready");
|
|
361
|
+
}
|
|
362
|
+
main().catch((error) => {
|
|
363
|
+
console.error("Fatal error in main():", error);
|
|
364
|
+
process.exit(1);
|
|
365
|
+
});
|
|
366
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
export declare const GetLogcatSchema: z.ZodObject<{
|
|
3
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
4
|
+
lines: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export declare const CaptureSessionSchema: z.ZodObject<{
|
|
7
|
+
stop_pattern: z.ZodString;
|
|
8
|
+
timeout_seconds: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
9
|
+
clear_buffer: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
10
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
11
|
+
priority: z.ZodOptional<z.ZodEnum<{
|
|
12
|
+
V: "V";
|
|
13
|
+
D: "D";
|
|
14
|
+
I: "I";
|
|
15
|
+
W: "W";
|
|
16
|
+
E: "E";
|
|
17
|
+
F: "F";
|
|
18
|
+
}>>;
|
|
19
|
+
buffer: z.ZodOptional<z.ZodEnum<{
|
|
20
|
+
main: "main";
|
|
21
|
+
system: "system";
|
|
22
|
+
crash: "crash";
|
|
23
|
+
radio: "radio";
|
|
24
|
+
events: "events";
|
|
25
|
+
all: "all";
|
|
26
|
+
default: "default";
|
|
27
|
+
}>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export declare const InspectAppSchema: z.ZodObject<{}, z.core.$strip>;
|
|
30
|
+
export declare const ViewHierarchySchema: z.ZodObject<{
|
|
31
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
xml: "xml";
|
|
33
|
+
json: "json";
|
|
34
|
+
compact: "compact";
|
|
35
|
+
}>>>;
|
|
36
|
+
include_invisible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export declare const CaptureScreenshotSchema: z.ZodObject<{
|
|
39
|
+
output: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
40
|
+
base64: "base64";
|
|
41
|
+
file: "file";
|
|
42
|
+
}>>>;
|
|
43
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
44
|
+
webp: "webp";
|
|
45
|
+
png: "png";
|
|
46
|
+
}>>>;
|
|
47
|
+
scale: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
48
|
+
quality: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export type GetLogcatParams = z.infer<typeof GetLogcatSchema>;
|
|
51
|
+
export type CaptureSessionParams = z.infer<typeof CaptureSessionSchema>;
|
|
52
|
+
export type ViewHierarchyParams = z.infer<typeof ViewHierarchySchema>;
|
|
53
|
+
export type CaptureScreenshotParams = z.infer<typeof CaptureScreenshotSchema>;
|
|
54
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;iBAO/B,CAAC;AAEH,eAAO,MAAM,gBAAgB,gCAAe,CAAC;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;iBAK9B,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBASlC,CAAC;AAGH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC9D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACtE,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Domain-specific types for ADB operations
|
|
2
|
+
// MCP protocol types are now provided by @modelcontextprotocol/sdk
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
// Zod schemas for tool input validation
|
|
5
|
+
export const GetLogcatSchema = z.object({
|
|
6
|
+
tag: z.string().optional().describe("Filter logs by tag (e.g., 'MyApp'). When provided, only logs with this tag will be returned."),
|
|
7
|
+
lines: z.number().int().min(1).max(2000).optional().default(200).describe("Number of log lines to retrieve. Default: 200, maximum: 2000."),
|
|
8
|
+
});
|
|
9
|
+
export const CaptureSessionSchema = z.object({
|
|
10
|
+
stop_pattern: z.string().describe("Regex pattern or string that stops the capture. When this pattern appears in the logs, capture will stop immediately."),
|
|
11
|
+
timeout_seconds: z.number().int().min(1).max(300).optional().default(30).describe("Maximum time to wait for stop_pattern in seconds. Default: 30, maximum: 300. Capture will stop when timeout is reached even if stop_pattern is not found."),
|
|
12
|
+
clear_buffer: z.boolean().optional().default(false).describe("Clear logcat buffer before starting capture. Default: false. Useful to start with fresh logs."),
|
|
13
|
+
tag: z.string().optional().describe("Filter logs by tag (e.g., 'MyApp'). When provided, only logs with this tag will be captured."),
|
|
14
|
+
priority: z.enum(["V", "D", "I", "W", "E", "F"]).optional().describe("Minimum log priority level: V (Verbose), D (Debug), I (Info), W (Warning), E (Error), F (Fatal). Only logs at or above this priority will be captured."),
|
|
15
|
+
buffer: z.enum(["main", "system", "crash", "radio", "events", "all", "default"]).optional().describe("Log buffer to read from: 'main' (default app logs), 'system' (system logs), 'crash' (crash logs), 'radio' (radio logs), 'events' (event logs), 'all' (all buffers), 'default' (main buffer)."),
|
|
16
|
+
});
|
|
17
|
+
export const InspectAppSchema = z.object({});
|
|
18
|
+
export const ViewHierarchySchema = z.object({
|
|
19
|
+
format: z.enum(["xml", "json", "compact"]).optional().default("compact")
|
|
20
|
+
.describe("Output format: 'xml' (raw uiautomator XML), 'json' (parsed full tree), 'compact' (AI-optimized JSON, default - filters empty containers)"),
|
|
21
|
+
include_invisible: z.boolean().optional().default(false)
|
|
22
|
+
.describe("Include non-clickable views without text/content-desc. Default: false (filters empty containers to save tokens). Only applies to 'json' and 'compact' formats."),
|
|
23
|
+
});
|
|
24
|
+
export const CaptureScreenshotSchema = z.object({
|
|
25
|
+
output: z.enum(["file", "base64"]).optional().default("file")
|
|
26
|
+
.describe("Output mode: 'file' (default, saves to output dir and returns absolute path) or 'base64' (embedded in response as data URL)."),
|
|
27
|
+
format: z.enum(["webp", "png"]).optional().default("webp")
|
|
28
|
+
.describe("Image format: 'webp' (default, AI-optimized, smaller size) or 'png' (lossless, larger size)."),
|
|
29
|
+
scale: z.number().min(0.25).max(1.0).optional().default(0.5)
|
|
30
|
+
.describe("Scale factor to reduce size. 0.5 = half resolution (~300KB, recommended for AI). 1.0 = original size (1-3MB)."),
|
|
31
|
+
quality: z.number().int().min(1).max(100).optional().default(85)
|
|
32
|
+
.describe("WebP quality 1-100. Only applies when format='webp'. Default: 85 (good balance)."),
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ddqd/droid-mcp",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MCP server for Android debugging: ADB logcat, view hierarchy, screenshots with AI optimization",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"droid-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"test": "npm run build && node --test tests/integration.test.js",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"publish:npm": "npm publish --access public",
|
|
16
|
+
"publish:gitverse": "npm publish --registry=https://gitverse.ru/api/packages/ddqd/npm/"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"mcp",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"adb",
|
|
22
|
+
"android",
|
|
23
|
+
"debugging",
|
|
24
|
+
"logcat",
|
|
25
|
+
"uiautomator",
|
|
26
|
+
"screenshot",
|
|
27
|
+
"ai-assistant",
|
|
28
|
+
"cursor",
|
|
29
|
+
"windsurf",
|
|
30
|
+
"claude"
|
|
31
|
+
],
|
|
32
|
+
"author": "",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"CLAUDE.md",
|
|
42
|
+
"EXAMPLES.md"
|
|
43
|
+
],
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^20.0.0",
|
|
49
|
+
"typescript": "^5.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
53
|
+
"sharp": "^0.34.5",
|
|
54
|
+
"zod": "^4.1.13",
|
|
55
|
+
"zod-to-json-schema": "^3.25.0"
|
|
56
|
+
}
|
|
57
|
+
}
|