@fluentui-react-native/desktop-driver-mcp 0.0.0-stage → 0.1.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.
@@ -0,0 +1,352 @@
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
+ #binding;
24
+ #open;
25
+ #uncertain;
26
+ #pending = Promise.resolve();
27
+ #disposed = false;
28
+ #disposing;
29
+ #disconnected = new AbortController();
30
+ constructor(connect) {
31
+ this.#connect = connect;
32
+ }
33
+ status() {
34
+ return this.enqueue(async () => {
35
+ const { client } = await this.connection();
36
+ const status = await this.guard(() => client.status());
37
+ const targets = Array.isArray(status.targets) ? status.targets.map(summarizeTarget) : [];
38
+ const session = this.#open ? await this.describe(this.#open) : undefined;
39
+ return { ...(session ? { session } : {}), ...(this.#uncertain ? { sessionState: 'uncertain' } : {}), targets };
40
+ });
41
+ }
42
+ open(request) {
43
+ return this.enqueue(async () => {
44
+ const connection = await this.connection();
45
+ if (this.#disposed)
46
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
47
+ this.assertCertain();
48
+ if (this.#open) {
49
+ throw new AdapterError('session-open', 'A session is already open. Close it first.');
50
+ }
51
+ // A lost response can hide a successful acquisition. Retain the fence until a definitive response or replacement.
52
+ this.#uncertain = connection;
53
+ let session;
54
+ try {
55
+ session = await this.guard(() => connection.client.newSession({
56
+ alwaysMatch: {
57
+ 'furn:launchMode': request.launch ? 'launch' : 'attach',
58
+ 'furn:target': request.target,
59
+ ...(request.clickMode === undefined ? {} : { 'furn:clickMode': request.clickMode }),
60
+ },
61
+ }));
62
+ }
63
+ catch (error) {
64
+ if (isWebDriverError(error))
65
+ this.#uncertain = undefined;
66
+ throw error;
67
+ }
68
+ this.#uncertain = undefined;
69
+ this.#open = { connection, session, target: request.target };
70
+ if (this.#disposed) {
71
+ await this.closeSession();
72
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
73
+ }
74
+ return this.describe(this.#open);
75
+ });
76
+ }
77
+ close() {
78
+ return this.enqueue(async () => {
79
+ if (!this.#open && !this.#uncertain)
80
+ return {};
81
+ await this.connection();
82
+ this.assertCertain();
83
+ return this.closeSession();
84
+ });
85
+ }
86
+ async closeSession() {
87
+ const open = this.#open;
88
+ if (!open) {
89
+ return {};
90
+ }
91
+ try {
92
+ await this.guard(() => open.session.delete());
93
+ }
94
+ catch (error) {
95
+ if (!isWebDriverError(error) || error.code !== 'invalid session id')
96
+ throw error;
97
+ }
98
+ this.#open = undefined;
99
+ return { closed: open.session.id };
100
+ }
101
+ /** Runs one operation in the open session, and names the session so a later reference can be tied to it. */
102
+ run(name, input, options = {}) {
103
+ return this.enqueue(async () => {
104
+ if (this.#open || this.#uncertain)
105
+ await this.connection();
106
+ this.assertCertain();
107
+ return this.runOperation(name, input, options);
108
+ });
109
+ }
110
+ async runOperation(name, input, options) {
111
+ const open = this.#open;
112
+ if (!open) {
113
+ throw new AdapterError('no-session', 'No session is open. Open one with desktop_session first.');
114
+ }
115
+ const signal = AbortSignal.any([this.#disconnected.signal, ...(options.signal ? [options.signal] : [])]);
116
+ const response = await this.guard(() => open.session.operation(name, input, { ...options, signal }), signal);
117
+ return { response, session: open.session.id };
118
+ }
119
+ /**
120
+ * Reads a whole captured image by paging through `artifact`. Artifact ids restart in every session, so a reference
121
+ * from a closed session is refused rather than read from whichever session is open now.
122
+ */
123
+ readArtifact(session, artifact, signal) {
124
+ return this.enqueue(async () => {
125
+ if (this.#open || this.#uncertain)
126
+ await this.connection();
127
+ this.assertCertain();
128
+ return this.readArtifactPages(session, artifact, signal);
129
+ });
130
+ }
131
+ async readArtifactPages(session, artifact, signal) {
132
+ if (this.#open?.session.id !== session) {
133
+ throw new AdapterError('artifact-expired', 'That capture belongs to a session that is no longer open.');
134
+ }
135
+ const pages = [];
136
+ let offset = 0;
137
+ let first;
138
+ let total = 0;
139
+ while (offset !== undefined) {
140
+ const { response } = await this.runOperation('artifact', { artifact, length: artifactPageBytes, offset }, { signal });
141
+ const page = response.result;
142
+ first ??= page;
143
+ if (page.sha256 !== first.sha256 || page.bytes > maxArtifactBytes) {
144
+ throw new AdapterError('artifact-changed', 'The capture changed while it was being read.');
145
+ }
146
+ const bytes = Buffer.from(page.data, 'base64');
147
+ total += bytes.byteLength;
148
+ if (total > page.bytes || (page.next !== undefined && page.next <= offset)) {
149
+ throw new AdapterError('artifact-changed', 'The capture changed while it was being read.');
150
+ }
151
+ pages.push(bytes);
152
+ offset = page.next;
153
+ }
154
+ const data = Buffer.concat(pages);
155
+ if (!first || data.byteLength !== first.bytes || createHash('sha256').update(data).digest('hex') !== first.sha256) {
156
+ throw new AdapterError('artifact-changed', 'The capture did not match its recorded digest.');
157
+ }
158
+ return { data, mimeType: first.mimeType };
159
+ }
160
+ get session() {
161
+ return this.#open?.session.id;
162
+ }
163
+ /** Stops admissions immediately. Late acquisitions still run their cleanup after the bounded close wait expires. */
164
+ dispose() {
165
+ this.#disposed = true;
166
+ this.#disconnected.abort();
167
+ return (this.#disposing ??= (async () => {
168
+ const cleanup = this.#pending.then(async () => {
169
+ if (this.#binding) {
170
+ await this.#binding.child.client.revokeConnection();
171
+ this.#open = undefined;
172
+ this.#uncertain = undefined;
173
+ this.#binding = undefined;
174
+ }
175
+ });
176
+ this.#pending = cleanup.catch(() => {
177
+ console.error('desktop-driver-mcp: session cleanup is incomplete; the service must drain or expire the session.');
178
+ });
179
+ let timer;
180
+ try {
181
+ await Promise.race([
182
+ this.#pending,
183
+ new Promise((resolve) => {
184
+ timer = setTimeout(() => {
185
+ console.error('desktop-driver-mcp: session cleanup is still pending; the service must drain or expire the session.');
186
+ resolve();
187
+ }, deleteTimeoutMs);
188
+ timer.unref();
189
+ }),
190
+ ]);
191
+ }
192
+ finally {
193
+ if (timer)
194
+ clearTimeout(timer);
195
+ if (this.#binding)
196
+ this.#disposing = undefined;
197
+ }
198
+ })());
199
+ }
200
+ async connection() {
201
+ if (this.#connection)
202
+ return this.#connection;
203
+ let connection;
204
+ try {
205
+ connection = await this.#connect();
206
+ }
207
+ catch {
208
+ // Discovery failures can contain descriptor credentials; neither protocol output nor diagnostics may echo them.
209
+ console.error('desktop-driver-mcp: connecting failed; verify private discovery and the service identity.');
210
+ throw new AdapterError('service-unavailable', 'The Desktop Driver service is not available. Ask the operator to start it.');
211
+ }
212
+ const binding = this.#binding;
213
+ if (binding && binding.root.incarnation === connection.incarnation && binding.root.principal === connection.principal) {
214
+ connection = binding.child;
215
+ }
216
+ else {
217
+ if (binding && binding.root.incarnation === connection.incarnation) {
218
+ await this.guard(() => binding.child.client.revokeConnection());
219
+ this.#open = undefined;
220
+ this.#uncertain = undefined;
221
+ }
222
+ const root = connection;
223
+ let child;
224
+ try {
225
+ child = await this.guard(() => root.client.delegateConnection());
226
+ }
227
+ catch (error) {
228
+ if (isWebDriverError(error) && ['unknown command', 'unsupported operation'].includes(error.code)) {
229
+ throw new AdapterError('connection-authority-unsupported', 'The service does not support isolated connection authority.');
230
+ }
231
+ throw error;
232
+ }
233
+ const principal = child.principalId;
234
+ if (!principal)
235
+ throw new AdapterError('service-unavailable', 'The service does not support isolated connection authority.');
236
+ connection = { client: child, incarnation: root.incarnation, principal };
237
+ this.#binding = { child: connection, root };
238
+ }
239
+ const previous = this.#open?.connection ?? this.#uncertain;
240
+ if (previous && previous.incarnation !== connection.incarnation) {
241
+ this.#open = undefined;
242
+ this.#uncertain = undefined;
243
+ }
244
+ else if (previous && previous.principal !== connection.principal) {
245
+ // A new grant on the same live service does not prove that the old grant's session has ended.
246
+ if (this.#open) {
247
+ try {
248
+ await this.closeSession();
249
+ }
250
+ catch (error) {
251
+ if (this.#open)
252
+ throw error;
253
+ }
254
+ }
255
+ if (this.#uncertain) {
256
+ try {
257
+ await this.guard(() => previous.client.status());
258
+ }
259
+ catch (error) {
260
+ if (this.#uncertain)
261
+ throw error;
262
+ }
263
+ }
264
+ this.assertCertain();
265
+ }
266
+ else if (this.#open) {
267
+ // Rebind only to the same verified service and principal. A subsequent command still validates session liveness.
268
+ this.#open = {
269
+ ...this.#open,
270
+ connection,
271
+ session: new DesktopSessionClient(connection.client, this.#open.session.id, this.#open.session.capabilities),
272
+ };
273
+ }
274
+ this.#connection = connection;
275
+ return connection;
276
+ }
277
+ enqueue(work) {
278
+ const result = this.#pending.then(() => {
279
+ if (this.#disposed)
280
+ throw new AdapterError('connection-closed', 'The MCP connection is closed.');
281
+ return work();
282
+ });
283
+ this.#pending = result.catch(() => undefined);
284
+ return result;
285
+ }
286
+ assertCertain() {
287
+ if (this.#uncertain) {
288
+ 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.');
289
+ }
290
+ }
291
+ async describe(open) {
292
+ const catalog = await this.guard(() => open.session.operations());
293
+ const operations = catalog.operations.map(({ available, name, unavailableReason }) => ({
294
+ available,
295
+ name,
296
+ ...(unavailableReason === undefined ? {} : { unavailableReason }),
297
+ }));
298
+ const clickMode = open.session.capabilities['furn:clickMode'];
299
+ return {
300
+ ...(typeof clickMode === 'string' ? { clickMode } : {}),
301
+ id: open.session.id,
302
+ operations,
303
+ target: open.target,
304
+ };
305
+ }
306
+ /** Transport errors retain ownership; authoritative invalidation never permits replaying a failed operation. */
307
+ async guard(call, signal) {
308
+ try {
309
+ return await call();
310
+ }
311
+ catch (error) {
312
+ if (signal?.aborted) {
313
+ throw new AdapterError('cancelled', 'The call was cancelled.');
314
+ }
315
+ if (isWebDriverError(error)) {
316
+ if (error.code === 'invalid session id') {
317
+ this.#open = undefined;
318
+ }
319
+ if (error.code === 'unauthorized') {
320
+ this.#open = undefined;
321
+ this.#uncertain = undefined;
322
+ this.#connection = undefined;
323
+ throw new AdapterError('service-unavailable', 'The Desktop Driver authority is no longer valid. Reconnect before opening a session.');
324
+ }
325
+ throw error;
326
+ }
327
+ this.#connection = undefined;
328
+ throw new AdapterError('service-unavailable', 'The Desktop Driver service stopped answering. Recheck status before continuing.');
329
+ }
330
+ }
331
+ }
332
+ export function isWebDriverError(error) {
333
+ return error instanceof Error && error.name === 'WebDriverError' && typeof error.code === 'string';
334
+ }
335
+ function summarizeTarget(target) {
336
+ const text = (value) => (typeof value === 'string' ? value : undefined);
337
+ const summary = { id: String(target.id) };
338
+ for (const key of ['endpoint', 'platformName', 'renderer']) {
339
+ const value = text(target[key]);
340
+ if (value !== undefined) {
341
+ summary[key] = value;
342
+ }
343
+ }
344
+ if (target.quarantine !== undefined) {
345
+ summary.quarantined = true;
346
+ }
347
+ if (Array.isArray(target.launchModes)) {
348
+ summary.launchModes = target.launchModes.filter((mode) => mode === 'launch' || mode === 'attach');
349
+ }
350
+ return summary;
351
+ }
352
+ //# 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAClH,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { connectWithDescriptor } from './connection.js';
2
+ export { createDesktopDriverMcpServer } from './server.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ type Content = CallToolResult['content'][number];
3
+ /**
4
+ * Renders a value as the model reads it: compact JSON, with any observation outline lifted out into its own text block
5
+ * so its lines read as lines instead of escaped `\n` runs. Nothing is sent twice.
6
+ */
7
+ export declare function jsonResult(value: unknown, extra?: Content[]): CallToolResult;
8
+ /** A failure the model can branch on: the WebDriver error code, the machine reason, and a bounded message. */
9
+ export declare function errorResult(error: unknown): CallToolResult;
10
+ export {};
11
+ //# sourceMappingURL=results.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAIzE,KAAK,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAIjD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,OAAO,EAAO,GAAG,cAAc,CAMhF;AAED,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAgB1D"}
package/lib/results.js ADDED
@@ -0,0 +1,61 @@
1
+ import { AdapterError, isWebDriverError } from './controller.js';
2
+ const maxMessageLength = 300;
3
+ /**
4
+ * Renders a value as the model reads it: compact JSON, with any observation outline lifted out into its own text block
5
+ * so its lines read as lines instead of escaped `\n` runs. Nothing is sent twice.
6
+ */
7
+ export function jsonResult(value, extra = []) {
8
+ const outlines = [];
9
+ const lifted = liftOutlines(value, outlines);
10
+ return {
11
+ content: [{ text: JSON.stringify(lifted), type: 'text' }, ...outlines.map((text) => ({ text, type: 'text' })), ...extra],
12
+ };
13
+ }
14
+ /** A failure the model can branch on: the WebDriver error code, the machine reason, and a bounded message. */
15
+ export function errorResult(error) {
16
+ let failure;
17
+ if (error instanceof AdapterError) {
18
+ failure = { error: 'adapter', message: error.message, reason: error.reason };
19
+ }
20
+ else if (isWebDriverError(error)) {
21
+ const data = error.data ?? {};
22
+ failure = {
23
+ error: error.code,
24
+ message: bound(error.message),
25
+ ...pick(data, ['reason', 'nativeCode', 'requestId', 'mutation']),
26
+ };
27
+ }
28
+ else {
29
+ console.error(`desktop-driver-mcp: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);
30
+ failure = { error: 'adapter', message: 'The adapter failed unexpectedly.', reason: 'internal' };
31
+ }
32
+ return { content: [{ text: JSON.stringify(failure), type: 'text' }], isError: true };
33
+ }
34
+ function liftOutlines(value, outlines) {
35
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
36
+ return value;
37
+ }
38
+ const copy = {};
39
+ for (const [key, child] of Object.entries(value)) {
40
+ if (key === 'outline' && typeof child === 'string') {
41
+ outlines.push(child);
42
+ copy.outline = `(text block ${outlines.length + 1})`;
43
+ }
44
+ else if (key === 'result' || key === 'observation') {
45
+ copy[key] = liftOutlines(child, outlines);
46
+ }
47
+ else {
48
+ copy[key] = child;
49
+ }
50
+ }
51
+ return copy;
52
+ }
53
+ function pick(data, keys) {
54
+ return Object.fromEntries(keys.filter((key) => data[key] !== undefined).map((key) => [key, data[key]]));
55
+ }
56
+ function bound(message) {
57
+ // The service already bounds operation messages; session errors may quote provider text, so bound them here too.
58
+ const visible = message.replace(/\p{Cc}/gu, ' ');
59
+ return visible.length > maxMessageLength ? `${visible.slice(0, maxMessageLength - 1)}…` : visible;
60
+ }
61
+ //# sourceMappingURL=results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.js","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ConnectDesktopDriver } from './connection.js';
3
+ export type DesktopDriverMcpServerOptions = {
4
+ /** Returns a verified client and authority identity; called again after transport failure or authority invalidation. */
5
+ connect: ConnectDesktopDriver;
6
+ /** How often a long call reports progress to a client that asked for it. */
7
+ progressIntervalMs?: number;
8
+ /** The adapter version reported at initialization. */
9
+ version: string;
10
+ };
11
+ /** Creates the MCP server for one client connection. Close the server to end the session it opened. */
12
+ export declare function createDesktopDriverMcpServer(options: DesktopDriverMcpServerOptions): McpServer;
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAMtF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,MAAM,MAAM,6BAA6B,GAAG;IAC1C,wHAAwH;IACxH,OAAO,EAAE,oBAAoB,CAAC;IAC9B,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqFF,uGAAuG;AACvG,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,SAAS,CAgK9F"}