appium-mcp 1.84.2 → 1.85.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +30 -2
  3. package/dist/core.d.ts +2 -0
  4. package/dist/core.d.ts.map +1 -1
  5. package/dist/core.js +2 -0
  6. package/dist/core.js.map +1 -1
  7. package/dist/create-server.d.ts +3 -3
  8. package/dist/create-server.d.ts.map +1 -1
  9. package/dist/create-server.js +7 -3
  10. package/dist/create-server.js.map +1 -1
  11. package/dist/server.d.ts.map +1 -1
  12. package/dist/server.js +1 -1
  13. package/dist/server.js.map +1 -1
  14. package/dist/session-store.d.ts +2 -2
  15. package/dist/session-store.d.ts.map +1 -1
  16. package/dist/session-store.js +5 -13
  17. package/dist/session-store.js.map +1 -1
  18. package/dist/telemetry/attributes.d.ts +46 -0
  19. package/dist/telemetry/attributes.d.ts.map +1 -0
  20. package/dist/telemetry/attributes.js +90 -0
  21. package/dist/telemetry/attributes.js.map +1 -0
  22. package/dist/telemetry/init.d.ts +19 -0
  23. package/dist/telemetry/init.d.ts.map +1 -0
  24. package/dist/telemetry/init.js +68 -0
  25. package/dist/telemetry/init.js.map +1 -0
  26. package/dist/telemetry/tracer.d.ts +31 -0
  27. package/dist/telemetry/tracer.d.ts.map +1 -0
  28. package/dist/telemetry/tracer.js +59 -0
  29. package/dist/telemetry/tracer.js.map +1 -0
  30. package/dist/telemetry/wrapOperations.d.ts +30 -0
  31. package/dist/telemetry/wrapOperations.d.ts.map +1 -0
  32. package/dist/telemetry/wrapOperations.js +156 -0
  33. package/dist/telemetry/wrapOperations.js.map +1 -0
  34. package/dist/tools/index.d.ts.map +1 -1
  35. package/dist/tools/index.js +2 -12
  36. package/dist/tools/index.js.map +1 -1
  37. package/dist/utils/env.d.ts +2 -0
  38. package/dist/utils/env.d.ts.map +1 -0
  39. package/dist/utils/env.js +5 -0
  40. package/dist/utils/env.js.map +1 -0
  41. package/dist/utils/sensitive.d.ts +8 -0
  42. package/dist/utils/sensitive.d.ts.map +1 -0
  43. package/dist/utils/sensitive.js +27 -0
  44. package/dist/utils/sensitive.js.map +1 -0
  45. package/package.json +10 -1
  46. package/server.json +2 -2
  47. package/src/core.ts +2 -0
  48. package/src/create-server.ts +8 -4
  49. package/src/server.ts +1 -1
  50. package/src/session-store.ts +6 -20
  51. package/src/telemetry/attributes.ts +104 -0
  52. package/src/telemetry/init.ts +77 -0
  53. package/src/telemetry/tracer.ts +75 -0
  54. package/src/telemetry/wrapOperations.ts +245 -0
  55. package/src/tools/index.ts +2 -14
  56. package/src/utils/env.ts +5 -0
  57. package/src/utils/sensitive.ts +30 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared tracer helpers for appium-mcp instrumentation. Tool, prompt, and
3
+ * resource wrappers use this module so span creation, exception recording, and
4
+ * disabled-telemetry behavior stay consistent across MCP operation types.
5
+ */
6
+ import { context, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
7
+ import { isTelemetryEnabled } from './attributes.js';
8
+ const TRACER_NAME = 'appium-mcp';
9
+ /**
10
+ * Gets the OpenTelemetry tracer for appium-mcp. This is used by tool, prompt,
11
+ * and resource wrappers to create spans with a consistent name and configuration.
12
+ * @returns The OpenTelemetry tracer for appium-mcp.
13
+ */
14
+ export function getAppiumMcpTracer() {
15
+ return trace.getTracer(TRACER_NAME);
16
+ }
17
+ /**
18
+ * Gets the currently active OpenTelemetry span from the context. This is used by
19
+ * tool, prompt, and resource wrappers to add attributes or record exceptions on the
20
+ * active span without needing to pass the span object through multiple layers of calls.
21
+ * @returns The currently active OpenTelemetry span, or undefined if there is no active span.
22
+ */
23
+ export function getActiveSpan() {
24
+ return trace.getActiveSpan();
25
+ }
26
+ /**
27
+ * Runs the given asynchronous operation within a new OpenTelemetry span with the specified name and attributes.
28
+ * If telemetry is not enabled, the operation is run without creating a span.
29
+ * If the operation throws an error, the error is recorded on the span and re-thrown.
30
+ * @param name The name of the span.
31
+ * @param attributes The attributes to set on the span.
32
+ * @param operation The asynchronous operation to run within the span.
33
+ * @returns The result of the asynchronous operation.
34
+ */
35
+ export async function withSpan(name, attributes, operation) {
36
+ if (!isTelemetryEnabled()) {
37
+ return operation();
38
+ }
39
+ const span = getAppiumMcpTracer().startSpan(name, {
40
+ attributes,
41
+ kind: SpanKind.INTERNAL,
42
+ });
43
+ try {
44
+ return await context.with(trace.setSpan(context.active(), span), operation);
45
+ }
46
+ catch (error) {
47
+ span.recordException(error);
48
+ span.setStatus({
49
+ code: SpanStatusCode.ERROR,
50
+ message: error instanceof Error ? error.message : String(error),
51
+ });
52
+ throw error;
53
+ }
54
+ finally {
55
+ span.end();
56
+ }
57
+ }
58
+ export { SpanStatusCode };
59
+ //# sourceMappingURL=tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/telemetry/tracer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,OAAO,EACP,QAAQ,EACR,cAAc,EACd,KAAK,GAEN,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,WAAW,GAAG,YAAY,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,KAAK,CAAC,aAAa,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAY,EACZ,UAAsB,EACtB,SAA2B;IAE3B,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAC1B,OAAO,SAAS,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE;QAChD,UAAU;QACV,IAAI,EAAE,QAAQ,CAAC,QAAQ;KACxB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,eAAe,CAAC,KAAc,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,cAAc,CAAC,KAAK;YAC1B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAC;QACH,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,GAAG,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * FastMCP operation wrappers that create spans around registered MCP handlers.
3
+ * Installing these wrappers before built-in and plugin registration covers
4
+ * tools, prompts, resources, and resource templates without changing handler
5
+ * return values or recording sensitive request/response payloads.
6
+ */
7
+ import type { FastMCP } from 'fastmcp';
8
+ type ToolDef = Parameters<FastMCP['addTool']>[0];
9
+ /**
10
+ * Installs telemetry wrappers on the given FastMCP server instance. This should be
11
+ * called early in the server setup process, before registering any tools, prompts,
12
+ * or resources, to ensure that all operations are wrapped with OpenTelemetry spans.
13
+ * Each span will be named according to the operation type and include attributes
14
+ * such as tool name, prompt name, resource URI, session ID, and input keys, while
15
+ * avoiding any sensitive information.
16
+ * @param server The FastMCP server instance on which to install telemetry wrappers.
17
+ */
18
+ export declare function installTelemetryWrappers(server: FastMCP): void;
19
+ /**
20
+ * Wraps a tool definition with telemetry spans around its execute function.
21
+ * The span will be named "tools/call {toolName}" and include attributes for the tool name,
22
+ * session ID (if available), and input keys. If the tool execution results in an error,
23
+ * the span status will be set to error and an attribute will indicate that the result is an error.
24
+ * @param toolDef The original tool definition to wrap.
25
+ * @returns A new tool definition with telemetry spans around the execute function.
26
+ */
27
+ export declare function wrapToolWithTelemetry(toolDef: ToolDef): ToolDef;
28
+ export declare function safeInputValueAttributes(args: unknown): Record<string, string | number | boolean | string[]>;
29
+ export {};
30
+ //# sourceMappingURL=wrapOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapOperations.d.ts","sourceRoot":"","sources":["../../src/telemetry/wrapOperations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWvC,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAUjD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAmC9D;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAwB/D;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAmBtD"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * FastMCP operation wrappers that create spans around registered MCP handlers.
3
+ * Installing these wrappers before built-in and plugin registration covers
4
+ * tools, prompts, resources, and resource templates without changing handler
5
+ * return values or recording sensitive request/response payloads.
6
+ */
7
+ import { isArgumentValueTelemetryEnabled, safeAttributeValue, safeInputKeys, safeSessionId, } from './attributes.js';
8
+ import { getActiveSpan, SpanStatusCode, withSpan } from './tracer.js';
9
+ import { isSensitiveKey } from '../utils/sensitive.js';
10
+ /**
11
+ * Installs telemetry wrappers on the given FastMCP server instance. This should be
12
+ * called early in the server setup process, before registering any tools, prompts,
13
+ * or resources, to ensure that all operations are wrapped with OpenTelemetry spans.
14
+ * Each span will be named according to the operation type and include attributes
15
+ * such as tool name, prompt name, resource URI, session ID, and input keys, while
16
+ * avoiding any sensitive information.
17
+ * @param server The FastMCP server instance on which to install telemetry wrappers.
18
+ */
19
+ export function installTelemetryWrappers(server) {
20
+ const originalAddTool = server.addTool.bind(server);
21
+ server.addTool = ((toolDef) => originalAddTool(wrapToolWithTelemetry(toolDef)));
22
+ if (typeof server.addPrompt === 'function') {
23
+ const originalAddPrompt = server.addPrompt.bind(server);
24
+ server.addPrompt = ((promptDef) => originalAddPrompt(wrapPromptWithTelemetry(promptDef)));
25
+ }
26
+ if (typeof server.addResource === 'function') {
27
+ const originalAddResource = server.addResource.bind(server);
28
+ server.addResource = ((resourceDef) => originalAddResource(wrapResourceWithTelemetry(resourceDef)));
29
+ }
30
+ if (typeof server.addResourceTemplate === 'function') {
31
+ const originalAddResourceTemplate = server.addResourceTemplate.bind(server);
32
+ server.addResourceTemplate = ((resourceTemplateDef) => originalAddResourceTemplate(wrapResourceTemplateWithTelemetry(resourceTemplateDef)));
33
+ }
34
+ }
35
+ /**
36
+ * Wraps a tool definition with telemetry spans around its execute function.
37
+ * The span will be named "tools/call {toolName}" and include attributes for the tool name,
38
+ * session ID (if available), and input keys. If the tool execution results in an error,
39
+ * the span status will be set to error and an attribute will indicate that the result is an error.
40
+ * @param toolDef The original tool definition to wrap.
41
+ * @returns A new tool definition with telemetry spans around the execute function.
42
+ */
43
+ export function wrapToolWithTelemetry(toolDef) {
44
+ const execute = toolDef.execute;
45
+ if (!execute) {
46
+ return toolDef;
47
+ }
48
+ const toolName = toolDef.name ?? 'unknown_tool';
49
+ return {
50
+ ...toolDef,
51
+ execute: async (args, context) => withSpan(`tools/call ${toolName}`, toolAttributes(toolName, args), async () => {
52
+ const result = await execute(args, context);
53
+ if (isErrorResult(result)) {
54
+ getActiveSpan()?.setStatus({ code: SpanStatusCode.ERROR });
55
+ getActiveSpan()?.setAttribute('mcp.tool.result.is_error', true);
56
+ }
57
+ return result;
58
+ }),
59
+ };
60
+ }
61
+ export function safeInputValueAttributes(args) {
62
+ if (!isArgumentValueTelemetryEnabled()) {
63
+ return {};
64
+ }
65
+ if (!args || typeof args !== 'object' || Array.isArray(args)) {
66
+ return {};
67
+ }
68
+ const attributes = {};
69
+ for (const [key, value] of Object.entries(args)) {
70
+ // do not include sensitive keys as attributes, and avoid logging large strings or buffers
71
+ if (isSensitiveKey(key)) {
72
+ continue;
73
+ }
74
+ attributes[`mcp.input.value.${key}`] = safeAttributeValue(value);
75
+ }
76
+ return attributes;
77
+ }
78
+ /**
79
+ * Wraps a prompt definition with telemetry spans around its load function.
80
+ * The span will be named "prompts/get {promptName}" and include attributes for the prompt name
81
+ * and input keys. If the prompt load results in an error, the span status will be set to error
82
+ * and an attribute will indicate that the result is an error.
83
+ * @param promptDef The original prompt definition to wrap.
84
+ * @returns A new prompt definition with telemetry spans around the load function.
85
+ */
86
+ function wrapPromptWithTelemetry(promptDef) {
87
+ const load = promptDef.load;
88
+ if (!load) {
89
+ return promptDef;
90
+ }
91
+ const promptName = promptDef.name ?? 'unknown_prompt';
92
+ return {
93
+ ...promptDef,
94
+ load: async (args, auth) => withSpan(`prompts/get ${promptName}`, {
95
+ 'mcp.prompt.name': promptName,
96
+ ...inputAttributes(args),
97
+ }, () => load(args, auth)),
98
+ };
99
+ }
100
+ function wrapResourceWithTelemetry(resourceDef) {
101
+ const load = resourceDef.load;
102
+ if (!load) {
103
+ return resourceDef;
104
+ }
105
+ const uri = resourceDef.uri ?? 'unknown_resource';
106
+ return {
107
+ ...resourceDef,
108
+ load: async () => withSpan('resources/read', {
109
+ 'mcp.resource.uri': uri,
110
+ }, () => load()),
111
+ };
112
+ }
113
+ function wrapResourceTemplateWithTelemetry(resourceTemplateDef) {
114
+ const load = resourceTemplateDef.load;
115
+ if (!load) {
116
+ return resourceTemplateDef;
117
+ }
118
+ const uriTemplate = resourceTemplateDef.uriTemplate?.toString() ?? 'unknown_resource_template';
119
+ return {
120
+ ...resourceTemplateDef,
121
+ load: async (args, auth) => withSpan('resources/read', {
122
+ 'mcp.resource.uri_template': uriTemplate,
123
+ ...inputAttributes(args),
124
+ }, () => load(args, auth)),
125
+ };
126
+ }
127
+ function toolAttributes(toolName, args) {
128
+ const attributes = {
129
+ 'mcp.tool.name': toolName,
130
+ };
131
+ const sessionId = safeSessionId(args);
132
+ if (sessionId) {
133
+ attributes['appium.session.id'] = sessionId;
134
+ }
135
+ return {
136
+ ...attributes,
137
+ ...inputAttributes(args),
138
+ };
139
+ }
140
+ function inputAttributes(args) {
141
+ return {
142
+ ...inputKeyAttributes(args),
143
+ ...safeInputValueAttributes(args),
144
+ };
145
+ }
146
+ function inputKeyAttributes(args) {
147
+ const inputKeys = safeInputKeys(args);
148
+ return inputKeys.length > 0 ? { 'mcp.input.keys': inputKeys } : {};
149
+ }
150
+ function isErrorResult(result) {
151
+ return (!!result &&
152
+ typeof result === 'object' &&
153
+ 'isError' in result &&
154
+ result.isError === true);
155
+ }
156
+ //# sourceMappingURL=wrapOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapOperations.js","sourceRoot":"","sources":["../../src/telemetry/wrapOperations.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAsCtD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAmJ3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAuCtD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAsI3D"}
@@ -1,4 +1,5 @@
1
1
  import log from '../logger.js';
2
+ import { isSensitiveKey } from '../utils/sensitive.js';
2
3
  import session from './session/session.js';
3
4
  import generateLocators from './test-generation/locators.js';
4
5
  import selectDevice from './session/select-device.js';
@@ -41,24 +42,13 @@ export default function registerTools(server) {
41
42
  if (typeof originalExecute !== 'function') {
42
43
  return originalAddTool(toolDef);
43
44
  }
44
- const SENSITIVE_KEYS = [
45
- 'password',
46
- 'token',
47
- 'accesstoken',
48
- 'authorization',
49
- 'apikey',
50
- 'secret',
51
- 'clientsecret',
52
- 'remoteserverurl',
53
- ];
54
45
  const redactArgs = (obj) => {
55
46
  if (obj === undefined || obj === null) {
56
47
  return obj;
57
48
  }
58
49
  try {
59
50
  return JSON.parse(JSON.stringify(obj, (key, value) => {
60
- if (key &&
61
- SENSITIVE_KEYS.some((k) => key.toLowerCase().includes(k))) {
51
+ if (key && isSensitiveKey(key)) {
62
52
  return '[REDACTED]';
63
53
  }
64
54
  // Avoid logging extremely large buffers/strings
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function isTruthyEnvValue(value: string | undefined): boolean;
2
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEnE"}
@@ -0,0 +1,5 @@
1
+ const TRUE_VALUES = new Set(['1', 'true', 'yes', 'on']);
2
+ export function isTruthyEnvValue(value) {
3
+ return TRUE_VALUES.has(value?.trim().toLowerCase() ?? '');
4
+ }
5
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAExD,MAAM,UAAU,gBAAgB,CAAC,KAAyB;IACxD,OAAO,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Determines if a given key is considered sensitive based on whether it includes any of the defined sensitive key parts.
3
+ * The check is case-insensitive and ignores non-alphanumeric characters, so keys like "API-Key", "client secret", or "remote_server_url" would all be correctly identified as sensitive.
4
+ * @param key The key to check for sensitivity.
5
+ * @returns True if the key is considered sensitive, false otherwise.
6
+ */
7
+ export declare function isSensitiveKey(key: string): boolean;
8
+ //# sourceMappingURL=sensitive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive.d.ts","sourceRoot":"","sources":["../../src/utils/sensitive.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKnD"}
@@ -0,0 +1,27 @@
1
+ const SENSITIVE_KEY_PARTS = [
2
+ 'api_key',
3
+ 'apikey',
4
+ 'authorization',
5
+ 'client_secret',
6
+ 'clientsecret',
7
+ 'credential',
8
+ 'password',
9
+ 'remote_server_url',
10
+ 'remoteserverurl',
11
+ 'secret',
12
+ 'token',
13
+ ];
14
+ /**
15
+ * Determines if a given key is considered sensitive based on whether it includes any of the defined sensitive key parts.
16
+ * The check is case-insensitive and ignores non-alphanumeric characters, so keys like "API-Key", "client secret", or "remote_server_url" would all be correctly identified as sensitive.
17
+ * @param key The key to check for sensitivity.
18
+ * @returns True if the key is considered sensitive, false otherwise.
19
+ */
20
+ export function isSensitiveKey(key) {
21
+ const normalized = normalizeKey(key);
22
+ return SENSITIVE_KEY_PARTS.some((part) => normalized.includes(normalizeKey(part)));
23
+ }
24
+ function normalizeKey(key) {
25
+ return key.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
26
+ }
27
+ //# sourceMappingURL=sensitive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive.js","sourceRoot":"","sources":["../../src/utils/sensitive.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG;IAC1B,SAAS;IACT,QAAQ;IACR,eAAe;IACf,eAAe;IACf,cAAc;IACd,YAAY;IACZ,UAAU;IACV,mBAAmB;IACnB,iBAAiB;IACjB,QAAQ;IACR,OAAO;CACR,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACvC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CACxC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACxD,CAAC"}
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.84.2",
4
+ "version": "1.85.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -32,6 +32,11 @@
32
32
  "start:stdio": "node dist/index.js",
33
33
  "start:httpStream": "node dist/index.js --httpStream",
34
34
  "start:httpStream:port": "node dist/index.js --httpStream --port=",
35
+ "telemetry:jaeger:start": "sh tools/telemetry/jaeger.sh start",
36
+ "telemetry:jaeger:stop": "sh tools/telemetry/jaeger.sh stop",
37
+ "telemetry:jaeger:logs": "sh tools/telemetry/jaeger.sh logs",
38
+ "telemetry:jaeger:config": "sh tools/telemetry/jaeger.sh config",
39
+ "telemetry:appium:start:httpStream": "APPIUM_MCP_OTEL_ENABLED=true OTEL_SERVICE_NAME=appium-mcp-local OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://127.0.0.1:4318/v1/traces OTEL_TRACES_SAMPLER=parentbased_always_on npm run start:httpStream",
35
40
  "dev": "npx fastmcp dev src/index.js",
36
41
  "inspect": "npx fastmcp inspect src/index.js",
37
42
  "dev:built": "node dist/index.js",
@@ -55,6 +60,10 @@
55
60
  "@appium/mcp-documentation": "^1.0.1",
56
61
  "@appium/support": "^7.0.2",
57
62
  "@modelcontextprotocol/sdk": "^1.22.0",
63
+ "@opentelemetry/api": "^1.9.1",
64
+ "@opentelemetry/exporter-trace-otlp-http": "^0.218.0",
65
+ "@opentelemetry/sdk-node": "^0.218.0",
66
+ "@xenova/transformers": "^2.17.2",
58
67
  "@xmldom/xmldom": "^0.9.8",
59
68
  "appium-adb": "^15.0.0",
60
69
  "appium-ios-device": "^3.1.0",
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.84.2",
6
+ "version": "1.85.0",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "appium-mcp",
11
- "version": "1.84.2",
11
+ "version": "1.85.0",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }
package/src/core.ts CHANGED
@@ -21,6 +21,8 @@ export {
21
21
  PluginManager,
22
22
  verifyAppiumMcpNames,
23
23
  } from './plugin.js';
24
+ export { isTelemetryEnabled } from './telemetry/attributes.js';
25
+ export { getAppiumMcpTracer, withSpan } from './telemetry/tracer.js';
24
26
  export type {
25
27
  AppiumMcpPlugin,
26
28
  PluginContext,
@@ -5,7 +5,7 @@
5
5
  * ```ts
6
6
  * import { createAppiumMcpServer } from 'appium-mcp/core';
7
7
  *
8
- * const server = createAppiumMcpServer({
8
+ * const server = await createAppiumMcpServer({
9
9
  * plugins: [new CheckoutPlugin(), new LoginGuardPlugin()],
10
10
  * });
11
11
  *
@@ -22,6 +22,8 @@ import log from './logger.js';
22
22
  import { PluginManager } from './plugin.js';
23
23
  import type { AppiumMcpPlugin } from './plugin.js';
24
24
  import { installPolicy, type AppiumMcpPolicy } from './policy.js';
25
+ import { initializeOpenTelemetry } from './telemetry/init.js';
26
+ import { installTelemetryWrappers } from './telemetry/wrapOperations.js';
25
27
 
26
28
  const SERVER_VERSION = pkg.version as `${number}.${number}.${number}`;
27
29
 
@@ -82,11 +84,11 @@ type DisconnectSessionPolicy = 'delete_all' | 'skip';
82
84
  * server. It replicates the setup that the default `server.ts` performs, while
83
85
  * also registering plugin tools and lifecycle hooks.
84
86
  *
85
- * @returns A configured `FastMCP` instance ready to be `start()`-ed.
87
+ * @returns A promise resolving to a configured `FastMCP` instance ready to be `start()`-ed.
86
88
  */
87
- export function createAppiumMcpServer(
89
+ export async function createAppiumMcpServer(
88
90
  options: CreateAppiumMcpServerOptions = {}
89
- ): FastMCP {
91
+ ): Promise<FastMCP> {
90
92
  const {
91
93
  plugins = [],
92
94
  serverName = 'MCP Appium',
@@ -110,6 +112,8 @@ export function createAppiumMcpServer(
110
112
  });
111
113
 
112
114
  installPolicy(server, policy);
115
+ await initializeOpenTelemetry();
116
+ installTelemetryWrappers(server);
113
117
 
114
118
  // -------------------------------------------------------------------------
115
119
  // 1. Install plugin hooks BEFORE registering any tools so that every built-in
package/src/server.ts CHANGED
@@ -8,5 +8,5 @@ try {
8
8
  plugins.push(new AppiumDocumentation());
9
9
  } catch (_err) {}
10
10
 
11
- const server = createAppiumMcpServer({ plugins });
11
+ const server = await createAppiumMcpServer({ plugins });
12
12
  export default server;
@@ -1,5 +1,5 @@
1
- import { AndroidUiautomator2Driver } from 'appium-uiautomator2-driver';
2
- import { XCUITestDriver } from 'appium-xcuitest-driver';
1
+ import type { AndroidUiautomator2Driver } from 'appium-uiautomator2-driver';
2
+ import type { XCUITestDriver } from 'appium-xcuitest-driver';
3
3
  import type { Client } from 'webdriver';
4
4
  import log from './logger.js';
5
5
  import {
@@ -58,9 +58,7 @@ export const PLATFORM = {
58
58
  export function isRemoteDriverSession(driver: NullableDriverInstance): boolean {
59
59
  if (driver) {
60
60
  return (
61
- !(driver instanceof AndroidUiautomator2Driver) &&
62
61
  driver.constructor?.name !== 'AndroidUiautomator2Driver' &&
63
- !(driver instanceof XCUITestDriver) &&
64
62
  driver.constructor?.name !== 'XCUITestDriver'
65
63
  );
66
64
  }
@@ -82,10 +80,7 @@ export function isRemoteDriverSession(driver: NullableDriverInstance): boolean {
82
80
  export function isAndroidUiautomator2DriverSession(
83
81
  driver: NullableDriverInstance
84
82
  ): driver is AndroidUiautomator2Driver {
85
- return (
86
- driver instanceof AndroidUiautomator2Driver ||
87
- driver?.constructor?.name === 'AndroidUiautomator2Driver'
88
- );
83
+ return driver?.constructor?.name === 'AndroidUiautomator2Driver';
89
84
  }
90
85
 
91
86
  /**
@@ -102,10 +97,7 @@ export function isAndroidUiautomator2DriverSession(
102
97
  export function isXCUITestDriverSession(
103
98
  driver: NullableDriverInstance
104
99
  ): driver is XCUITestDriver {
105
- return (
106
- driver instanceof XCUITestDriver ||
107
- driver?.constructor?.name === 'XCUITestDriver'
108
- );
100
+ return driver?.constructor?.name === 'XCUITestDriver';
109
101
  }
110
102
 
111
103
  export async function setSession(
@@ -392,16 +384,10 @@ function selectNextActiveSessionId(deletedSessionId: string): string | null {
392
384
  }
393
385
 
394
386
  export const getPlatformName = (driver: any): string => {
395
- if (
396
- driver instanceof AndroidUiautomator2Driver ||
397
- driver?.constructor?.name === 'AndroidUiautomator2Driver'
398
- ) {
387
+ if (driver?.constructor?.name === 'AndroidUiautomator2Driver') {
399
388
  return PLATFORM.android;
400
389
  }
401
- if (
402
- driver instanceof XCUITestDriver ||
403
- driver?.constructor?.name === 'XCUITestDriver'
404
- ) {
390
+ if (driver?.constructor?.name === 'XCUITestDriver') {
405
391
  return PLATFORM.ios;
406
392
  }
407
393