@browserstack/mcp-server 1.5.0-beta.2 → 1.5.0-beta.20

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.
@@ -27,7 +27,47 @@ export declare const SUPPORTED_SCHEMA_VERSION = 1;
27
27
  export declare const ENVELOPE_KEYS: readonly ["schema_version", "version", "build_id", "harness_commit", "products"];
28
28
  export type Mode = "read" | "write" | "destructive";
29
29
  /** One parameter, under the name the OpenAPI spec itself gives it. */
30
- export interface WireParam {
30
+ /**
31
+ * The constraints a parameter may declare beyond its type.
32
+ *
33
+ * ALL OPTIONAL, and absent means unchecked. The released artifact carries none of these
34
+ * yet — tm's spec holds 59 `format`, 50 `default`, 23 `minimum`, 12 `maximum`, 10
35
+ * `minItems`, 7 `maxItems`, 4 `minLength`, 3 `pattern` and 2 `maxLength` that the export
36
+ * currently drops — so this ships inert and starts working the moment the export carries
37
+ * them. An older index must keep binding exactly as it does today.
38
+ */
39
+ export interface WireConstraints {
40
+ /** Numbers. `multipleOf` is checked on the coerced number, not the raw string. */
41
+ minimum?: number;
42
+ maximum?: number;
43
+ multipleOf?: number;
44
+ /** Strings. `pattern` is an unanchored regex, compiled with `u` for `\p{…}` classes. */
45
+ minLength?: number;
46
+ maxLength?: number;
47
+ pattern?: string;
48
+ format?: string;
49
+ /** Arrays. */
50
+ minItems?: number;
51
+ maxItems?: number;
52
+ uniqueItems?: boolean;
53
+ /**
54
+ * The value the product uses when the field is omitted.
55
+ *
56
+ * PUBLISHED, NOT INJECTED. Telling a caller the default is what stops the redundant send;
57
+ * filling it in here would put a value on the wire that the caller never chose, and pin
58
+ * a server-side default that is free to change. Omission and "explicitly the default" are
59
+ * different requests, and only the product knows whether that difference matters.
60
+ */
61
+ default?: unknown;
62
+ }
63
+ /** One field inside an array item or a nested object — same constraints, one level down. */
64
+ export interface WireField extends WireConstraints {
65
+ name: string;
66
+ type: string;
67
+ required?: true;
68
+ values?: unknown[];
69
+ }
70
+ export interface WireParam extends WireConstraints {
31
71
  name: string;
32
72
  type: string;
33
73
  required?: true;
@@ -35,11 +75,7 @@ export interface WireParam {
35
75
  example?: unknown;
36
76
  description?: string;
37
77
  /** Field names/types one level inside an array item or nested object. */
38
- fields?: {
39
- name: string;
40
- type: string;
41
- required?: true;
42
- }[];
78
+ fields?: WireField[];
43
79
  /**
44
80
  * Where a body field sits in the JSON, when that differs from its name. Published
45
81
  * because the nesting is not guessable and getting it wrong fails silently — tm's folder
@@ -67,6 +103,17 @@ export interface ResponseDoc extends ComponentRef {
67
103
  }
68
104
  /** A capability, keyed by the endpoint it exposes. There is deliberately no name. */
69
105
  export interface Capability {
106
+ /**
107
+ * The caller-facing handle — the snake-cased `operationId`, unique within its product.
108
+ *
109
+ * This is what `invokeCapability` takes, and what `entities[*].capabilities[]` lists. It
110
+ * is stable where a route is not: `/edit` becoming `/edit-v2` must not break a caller
111
+ * holding a handle.
112
+ *
113
+ * OPTIONAL because not every product publishes it yet — loadtesting's index carries none.
114
+ * For those, the endpoint remains the handle, so nothing may assume this is present.
115
+ */
116
+ name?: string;
70
117
  method: string;
71
118
  path: string;
72
119
  mode: Mode;
@@ -101,6 +148,20 @@ export interface Capability {
101
148
  }
102
149
  export interface EntityDoc {
103
150
  title?: string;
151
+ /**
152
+ * One line saying what this entity IS. Rides on `listProducts`, next to the aliases.
153
+ *
154
+ * Aliases route; they do not define. `version -> history, revision, version-history`
155
+ * tells a caller which words land here and nothing about whether that is the versioning
156
+ * of a test case or of a project. Without this line the only way to find out is
157
+ * `describeEntity`, once per entity — 19 calls at ~1.4KB for tm, against ~1.6KB to
158
+ * answer it for all of them at once.
159
+ *
160
+ * Capped at 140 characters by the build, and dropped rather than truncated when longer.
161
+ * Often absent: a product that has not authored these emits none (loadtesting has 0 of
162
+ * 9 today), and absence means "unwritten", never an error.
163
+ */
164
+ description?: string;
104
165
  aliases?: string[];
105
166
  id_convention?: string;
106
167
  parents?: string[];
@@ -108,6 +169,19 @@ export interface EntityDoc {
108
169
  entity?: string;
109
170
  via?: string;
110
171
  }[];
172
+ /**
173
+ * What a caller gets wrong about this ENTITY, as opposed to one operation.
174
+ *
175
+ * The entity-wide half of guidance: "a run's `id` is the display string, take `uuid`"
176
+ * holds for every capability returning a run, so it is stated once here rather than
177
+ * copied onto each capability's `guidance` — which would repeat across ~20 records and,
178
+ * since guidance is a search haystack, dilute ranking with boilerplate.
179
+ *
180
+ * Filtered at build time and often absent: of tm's 155 authored facts, 73 are publishable
181
+ * as written and the rest name routes, HTTP verbs or wire-shaped parameters. Absent means
182
+ * "none passed", never an error.
183
+ */
184
+ key_facts?: string[];
111
185
  [key: string]: unknown;
112
186
  }
113
187
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserstack/mcp-server",
3
- "version": "1.5.0-beta.2",
3
+ "version": "1.5.0-beta.20",
4
4
  "description": "BrowserStack's Official MCP Server",
5
5
  "mcpName": "io.github.browserstack/mcp-server",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,12 @@
15
15
  "dev": "tsx watch --clear-screen=false src/index.ts",
16
16
  "test": "vitest run",
17
17
  "lint": "eslint . --ext .ts",
18
- "format": "prettier --write \"src/**/*.ts\""
18
+ "format": "prettier --write \"src/**/*.ts\"",
19
+ "check:contract": "python3 scripts/check-contract.py capability/tm.capability-index.json --baseline scripts/contract-baseline/tm.json --quiet && python3 scripts/check-contract.py capability/loadtesting.capability-index.json --baseline scripts/contract-baseline/loadtesting.json --quiet",
20
+ "eval:index": "tsx scripts/eval-index.mts",
21
+ "seed:live": "tsx scripts/seed-live.mts",
22
+ "plan:tests": "tsx scripts/plan-capability-tests.mts",
23
+ "replay:live": "tsx scripts/replay-live.mts"
19
24
  },
20
25
  "bin": {
21
26
  "browserstack-mcp-server": "dist/index.js"