@fluentui-react-native/desktop-driver-mcp 0.0.0-stage → 0.1.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/AGENTS.md ADDED
@@ -0,0 +1,44 @@
1
+ # Desktop Driver MCP agent instructions
2
+
3
+ This package is the Model Context Protocol adapter for the Desktop Driver agent
4
+ operations. It is the instruction root for this package and every descendant.
5
+
6
+ ## Start here
7
+
8
+ Read the [README](README.md), then the narrowest entry in the
9
+ [reference index](references/README.md). The operations themselves, their
10
+ schemas, and their failure reasons belong to `@fluentui-react-native/desktop-driver`
11
+ (its agent operations reference); this package
12
+ only maps them onto MCP.
13
+
14
+ ## Invariants
15
+
16
+ - Stay a thin client. Every tool calls the service's operation routes through
17
+ the typed client; never add a second execution path, a host, or state the
18
+ service does not own. Tool input schemas come from the driver's registered
19
+ operation schemas, so the service and the adapter cannot drift apart.
20
+ - stdout carries MCP protocol only. Diagnostics go to stderr. Never log the
21
+ grant, the descriptor contents, or application text.
22
+ - Connect only through a private connection descriptor, verified by the
23
+ installed native helper before the grant is sent. Never launch or build the
24
+ service or a helper, and never accept a URL or grant from a command line,
25
+ environment variable, or the model.
26
+ - Serialize acquisition, use, close, and disposal per MCP connection. Retain
27
+ cleanup responsibility after transport loss; reverify discovery and never
28
+ replay a failed mutation. A verified replacement invalidates old references.
29
+ Fence a lost acquisition response; disposal also cleans up late acquisitions.
30
+ - Tie every artifact link to its session. Artifact ids restart in each session.
31
+ - Progress ticks come from the adapter and never reach the service, so a waiting
32
+ model does not keep an idle session alive. Cancellation aborts the HTTP call,
33
+ which the service treats as the caller leaving.
34
+ - Messages the model reads are fixed or bounded. Connection failures name no
35
+ paths; the details go to stderr.
36
+
37
+ ## Validation
38
+
39
+ Run `yarn format`, `yarn lint`, `yarn build`, and `yarn test` in this package.
40
+ Changes to tool schemas also need the tool-list size bound in `src/server.test.ts`
41
+ to hold. A change to driver operations is validated in the driver package first.
42
+ JavaScript tests use the fake host and are not native qualification; record a
43
+ live run against a real application for native claims. Add a patch changeset
44
+ for this published package when its behavior or shipped guidance changes.
package/README.md CHANGED
@@ -1,3 +1,47 @@
1
- # Temporary Holding Version
1
+ # @fluentui-react-native/desktop-driver-mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that gives
4
+ coding agents the Desktop Driver agent operations: bounded observation,
5
+ element search, actions, checks with waits, captures, and Storybook story
6
+ selection on a native macOS or Windows application.
7
+
8
+ **Work in progress:** [current status](references/current-status.md) records
9
+ implemented connection safeguards, orchestration gaps, native qualification
10
+ requirements, and measured MCP discovery costs.
11
+
12
+ Agents working in this package start at [AGENTS.md](AGENTS.md).
13
+
14
+ ## How it connects
15
+
16
+ The adapter does not start anything. A trusted supervisor runs the Desktop
17
+ Driver service with an authority, issues the agent a grant, and publishes a
18
+ private connection descriptor. The adapter reads that descriptor, has the
19
+ installed native helper verify the listening service's process identity, and
20
+ only then sends the grant. See
21
+ [Connection and setup](references/connection.md).
22
+
23
+ ## Use it
24
+
25
+ Register the server with an MCP client that launches it over stdio:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "desktop-driver": {
31
+ "command": "npx",
32
+ "args": ["desktop-driver-mcp", "--descriptor", "agent-connection.json"]
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ The agent then calls `desktop_session` to list targets and open one,
39
+ `desktop_observe` to read or page an immutable observation, compare it with a
40
+ retained sample, search, or inspect the journal, `desktop_act` to change it,
41
+ `desktop_check` to verify state, and `desktop_capture` for pixels. On a
42
+ Storybook target, `desktop_story` lists the stories and renders one. See
43
+ [Tools](references/tools.md).
44
+
45
+ ## References
46
+
47
+ The [reference index](references/README.md) lists every package reference.
package/config/cli.cjs ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { version } = require('../package.json');
4
+
5
+ import('../lib/cli.js')
6
+ .then(({ runDesktopDriverMcpCli }) => runDesktopDriverMcpCli({ version }))
7
+ .catch((error) => {
8
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
9
+ process.exitCode = 1;
10
+ });
package/lib/cli.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export type DesktopDriverMcpCliOptions = {
2
+ argv?: readonly string[];
3
+ /** The package version, reported by `--version` and at MCP initialization. */
4
+ version: string;
5
+ };
6
+ /**
7
+ * Serves MCP over stdio until the client closes stdin. stdout carries protocol only; diagnostics go to stderr.
8
+ */
9
+ export declare function runDesktopDriverMcpCli({ argv, version }: DesktopDriverMcpCliOptions): Promise<void>;
10
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,EAAE,IAAmB,EAAE,OAAO,EAAE,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBxH"}
package/lib/cli.js ADDED
@@ -0,0 +1,30 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { Command } from 'commander';
3
+ import { connectWithDescriptor } from './connection.js';
4
+ import { createDesktopDriverMcpServer } from './server.js';
5
+ /**
6
+ * Serves MCP over stdio until the client closes stdin. stdout carries protocol only; diagnostics go to stderr.
7
+ */
8
+ export async function runDesktopDriverMcpCli({ argv = process.argv, version }) {
9
+ const program = new Command()
10
+ .name('desktop-driver-mcp')
11
+ .description('Serve Desktop Driver agent operations to an MCP client over stdio.')
12
+ .option('--descriptor <name>', 'record name of the connection descriptor a supervisor published', 'agent-connection.json')
13
+ .option('--root <path>', 'private storage root the descriptor was published under; defaults to the platform location')
14
+ .version(version)
15
+ .configureOutput({ writeOut: (value) => process.stderr.write(value) });
16
+ program.parse(argv);
17
+ const flags = program.opts();
18
+ const server = createDesktopDriverMcpServer({
19
+ connect: connectWithDescriptor({ descriptor: flags.descriptor, ...(flags.root === undefined ? {} : { root: flags.root }) }),
20
+ version,
21
+ });
22
+ await server.connect(new StdioServerTransport());
23
+ const close = () => {
24
+ void server.close();
25
+ };
26
+ process.stdin.once('end', close);
27
+ process.once('SIGINT', close);
28
+ process.once('SIGTERM', close);
29
+ }
30
+ //# sourceMappingURL=cli.js.map
package/lib/cli.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAQ3D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,EAA8B;IACvG,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;SAC1B,IAAI,CAAC,oBAAoB,CAAC;SAC1B,WAAW,CAAC,oEAAoE,CAAC;SACjF,MAAM,CAAC,qBAAqB,EAAE,iEAAiE,EAAE,uBAAuB,CAAC;SACzH,MAAM,CAAC,eAAe,EAAE,4FAA4F,CAAC;SACrH,OAAO,CAAC,OAAO,CAAC;SAChB,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAyC,CAAC;IACpE,MAAM,MAAM,GAAG,4BAA4B,CAAC;QAC1C,OAAO,EAAE,qBAAqB,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3H,OAAO;KACR,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { DesktopDriverClient } from '@fluentui-react-native/desktop-driver/client';
2
+ export type DesktopDriverConnection = {
3
+ client: DesktopDriverClient;
4
+ /** The verified service incarnation. Never a URL or a credential. */
5
+ incarnation: string;
6
+ /** The non-secret grant id, not its bearer token or display label. */
7
+ principal: string;
8
+ };
9
+ /** Revalidates private discovery and returns the client and its verified authority, without launching anything. */
10
+ export type ConnectDesktopDriver = () => Promise<DesktopDriverConnection>;
11
+ export type DescriptorConnectionOptions = {
12
+ /** The record name the supervisor published the connection descriptor under, such as `agent-connection.json`. */
13
+ descriptor: string;
14
+ /** The private storage root, when the supervisor published somewhere other than the platform default. */
15
+ root?: string;
16
+ };
17
+ /**
18
+ * Connects through the private descriptor a trusted supervisor published. The service's identity is verified by the
19
+ * installed native helper before the grant is sent. Nothing is launched or built: a missing helper, descriptor, or
20
+ * service is an error.
21
+ */
22
+ export declare function connectWithDescriptor(options: DescriptorConnectionOptions): ConnectDesktopDriver;
23
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAC;AAExF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,mHAAmH;AACnH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAE1E,MAAM,MAAM,2BAA2B,GAAG;IACxC,iHAAiH;IACjH,UAAU,EAAE,MAAM,CAAC;IACnB,yGAAyG;IACzG,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CAmBhG"}
@@ -0,0 +1,28 @@
1
+ import { resolveNativeDesktopDriver } from '@fluentui-react-native/desktop-driver';
2
+ import { createMacOSPrivateStorage, createMacOSServiceVerifier, createWindowsPrivateStorage, createWindowsServiceVerifier, readConnectionDescriptor, } from '@fluentui-react-native/desktop-driver/authority';
3
+ import { createDesktopDriverClient } from '@fluentui-react-native/desktop-driver/client';
4
+ /**
5
+ * Connects through the private descriptor a trusted supervisor published. The service's identity is verified by the
6
+ * installed native helper before the grant is sent. Nothing is launched or built: a missing helper, descriptor, or
7
+ * service is an error.
8
+ */
9
+ export function connectWithDescriptor(options) {
10
+ return async () => {
11
+ const platform = process.platform === 'darwin' ? 'macos' : process.platform === 'win32' ? 'windows' : undefined;
12
+ if (platform === undefined) {
13
+ throw new Error('Desktop Driver services run on macOS and Windows.');
14
+ }
15
+ const artifact = await resolveNativeDesktopDriver({ buildPolicy: 'never', platform });
16
+ const storage = platform === 'macos'
17
+ ? await createMacOSPrivateStorage(...(options.root === undefined ? [] : [options.root]))
18
+ : await createWindowsPrivateStorage({ artifact, ...(options.root === undefined ? {} : { root: options.root }) });
19
+ const verify = platform === 'macos' ? createMacOSServiceVerifier({ artifact }) : createWindowsServiceVerifier({ artifact });
20
+ const descriptor = await readConnectionDescriptor(storage, options.descriptor, verify);
21
+ return {
22
+ client: createDesktopDriverClient({ grant: descriptor.grant, url: descriptor.url }),
23
+ incarnation: descriptor.service.incarnation,
24
+ principal: descriptor.grant.split('.')[1],
25
+ };
26
+ };
27
+ }
28
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAC;AAqBzF;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAoC;IACxE,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAChH,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtF,MAAM,OAAO,GACX,QAAQ,KAAK,OAAO;YAClB,CAAC,CAAC,MAAM,yBAAyB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACxF,CAAC,CAAC,MAAM,2BAA2B,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QACrH,MAAM,MAAM,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5H,MAAM,UAAU,GAAG,MAAM,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvF,OAAO;YACL,MAAM,EAAE,yBAAyB,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC;YACnF,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,WAAW;YAC3C,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC1C,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,80 @@
1
+ import type { OperationCallOptions } from '@fluentui-react-native/desktop-driver/client';
2
+ import type { OperationResponse } from '@fluentui-react-native/desktop-driver/operations';
3
+ import type { ConnectDesktopDriver } from './connection.js';
4
+ /** A failure the adapter itself reports, with a machine reason as the service's own errors carry. */
5
+ export declare class AdapterError extends Error {
6
+ readonly reason: string;
7
+ constructor(reason: string, message: string);
8
+ }
9
+ export type TargetSummary = {
10
+ endpoint?: string;
11
+ id: string;
12
+ launchModes?: ('launch' | 'attach')[];
13
+ platformName?: string;
14
+ quarantined?: true;
15
+ renderer?: string;
16
+ };
17
+ export type OperationSummary = {
18
+ available: boolean;
19
+ name: string;
20
+ unavailableReason?: string;
21
+ };
22
+ export type SessionSummary = {
23
+ clickMode?: string;
24
+ id: string;
25
+ operations: OperationSummary[];
26
+ target: string;
27
+ };
28
+ export type SessionResponse<Result> = {
29
+ response: OperationResponse<Result>;
30
+ session: string;
31
+ };
32
+ export type OpenSessionRequest = {
33
+ clickMode?: 'accessibility' | 'auto' | 'physical';
34
+ launch: boolean;
35
+ target: string;
36
+ };
37
+ /**
38
+ * Serializes one MCP connection's client lifetime. Transport failure retains cleanup responsibility; only verified
39
+ * replacement or an authoritative rejection invalidates it. No failed mutation or ambiguous acquisition is replayed.
40
+ */
41
+ export declare class DesktopController {
42
+ #private;
43
+ constructor(connect: ConnectDesktopDriver);
44
+ status(): Promise<{
45
+ session?: SessionSummary;
46
+ sessionState?: 'uncertain';
47
+ targets: TargetSummary[];
48
+ }>;
49
+ open(request: OpenSessionRequest): Promise<SessionSummary>;
50
+ close(): Promise<{
51
+ closed?: string;
52
+ }>;
53
+ private closeSession;
54
+ /** Runs one operation in the open session, and names the session so a later reference can be tied to it. */
55
+ run<Result>(name: string, input: object, options?: OperationCallOptions): Promise<SessionResponse<Result>>;
56
+ private runOperation;
57
+ /**
58
+ * Reads a whole captured image by paging through `artifact`. Artifact ids restart in every session, so a reference
59
+ * from a closed session is refused rather than read from whichever session is open now.
60
+ */
61
+ readArtifact(session: string, artifact: string, signal?: AbortSignal): Promise<{
62
+ data: Buffer;
63
+ mimeType: string;
64
+ }>;
65
+ private readArtifactPages;
66
+ get session(): string | undefined;
67
+ /** Stops admissions immediately. Late acquisitions still run their cleanup after the bounded close wait expires. */
68
+ dispose(): Promise<void>;
69
+ private connection;
70
+ private enqueue;
71
+ private assertCertain;
72
+ private describe;
73
+ /** Transport errors retain ownership; authoritative invalidation never permits replaying a failed operation. */
74
+ private guard;
75
+ }
76
+ export declare function isWebDriverError(error: unknown): error is Error & {
77
+ code: string;
78
+ data?: Record<string, unknown>;
79
+ };
80
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,318 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { DesktopSessionClient } from '@fluentui-react-native/desktop-driver/client';
3
+ /** A failure the adapter itself reports, with a machine reason as the service's own errors carry. */
4
+ export class AdapterError extends Error {
5
+ reason;
6
+ constructor(reason, message) {
7
+ super(message);
8
+ this.name = 'AdapterError';
9
+ this.reason = reason;
10
+ }
11
+ }
12
+ const deleteTimeoutMs = 10_000;
13
+ const artifactPageBytes = 1024 * 1024;
14
+ /** The service never keeps a larger capture; a larger claim is a fault, not something to buffer. */
15
+ const maxArtifactBytes = 16 * 1024 * 1024;
16
+ /**
17
+ * Serializes one MCP connection's client lifetime. Transport failure retains cleanup responsibility; only verified
18
+ * replacement or an authoritative rejection invalidates it. No failed mutation or ambiguous acquisition is replayed.
19
+ */
20
+ export class DesktopController {
21
+ #connect;
22
+ #connection;
23
+ #open;
24
+ #uncertain;
25
+ #pending = Promise.resolve();
26
+ #disposed = false;
27
+ #disposing;
28
+ #disconnected = new AbortController();
29
+ constructor(connect) {
30
+ this.#connect = connect;
31
+ }
32
+ status() {
33
+ return this.enqueue(async () => {
34
+ const { client } = await this.connection();
35
+ const status = await this.guard(() => client.status());
36
+ const targets = Array.isArray(status.targets) ? status.targets.map(summarizeTarget) : [];
37
+ const session = this.#open ? await this.describe(this.#open) : undefined;
38
+ return { ...(session ? { session } : {}), ...(this.#uncertain ? { sessionState: 'uncertain' } : {}), targets };
39
+ });
40
+ }
41
+ open(request) {
42
+ return this.enqueue(async () => {
43
+ const connection = await this.connection();
44
+ if (this.#disposed)
45
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
46
+ this.assertCertain();
47
+ if (this.#open) {
48
+ throw new AdapterError('session-open', 'A session is already open. Close it first.');
49
+ }
50
+ // A lost response can hide a successful acquisition. Retain the fence until a definitive response or replacement.
51
+ this.#uncertain = connection;
52
+ let session;
53
+ try {
54
+ session = await this.guard(() => connection.client.newSession({
55
+ alwaysMatch: {
56
+ 'furn:launchMode': request.launch ? 'launch' : 'attach',
57
+ 'furn:target': request.target,
58
+ ...(request.clickMode === undefined ? {} : { 'furn:clickMode': request.clickMode }),
59
+ },
60
+ }));
61
+ }
62
+ catch (error) {
63
+ if (isWebDriverError(error))
64
+ this.#uncertain = undefined;
65
+ throw error;
66
+ }
67
+ this.#uncertain = undefined;
68
+ this.#open = { connection, session, target: request.target };
69
+ if (this.#disposed) {
70
+ await this.closeSession();
71
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
72
+ }
73
+ return this.describe(this.#open);
74
+ });
75
+ }
76
+ close() {
77
+ return this.enqueue(async () => {
78
+ if (!this.#open && !this.#uncertain)
79
+ return {};
80
+ await this.connection();
81
+ this.assertCertain();
82
+ return this.closeSession();
83
+ });
84
+ }
85
+ async closeSession() {
86
+ const open = this.#open;
87
+ if (!open) {
88
+ return {};
89
+ }
90
+ try {
91
+ await this.guard(() => open.session.delete());
92
+ }
93
+ catch (error) {
94
+ if (!isWebDriverError(error) || error.code !== 'invalid session id')
95
+ throw error;
96
+ }
97
+ this.#open = undefined;
98
+ return { closed: open.session.id };
99
+ }
100
+ /** Runs one operation in the open session, and names the session so a later reference can be tied to it. */
101
+ run(name, input, options = {}) {
102
+ return this.enqueue(async () => {
103
+ if (this.#open || this.#uncertain)
104
+ await this.connection();
105
+ this.assertCertain();
106
+ return this.runOperation(name, input, options);
107
+ });
108
+ }
109
+ async runOperation(name, input, options) {
110
+ const open = this.#open;
111
+ if (!open) {
112
+ throw new AdapterError('no-session', 'No session is open. Open one with desktop_session first.');
113
+ }
114
+ const signal = AbortSignal.any([this.#disconnected.signal, ...(options.signal ? [options.signal] : [])]);
115
+ const response = await this.guard(() => open.session.operation(name, input, { ...options, signal }), signal);
116
+ return { response, session: open.session.id };
117
+ }
118
+ /**
119
+ * Reads a whole captured image by paging through `artifact`. Artifact ids restart in every session, so a reference
120
+ * from a closed session is refused rather than read from whichever session is open now.
121
+ */
122
+ readArtifact(session, artifact, signal) {
123
+ return this.enqueue(async () => {
124
+ if (this.#open || this.#uncertain)
125
+ await this.connection();
126
+ this.assertCertain();
127
+ return this.readArtifactPages(session, artifact, signal);
128
+ });
129
+ }
130
+ async readArtifactPages(session, artifact, signal) {
131
+ if (this.#open?.session.id !== session) {
132
+ throw new AdapterError('artifact-expired', 'That capture belongs to a session that is no longer open.');
133
+ }
134
+ const pages = [];
135
+ let offset = 0;
136
+ let first;
137
+ let total = 0;
138
+ while (offset !== undefined) {
139
+ const { response } = await this.runOperation('artifact', { artifact, length: artifactPageBytes, offset }, { signal });
140
+ const page = response.result;
141
+ first ??= page;
142
+ if (page.sha256 !== first.sha256 || page.bytes > maxArtifactBytes) {
143
+ throw new AdapterError('artifact-changed', 'The capture changed while it was being read.');
144
+ }
145
+ const bytes = Buffer.from(page.data, 'base64');
146
+ total += bytes.byteLength;
147
+ if (total > page.bytes || (page.next !== undefined && page.next <= offset)) {
148
+ throw new AdapterError('artifact-changed', 'The capture changed while it was being read.');
149
+ }
150
+ pages.push(bytes);
151
+ offset = page.next;
152
+ }
153
+ const data = Buffer.concat(pages);
154
+ if (!first || data.byteLength !== first.bytes || createHash('sha256').update(data).digest('hex') !== first.sha256) {
155
+ throw new AdapterError('artifact-changed', 'The capture did not match its recorded digest.');
156
+ }
157
+ return { data, mimeType: first.mimeType };
158
+ }
159
+ get session() {
160
+ return this.#open?.session.id;
161
+ }
162
+ /** Stops admissions immediately. Late acquisitions still run their cleanup after the bounded close wait expires. */
163
+ dispose() {
164
+ this.#disposed = true;
165
+ this.#disconnected.abort();
166
+ return (this.#disposing ??= (async () => {
167
+ const cleanup = this.#pending.then(async () => {
168
+ await this.closeSession();
169
+ this.assertCertain();
170
+ });
171
+ this.#pending = cleanup.catch(() => {
172
+ console.error('desktop-driver-mcp: session cleanup is incomplete; the service must drain or expire the session.');
173
+ });
174
+ let timer;
175
+ try {
176
+ await Promise.race([
177
+ this.#pending,
178
+ new Promise((resolve) => {
179
+ timer = setTimeout(() => {
180
+ console.error('desktop-driver-mcp: session cleanup is still pending; the service must drain or expire the session.');
181
+ resolve();
182
+ }, deleteTimeoutMs);
183
+ timer.unref();
184
+ }),
185
+ ]);
186
+ }
187
+ finally {
188
+ if (timer)
189
+ clearTimeout(timer);
190
+ }
191
+ })());
192
+ }
193
+ async connection() {
194
+ if (this.#connection)
195
+ return this.#connection;
196
+ let connection;
197
+ try {
198
+ connection = await this.#connect();
199
+ }
200
+ catch (error) {
201
+ // The cause can name machine-local paths; the operator reads it on stderr, the model reads a fixed message.
202
+ console.error(`desktop-driver-mcp: connecting failed: ${error instanceof Error ? error.message : String(error)}`);
203
+ throw new AdapterError('service-unavailable', 'The Desktop Driver service is not available. Ask the operator to start it.');
204
+ }
205
+ const previous = this.#open?.connection ?? this.#uncertain;
206
+ if (previous && previous.incarnation !== connection.incarnation) {
207
+ this.#open = undefined;
208
+ this.#uncertain = undefined;
209
+ }
210
+ else if (previous && previous.principal !== connection.principal) {
211
+ // A new grant on the same live service does not prove that the old grant's session has ended.
212
+ if (this.#open) {
213
+ try {
214
+ await this.closeSession();
215
+ }
216
+ catch (error) {
217
+ if (this.#open)
218
+ throw error;
219
+ }
220
+ }
221
+ if (this.#uncertain) {
222
+ try {
223
+ await this.guard(() => previous.client.status());
224
+ }
225
+ catch (error) {
226
+ if (this.#uncertain)
227
+ throw error;
228
+ }
229
+ }
230
+ this.assertCertain();
231
+ }
232
+ else if (this.#open) {
233
+ // Rebind only to the same verified service and principal. A subsequent command still validates session liveness.
234
+ this.#open = {
235
+ ...this.#open,
236
+ connection,
237
+ session: new DesktopSessionClient(connection.client, this.#open.session.id, this.#open.session.capabilities),
238
+ };
239
+ }
240
+ this.#connection = connection;
241
+ return connection;
242
+ }
243
+ enqueue(work) {
244
+ const result = this.#pending.then(() => {
245
+ if (this.#disposed)
246
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
247
+ return work();
248
+ });
249
+ this.#pending = result.catch(() => undefined);
250
+ return result;
251
+ }
252
+ assertCertain() {
253
+ if (this.#uncertain) {
254
+ throw new AdapterError('session-uncertain', 'A session acquisition lost its response. Ask the operator to revoke the old grant or restart the service before opening another.');
255
+ }
256
+ }
257
+ async describe(open) {
258
+ const catalog = await this.guard(() => open.session.operations());
259
+ const operations = catalog.operations.map(({ available, name, unavailableReason }) => ({
260
+ available,
261
+ name,
262
+ ...(unavailableReason === undefined ? {} : { unavailableReason }),
263
+ }));
264
+ const clickMode = open.session.capabilities['furn:clickMode'];
265
+ return {
266
+ ...(typeof clickMode === 'string' ? { clickMode } : {}),
267
+ id: open.session.id,
268
+ operations,
269
+ target: open.target,
270
+ };
271
+ }
272
+ /** Transport errors retain ownership; authoritative invalidation never permits replaying a failed operation. */
273
+ async guard(call, signal) {
274
+ try {
275
+ return await call();
276
+ }
277
+ catch (error) {
278
+ if (signal?.aborted) {
279
+ throw new AdapterError('cancelled', 'The call was cancelled.');
280
+ }
281
+ if (isWebDriverError(error)) {
282
+ if (error.code === 'invalid session id') {
283
+ this.#open = undefined;
284
+ }
285
+ if (error.code === 'unauthorized') {
286
+ this.#open = undefined;
287
+ this.#uncertain = undefined;
288
+ this.#connection = undefined;
289
+ throw new AdapterError('service-unavailable', 'The Desktop Driver authority is no longer valid. Reconnect before opening a session.');
290
+ }
291
+ throw error;
292
+ }
293
+ this.#connection = undefined;
294
+ throw new AdapterError('service-unavailable', 'The Desktop Driver service stopped answering. Recheck status before continuing.');
295
+ }
296
+ }
297
+ }
298
+ export function isWebDriverError(error) {
299
+ return error instanceof Error && error.name === 'WebDriverError' && typeof error.code === 'string';
300
+ }
301
+ function summarizeTarget(target) {
302
+ const text = (value) => (typeof value === 'string' ? value : undefined);
303
+ const summary = { id: String(target.id) };
304
+ for (const key of ['endpoint', 'platformName', 'renderer']) {
305
+ const value = text(target[key]);
306
+ if (value !== undefined) {
307
+ summary[key] = value;
308
+ }
309
+ }
310
+ if (target.quarantine !== undefined) {
311
+ summary.quarantined = true;
312
+ }
313
+ if (Array.isArray(target.launchModes)) {
314
+ summary.launchModes = target.launchModes.filter((mode) => mode === 'launch' || mode === 'attach');
315
+ }
316
+ return summary;
317
+ }
318
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { connectWithDescriptor } from './connection.js';
2
+ export type { ConnectDesktopDriver, DescriptorConnectionOptions, DesktopDriverConnection } from './connection.js';
3
+ export { createDesktopDriverMcpServer } from './server.js';
4
+ export type { DesktopDriverMcpServerOptions } from './server.js';
5
+ //# sourceMappingURL=index.d.ts.map