@trycua/cua 0.2.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 (91) hide show
  1. package/README.md +121 -0
  2. package/bin/cua.js +37 -0
  3. package/browser/cua_sdk-ffi.d.ts +6 -0
  4. package/browser/cua_sdk-ffi.js +3 -0
  5. package/browser/cua_sdk-ffi.ts +14 -0
  6. package/browser/cua_sdk.d.ts +2237 -0
  7. package/browser/cua_sdk.js +2607 -0
  8. package/browser/cua_sdk.ts +3644 -0
  9. package/browser/cyclops_sdk_schema-ffi.d.ts +6 -0
  10. package/browser/cyclops_sdk_schema-ffi.js +3 -0
  11. package/browser/cyclops_sdk_schema-ffi.ts +14 -0
  12. package/browser/cyclops_sdk_schema.d.ts +996 -0
  13. package/browser/cyclops_sdk_schema.js +2194 -0
  14. package/browser/cyclops_sdk_schema.ts +2934 -0
  15. package/browser/fleet_sdk-ffi.d.ts +28 -0
  16. package/browser/fleet_sdk-ffi.js +3 -0
  17. package/browser/fleet_sdk-ffi.ts +35 -0
  18. package/browser/fleet_sdk.d.ts +3056 -0
  19. package/browser/fleet_sdk.js +5088 -0
  20. package/browser/fleet_sdk.ts +6830 -0
  21. package/browser/index.d.ts +2 -0
  22. package/browser/index.js +18 -0
  23. package/browser/index.web.ts +34 -0
  24. package/browser/tsconfig.json +20 -0
  25. package/browser/wasm-bindgen/index.d.ts +2346 -0
  26. package/browser/wasm-bindgen/index.js +6642 -0
  27. package/browser/wasm-bindgen/index_bg.wasm +0 -0
  28. package/browser/wasm-bindgen/index_bg.wasm.d.ts +1154 -0
  29. package/dist/index.d.ts +118 -0
  30. package/dist/index.js +207 -0
  31. package/dist/mcp.d.ts +33 -0
  32. package/dist/mcp.js +41 -0
  33. package/dist/native/cua_sdk-ffi.d.ts +1038 -0
  34. package/dist/native/cua_sdk-ffi.js +5095 -0
  35. package/dist/native/cua_sdk.d.ts +15906 -0
  36. package/dist/native/cua_sdk.js +27061 -0
  37. package/dist/native/index.d.ts +7 -0
  38. package/dist/native/index.js +12 -0
  39. package/dist/native/node-runtime.d.ts +72 -0
  40. package/dist/native/node-runtime.js +35 -0
  41. package/dist/spaces/cursorArt.d.ts +27 -0
  42. package/dist/spaces/cursorArt.js +59 -0
  43. package/dist/spaces/errors.d.ts +81 -0
  44. package/dist/spaces/errors.js +102 -0
  45. package/dist/spaces/events.d.ts +154 -0
  46. package/dist/spaces/events.js +182 -0
  47. package/dist/spaces/groups.d.ts +130 -0
  48. package/dist/spaces/groups.js +275 -0
  49. package/dist/spaces/host.d.ts +71 -0
  50. package/dist/spaces/host.js +154 -0
  51. package/dist/spaces/index.d.ts +48 -0
  52. package/dist/spaces/index.js +44 -0
  53. package/dist/spaces/pip.d.ts +128 -0
  54. package/dist/spaces/pip.js +250 -0
  55. package/dist/spaces/presence.d.ts +187 -0
  56. package/dist/spaces/presence.js +449 -0
  57. package/dist/spaces/presenceTypes.check.d.ts +12 -0
  58. package/dist/spaces/presenceTypes.check.js +1 -0
  59. package/dist/spaces/presenceTypes.d.ts +47 -0
  60. package/dist/spaces/presenceTypes.js +7 -0
  61. package/dist/spaces/routines.d.ts +158 -0
  62. package/dist/spaces/routines.js +339 -0
  63. package/dist/spaces/thread.d.ts +147 -0
  64. package/dist/spaces/thread.js +285 -0
  65. package/dist/spaces/transport/http.d.ts +51 -0
  66. package/dist/spaces/transport/http.js +113 -0
  67. package/dist/spaces/transport/index.d.ts +19 -0
  68. package/dist/spaces/transport/index.js +19 -0
  69. package/dist/spaces/transport/session.d.ts +120 -0
  70. package/dist/spaces/transport/session.js +188 -0
  71. package/dist/spaces/transport/tauri.d.ts +50 -0
  72. package/dist/spaces/transport/tauri.js +90 -0
  73. package/dist/spaces/transport/types.d.ts +123 -0
  74. package/dist/spaces/transport/types.js +59 -0
  75. package/dist/teleport/controller.d.ts +34 -0
  76. package/dist/teleport/controller.js +107 -0
  77. package/dist/teleport/drop.d.ts +62 -0
  78. package/dist/teleport/drop.js +138 -0
  79. package/dist/teleport/dropZone.d.ts +59 -0
  80. package/dist/teleport/dropZone.js +166 -0
  81. package/dist/teleport/element.d.ts +28 -0
  82. package/dist/teleport/element.js +340 -0
  83. package/dist/teleport/index.d.ts +32 -0
  84. package/dist/teleport/index.js +32 -0
  85. package/dist/teleport/install.d.ts +31 -0
  86. package/dist/teleport/install.js +65 -0
  87. package/dist/teleport/model.d.ts +245 -0
  88. package/dist/teleport/model.js +334 -0
  89. package/dist/teleport/windowDrag.d.ts +86 -0
  90. package/dist/teleport/windowDrag.js +71 -0
  91. package/package.json +93 -0
@@ -0,0 +1,118 @@
1
+ import { Container, CuaConfig, type CuaLike, type FleetLike, type FleetPool, PoolOptions, ReadinessProbe, RegistrySecret, type ResolvedImage, SandboxSpec } from "./native/index.js";
2
+ export * from "./native/index.js";
3
+ export { connectMcp, mcpHeaders, type McpEndpointConfig } from "./mcp.js";
4
+ /**
5
+ * The qualified refs (`local:box`, `cloud:box`) a `CuaError.AmbiguousSandbox`
6
+ * lists: a bare sandbox name that matches sandboxes in more than one
7
+ * location. Empty for any other error.
8
+ */
9
+ export declare function ambiguousCandidates(error: unknown): string[];
10
+ /**
11
+ * The link to a `CuaError`'s entry (cause and fix) on the errors
12
+ * reference; `undefined` for any other value. Every `CuaError` also carries
13
+ * it as `docUrl`.
14
+ */
15
+ export declare function cuaErrorDocUrl(error: unknown): string | undefined;
16
+ /**
17
+ * An SDK runtime in this process (no I/O until the first call). Fleet uses
18
+ * `CUA_CLIENT_ID`/`CUA_CLIENT_SECRET` (or `FLEETS_TOKEN`); pass
19
+ * `fleetFromSession: true` to fall back to the `cua auth login` session.
20
+ */
21
+ export declare function embedded(config?: Partial<CuaConfig>): CuaLike;
22
+ /** A client of a running `cua daemon` (socket path or loopback URL). */
23
+ export declare function connect(address?: string, token?: string): CuaLike;
24
+ /** An image tier: `slim`, `full` (the default), or on macOS `xcode` / `xcode-<X.Y>`. */
25
+ export type ImageTier = "slim" | "full" | "xcode" | `xcode-${string}`;
26
+ /** Options for `Image.linux()` / `windows()` / `macos()`. */
27
+ export interface ImageOptions {
28
+ version?: string;
29
+ tier?: ImageTier;
30
+ }
31
+ /**
32
+ * Canonical images: `Image.linux()` is `ghcr.io/trycua/linux:24.04`
33
+ * (`CUA_IMAGE_LINUX` overrides it), `Image.windows()`
34
+ * `ghcr.io/trycua/windows:2022`, `Image.macos()` `ghcr.io/trycua/macos:26`.
35
+ * These are the full tier (dev tooling); `{ tier: "slim" }` is the minimal
36
+ * image CI runs and, on macOS, `{ tier: "xcode" }` adds a pinned Xcode.
37
+ * `Image.omarchy()` is `ghcr.io/trycua/omarchy:edge`, an amd64 VM. Images CI
38
+ * has not published yet throw `ImageNotPublished`; pass the reference to
39
+ * `fromRegistry` to use one anyway.
40
+ * `Image.resolve(ref, backend)` is the one resolver: the digest-pinned
41
+ * variant a backend runs (rootfs, the `-disk` containerDisk, Lume).
42
+ */
43
+ export declare const Image: {
44
+ linux: (version?: string | ImageOptions, tier?: ImageTier) => string;
45
+ windows: (version?: string | ImageOptions, tier?: ImageTier) => string;
46
+ macos: (version?: string | ImageOptions, tier?: ImageTier) => string;
47
+ /** Omarchy (Arch Linux, Hyprland) with cua-spacesd: an amd64 VM. */
48
+ omarchy: (channel?: string) => string;
49
+ fromRegistry: (reference: string) => string;
50
+ resolve: (reference: string, backend?: string, arch?: string) => ResolvedImage;
51
+ };
52
+ /** Ready once a TCP connect to the declared `service` succeeds. */
53
+ export declare function tcp(service: string): ReadinessProbe;
54
+ /** Ready once `GET path` on the declared `service` returns 2xx. */
55
+ export declare function http(service: string, path?: string): ReadinessProbe;
56
+ /**
57
+ * A sidecar container, addressed by name on every runtime: the sandbox
58
+ * reaches it at its `name` (and on `localhost` where they share a network
59
+ * namespace), it reaches the sandbox at `main`, and `services` may name its
60
+ * ports. Local containers (with `runtime: "runc"`) and every cloud sandbox;
61
+ * local VM sandboxes refuse sidecars. With sidecars the service names
62
+ * `main`, `sidecars` and `sc` are reserved.
63
+ *
64
+ * ```ts
65
+ * SandboxCreateOptions.create({ image: "python:3.12-slim",
66
+ * sidecars: [sidecar("redis:7-alpine", { ports: [6379] })],
67
+ * services: new Map([["db", 6379]]) })
68
+ * ```
69
+ */
70
+ export declare function sidecar(image: string, opts?: {
71
+ command?: string[];
72
+ env?: Record<string, string>;
73
+ ports?: number[];
74
+ name?: string;
75
+ }): Container;
76
+ /**
77
+ * Credentials for a private registry image (`registrySecret` on
78
+ * `SandboxCreateOptions`). Locally they authenticate the pull; in the cloud
79
+ * the SDK stores them as the sandbox's registry pull secret. Never logged.
80
+ */
81
+ export declare const registrySecret: {
82
+ /** A user name and password (or token). */
83
+ basic: (username: string, password: string, registry?: string) => RegistrySecret;
84
+ /** Read from environment variables at create time. */
85
+ fromEnv: (usernameVar?: string, passwordVar?: string, registry?: string) => RegistrySecret;
86
+ /** A private Amazon ECR image: a login token from the AWS CLI. */
87
+ awsEcr: (region?: string) => RegistrySecret;
88
+ };
89
+ type StringMap = Record<string, string> | Map<string, string>;
90
+ type PortMap = Record<string, number> | Map<string, number>;
91
+ /**
92
+ * What a sandbox runs: the one model behind `Sandbox.create`, managed pools
93
+ * and `fleet.apply(name, spec, options)`. `env` and `services` take plain
94
+ * objects too. Unset fields keep Fleet's defaults (and are not compared by
95
+ * `fleet.checkPoolSpec`).
96
+ *
97
+ * ```ts
98
+ * const spec = sandboxSpec("python:3.12-slim", {
99
+ * command: ["python", "-m", "srv"], services: { mcp: 8765 }, readiness: http("mcp", "/health") })
100
+ * await c.fleet().apply("my-pool", spec, poolOptions({ warm: true, idleTtlSeconds: 3600 }))
101
+ * ```
102
+ */
103
+ export declare function sandboxSpec(image: string, opts?: Partial<Omit<SandboxSpec, "image" | "env" | "services">> & {
104
+ env?: StringMap;
105
+ services?: PortMap;
106
+ }): SandboxSpec;
107
+ /** How a pool keeps capacity for a `SandboxSpec` (warm floor, size, TTLs, runtime). */
108
+ export declare function poolOptions(opts?: Partial<PoolOptions>): PoolOptions;
109
+ /**
110
+ * `Pool.apply(fleet, name, spec, options)`: the one pool writer, the same
111
+ * call as `fleet.apply`. Named pools are compared against a spec with
112
+ * `fleet.checkPoolSpec` (raises `CuaError.PoolSpecMismatch` with a diff) and
113
+ * updated with `fleet.applyPoolTemplate`; `fleet.exportPool(name).terraform`
114
+ * prints the equivalent `fleets_pool` block.
115
+ */
116
+ export declare const Pool: {
117
+ apply: (fleet: FleetLike, name: string, spec: SandboxSpec, options?: PoolOptions) => Promise<FleetPool>;
118
+ };
package/dist/index.js ADDED
@@ -0,0 +1,207 @@
1
+ /**
2
+ * The cua SDK for Node: a generated binding over the Rust `cua-sdk` crate.
3
+ *
4
+ * ```ts
5
+ * import { embedded, SandboxCreateOptions, http } from "@trycua/cua"
6
+ * const cua = embedded()
7
+ * const sb = await cua.sandboxes().create(SandboxCreateOptions.create({
8
+ * on: "local", // or "cloud"; kind / runtime: "auto" by default
9
+ * image: "python:3.12-slim",
10
+ * command: ["python", "-m", "my_mcp", "--port", "8765"],
11
+ * services: new Map([["mcp", 8765]]),
12
+ * waitFor: [http("mcp", "/health")],
13
+ * }))
14
+ * const r = await sb.service("mcp").request("POST", "/mcp", body, undefined, headers)
15
+ * const url = await sb.service("mcp").url() // usable from this machine
16
+ * const share = await sb.publicUrl("mcp", 3600, undefined) // shareable, expires
17
+ * ```
18
+ *
19
+ * The same objects work against a running `cua daemon` (`connect()`).
20
+ * Browser builds use `@trycua/cua/browser` (env over gRPC-Web + Fleet).
21
+ */
22
+ import { existsSync } from "node:fs";
23
+ import { createRequire } from "node:module";
24
+ import { dirname, join } from "node:path";
25
+ import { Container, Cua, CuaConfig, CuaError, CuaError_Tags, PoolOptions, ReadinessProbe, RegistrySecret, SandboxSpec, ambiguousSandboxCandidates, canonicalImageTier, errorDocUrl, omarchyImage, resolveImage, cuaSdkVersion, telemetrySetSurface, } from "./native/index.js";
26
+ export * from "./native/index.js";
27
+ export { connectMcp, mcpHeaders } from "./mcp.js";
28
+ // Usage telemetry (anonymous, content-free; https://cua.ai/docs/cua-sdk/concepts/telemetry)
29
+ // attributes events to this binding. It sends nothing by itself; off with
30
+ // DO_NOT_TRACK=1, CUA_TELEMETRY=0 or `telemetrySetEnabled(false)`.
31
+ try {
32
+ telemetrySetSurface("sdk_typescript", cuaSdkVersion());
33
+ }
34
+ catch {
35
+ // Telemetry never fails an import.
36
+ }
37
+ /**
38
+ * The qualified refs (`local:box`, `cloud:box`) a `CuaError.AmbiguousSandbox`
39
+ * lists: a bare sandbox name that matches sandboxes in more than one
40
+ * location. Empty for any other error.
41
+ */
42
+ export function ambiguousCandidates(error) {
43
+ if (!CuaError.AmbiguousSandbox.instanceOf(error))
44
+ return [];
45
+ return ambiguousSandboxCandidates(String(error.message ?? error));
46
+ }
47
+ /**
48
+ * The link to a `CuaError`'s entry (cause and fix) on the errors
49
+ * reference; `undefined` for any other value. Every `CuaError` also carries
50
+ * it as `docUrl`.
51
+ */
52
+ export function cuaErrorDocUrl(error) {
53
+ if (!CuaError.instanceOf(error))
54
+ return undefined;
55
+ return errorDocUrl(String(error.tag ?? ""));
56
+ }
57
+ // `docUrl` on every CuaError variant (a getter on each variant class).
58
+ for (const tag of Object.values(CuaError_Tags)) {
59
+ const variant = CuaError[tag];
60
+ if (variant && !Object.prototype.hasOwnProperty.call(variant.prototype, "docUrl")) {
61
+ Object.defineProperty(variant.prototype, "docUrl", {
62
+ get() {
63
+ return errorDocUrl(String(this.tag ?? ""));
64
+ },
65
+ configurable: true,
66
+ });
67
+ }
68
+ }
69
+ /**
70
+ * Points `CUA_BIN` at the CLI of the matching `@trycua/cua-<platform>`
71
+ * package, so the SDK can start the cua daemon (which serves local public
72
+ * URLs) on demand. An explicit `CUA_BIN` wins.
73
+ */
74
+ function defaultCuaBin() {
75
+ if (process.env.CUA_BIN)
76
+ return;
77
+ const arch = process.arch;
78
+ const triple = process.platform === "linux"
79
+ ? `linux-${arch}-gnu`
80
+ : process.platform === "win32"
81
+ ? `win32-${arch}-msvc`
82
+ : `${process.platform}-${arch}`;
83
+ try {
84
+ const require = createRequire(import.meta.url);
85
+ const exe = process.platform === "win32" ? "cua.exe" : "cua";
86
+ const bin = join(dirname(require.resolve(`@trycua/cua-${triple}/package.json`)), exe);
87
+ if (existsSync(bin))
88
+ process.env.CUA_BIN = bin;
89
+ }
90
+ catch {
91
+ // No platform package: the SDK looks for `cua` on PATH.
92
+ }
93
+ }
94
+ /**
95
+ * An SDK runtime in this process (no I/O until the first call). Fleet uses
96
+ * `CUA_CLIENT_ID`/`CUA_CLIENT_SECRET` (or `FLEETS_TOKEN`); pass
97
+ * `fleetFromSession: true` to fall back to the `cua auth login` session.
98
+ */
99
+ export function embedded(config = {}) {
100
+ defaultCuaBin();
101
+ return Cua.embedded(CuaConfig.create(config));
102
+ }
103
+ /** A client of a running `cua daemon` (socket path or loopback URL). */
104
+ export function connect(address, token) {
105
+ return Cua.connect(address, token);
106
+ }
107
+ function tierImage(os, version, tier) {
108
+ const o = typeof version === "object" ? version : { version, tier };
109
+ return canonicalImageTier(os, o.version, o.tier);
110
+ }
111
+ /**
112
+ * Canonical images: `Image.linux()` is `ghcr.io/trycua/linux:24.04`
113
+ * (`CUA_IMAGE_LINUX` overrides it), `Image.windows()`
114
+ * `ghcr.io/trycua/windows:2022`, `Image.macos()` `ghcr.io/trycua/macos:26`.
115
+ * These are the full tier (dev tooling); `{ tier: "slim" }` is the minimal
116
+ * image CI runs and, on macOS, `{ tier: "xcode" }` adds a pinned Xcode.
117
+ * `Image.omarchy()` is `ghcr.io/trycua/omarchy:edge`, an amd64 VM. Images CI
118
+ * has not published yet throw `ImageNotPublished`; pass the reference to
119
+ * `fromRegistry` to use one anyway.
120
+ * `Image.resolve(ref, backend)` is the one resolver: the digest-pinned
121
+ * variant a backend runs (rootfs, the `-disk` containerDisk, Lume).
122
+ */
123
+ export const Image = {
124
+ linux: (version, tier) => tierImage("linux", version, tier),
125
+ windows: (version, tier) => tierImage("windows", version, tier),
126
+ macos: (version, tier) => tierImage("macos", version, tier),
127
+ /** Omarchy (Arch Linux, Hyprland) with cua-spacesd: an amd64 VM. */
128
+ omarchy: (channel) => omarchyImage(channel),
129
+ // Literal: `ubuntu:24.04` is docker.io/library/ubuntu:24.04.
130
+ fromRegistry: (reference) => reference,
131
+ resolve: (reference, backend = "local", arch) => resolveImage(reference, backend, arch),
132
+ };
133
+ /** Ready once a TCP connect to the declared `service` succeeds. */
134
+ export function tcp(service) {
135
+ return ReadinessProbe.create({ service });
136
+ }
137
+ /** Ready once `GET path` on the declared `service` returns 2xx. */
138
+ export function http(service, path = "/") {
139
+ return ReadinessProbe.create({ service, httpPath: path });
140
+ }
141
+ /**
142
+ * A sidecar container, addressed by name on every runtime: the sandbox
143
+ * reaches it at its `name` (and on `localhost` where they share a network
144
+ * namespace), it reaches the sandbox at `main`, and `services` may name its
145
+ * ports. Local containers (with `runtime: "runc"`) and every cloud sandbox;
146
+ * local VM sandboxes refuse sidecars. With sidecars the service names
147
+ * `main`, `sidecars` and `sc` are reserved.
148
+ *
149
+ * ```ts
150
+ * SandboxCreateOptions.create({ image: "python:3.12-slim",
151
+ * sidecars: [sidecar("redis:7-alpine", { ports: [6379] })],
152
+ * services: new Map([["db", 6379]]) })
153
+ * ```
154
+ */
155
+ export function sidecar(image, opts = {}) {
156
+ return Container.create({
157
+ image,
158
+ env: new Map(Object.entries(opts.env ?? {})),
159
+ ports: opts.ports ?? [],
160
+ ...(opts.command ? { command: opts.command } : {}),
161
+ ...(opts.name ? { name: opts.name } : {}),
162
+ });
163
+ }
164
+ /**
165
+ * Credentials for a private registry image (`registrySecret` on
166
+ * `SandboxCreateOptions`). Locally they authenticate the pull; in the cloud
167
+ * the SDK stores them as the sandbox's registry pull secret. Never logged.
168
+ */
169
+ export const registrySecret = {
170
+ /** A user name and password (or token). */
171
+ basic: (username, password, registry) => new RegistrySecret.Basic({ username, password, ...(registry ? { registry } : {}) }),
172
+ /** Read from environment variables at create time. */
173
+ fromEnv: (usernameVar = "CUA_REGISTRY_USERNAME", passwordVar = "CUA_REGISTRY_PASSWORD", registry) => new RegistrySecret.FromEnv({ usernameVar, passwordVar, ...(registry ? { registry } : {}) }),
174
+ /** A private Amazon ECR image: a login token from the AWS CLI. */
175
+ awsEcr: (region) => new RegistrySecret.AwsEcr(region ? { region } : {}),
176
+ };
177
+ const toMap = (m) => m instanceof Map ? new Map(m) : new Map(Object.entries(m ?? {}));
178
+ /**
179
+ * What a sandbox runs: the one model behind `Sandbox.create`, managed pools
180
+ * and `fleet.apply(name, spec, options)`. `env` and `services` take plain
181
+ * objects too. Unset fields keep Fleet's defaults (and are not compared by
182
+ * `fleet.checkPoolSpec`).
183
+ *
184
+ * ```ts
185
+ * const spec = sandboxSpec("python:3.12-slim", {
186
+ * command: ["python", "-m", "srv"], services: { mcp: 8765 }, readiness: http("mcp", "/health") })
187
+ * await c.fleet().apply("my-pool", spec, poolOptions({ warm: true, idleTtlSeconds: 3600 }))
188
+ * ```
189
+ */
190
+ export function sandboxSpec(image, opts = {}) {
191
+ const { env, services, ...rest } = opts;
192
+ return SandboxSpec.create({ ...rest, image, env: toMap(env), services: toMap(services) });
193
+ }
194
+ /** How a pool keeps capacity for a `SandboxSpec` (warm floor, size, TTLs, runtime). */
195
+ export function poolOptions(opts = {}) {
196
+ return PoolOptions.create(opts);
197
+ }
198
+ /**
199
+ * `Pool.apply(fleet, name, spec, options)`: the one pool writer, the same
200
+ * call as `fleet.apply`. Named pools are compared against a spec with
201
+ * `fleet.checkPoolSpec` (raises `CuaError.PoolSpecMismatch` with a diff) and
202
+ * updated with `fleet.applyPoolTemplate`; `fleet.exportPool(name).terraform`
203
+ * prints the equivalent `fleets_pool` block.
204
+ */
205
+ export const Pool = {
206
+ apply: (fleet, name, spec, options = poolOptions()) => fleet.apply(name, spec, options),
207
+ };
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * MCP servers inside a sandbox, with the official TypeScript SDK
3
+ * (`@modelcontextprotocol/client`, an optional peer dependency).
4
+ *
5
+ * cua does not implement MCP: `sandbox.mcpConfig(service)` returns the
6
+ * endpoint URL and the headers its route needs (nothing locally; the Fleet
7
+ * gateway bearer and claim in the cloud; the daemon bearer through
8
+ * `cua daemon`), and `connectMcp` hands that to the SDK's streamable-HTTP
9
+ * transport, so every protocol revision and content block works unchanged.
10
+ *
11
+ * ```ts
12
+ * const client = await connectMcp(await sb.mcpConfig("mcp", undefined))
13
+ * const result = await client.callTool({ name: "add", arguments: { a: 2, b: 3 } })
14
+ * ```
15
+ */
16
+ /** Where an MCP endpoint is: `Sandbox.mcpConfig()` returns one. */
17
+ export interface McpEndpointConfig {
18
+ url: string;
19
+ headers: Array<{
20
+ name: string;
21
+ value: string;
22
+ }> | Record<string, string>;
23
+ }
24
+ /** The headers as a plain object. */
25
+ export declare function mcpHeaders(config: McpEndpointConfig): Record<string, string>;
26
+ /**
27
+ * Connects the official SDK's `Client` to `config` over streamable HTTP.
28
+ * Fleet bearers are short-lived: fetch a fresh config per connection.
29
+ */
30
+ export declare function connectMcp(config: McpEndpointConfig, clientInfo?: {
31
+ name: string;
32
+ version: string;
33
+ }): Promise<any>;
package/dist/mcp.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * MCP servers inside a sandbox, with the official TypeScript SDK
3
+ * (`@modelcontextprotocol/client`, an optional peer dependency).
4
+ *
5
+ * cua does not implement MCP: `sandbox.mcpConfig(service)` returns the
6
+ * endpoint URL and the headers its route needs (nothing locally; the Fleet
7
+ * gateway bearer and claim in the cloud; the daemon bearer through
8
+ * `cua daemon`), and `connectMcp` hands that to the SDK's streamable-HTTP
9
+ * transport, so every protocol revision and content block works unchanged.
10
+ *
11
+ * ```ts
12
+ * const client = await connectMcp(await sb.mcpConfig("mcp", undefined))
13
+ * const result = await client.callTool({ name: "add", arguments: { a: 2, b: 3 } })
14
+ * ```
15
+ */
16
+ /** The headers as a plain object. */
17
+ export function mcpHeaders(config) {
18
+ if (Array.isArray(config.headers)) {
19
+ return Object.fromEntries(config.headers.map((h) => [h.name, h.value]));
20
+ }
21
+ return { ...config.headers };
22
+ }
23
+ /**
24
+ * Connects the official SDK's `Client` to `config` over streamable HTTP.
25
+ * Fleet bearers are short-lived: fetch a fresh config per connection.
26
+ */
27
+ export async function connectMcp(config, clientInfo = { name: "cua", version: "0" }) {
28
+ let sdk;
29
+ try {
30
+ sdk = await import("@modelcontextprotocol/client");
31
+ }
32
+ catch (error) {
33
+ throw new Error("connectMcp needs the official MCP SDK: npm install @modelcontextprotocol/client", { cause: error });
34
+ }
35
+ const transport = new sdk.StreamableHTTPClientTransport(new URL(config.url), {
36
+ requestInit: { headers: mcpHeaders(config) },
37
+ });
38
+ const client = new sdk.Client(clientInfo);
39
+ await client.connect(transport);
40
+ return client;
41
+ }