appium-mcp 1.2.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.3.0](https://github.com/appium/appium-mcp/compare/v1.2.0...v1.3.0) (2025-12-05)
2
+
3
+ ### Features
4
+
5
+ * add new tools to get active contexts and switch context ([#51](https://github.com/appium/appium-mcp/issues/51)) ([e6ffad0](https://github.com/appium/appium-mcp/commit/e6ffad0a73522f0df2d6a8550fd0a751f797cc40))
6
+
1
7
  ## [1.2.0](https://github.com/appium/appium-mcp/compare/v1.1.17...v1.2.0) (2025-12-01)
2
8
 
3
9
  ### Features
package/README.md CHANGED
@@ -178,6 +178,13 @@ MCP Appium provides a comprehensive set of tools organized into the following ca
178
178
  | `create_session` | Create a new mobile automation session for Android or iOS |
179
179
  | `delete_session` | Delete the current mobile session and clean up resources |
180
180
 
181
+ ### Context Management
182
+
183
+ | Tool | Description |
184
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
185
+ | `appium_get_contexts` | Get all available contexts in the current Appium session. Returns a list of context names including NATIVE_APP and any webview contexts (e.g., WEBVIEW_<id> or WEBVIEW_<package>). |
186
+ | `appium_switch_context` | Switch to a specific context in the Appium session. Use this to switch between native app context (NATIVE_APP) and webview contexts (WEBVIEW_<id> or WEBVIEW_<package>). Use appium_get_contexts to see available contexts first. |
187
+
181
188
  ### Element Discovery & Interaction
182
189
 
183
190
  | Tool | Description |
@@ -1,3 +1,7 @@
1
+ export declare const PLATFORM: {
2
+ android: string;
3
+ ios: string;
4
+ };
1
5
  export declare function setSession(d: any, id: string | null): void;
2
6
  export declare function getDriver(): any;
3
7
  export declare function getSessionId(): string | null;
@@ -4,6 +4,10 @@ import log from './logger.js';
4
4
  let driver = null;
5
5
  let sessionId = null;
6
6
  let isDeletingSession = false; // Lock to prevent concurrent deletion
7
+ export const PLATFORM = {
8
+ android: 'Android',
9
+ ios: 'iOS',
10
+ };
7
11
  export function setSession(d, id) {
8
12
  driver = d;
9
13
  sessionId = id;
@@ -57,9 +61,9 @@ export async function safeDeleteSession() {
57
61
  }
58
62
  export const getPlatformName = (driver) => {
59
63
  if (driver instanceof AndroidUiautomator2Driver)
60
- return 'Android';
64
+ return PLATFORM.android;
61
65
  if (driver instanceof XCUITestDriver)
62
- return 'iOS';
66
+ return PLATFORM.ios;
63
67
  throw new Error('Unknown driver type');
64
68
  };
65
69
  //# sourceMappingURL=session-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,GAAG,MAAM,aAAa,CAAC;AAE9B,IAAI,MAAM,GAAQ,IAAI,CAAC;AACvB,IAAI,SAAS,GAAkB,IAAI,CAAC;AACpC,IAAI,iBAAiB,GAAG,KAAK,CAAC,CAAC,sCAAsC;AAErE,MAAM,UAAU,UAAU,CAAC,CAAM,EAAE,EAAiB;IAClD,MAAM,GAAG,CAAC,CAAC;IACX,SAAS,GAAG,EAAE,CAAC;IACf,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACZ,iBAAiB,GAAG,KAAK,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,iBAAiB,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,wCAAwC;IACxC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2CAA2C;IAC3C,IAAI,iBAAiB,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW;IACX,iBAAiB,GAAG,IAAI,CAAC;IAEzB,IAAI,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACrC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;QAE7B,+BAA+B;QAC/B,MAAM,GAAG,IAAI,CAAC;QACd,SAAS,GAAG,IAAI,CAAC;QAEjB,GAAG,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,sBAAsB;QACtB,iBAAiB,GAAG,KAAK,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAW,EAAU,EAAE;IACrD,IAAI,MAAM,YAAY,yBAAyB;QAAE,OAAO,SAAS,CAAC;IAClE,IAAI,MAAM,YAAY,cAAc;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AACzC,CAAC,CAAC"}
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,GAAG,MAAM,aAAa,CAAC;AAE9B,IAAI,MAAM,GAAQ,IAAI,CAAC;AACvB,IAAI,SAAS,GAAkB,IAAI,CAAC;AACpC,IAAI,iBAAiB,GAAG,KAAK,CAAC,CAAC,sCAAsC;AAErE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,KAAK;CACX,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,CAAM,EAAE,EAAiB;IAClD,MAAM,GAAG,CAAC,CAAC;IACX,SAAS,GAAG,EAAE,CAAC;IACf,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACZ,iBAAiB,GAAG,KAAK,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,iBAAiB,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,wCAAwC;IACxC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2CAA2C;IAC3C,IAAI,iBAAiB,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW;IACX,iBAAiB,GAAG,IAAI,CAAC;IAEzB,IAAI,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACrC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;QAE7B,+BAA+B;QAC/B,MAAM,GAAG,IAAI,CAAC;QACd,SAAS,GAAG,IAAI,CAAC;QAEjB,GAAG,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,sBAAsB;QACtB,iBAAiB,GAAG,KAAK,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAW,EAAU,EAAE;IACrD,IAAI,MAAM,YAAY,yBAAyB;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;IACzE,IAAI,MAAM,YAAY,cAAc;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC;IAC1D,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AACzC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { FastMCP } from 'fastmcp/dist/FastMCP.js';
2
+ export default function getContexts(server: FastMCP): void;
@@ -0,0 +1,55 @@
1
+ import { z } from 'zod';
2
+ import { getDriver } from '../../session-store.js';
3
+ export default function getContexts(server) {
4
+ server.addTool({
5
+ name: 'appium_get_contexts',
6
+ description: 'Get all available contexts in the current Appium session. Returns a list of context names including NATIVE_APP and any webview contexts (e.g., WEBVIEW_<id> or WEBVIEW_<package>).',
7
+ parameters: z.object({}),
8
+ annotations: {
9
+ readOnlyHint: true,
10
+ openWorldHint: false,
11
+ },
12
+ execute: async (args, context) => {
13
+ const driver = getDriver();
14
+ if (!driver) {
15
+ throw new Error('No driver found. Please create a session first.');
16
+ }
17
+ try {
18
+ const [currentContext, contexts] = await Promise.all([
19
+ driver.getCurrentContext().catch(() => null),
20
+ driver.getContexts().catch(() => []),
21
+ ]);
22
+ if (!contexts || contexts.length === 0) {
23
+ return {
24
+ content: [
25
+ {
26
+ type: 'text',
27
+ text: 'No contexts available.',
28
+ },
29
+ ],
30
+ };
31
+ }
32
+ return {
33
+ content: [
34
+ {
35
+ type: 'text',
36
+ text: `Available contexts: ${JSON.stringify(contexts, null, 2)}\nCurrent context: ${currentContext || 'N/A'}`,
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ catch (err) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: 'text',
46
+ text: `Failed to get contexts. Error: ${err.toString()}`,
47
+ },
48
+ ],
49
+ isError: true,
50
+ };
51
+ }
52
+ },
53
+ });
54
+ }
55
+ //# sourceMappingURL=get-contexts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-contexts.js","sourceRoot":"","sources":["../../../src/tools/context/get-contexts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,MAAe;IACjD,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,oLAAoL;QACtL,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,OAAY,EAAgB,EAAE;YACvD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBACnD,MAAM,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;oBAC5C,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;iBACrC,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvC,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,wBAAwB;6BAC/B;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,uBAAuB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,sBAAsB,cAAc,IAAI,KAAK,EAAE;yBAC9G;qBACF;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,kCAAkC,GAAG,CAAC,QAAQ,EAAE,EAAE;yBACzD;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { FastMCP } from 'fastmcp/dist/FastMCP.js';
2
+ export default function switchContext(server: FastMCP): void;
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+ import { getDriver } from '../../session-store.js';
3
+ export default function switchContext(server) {
4
+ const schema = z.object({
5
+ context: z
6
+ .string()
7
+ .describe('The name of the context to switch to. Common values: "NATIVE_APP" for native context, or "WEBVIEW_<id>" / "WEBVIEW_<package>" for webview contexts.'),
8
+ });
9
+ server.addTool({
10
+ name: 'appium_switch_context',
11
+ description: 'Switch to a specific context in the Appium session. Use this to switch between native app context (NATIVE_APP) and webview contexts (WEBVIEW_<id> or WEBVIEW_<package>). Use appium_get_contexts to see available contexts first.',
12
+ parameters: schema,
13
+ annotations: {
14
+ readOnlyHint: false,
15
+ openWorldHint: false,
16
+ },
17
+ execute: async (args, context) => {
18
+ const driver = getDriver();
19
+ if (!driver) {
20
+ throw new Error('No driver found. Please create a session first.');
21
+ }
22
+ try {
23
+ const [currentContext, availableContexts] = await Promise.all([
24
+ driver.getCurrentContext().catch(() => null),
25
+ driver.getContexts().catch(() => []),
26
+ ]);
27
+ if (currentContext === args.context) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: `Already on context "${args.context}".`,
33
+ },
34
+ ],
35
+ };
36
+ }
37
+ if (!availableContexts || availableContexts.length === 0) {
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: 'No contexts available. Cannot switch context.',
43
+ },
44
+ ],
45
+ isError: true,
46
+ };
47
+ }
48
+ if (!availableContexts.includes(args.context)) {
49
+ return {
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: `Context "${args.context}" not found. Available contexts: ${JSON.stringify(availableContexts, null, 2)}`,
54
+ },
55
+ ],
56
+ isError: true,
57
+ };
58
+ }
59
+ await driver.switchContext(args.context);
60
+ // Verify the switch was successful
61
+ const newContext = await driver.getCurrentContext();
62
+ return {
63
+ content: [
64
+ {
65
+ type: 'text',
66
+ text: `Successfully switched context from "${currentContext || 'N/A'}" to "${newContext}".`,
67
+ },
68
+ ],
69
+ };
70
+ }
71
+ catch (err) {
72
+ return {
73
+ content: [
74
+ {
75
+ type: 'text',
76
+ text: `Failed to switch context. Error: ${err.toString()}`,
77
+ },
78
+ ],
79
+ isError: true,
80
+ };
81
+ }
82
+ },
83
+ });
84
+ }
85
+ //# sourceMappingURL=switch-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch-context.js","sourceRoot":"","sources":["../../../src/tools/context/switch-context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAA6B,MAAM,wBAAwB,CAAC;AAE9E,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAe;IACnD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QACtB,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CACP,qJAAqJ,CACtJ;KACJ,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EACT,mOAAmO;QACrO,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE;YACX,YAAY,EAAE,KAAK;YACnB,aAAa,EAAE,KAAK;SACrB;QACD,OAAO,EAAE,KAAK,EAAE,IAAS,EAAE,OAAY,EAAgB,EAAE;YACvD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBAC5D,MAAM,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;oBAC5C,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;iBACrC,CAAC,CAAC;gBAEH,IAAI,cAAc,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;oBACpC,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,uBAAuB,IAAI,CAAC,OAAO,IAAI;6BAC9C;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzD,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,+CAA+C;6BACtD;yBACF;wBACD,OAAO,EAAE,IAAI;qBACd,CAAC;gBACJ,CAAC;gBAED,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC9C,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,YAAY,IAAI,CAAC,OAAO,oCAAoC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;6BAC/G;yBACF;wBACD,OAAO,EAAE,IAAI;qBACd,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAEzC,mCAAmC;gBACnC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAEpD,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,uCAAuC,cAAc,IAAI,KAAK,SAAS,UAAU,IAAI;yBAC5F;qBACF;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,oCAAoC,GAAG,CAAC,QAAQ,EAAE,EAAE;yBAC3D;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -24,6 +24,8 @@ import installApp from './app-management/install-app.js';
24
24
  import uninstallApp from './app-management/uninstall-app.js';
25
25
  import terminateApp from './app-management/terminate-app.js';
26
26
  import listApps from './app-management/list-apps.js';
27
+ import getContexts from './context/get-contexts.js';
28
+ import switchContext from './context/switch-context.js';
27
29
  export default function registerTools(server) {
28
30
  // Wrap addTool to inject logging around tool execution
29
31
  const originalAddTool = server.addTool.bind(server);
@@ -113,6 +115,9 @@ export default function registerTools(server) {
113
115
  uninstallApp(server);
114
116
  terminateApp(server);
115
117
  listApps(server);
118
+ // Context Management
119
+ getContexts(server);
120
+ switchContext(server);
116
121
  // Test Generation
117
122
  generateLocators(server);
118
123
  generateTest(server);
@@ -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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"}
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.2.0",
4
+ "version": "1.3.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -6,6 +6,11 @@ let driver: any = null;
6
6
  let sessionId: string | null = null;
7
7
  let isDeletingSession = false; // Lock to prevent concurrent deletion
8
8
 
9
+ export const PLATFORM = {
10
+ android: 'Android',
11
+ ios: 'iOS',
12
+ };
13
+
9
14
  export function setSession(d: any, id: string | null) {
10
15
  driver = d;
11
16
  sessionId = id;
@@ -67,7 +72,7 @@ export async function safeDeleteSession(): Promise<boolean> {
67
72
  }
68
73
 
69
74
  export const getPlatformName = (driver: any): string => {
70
- if (driver instanceof AndroidUiautomator2Driver) return 'Android';
71
- if (driver instanceof XCUITestDriver) return 'iOS';
75
+ if (driver instanceof AndroidUiautomator2Driver) return PLATFORM.android;
76
+ if (driver instanceof XCUITestDriver) return PLATFORM.ios;
72
77
  throw new Error('Unknown driver type');
73
78
  };
@@ -0,0 +1,59 @@
1
+ import { FastMCP } from 'fastmcp/dist/FastMCP.js';
2
+ import { z } from 'zod';
3
+ import { getDriver } from '../../session-store.js';
4
+
5
+ export default function getContexts(server: FastMCP): void {
6
+ server.addTool({
7
+ name: 'appium_get_contexts',
8
+ description:
9
+ 'Get all available contexts in the current Appium session. Returns a list of context names including NATIVE_APP and any webview contexts (e.g., WEBVIEW_<id> or WEBVIEW_<package>).',
10
+ parameters: z.object({}),
11
+ annotations: {
12
+ readOnlyHint: true,
13
+ openWorldHint: false,
14
+ },
15
+ execute: async (args: any, context: any): Promise<any> => {
16
+ const driver = getDriver();
17
+ if (!driver) {
18
+ throw new Error('No driver found. Please create a session first.');
19
+ }
20
+
21
+ try {
22
+ const [currentContext, contexts] = await Promise.all([
23
+ driver.getCurrentContext().catch(() => null),
24
+ driver.getContexts().catch(() => []),
25
+ ]);
26
+
27
+ if (!contexts || contexts.length === 0) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: 'No contexts available.',
33
+ },
34
+ ],
35
+ };
36
+ }
37
+
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: `Available contexts: ${JSON.stringify(contexts, null, 2)}\nCurrent context: ${currentContext || 'N/A'}`,
43
+ },
44
+ ],
45
+ };
46
+ } catch (err: any) {
47
+ return {
48
+ content: [
49
+ {
50
+ type: 'text',
51
+ text: `Failed to get contexts. Error: ${err.toString()}`,
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ },
58
+ });
59
+ }
@@ -0,0 +1,95 @@
1
+ import { FastMCP } from 'fastmcp/dist/FastMCP.js';
2
+ import { z } from 'zod';
3
+ import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
4
+
5
+ export default function switchContext(server: FastMCP): void {
6
+ const schema = z.object({
7
+ context: z
8
+ .string()
9
+ .describe(
10
+ 'The name of the context to switch to. Common values: "NATIVE_APP" for native context, or "WEBVIEW_<id>" / "WEBVIEW_<package>" for webview contexts.'
11
+ ),
12
+ });
13
+
14
+ server.addTool({
15
+ name: 'appium_switch_context',
16
+ description:
17
+ 'Switch to a specific context in the Appium session. Use this to switch between native app context (NATIVE_APP) and webview contexts (WEBVIEW_<id> or WEBVIEW_<package>). Use appium_get_contexts to see available contexts first.',
18
+ parameters: schema,
19
+ annotations: {
20
+ readOnlyHint: false,
21
+ openWorldHint: false,
22
+ },
23
+ execute: async (args: any, context: any): Promise<any> => {
24
+ const driver = getDriver();
25
+ if (!driver) {
26
+ throw new Error('No driver found. Please create a session first.');
27
+ }
28
+
29
+ try {
30
+ const [currentContext, availableContexts] = await Promise.all([
31
+ driver.getCurrentContext().catch(() => null),
32
+ driver.getContexts().catch(() => []),
33
+ ]);
34
+
35
+ if (currentContext === args.context) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: 'text',
40
+ text: `Already on context "${args.context}".`,
41
+ },
42
+ ],
43
+ };
44
+ }
45
+
46
+ if (!availableContexts || availableContexts.length === 0) {
47
+ return {
48
+ content: [
49
+ {
50
+ type: 'text',
51
+ text: 'No contexts available. Cannot switch context.',
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+
58
+ if (!availableContexts.includes(args.context)) {
59
+ return {
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: `Context "${args.context}" not found. Available contexts: ${JSON.stringify(availableContexts, null, 2)}`,
64
+ },
65
+ ],
66
+ isError: true,
67
+ };
68
+ }
69
+ await driver.switchContext(args.context);
70
+
71
+ // Verify the switch was successful
72
+ const newContext = await driver.getCurrentContext();
73
+
74
+ return {
75
+ content: [
76
+ {
77
+ type: 'text',
78
+ text: `Successfully switched context from "${currentContext || 'N/A'}" to "${newContext}".`,
79
+ },
80
+ ],
81
+ };
82
+ } catch (err: any) {
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text',
87
+ text: `Failed to switch context. Error: ${err.toString()}`,
88
+ },
89
+ ],
90
+ isError: true,
91
+ };
92
+ }
93
+ },
94
+ });
95
+ }
@@ -39,6 +39,8 @@ import installApp from './app-management/install-app.js';
39
39
  import uninstallApp from './app-management/uninstall-app.js';
40
40
  import terminateApp from './app-management/terminate-app.js';
41
41
  import listApps from './app-management/list-apps.js';
42
+ import getContexts from './context/get-contexts.js';
43
+ import switchContext from './context/switch-context.js';
42
44
 
43
45
  export default function registerTools(server: FastMCP): void {
44
46
  // Wrap addTool to inject logging around tool execution
@@ -139,6 +141,10 @@ export default function registerTools(server: FastMCP): void {
139
141
  terminateApp(server);
140
142
  listApps(server);
141
143
 
144
+ // Context Management
145
+ getContexts(server);
146
+ switchContext(server);
147
+
142
148
  // Test Generation
143
149
  generateLocators(server);
144
150
  generateTest(server);