@solarisdk/mcp 0.3.0 → 0.3.1
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/README.md +77 -7
- package/dist/browser.js +60 -6
- package/dist/solari-mcp-http.bundle.cjs +19 -4
- package/dist/solari-mcp.bundle.cjs +19 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,7 +20,8 @@ registry**: `*_create` tools return a `sessionId`, and the rest take it.
|
|
|
20
20
|
Point any MCP client at the hosted Streamable HTTP endpoint with your API key:
|
|
21
21
|
|
|
22
22
|
- **Prod:** `https://mcp.getsolari.com/mcp`
|
|
23
|
-
- **Staging:**
|
|
23
|
+
- **Staging:** currently NOT deployed — the us-east-1 ALB it rode was
|
|
24
|
+
removed in the us-west-1 migration and its DNS record has been deleted.
|
|
24
25
|
|
|
25
26
|
Claude Desktop / claude.ai: **Settings → Connectors → Add custom connector**,
|
|
26
27
|
URL as above, and send `Authorization: Bearer slr_live_…`. Or in
|
|
@@ -68,8 +69,9 @@ lifecycles — re-attach with `solari_connect`).
|
|
|
68
69
|
"env": {
|
|
69
70
|
"SOLARI_API_KEY": "slr_live_…"
|
|
70
71
|
// optional overrides (defaults hit prod https://api.getsolari.com):
|
|
71
|
-
//
|
|
72
|
-
// "
|
|
72
|
+
// optional staging override — ONE host now serves both gateways:
|
|
73
|
+
// "SOLARI_BASE_URL": "https://api-sta.getsolari.com",
|
|
74
|
+
// "SOLARI_BROWSER_URL": "https://api-sta.getsolari.com"
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
}
|
|
@@ -85,7 +87,7 @@ Chat, Code and Cowork alike.
|
|
|
85
87
|
|---|---|---|---|
|
|
86
88
|
| `SOLARI_API_KEY` | ✅ | — | unified `slr_live_…` key (works on both gateways) |
|
|
87
89
|
| `SOLARI_BASE_URL` | | `https://api.getsolari.com` | sandbox/desktop gateway |
|
|
88
|
-
| `SOLARI_BROWSER_URL` | | `SOLARI_BASE_URL` → prod | cloud-browser gateway
|
|
90
|
+
| `SOLARI_BROWSER_URL` | | `SOLARI_BASE_URL` → prod | cloud-browser gateway. Both prod (`api.getsolari.com`) and staging (`api-sta.getsolari.com`) now path-route browser AND desktop on one host, so this rarely needs setting |
|
|
89
91
|
| `SOLARI_BROWSER_API_KEY` | | `SOLARI_API_KEY` | separate key for the browser gateway, for environments where the browser and desktop key stores are split |
|
|
90
92
|
|
|
91
93
|
## Tools
|
|
@@ -94,7 +96,7 @@ Chat, Code and Cowork alike.
|
|
|
94
96
|
|
|
95
97
|
| Tool | What it does |
|
|
96
98
|
|---|---|
|
|
97
|
-
| `solari_browser_create` | Start a browser session (`
|
|
99
|
+
| `solari_browser_create` | Start a browser session (`mode`, `proxy`, `captcha`, `recording`, `profileId`) → `{sessionId, mode, captcha}` |
|
|
98
100
|
| `solari_browser_navigate` | Go to a URL → `{url, title, status}` |
|
|
99
101
|
| `solari_browser_read_page` | Page text / links / HTML (30k-char cap) |
|
|
100
102
|
| `solari_browser_screenshot` | JPEG screenshot (image content) |
|
|
@@ -103,6 +105,39 @@ Chat, Code and Cowork alike.
|
|
|
103
105
|
| `solari_browser_replay_url` | rrweb replay URL (needs `recording: true`) |
|
|
104
106
|
| `solari_browser_close` | Release the session |
|
|
105
107
|
|
|
108
|
+
### Browser mode — stealth by default
|
|
109
|
+
|
|
110
|
+
`solari_browser_create` defaults to **`mode: "stealth"`** (the anti-bot hardened pool). A bare
|
|
111
|
+
call with no arguments gets it; the model does not have to ask.
|
|
112
|
+
|
|
113
|
+
This used to be an optional `stealth: true` boolean, and in practice models did not opt in — so
|
|
114
|
+
sessions quietly landed on the fast pool and got blocked by bot detection. The failure looked
|
|
115
|
+
like "the site is broken" rather than "we chose the wrong pool", which is the worst way for a
|
|
116
|
+
default to be wrong.
|
|
117
|
+
|
|
118
|
+
`mode: "fast"` is the explicit opt-out: lower latency, for sites you already know do not
|
|
119
|
+
fingerprint or block automation (internal tools, localhost, your own app, plain docs). If a page
|
|
120
|
+
returns a block/captcha/challenge in fast mode, close the session and retry on stealth.
|
|
121
|
+
|
|
122
|
+
`proxy` and `captcha` are stealth-only upstream and are now **rejected** in fast mode rather than
|
|
123
|
+
silently dropped — a quietly unproxied request leaks the origin IP, which is the one thing the
|
|
124
|
+
caller was trying to avoid. The response echoes the resolved `mode`, so a later block is
|
|
125
|
+
actionable.
|
|
126
|
+
|
|
127
|
+
The deprecated `stealth` boolean still works in both directions for existing callers
|
|
128
|
+
(`stealth: false` still means fast); an explicit `mode` wins when both are supplied.
|
|
129
|
+
|
|
130
|
+
**Captcha auto-solving is on by default too**, for the same reason: an option a model has to opt
|
|
131
|
+
into does not get used, and the resulting failure ("the page is a challenge screen") reads as a
|
|
132
|
+
broken site rather than a missing flag. Pass **`captcha: false`** to opt out — solving costs money
|
|
133
|
+
and adds latency, so turn it off for sites you know never challenge.
|
|
134
|
+
|
|
135
|
+
The default *follows the pool* rather than being a flat `true`: captcha is stealth-only upstream,
|
|
136
|
+
so a flat default would make a plain `mode: "fast"` call throw on an option the caller never
|
|
137
|
+
asked for. Stealth ⇒ on, fast ⇒ off, explicit value always wins. Asking for `captcha: true`
|
|
138
|
+
*together with* `mode: "fast"` is a real contradiction and is refused. The response echoes the
|
|
139
|
+
resolved `captcha` alongside `mode`.
|
|
140
|
+
|
|
106
141
|
### Sandboxes + desktops
|
|
107
142
|
|
|
108
143
|
| Tool | What it does |
|
|
@@ -137,11 +172,46 @@ npm run build:bundle # esbuild → dist/solari-mcp.bundle.cjs (single file, no n
|
|
|
137
172
|
|
|
138
173
|
```bash
|
|
139
174
|
SOLARI_API_KEY=slr_live_… \
|
|
140
|
-
SOLARI_BASE_URL=https://
|
|
141
|
-
SOLARI_BROWSER_URL=https://api-sta.
|
|
175
|
+
SOLARI_BASE_URL=https://api-sta.getsolari.com \
|
|
176
|
+
SOLARI_BROWSER_URL=https://api-sta.getsolari.com \
|
|
142
177
|
node test/live-smoke.mjs # add SMOKE_SERVER=dist/solari-mcp.bundle.cjs to test the bundle
|
|
143
178
|
```
|
|
144
179
|
|
|
145
180
|
Round-trips browser create→navigate→read→screenshot→search→close, sandbox
|
|
146
181
|
create→exec→run_code→kill, and desktop create→screenshot→kill as a real MCP
|
|
147
182
|
client over stdio.
|
|
183
|
+
|
|
184
|
+
## Hosted connector — where it runs (ops)
|
|
185
|
+
|
|
186
|
+
All of this is **manual**, not terraform.
|
|
187
|
+
|
|
188
|
+
| | Prod | Staging |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| URL | `https://mcp.getsolari.com/mcp` | *(not deployed — see above)* |
|
|
191
|
+
| Region | **us-west-1** | — |
|
|
192
|
+
| Cluster | `solari-desktops-prod-usw1-gw` | — |
|
|
193
|
+
| Service / taskdef | `solari-mcp-prod-usw1` | — |
|
|
194
|
+
| Image | ECR `solari-mcp:prod` (us-west-1) | — |
|
|
195
|
+
| Ingress | listener rule **prio 20** on the gateway ALB, host-header match | — |
|
|
196
|
+
|
|
197
|
+
It rides the desktop gateway's ALB, so it is **coupled to that ALB's lifetime**.
|
|
198
|
+
|
|
199
|
+
### ⚠️ `/health` returning 200 does NOT mean the connector is up
|
|
200
|
+
|
|
201
|
+
The desktop gateway answers `GET /health` with `{"ok":true}` too. If DNS points at the
|
|
202
|
+
gateway instead of the connector — which is exactly what happened on 2026-07-28, when the
|
|
203
|
+
us-west-1 migration deleted the old us-east-1 gateway ALB and re-aliased
|
|
204
|
+
`mcp.getsolari.com` to the new one — `/health` still returns 200 while **every MCP call
|
|
205
|
+
404s**. The connector was down and the health check was green.
|
|
206
|
+
|
|
207
|
+
Two checks that actually discriminate:
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
curl -s https://mcp.getsolari.com/health # connector's body has a "sessions" field; the gateway's does not
|
|
211
|
+
curl -s -o /dev/null -w '%{http_code}\n' -XPOST https://mcp.getsolari.com/mcp \
|
|
212
|
+
-H 'content-type: application/json' -d '{}'
|
|
213
|
+
# 401 = the connector (auth required) 404 = the gateway is answering — connector NOT reachable
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**If you move or rebuild the desktop gateway ALB, you must re-point this service too** —
|
|
217
|
+
target group, listener rule, and the Route53 alias all live on that ALB.
|
package/dist/browser.js
CHANGED
|
@@ -131,21 +131,69 @@ export function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
131
131
|
return {
|
|
132
132
|
solari_browser_create: {
|
|
133
133
|
description: "Start a Solari cloud browser session. Use this whenever you need to browse the web. " +
|
|
134
|
-
"Returns a sessionId for the other solari_browser_* tools
|
|
135
|
-
"
|
|
136
|
-
"
|
|
134
|
+
"Returns a sessionId for the other solari_browser_* tools.\n" +
|
|
135
|
+
"mode defaults to 'stealth' — the anti-bot hardened pool. Just call this with no " +
|
|
136
|
+
"arguments and you get it; you do NOT need to ask for stealth explicitly. Stealth is " +
|
|
137
|
+
"the right default for the open web: ordinary sites work fine on it, and it is what " +
|
|
138
|
+
"keeps bot-detection from blocking the session.\n" +
|
|
139
|
+
"Pass mode:'fast' ONLY for a site you already know does not fingerprint or block " +
|
|
140
|
+
"automation (internal tools, localhost, your own app, plain docs/API pages) and you " +
|
|
141
|
+
"want the lower-latency pool. If a page in fast mode returns a block/captcha/challenge, " +
|
|
142
|
+
"close the session and retry with mode:'stealth'.\n" +
|
|
143
|
+
"captcha auto-solving is ALSO on by default (it follows the pool: on for stealth, off " +
|
|
144
|
+
"for fast). Pass captcha:false to turn it off — solving a challenge costs money and " +
|
|
145
|
+
"adds latency, so switch it off for sites you know never challenge.\n" +
|
|
146
|
+
"proxy ('smart' | country code like 'us') REQUIRES stealth, as does captcha; both are " +
|
|
147
|
+
"rejected if you ask for them explicitly in fast mode. recording gives an rrweb replay.",
|
|
137
148
|
inputSchema: {
|
|
149
|
+
mode: z.enum(["stealth", "fast"]).optional(),
|
|
150
|
+
/** @deprecated use mode. Kept so existing callers keep working. */
|
|
138
151
|
stealth: z.boolean().optional(),
|
|
139
152
|
proxy: z.string().optional(),
|
|
153
|
+
/** Defaults to ON (following the pool). Pass false to opt out. */
|
|
140
154
|
captcha: z.boolean().optional(),
|
|
141
155
|
recording: z.boolean().optional(),
|
|
142
156
|
profileId: z.string().optional(),
|
|
143
157
|
},
|
|
144
158
|
handler: async (a) => {
|
|
159
|
+
// STEALTH IS THE DEFAULT. Models consistently declined to opt in when it
|
|
160
|
+
// was an optional boolean, so sessions silently landed on the fast pool
|
|
161
|
+
// and got blocked by bot detection — the failure looked like "the site
|
|
162
|
+
// is broken" rather than "we picked the wrong pool". Defaulting on, with
|
|
163
|
+
// an explicit escape hatch, removes that whole class of confusion.
|
|
164
|
+
//
|
|
165
|
+
// Precedence: explicit mode wins; then the deprecated stealth boolean
|
|
166
|
+
// (so `stealth:false` still means fast for old callers); then stealth.
|
|
167
|
+
const stealth = a.mode !== undefined ? a.mode === "stealth" : (a.stealth ?? true);
|
|
168
|
+
// CAPTCHA IS ALSO ON BY DEFAULT — same reasoning as stealth: a model
|
|
169
|
+
// that has to opt in does not, and the resulting failure ("the page is
|
|
170
|
+
// a challenge screen") reads as a broken site rather than a missing
|
|
171
|
+
// option.
|
|
172
|
+
//
|
|
173
|
+
// The default FOLLOWS the pool rather than being a flat `true`, because
|
|
174
|
+
// captcha is stealth-only upstream. A flat true would make plain
|
|
175
|
+
// mode:'fast' throw on an option the caller never asked for, turning the
|
|
176
|
+
// escape hatch into a dead end. So: stealth ⇒ on, fast ⇒ off, and an
|
|
177
|
+
// explicit value always wins (captcha:false is the opt-out).
|
|
178
|
+
const captcha = a.captcha ?? stealth;
|
|
179
|
+
// proxy/captcha are stealth-only upstream. Previously a fast-pool
|
|
180
|
+
// session with proxy came back with the proxy silently dropped and only
|
|
181
|
+
// a note in the response; fail loudly instead — a silently unproxied
|
|
182
|
+
// request can leak the origin IP, which is the one thing the caller was
|
|
183
|
+
// trying to avoid. Only an EXPLICIT ask conflicts; the captcha default
|
|
184
|
+
// simply turns itself off in fast mode.
|
|
185
|
+
if (!stealth) {
|
|
186
|
+
const needsStealth = [a.proxy ? "proxy" : "", a.captcha === true ? "captcha" : ""].filter(Boolean);
|
|
187
|
+
if (needsStealth.length) {
|
|
188
|
+
throw new Error(`${needsStealth.join(" and ")} ${needsStealth.length > 1 ? "require" : "requires"} ` +
|
|
189
|
+
`stealth, but mode is 'fast'. ` +
|
|
190
|
+
`Drop ${needsStealth.length > 1 ? "them" : "it"} or use mode:'stealth'.`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
145
193
|
const body = {};
|
|
146
|
-
if (
|
|
194
|
+
if (stealth)
|
|
147
195
|
body.stealth = true;
|
|
148
|
-
if (
|
|
196
|
+
if (captcha)
|
|
149
197
|
body.captcha = true;
|
|
150
198
|
if (a.recording)
|
|
151
199
|
body.recording = true;
|
|
@@ -196,10 +244,16 @@ export function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
196
244
|
throw new Error(`browser session started but could not be attached (released it): ${redact(err instanceof Error ? err.message : String(err))}`);
|
|
197
245
|
}
|
|
198
246
|
// Proxy silently degrades rather than erroring — surface what we got.
|
|
247
|
+
// Echo the resolved mode back: the caller did not necessarily pick it
|
|
248
|
+
// (stealth is the default), and knowing which pool it landed on is what
|
|
249
|
+
// makes a later block actionable — "retry on stealth" vs "this site
|
|
250
|
+
// blocks us even hardened".
|
|
199
251
|
return text({
|
|
200
252
|
sessionId: s.sessionId,
|
|
253
|
+
mode: stealth ? "stealth" : "fast",
|
|
254
|
+
captcha,
|
|
201
255
|
expiresAt: s.expiresAt,
|
|
202
|
-
proxy: s.proxy ?? (a.proxy ? "NOT APPLIED (check plan
|
|
256
|
+
proxy: s.proxy ?? (a.proxy ? "NOT APPLIED (check plan)" : undefined),
|
|
203
257
|
});
|
|
204
258
|
},
|
|
205
259
|
},
|
|
@@ -113768,18 +113768,31 @@ function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
113768
113768
|
\u2026[truncated ${s.length - MAX_PAGE_TEXT} of ${s.length} ${what}]` : s;
|
|
113769
113769
|
return {
|
|
113770
113770
|
solari_browser_create: {
|
|
113771
|
-
description: "Start a Solari cloud browser session. Use this whenever you need to browse the web. Returns a sessionId for the other solari_browser_* tools
|
|
113771
|
+
description: "Start a Solari cloud browser session. Use this whenever you need to browse the web. Returns a sessionId for the other solari_browser_* tools.\nmode defaults to 'stealth' \u2014 the anti-bot hardened pool. Just call this with no arguments and you get it; you do NOT need to ask for stealth explicitly. Stealth is the right default for the open web: ordinary sites work fine on it, and it is what keeps bot-detection from blocking the session.\nPass mode:'fast' ONLY for a site you already know does not fingerprint or block automation (internal tools, localhost, your own app, plain docs/API pages) and you want the lower-latency pool. If a page in fast mode returns a block/captcha/challenge, close the session and retry with mode:'stealth'.\ncaptcha auto-solving is ALSO on by default (it follows the pool: on for stealth, off for fast). Pass captcha:false to turn it off \u2014 solving a challenge costs money and adds latency, so switch it off for sites you know never challenge.\nproxy ('smart' | country code like 'us') REQUIRES stealth, as does captcha; both are rejected if you ask for them explicitly in fast mode. recording gives an rrweb replay.",
|
|
113772
113772
|
inputSchema: {
|
|
113773
|
+
mode: external_exports.enum(["stealth", "fast"]).optional(),
|
|
113774
|
+
/** @deprecated use mode. Kept so existing callers keep working. */
|
|
113773
113775
|
stealth: external_exports.boolean().optional(),
|
|
113774
113776
|
proxy: external_exports.string().optional(),
|
|
113777
|
+
/** Defaults to ON (following the pool). Pass false to opt out. */
|
|
113775
113778
|
captcha: external_exports.boolean().optional(),
|
|
113776
113779
|
recording: external_exports.boolean().optional(),
|
|
113777
113780
|
profileId: external_exports.string().optional()
|
|
113778
113781
|
},
|
|
113779
113782
|
handler: async (a2) => {
|
|
113783
|
+
const stealth = a2.mode !== void 0 ? a2.mode === "stealth" : a2.stealth ?? true;
|
|
113784
|
+
const captcha = a2.captcha ?? stealth;
|
|
113785
|
+
if (!stealth) {
|
|
113786
|
+
const needsStealth = [a2.proxy ? "proxy" : "", a2.captcha === true ? "captcha" : ""].filter(Boolean);
|
|
113787
|
+
if (needsStealth.length) {
|
|
113788
|
+
throw new Error(
|
|
113789
|
+
`${needsStealth.join(" and ")} ${needsStealth.length > 1 ? "require" : "requires"} stealth, but mode is 'fast'. Drop ${needsStealth.length > 1 ? "them" : "it"} or use mode:'stealth'.`
|
|
113790
|
+
);
|
|
113791
|
+
}
|
|
113792
|
+
}
|
|
113780
113793
|
const body = {};
|
|
113781
|
-
if (
|
|
113782
|
-
if (
|
|
113794
|
+
if (stealth) body.stealth = true;
|
|
113795
|
+
if (captcha) body.captcha = true;
|
|
113783
113796
|
if (a2.recording) body.recording = true;
|
|
113784
113797
|
if (a2.proxy) body.proxy = a2.proxy;
|
|
113785
113798
|
if (a2.profileId) body.profileId = a2.profileId;
|
|
@@ -113819,8 +113832,10 @@ function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
113819
113832
|
}
|
|
113820
113833
|
return text({
|
|
113821
113834
|
sessionId: s.sessionId,
|
|
113835
|
+
mode: stealth ? "stealth" : "fast",
|
|
113836
|
+
captcha,
|
|
113822
113837
|
expiresAt: s.expiresAt,
|
|
113823
|
-
proxy: s.proxy ?? (a2.proxy ? "NOT APPLIED (check plan
|
|
113838
|
+
proxy: s.proxy ?? (a2.proxy ? "NOT APPLIED (check plan)" : void 0)
|
|
113824
113839
|
});
|
|
113825
113840
|
}
|
|
113826
113841
|
},
|
|
@@ -112437,18 +112437,31 @@ function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
112437
112437
|
\u2026[truncated ${s.length - MAX_PAGE_TEXT} of ${s.length} ${what}]` : s;
|
|
112438
112438
|
return {
|
|
112439
112439
|
solari_browser_create: {
|
|
112440
|
-
description: "Start a Solari cloud browser session. Use this whenever you need to browse the web. Returns a sessionId for the other solari_browser_* tools
|
|
112440
|
+
description: "Start a Solari cloud browser session. Use this whenever you need to browse the web. Returns a sessionId for the other solari_browser_* tools.\nmode defaults to 'stealth' \u2014 the anti-bot hardened pool. Just call this with no arguments and you get it; you do NOT need to ask for stealth explicitly. Stealth is the right default for the open web: ordinary sites work fine on it, and it is what keeps bot-detection from blocking the session.\nPass mode:'fast' ONLY for a site you already know does not fingerprint or block automation (internal tools, localhost, your own app, plain docs/API pages) and you want the lower-latency pool. If a page in fast mode returns a block/captcha/challenge, close the session and retry with mode:'stealth'.\ncaptcha auto-solving is ALSO on by default (it follows the pool: on for stealth, off for fast). Pass captcha:false to turn it off \u2014 solving a challenge costs money and adds latency, so switch it off for sites you know never challenge.\nproxy ('smart' | country code like 'us') REQUIRES stealth, as does captcha; both are rejected if you ask for them explicitly in fast mode. recording gives an rrweb replay.",
|
|
112441
112441
|
inputSchema: {
|
|
112442
|
+
mode: external_exports.enum(["stealth", "fast"]).optional(),
|
|
112443
|
+
/** @deprecated use mode. Kept so existing callers keep working. */
|
|
112442
112444
|
stealth: external_exports.boolean().optional(),
|
|
112443
112445
|
proxy: external_exports.string().optional(),
|
|
112446
|
+
/** Defaults to ON (following the pool). Pass false to opt out. */
|
|
112444
112447
|
captcha: external_exports.boolean().optional(),
|
|
112445
112448
|
recording: external_exports.boolean().optional(),
|
|
112446
112449
|
profileId: external_exports.string().optional()
|
|
112447
112450
|
},
|
|
112448
112451
|
handler: async (a2) => {
|
|
112452
|
+
const stealth = a2.mode !== void 0 ? a2.mode === "stealth" : a2.stealth ?? true;
|
|
112453
|
+
const captcha = a2.captcha ?? stealth;
|
|
112454
|
+
if (!stealth) {
|
|
112455
|
+
const needsStealth = [a2.proxy ? "proxy" : "", a2.captcha === true ? "captcha" : ""].filter(Boolean);
|
|
112456
|
+
if (needsStealth.length) {
|
|
112457
|
+
throw new Error(
|
|
112458
|
+
`${needsStealth.join(" and ")} ${needsStealth.length > 1 ? "require" : "requires"} stealth, but mode is 'fast'. Drop ${needsStealth.length > 1 ? "them" : "it"} or use mode:'stealth'.`
|
|
112459
|
+
);
|
|
112460
|
+
}
|
|
112461
|
+
}
|
|
112449
112462
|
const body = {};
|
|
112450
|
-
if (
|
|
112451
|
-
if (
|
|
112463
|
+
if (stealth) body.stealth = true;
|
|
112464
|
+
if (captcha) body.captcha = true;
|
|
112452
112465
|
if (a2.recording) body.recording = true;
|
|
112453
112466
|
if (a2.proxy) body.proxy = a2.proxy;
|
|
112454
112467
|
if (a2.profileId) body.profileId = a2.profileId;
|
|
@@ -112488,8 +112501,10 @@ function makeBrowserToolset(cfg, reg, deps = defaultDeps) {
|
|
|
112488
112501
|
}
|
|
112489
112502
|
return text({
|
|
112490
112503
|
sessionId: s.sessionId,
|
|
112504
|
+
mode: stealth ? "stealth" : "fast",
|
|
112505
|
+
captcha,
|
|
112491
112506
|
expiresAt: s.expiresAt,
|
|
112492
|
-
proxy: s.proxy ?? (a2.proxy ? "NOT APPLIED (check plan
|
|
112507
|
+
proxy: s.proxy ?? (a2.proxy ? "NOT APPLIED (check plan)" : void 0)
|
|
112493
112508
|
});
|
|
112494
112509
|
}
|
|
112495
112510
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solarisdk/mcp",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Model Context Protocol server for the Solari cloud browser, sandboxes + desktops
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Model Context Protocol server for the Solari cloud browser, sandboxes + desktops \u2014 drive them from Claude Desktop/Cowork, Claude Code, Cursor, etc.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"solari-mcp": "./dist/cli.js"
|