@browserstack/mcp-server 2.3.0-beta.1 → 2.3.0-beta.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.
@@ -2,8 +2,8 @@
2
2
  "schema_version": 1,
3
3
  "version": "0.1",
4
4
  "build_id": "automate-authored",
5
- "automate": {
6
- "summary": "BrowserStack Automate: drive a real desktop or mobile browser page by page. The account side lists every operating system, browser and version combination available, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link, video, and console, network and profiling logs \u2014 after the browser is released. The session side opens a browser on a chosen combination and drives it: navigate, go back and forward, reload, read the page HTML and element text, find elements by CSS or XPath, click, type, clear, run JavaScript, screenshot the viewport, resize the window, move between tabs and iframes, and read cookies. Web pages are RUN here \u2014 unlike Test Management, which authors cases, and Test Reporting, which records results pushed in from a runner. Mobile APPS are not here: those are App Automate, which drives an installed app rather than a browser. Scrolling is done through execute_script, there is no capability that waits, and element ids go stale as soon as the page navigates or re-renders. A session holds a browser until it is ended.",
5
+ "devicecontrol": {
6
+ "summary": "Device control: drive a real desktop or mobile browser page by page. The account side lists every operating system, browser and version combination available, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link, video, and console, network and profiling logs \u2014 after the browser is released. The session side opens a browser on a chosen combination and drives it: navigate, go back and forward, reload, read the page HTML and element text, find elements by CSS or XPath, click, type, clear, run JavaScript, screenshot the viewport, resize the window, move between tabs and iframes, and read cookies. Web pages are RUN here \u2014 unlike Test Management, which authors cases, and Test Reporting, which records results pushed in from a runner. Mobile APPS are not here: those are mobile device control, which drives an installed app rather than a browser. Scrolling is done through execute_script, there is no capability that waits, and element ids go stale as soon as the page navigates or re-renders. A session holds a browser until it is ended.",
7
7
  "routing_terms": [
8
8
  "automate",
9
9
  "browser",
@@ -31,7 +31,9 @@
31
31
  "network logs",
32
32
  "har",
33
33
  "browser session",
34
- "cross browser"
34
+ "cross browser",
35
+ "device control",
36
+ "browser control"
35
37
  ],
36
38
  "base_url": "https://hub.browserstack.com",
37
39
  "hosts": {
@@ -204,7 +206,7 @@
204
206
  "type": "string",
205
207
  "maxLength": 255,
206
208
  "description": "Short explanation shown beside the status.",
207
- "example": "Cart totalled correctly after adding two items"
209
+ "example": "The page behaved as expected"
208
210
  }
209
211
  ],
210
212
  "returns": [
@@ -246,7 +248,8 @@
246
248
  "A session starts in seconds rather than the tens of seconds a device session takes, but it still holds a browser and consumes Automate minutes until it ends: always finish with set_session_status and then delete_session.",
247
249
  "The session ends itself after idle_timeout seconds without a command, and after 2 hours in total.",
248
250
  "console_logs and network_logs must be asked for here; they cannot be turned on once the session is running, and get_session only links to them when they were.",
249
- "Credentials belong in the Authorization header, never inside bstack:options: capabilities are echoed back in session-not-created errors."
251
+ "Credentials belong in the Authorization header, never inside bstack:options: capabilities are echoed back in session-not-created errors.",
252
+ "resolution takes one of a fixed set of values per operating system, not any width and height: an unsupported pair is refused outright rather than rounded to the nearest one. The browser window is well short of the screen it sits on \u2014 1920x1080 gives a viewport around 930x860 \u2014 so measure it rather than assuming the request was honoured."
250
253
  ],
251
254
  "body": [
252
255
  {
@@ -317,7 +320,7 @@
317
320
  "name": "resolution",
318
321
  "type": "string",
319
322
  "json_path": "/capabilities/alwaysMatch/bstack:options/resolution",
320
- "description": "Desktop screen resolution. The browser window is smaller than this; read the real size from get_window_rect.",
323
+ "description": "Desktop screen resolution, from a fixed set the chosen OS supports \u2014 an unsupported value is refused with \"The specified screen resolution is not compatible with the chosen OS version\" and no session starts. 1920x1080 is accepted on Windows 11; 2560x1440 is not. The browser window is much smaller than the screen either way, so read the real size rather than assuming it.",
321
324
  "example": "1920x1080"
322
325
  },
323
326
  {
@@ -363,14 +366,14 @@
363
366
  "type": "string",
364
367
  "json_path": "/capabilities/alwaysMatch/bstack:options/projectName",
365
368
  "description": "Groups sessions on the dashboard.",
366
- "example": "Checkout flows"
369
+ "example": "Web checkout"
367
370
  },
368
371
  {
369
372
  "name": "build_name",
370
373
  "type": "string",
371
374
  "json_path": "/capabilities/alwaysMatch/bstack:options/buildName",
372
375
  "description": "Build the session is filed under.",
373
- "example": "agent-exploration"
376
+ "example": "nightly"
374
377
  },
375
378
  {
376
379
  "name": "session_name",
@@ -378,7 +381,7 @@
378
381
  "maxLength": 255,
379
382
  "json_path": "/capabilities/alwaysMatch/bstack:options/sessionName",
380
383
  "description": "Name shown for this session.",
381
- "example": "cart totals"
384
+ "example": "sign in and add to basket"
382
385
  }
383
386
  ],
384
387
  "returns": [
@@ -424,7 +427,7 @@
424
427
  "required": true,
425
428
  "format": "uri",
426
429
  "description": "Absolute URL including the scheme.",
427
- "example": "https://www.bstackdemo.com/"
430
+ "example": "https://www.example.com/products"
428
431
  }
429
432
  ],
430
433
  "returns": [
@@ -648,8 +651,7 @@
648
651
  "404": {
649
652
  "$response": "WebDriverError"
650
653
  }
651
- },
652
- "disabled": true
654
+ }
653
655
  },
654
656
  {
655
657
  "name": "find_element",
@@ -691,7 +693,7 @@
691
693
  "type": "string",
692
694
  "required": true,
693
695
  "description": "The selector itself, interpreted according to using.",
694
- "example": ".shelf-item__buy-btn"
696
+ "example": "#add-to-cart"
695
697
  }
696
698
  ],
697
699
  "returns": [
@@ -748,7 +750,7 @@
748
750
  "type": "string",
749
751
  "required": true,
750
752
  "description": "The selector itself, interpreted according to using.",
751
- "example": ".shelf-item__buy-btn"
753
+ "example": ".product-card"
752
754
  }
753
755
  ],
754
756
  "returns": [
@@ -791,7 +793,7 @@
791
793
  "type": "string",
792
794
  "required": true,
793
795
  "description": "Element id from find_element.",
794
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
796
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
795
797
  }
796
798
  ],
797
799
  "returns": [
@@ -820,7 +822,7 @@
820
822
  "guidance": [
821
823
  "APPENDS to whatever the field already holds. Call clear_element first to replace the value rather than adding to it.",
822
824
  "Read the result back with get_element_property on \"value\", not get_element_text, which is empty for an input.",
823
- "A \\n at the end submits the form, which is usually quicker than finding and clicking the submit button.",
825
+ "A \\n at the end submits the form on a desktop browser and on Chrome for Android, and is quicker than finding the submit button. IT DOES NOT SUBMIT ON SAFARI FOR iOS \u2014 the text lands in the field and the page stays where it is, whether the newline is sent with the text or on its own. There, click the form's submit button, or call arguments[0].form.submit() through execute_script with the field as the argument.",
824
826
  "The element must be editable; typing into anything else answers \"element not interactable\".",
825
827
  "A site's own autocomplete or dropdown may swallow the keystrokes and require a click on a suggestion instead."
826
828
  ],
@@ -836,7 +838,7 @@
836
838
  "type": "string",
837
839
  "required": true,
838
840
  "description": "Element id from find_element.",
839
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
841
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
840
842
  }
841
843
  ],
842
844
  "body": [
@@ -845,7 +847,7 @@
845
847
  "type": "string",
846
848
  "required": true,
847
849
  "description": "The characters to type. End with \\n to submit.",
848
- "example": "BrowserStack"
850
+ "example": "hello"
849
851
  }
850
852
  ],
851
853
  "returns": [
@@ -888,7 +890,7 @@
888
890
  "type": "string",
889
891
  "required": true,
890
892
  "description": "Element id from find_element.",
891
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
893
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
892
894
  }
893
895
  ],
894
896
  "returns": [
@@ -931,7 +933,7 @@
931
933
  "type": "string",
932
934
  "required": true,
933
935
  "description": "Element id from find_element.",
934
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
936
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
935
937
  }
936
938
  ],
937
939
  "returns": [
@@ -974,7 +976,7 @@
974
976
  "type": "string",
975
977
  "required": true,
976
978
  "description": "Element id from find_element.",
977
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
979
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
978
980
  },
979
981
  {
980
982
  "name": "name",
@@ -1023,14 +1025,14 @@
1023
1025
  "type": "string",
1024
1026
  "required": true,
1025
1027
  "description": "Element id from find_element.",
1026
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
1028
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
1027
1029
  },
1028
1030
  {
1029
1031
  "name": "name",
1030
1032
  "type": "string",
1031
1033
  "required": true,
1032
1034
  "description": "The attribute to read.",
1033
- "example": "class"
1035
+ "example": "href"
1034
1036
  }
1035
1037
  ],
1036
1038
  "returns": [
@@ -1072,7 +1074,7 @@
1072
1074
  "type": "string",
1073
1075
  "required": true,
1074
1076
  "description": "Element id from find_element.",
1075
- "example": "f.31006BCEEF25A5A489371DAD0726B51F.d.B5F92408.e.13"
1077
+ "example": "f.00000000000000000000000000000000.d.0000000000000000.e.1"
1076
1078
  }
1077
1079
  ],
1078
1080
  "returns": [
@@ -1213,8 +1215,7 @@
1213
1215
  "404": {
1214
1216
  "$response": "WebDriverError"
1215
1217
  }
1216
- },
1217
- "disabled": true
1218
+ }
1218
1219
  },
1219
1220
  {
1220
1221
  "name": "set_window_rect",
@@ -1380,7 +1381,7 @@
1380
1381
  "type": "string",
1381
1382
  "required": true,
1382
1383
  "description": "Handle from list_window_handles.",
1383
- "example": "2FFCF2904DC789DD82BACEF48E43AE93"
1384
+ "example": "00000000000000000000000000000000"
1384
1385
  }
1385
1386
  ],
1386
1387
  "returns": [
@@ -2,8 +2,8 @@
2
2
  "schema_version": 1,
3
3
  "version": "0.1",
4
4
  "build_id": "appautomate-demo",
5
- "appautomate": {
6
- "summary": "BrowserStack App Automate: run a real Android or iOS device and drive the app on it step by step. The account side lists the devices this account can use, including private ones, uploads and lists app builds, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link and video \u2014 after the device is released. The session side starts a device with an installed build and drives it: read the UI tree, find and tap elements, type, swipe, screenshot, press keys, rotate, switch between the native app and a web view, push and pull files, move the simulated GPS, change the network profile, launch, close and uninstall apps, answer biometric prompts and feed images to the camera. Apps are RUN here \u2014 unlike Test Management, which authors cases, and Test Reporting, which records results pushed in from a runner. Web browsers are not here, and neither is App Live: it has no API an agent can drive, so agent sessions run on App Automate and consume its minutes. A build must exist before a session starts and can only be uploaded from a public link, never a file on disk \u2014 so media for camera injection must come from elsewhere. The default Appium server is 1.x and rejects every `mobile:` command; ask for 2.19.0.",
5
+ "mobiledevicecontrol": {
6
+ "summary": "Mobile device control: run a real Android or iOS device and drive the app on it step by step. The account side lists the devices this account can use, including private ones, uploads and lists app builds, reports parallel-session capacity, and keeps each session's record \u2014 status, shareable link and video \u2014 after the device is released. The session side starts a device with an installed build and drives it: read the UI tree, find and tap elements, type, swipe, screenshot, press keys, rotate, switch between the native app and a web view, push and pull files, move the simulated GPS, change the network profile, launch, close and uninstall apps, answer biometric prompts and feed images to the camera. Apps are RUN here \u2014 unlike Test Management, which authors cases, and Test Reporting, which records results pushed in from a runner. Browsers are not here \u2014 those are device control, which drives a page rather than an installed app \u2014 and neither is App Live: it has no API an agent can drive, so agent sessions run on App Automate and consume its minutes. A build must exist before a session starts and can only be uploaded from a public link, never a file on disk \u2014 so media for camera injection must come from elsewhere. The default Appium server is 1.x and rejects every `mobile:` command; ask for 2.19.0.",
7
7
  "routing_terms": [
8
8
  "app automate",
9
9
  "appium",
@@ -51,7 +51,10 @@
51
51
  "os build",
52
52
  "upload apk",
53
53
  "upload ipa",
54
- "local build"
54
+ "local build",
55
+ "mobile device control",
56
+ "device control",
57
+ "drive a device"
55
58
  ],
56
59
  "base_url": "https://hub-cloud.browserstack.com",
57
60
  "auth": {
@@ -72,7 +75,7 @@
72
75
  "The session ends itself after idle_timeout seconds with no command (90 by default, 300 at most) and after 2 hours in total. Keep calling, or call get_window_rect as a cheap keep-alive, while deciding the next step.",
73
76
  "Every session occupies a device and consumes App Automate minutes until it ends: always finish with execute_script setSessionStatus and then delete_session.",
74
77
  "To let a person watch the device live while the agent drives it, set interactive_debugging true and leave video on; they then open the running session on the App Automate dashboard and start the interactive session there. That window is two-way: a person's taps and scrolls reach the same device, so ask them to watch only, or re-read the page source before every action.",
75
- "device_name and platform_version must be a combination App Automate offers; an unknown pair fails with a session-not-created error naming the capability.",
78
+ "device_name and platform_version must be a combination mobile device control offers; an unknown pair fails with a session-not-created error naming the capability.",
76
79
  "Set appium_version to 2.19.0 for any session that will use execute_script with a `mobile:` command; the default server is 1.x and answers those with a 404 listing the commands it does know.",
77
80
  "enable_biometric, enable_camera_image_injection and upload_media only take effect when set here \u2014 none of them can be turned on once the session is running.",
78
81
  "Credentials belong in the Authorization header, never inside bstack:options: capabilities are echoed back in session-not-created errors.",
@@ -145,21 +148,21 @@
145
148
  "type": "string",
146
149
  "json_path": "/capabilities/alwaysMatch/bstack:options/projectName",
147
150
  "description": "Groups sessions on the App Automate dashboard.",
148
- "example": "Checkout flows"
151
+ "example": "Mobile checkout"
149
152
  },
150
153
  {
151
154
  "name": "build_name",
152
155
  "type": "string",
153
156
  "json_path": "/capabilities/alwaysMatch/bstack:options/buildName",
154
157
  "description": "Build the session is filed under on the dashboard.",
155
- "example": "agent-exploration"
158
+ "example": "nightly"
156
159
  },
157
160
  {
158
161
  "name": "session_name",
159
162
  "type": "string",
160
163
  "json_path": "/capabilities/alwaysMatch/bstack:options/sessionName",
161
164
  "description": "Name shown for this session on the dashboard.",
162
- "example": "Add a product to the cart"
165
+ "example": "sign in and add to basket"
163
166
  },
164
167
  {
165
168
  "name": "interactive_debugging",
@@ -342,8 +345,7 @@
342
345
  "404": {
343
346
  "$response": "WebDriverError"
344
347
  }
345
- },
346
- "disabled": true
348
+ }
347
349
  },
348
350
  {
349
351
  "name": "find_element",
@@ -356,7 +358,8 @@
356
358
  "The element id comes back under the W3C key value[\"element-6066-11e4-a52e-4f735466cecf\"]; pass that string as element_id.",
357
359
  "Take the selector from get_page_source rather than guessing: resource-id \u2192 \"id\", content-desc (Android) or name (iOS) \u2192 \"accessibility id\".",
358
360
  "No match is a 404 with error \"no such element\" \u2014 re-read the page source; the screen may have changed or the element may be off-screen and need a scroll first.",
359
- "\"-android uiautomator\" accepts a UiSelector expression, which can scroll an element into view: new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text(\"Checkout\"))."
361
+ "\"-android uiautomator\" accepts a UiSelector expression, which can scroll an element into view: new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text(\"Checkout\")).",
362
+ "find_elements answers the same query with a list and never a 404, which is how to ask whether something is present without treating absence as a failure."
360
363
  ],
361
364
  "path_params": [
362
365
  {
@@ -387,7 +390,7 @@
387
390
  "type": "string",
388
391
  "required": true,
389
392
  "description": "The selector itself, interpreted according to using.",
390
- "example": "nav-cart"
393
+ "example": "cart-button"
391
394
  }
392
395
  ],
393
396
  "returns": [
@@ -483,7 +486,7 @@
483
486
  "type": "string",
484
487
  "required": true,
485
488
  "description": "The characters to type.",
486
- "example": "Galaxy S20"
489
+ "example": "hello"
487
490
  }
488
491
  ],
489
492
  "returns": [
@@ -703,8 +706,7 @@
703
706
  "404": {
704
707
  "$response": "WebDriverError"
705
708
  }
706
- },
707
- "disabled": true
709
+ }
708
710
  },
709
711
  {
710
712
  "name": "delete_session",
@@ -1122,7 +1124,7 @@
1122
1124
  "type": "string",
1123
1125
  "maxLength": 255,
1124
1126
  "description": "Short explanation shown beside the status.",
1125
- "example": "Checkout completed and the cart showed the right total"
1127
+ "example": "The app behaved as expected"
1126
1128
  }
1127
1129
  ],
1128
1130
  "returns": [
@@ -1808,7 +1810,7 @@
1808
1810
  "Android takes appId and iOS takes bundleId \u2014 send exactly the one for the platform. The wrong name is refused with a 400 \"invalid argument\" that names the parameter it wanted, and no action is taken.",
1809
1811
  "Launching an app that is already in the foreground does nothing and still reports success.",
1810
1812
  "To restart an app from a clean state, call terminate_app first and then this.",
1811
- "Succeeding means the app was activated, not that it finished drawing; read the page source before acting.",
1813
+ "Succeeding means the app was activated, not that it finished drawing, so give it a moment and confirm before acting. An app that cannot be brought forward at all answers 400 rather than reporting success, and get_app_state reads 4 once it really is in front \u2014 sampled too early it can still report the home screen mid-switch.",
1812
1814
  "The app must be installed \u2014 a package that is not there fails rather than installing it."
1813
1815
  ],
1814
1816
  "path_params": [
@@ -1953,7 +1955,7 @@
1953
1955
  "Android takes appId and iOS takes bundleId \u2014 send exactly the one for the platform. The wrong name is refused with a 400 \"invalid argument\" that names the parameter it wanted, and no action is taken.",
1954
1956
  "The value is a number: 0 not installed, 1 installed but not running, 2 running in the background and suspended, 3 running in the background, 4 running in the foreground.",
1955
1957
  "4 is the only state in which the app is on screen and can be driven.",
1956
- "The same scale applies on both platforms. Sending an app to the background with press_button home leaves it at 2, and launching it again returns it to 4."
1958
+ "The same scale applies on both platforms. Sending an app to the background leaves it at 3 or 2 \u2014 the system suspends it a moment after it stops being visible \u2014 so treat anything below 4 as not on screen rather than waiting for one number. Launching it again returns it to 4."
1957
1959
  ],
1958
1960
  "path_params": [
1959
1961
  {
@@ -2638,6 +2640,67 @@
2638
2640
  }
2639
2641
  },
2640
2642
  "unavailable_note": "This server does not run on your own machine, so it cannot read a file you name \u2014 a path sent here would point at the machine hosting the server. Upload the build yourself with a multipart request carrying the file to the same endpoint, which the asset-upload helper will write out for you, and then use the bs:// url it returns as the app for create_session. upload_app_build does the same thing from a public download link, if the build is reachable at one."
2643
+ },
2644
+ {
2645
+ "name": "find_elements",
2646
+ "method": "POST",
2647
+ "path": "/wd/hub/session/{session_id}/elements",
2648
+ "mode": "read",
2649
+ "entity": "app_session",
2650
+ "intent": "Find every element matching a selector \u2014 use this to count matches, work through a list, or check whether something is present at all.",
2651
+ "guidance": [
2652
+ "No match is an EMPTY LIST and a 200, where find_element answers 404. That makes this the way to test whether something is there without handling an error.",
2653
+ "An empty list can be trusted to mean absent: a strategy this surface does not accept is refused before the request is sent, and an iOS strategy aimed at an Android screen comes back as a 400 \"invalid selector\" rather than as nothing found.",
2654
+ "Each entry carries the same element-6066-11e4-a52e-4f735466cecf key as find_element, and the ids go stale when the screen changes just as readily.",
2655
+ "The order is the UI tree's own, so it follows the screen's layout rather than anything meaningful to the app.",
2656
+ "Use find_element when exactly one match is expected: its 404 says plainly that the screen is not what you thought."
2657
+ ],
2658
+ "path_params": [
2659
+ {
2660
+ "name": "session_id",
2661
+ "type": "string",
2662
+ "required": true,
2663
+ "example": "0123456789abcdef0123456789abcdef01234567"
2664
+ }
2665
+ ],
2666
+ "body": [
2667
+ {
2668
+ "name": "using",
2669
+ "type": "string",
2670
+ "required": true,
2671
+ "values": [
2672
+ "id",
2673
+ "accessibility id",
2674
+ "xpath",
2675
+ "class name",
2676
+ "-android uiautomator",
2677
+ "-ios predicate string",
2678
+ "-ios class chain"
2679
+ ],
2680
+ "example": "accessibility id"
2681
+ },
2682
+ {
2683
+ "name": "value",
2684
+ "type": "string",
2685
+ "required": true,
2686
+ "description": "The selector itself, interpreted according to using.",
2687
+ "example": "cart-button"
2688
+ }
2689
+ ],
2690
+ "returns": [
2691
+ "value"
2692
+ ],
2693
+ "responses": {
2694
+ "200": {
2695
+ "description": "Every matching element, possibly none.",
2696
+ "schema": {
2697
+ "$schema": "ElementListResponse"
2698
+ }
2699
+ },
2700
+ "404": {
2701
+ "$response": "WebDriverError"
2702
+ }
2703
+ }
2641
2704
  }
2642
2705
  ],
2643
2706
  "schemas": {
@@ -3065,6 +3128,23 @@
3065
3128
  }
3066
3129
  }
3067
3130
  }
3131
+ },
3132
+ "ElementListResponse": {
3133
+ "type": "object",
3134
+ "properties": {
3135
+ "value": {
3136
+ "type": "array",
3137
+ "items": {
3138
+ "type": "object",
3139
+ "properties": {
3140
+ "element-6066-11e4-a52e-4f735466cecf": {
3141
+ "type": "string",
3142
+ "description": "The element id to pass as element_id."
3143
+ }
3144
+ }
3145
+ }
3146
+ }
3147
+ }
3068
3148
  }
3069
3149
  },
3070
3150
  "responses": {
@@ -3139,7 +3219,8 @@
3139
3219
  "press_button",
3140
3220
  "get_simulated_location",
3141
3221
  "get_active_app_info",
3142
- "read_device_property"
3222
+ "read_device_property",
3223
+ "find_elements"
3143
3224
  ]
3144
3225
  },
3145
3226
  "device": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserstack/mcp-server",
3
- "version": "2.3.0-beta.1",
3
+ "version": "2.3.0-beta.3",
4
4
  "description": "BrowserStack's Official MCP Server",
5
5
  "mcpName": "io.github.browserstack/mcp-server",
6
6
  "main": "dist/index.js",