appium-mcp 1.88.2 → 1.88.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/CHANGELOG.md +2 -0
- package/package.json +2 -1
- package/scripts/audit-tool-footprint.mjs +129 -0
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
## [1.88.3](https://github.com/appium/appium-mcp/compare/v1.88.2...v1.88.3) (2026-07-25)
|
|
2
|
+
|
|
1
3
|
## [1.88.2](https://github.com/appium/appium-mcp/compare/v1.88.1...v1.88.2) (2026-07-25)
|
|
2
4
|
|
|
3
5
|
## [1.88.1](https://github.com/appium/appium-mcp/compare/v1.88.0...v1.88.1) (2026-07-25)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-mcp",
|
|
3
3
|
"mcpName": "io.github.appium/appium-mcp",
|
|
4
|
-
"version": "1.88.
|
|
4
|
+
"version": "1.88.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"inspect": "npx fastmcp inspect src/index.js",
|
|
42
42
|
"dev:built": "node dist/index.js",
|
|
43
43
|
"inspect:built": "npx @modelcontextprotocol/inspector node dist/index.js",
|
|
44
|
+
"audit:tools": "node scripts/audit-tool-footprint.mjs",
|
|
44
45
|
"verify:names": "node scripts/verify-names.mjs",
|
|
45
46
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
46
47
|
"test:locators": "NODE_OPTIONS=--experimental-vm-modules jest src/tests/generate-all-locators.test.ts",
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
8
|
+
|
|
9
|
+
const MAX_DISCOVERY_CHARS = 47_000;
|
|
10
|
+
const ESTIMATED_CHARS_PER_TOKEN = 4;
|
|
11
|
+
const LARGEST_TOOL_COUNT = 10;
|
|
12
|
+
|
|
13
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const projectRoot = join(scriptDir, '..');
|
|
15
|
+
const serverEntry = join(projectRoot, 'dist', 'index.js');
|
|
16
|
+
|
|
17
|
+
if (!existsSync(serverEntry)) {
|
|
18
|
+
console.error(
|
|
19
|
+
`Built server not found at ${serverEntry}. Run "npm run build" first.`
|
|
20
|
+
);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const transport = new StdioClientTransport({
|
|
25
|
+
command: process.execPath,
|
|
26
|
+
args: [serverEntry],
|
|
27
|
+
cwd: projectRoot,
|
|
28
|
+
env: {
|
|
29
|
+
AI_VISION_ENABLED: 'false',
|
|
30
|
+
APPIUM_MCP_DOCS_ENABLED: 'false',
|
|
31
|
+
APPIUM_MCP_OTEL_ENABLED: 'false',
|
|
32
|
+
NO_UI: 'true',
|
|
33
|
+
},
|
|
34
|
+
stderr: 'ignore',
|
|
35
|
+
});
|
|
36
|
+
const client = new Client({
|
|
37
|
+
name: 'appium-mcp-tool-footprint-audit',
|
|
38
|
+
version: '1.0.0',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
await client.connect(transport);
|
|
43
|
+
const result = await client.listTools();
|
|
44
|
+
const payloadChars = JSON.stringify(result).length;
|
|
45
|
+
const withoutDescriptionsChars = JSON.stringify(
|
|
46
|
+
removeDescriptionFields(result)
|
|
47
|
+
).length;
|
|
48
|
+
const withoutParameterDescriptionsChars = JSON.stringify(
|
|
49
|
+
removeParameterDescriptions(result)
|
|
50
|
+
).length;
|
|
51
|
+
const estimatedTokens = Math.ceil(payloadChars / ESTIMATED_CHARS_PER_TOKEN);
|
|
52
|
+
const remainingChars = MAX_DISCOVERY_CHARS - payloadChars;
|
|
53
|
+
const largestTools = result.tools
|
|
54
|
+
.map((tool) => ({
|
|
55
|
+
name: tool.name,
|
|
56
|
+
chars: JSON.stringify(tool).length,
|
|
57
|
+
}))
|
|
58
|
+
.sort((a, b) => b.chars - a.chars || a.name.localeCompare(b.name))
|
|
59
|
+
.slice(0, LARGEST_TOOL_COUNT);
|
|
60
|
+
|
|
61
|
+
console.log('MCP tool discovery footprint');
|
|
62
|
+
console.log(`Tools: ${formatNumber(result.tools.length)}`);
|
|
63
|
+
console.log(
|
|
64
|
+
`Payload: ${formatNumber(payloadChars)} chars (~${formatNumber(estimatedTokens)} tokens)`
|
|
65
|
+
);
|
|
66
|
+
console.log(
|
|
67
|
+
`Description overhead: ${formatNumber(payloadChars - withoutDescriptionsChars)} chars`
|
|
68
|
+
);
|
|
69
|
+
console.log(
|
|
70
|
+
`Parameter-description overhead: ${formatNumber(payloadChars - withoutParameterDescriptionsChars)} chars`
|
|
71
|
+
);
|
|
72
|
+
console.log(
|
|
73
|
+
`Budget: ${formatNumber(MAX_DISCOVERY_CHARS)} chars (${formatSignedNumber(remainingChars)} remaining)`
|
|
74
|
+
);
|
|
75
|
+
console.log('Largest tools:');
|
|
76
|
+
for (const tool of largestTools) {
|
|
77
|
+
console.log(` ${tool.name}: ${formatNumber(tool.chars)} chars`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (remainingChars < 0) {
|
|
81
|
+
console.error(
|
|
82
|
+
`Tool discovery payload exceeds the budget by ${formatNumber(-remainingChars)} chars.`
|
|
83
|
+
);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
} else {
|
|
86
|
+
console.log('Tool discovery payload is within budget.');
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(
|
|
90
|
+
`Failed to audit MCP tool discovery footprint: ${
|
|
91
|
+
error instanceof Error ? error.message : String(error)
|
|
92
|
+
}`
|
|
93
|
+
);
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
} finally {
|
|
96
|
+
await client.close().catch(() => undefined);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function removeDescriptionFields(value) {
|
|
100
|
+
if (Array.isArray(value)) {
|
|
101
|
+
return value.map(removeDescriptionFields);
|
|
102
|
+
}
|
|
103
|
+
if (value === null || typeof value !== 'object') {
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
return Object.fromEntries(
|
|
107
|
+
Object.entries(value)
|
|
108
|
+
.filter(([key]) => key !== 'description')
|
|
109
|
+
.map(([key, child]) => [key, removeDescriptionFields(child)])
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function removeParameterDescriptions(result) {
|
|
114
|
+
return {
|
|
115
|
+
...result,
|
|
116
|
+
tools: result.tools.map((tool) => ({
|
|
117
|
+
...tool,
|
|
118
|
+
inputSchema: removeDescriptionFields(tool.inputSchema),
|
|
119
|
+
})),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function formatNumber(value) {
|
|
124
|
+
return new Intl.NumberFormat('en-US').format(value);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function formatSignedNumber(value) {
|
|
128
|
+
return `${value >= 0 ? '+' : '-'}${formatNumber(Math.abs(value))}`;
|
|
129
|
+
}
|
package/server.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"name": "io.github.appium/appium-mcp",
|
|
4
4
|
"title": "MCP Appium - Mobile Development and Automation Server",
|
|
5
5
|
"description": "MCP server for Appium mobile automation on iOS and Android devices with test creation tools.",
|
|
6
|
-
"version": "1.88.
|
|
6
|
+
"version": "1.88.3",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.88.
|
|
11
|
+
"version": "1.88.3",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|