@gtkx/mcp 2.0.0-beta.1 → 2.0.0-beta.2

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.
@@ -12,6 +12,8 @@ declare class AppRouter extends EventTarget {
12
12
  private connectionToApp;
13
13
  private requestTimeout;
14
14
  private connections;
15
+ private pendingAppWaits;
16
+ private isDisposed;
15
17
  constructor(connections: AppConnections, options?: {
16
18
  requestTimeout?: number;
17
19
  });
@@ -20,12 +22,14 @@ declare class AppRouter extends EventTarget {
20
22
  private handleRegister;
21
23
  private toAppError;
22
24
  private removeApp;
25
+ private waitForRegistration;
23
26
  getApps(): AppInfo[];
24
27
  hasConnectedApps(): boolean;
25
28
  getDefaultApp(): RegisteredApp | undefined;
26
29
  getProjectRoot(): string | undefined;
27
- waitForApp(timeout?: number): Promise<AppInfo>;
28
- sendToApp<T>(applicationId: string | undefined, method: string, params?: RequestParams): Promise<T>;
30
+ dispose(): void;
31
+ waitForApp(applicationId?: string, timeout?: number): Promise<AppInfo>;
32
+ sendToApp<T>(applicationId: string | undefined, method: string, params?: RequestParams, waitTimeout?: number): Promise<T>;
29
33
  }
30
34
  export { AppRouter, type AppRegisteredEvent, type AppUnregisteredEvent };
31
35
  //# sourceMappingURL=app-router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-router.d.ts","sourceRoot":"","sources":["../src/app-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAmB,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAazG,OAAO,EAAE,KAAK,OAAO,EAAwB,MAAM,uBAAuB,CAAC;AAE3E,KAAK,kBAAkB,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAC/C,KAAK,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEhD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAYF,cAAM,SAAU,SAAQ,WAAW;IAC/B,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAU;IAE3C,OAAO,CAAC,IAAI,CAAyC;IAErD,OAAO,CAAC,eAAe,CAAkC;IAEzD,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,WAAW,CAAiB;gBAExB,WAAW,EAAE,cAAc,EAAE,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO;IAWlF,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,SAAS;IAgBjB,OAAO,IAAI,OAAO,EAAE;IAIpB,gBAAgB,IAAI,OAAO;IAI3B,aAAa,IAAI,aAAa,GAAG,SAAS;IAM1C,cAAc,IAAI,MAAM,GAAG,SAAS;IAIpC,UAAU,CAAC,OAAO,GAAE,MAAqC,GAAG,OAAO,CAAC,OAAO,CAAC;IA6BtE,SAAS,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC;CAa5G;AAED,OAAO,EAAE,SAAS,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"app-router.d.ts","sourceRoot":"","sources":["../src/app-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAmB,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAazG,OAAO,EAAE,KAAK,OAAO,EAAwB,MAAM,uBAAuB,CAAC;AAE3E,KAAK,kBAAkB,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAC/C,KAAK,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAGhD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAoBF,cAAM,SAAU,SAAQ,WAAW;IAC/B,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAU;IAE3C,OAAO,CAAC,IAAI,CAAyC;IAErD,OAAO,CAAC,eAAe,CAAkC;IAEzD,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,WAAW,CAAiB;IAEpC,OAAO,CAAC,eAAe,CAAkC;IAEzD,OAAO,CAAC,UAAU,CAAS;gBAEf,WAAW,EAAE,cAAc,EAAE,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO;IAWlF,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,SAAS;YAgBH,mBAAmB;IAkCjC,OAAO,IAAI,OAAO,EAAE;IAIpB,gBAAgB,IAAI,OAAO;IAI3B,aAAa,IAAI,aAAa,GAAG,SAAS;IAM1C,cAAc,IAAI,MAAM,GAAG,SAAS;IAIpC,OAAO,IAAI,IAAI;IAaf,UAAU,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,MAAqC,GAAG,OAAO,CAAC,OAAO,CAAC;IAc9F,SAAS,CAAC,CAAC,EACb,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,aAAa,EACtB,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,CAAC,CAAC;CAchB;AAED,OAAO,EAAE,SAAS,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,CAAC"}
@@ -2,6 +2,9 @@ import { McpError } from "@modelcontextprotocol/sdk/types.js";
2
2
  import { appNotFoundError, CONNECTION_CLOSED_CODE, connectionWriteFailedError, invalidRequestError, methodNotFoundError, noAppConnectedError, protocolErrorFrom, REQUEST_TIMEOUT_CODE, requestTimeoutError, } from "./protocol/errors.js";
3
3
  import { RegisterParamsSchema } from "./protocol/schemas.js";
4
4
  const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
5
+ const routerStoppedError = () => new Error("GTKX MCP server stopped while waiting for an application");
6
+ const appWaitTimeoutError = (timeout) => new Error(`Timeout waiting for app registration after ${String(timeout)}ms. ` +
7
+ "Make sure your GTKX app is running with 'gtkx dev'.");
5
8
  function appRegisteredEvent(info) {
6
9
  return new CustomEvent("appRegistered", { detail: info });
7
10
  }
@@ -14,6 +17,8 @@ class AppRouter extends EventTarget {
14
17
  connectionToApp = new Map();
15
18
  requestTimeout;
16
19
  connections;
20
+ pendingAppWaits = new Set();
21
+ isDisposed = false;
17
22
  constructor(connections, options = {}) {
18
23
  super();
19
24
  this.connections = connections;
@@ -34,6 +39,9 @@ class AppRouter extends EventTarget {
34
39
  throw noAppConnectedError();
35
40
  }
36
41
  handleRequest(connection, request) {
42
+ if (this.isDisposed) {
43
+ return Promise.reject(routerStoppedError());
44
+ }
37
45
  if (request.method === "app.register") {
38
46
  return Promise.resolve(this.handleRegister(connection, request));
39
47
  }
@@ -81,6 +89,33 @@ class AppRouter extends EventTarget {
81
89
  this.apps.delete(applicationId);
82
90
  this.dispatchEvent(appUnregisteredEvent(applicationId));
83
91
  }
92
+ async waitForRegistration(applicationId, timeout) {
93
+ const controller = new AbortController();
94
+ const { promise, reject, resolve } = Promise.withResolvers();
95
+ const rejectWait = (error) => {
96
+ controller.abort();
97
+ reject(error);
98
+ };
99
+ const pendingWait = { reject: rejectWait };
100
+ const timeoutId = setTimeout(() => {
101
+ rejectWait(appWaitTimeoutError(timeout));
102
+ }, timeout);
103
+ this.addEventListener("appRegistered", (event) => {
104
+ const info = event.detail;
105
+ if (applicationId === undefined || info.applicationId === applicationId) {
106
+ resolve(info);
107
+ }
108
+ }, { signal: controller.signal });
109
+ this.pendingAppWaits.add(pendingWait);
110
+ try {
111
+ return await promise;
112
+ }
113
+ finally {
114
+ clearTimeout(timeoutId);
115
+ controller.abort();
116
+ this.pendingAppWaits.delete(pendingWait);
117
+ }
118
+ }
84
119
  getApps() {
85
120
  return this.apps.values().map((app) => app.info).toArray();
86
121
  }
@@ -94,26 +129,28 @@ class AppRouter extends EventTarget {
94
129
  getProjectRoot() {
95
130
  return this.getDefaultApp()?.info.projectRoot;
96
131
  }
97
- waitForApp(timeout = AppRouter.defaultWaitTimeout) {
98
- const defaultApp = this.getDefaultApp();
99
- if (defaultApp) {
100
- return Promise.resolve(defaultApp.info);
101
- }
102
- return new Promise((resolve, reject) => {
103
- const timeoutId = setTimeout(() => {
104
- this.removeEventListener("appRegistered", onRegister);
105
- reject(new Error(`Timeout waiting for app registration after ${String(timeout)}ms. ` +
106
- "Make sure your GTKX app is running with 'gtkx dev'."));
107
- }, timeout);
108
- const onRegister = (event) => {
109
- clearTimeout(timeoutId);
110
- this.removeEventListener("appRegistered", onRegister);
111
- resolve(event.detail);
112
- };
113
- this.addEventListener("appRegistered", onRegister);
114
- });
132
+ dispose() {
133
+ if (this.isDisposed) {
134
+ return;
135
+ }
136
+ this.isDisposed = true;
137
+ const error = routerStoppedError();
138
+ for (const pendingWait of this.pendingAppWaits) {
139
+ pendingWait.reject(error);
140
+ }
141
+ }
142
+ waitForApp(applicationId, timeout = AppRouter.defaultWaitTimeout) {
143
+ if (this.isDisposed) {
144
+ return Promise.reject(routerStoppedError());
145
+ }
146
+ const app = applicationId === undefined ? this.getDefaultApp() : this.apps.get(applicationId);
147
+ if (app) {
148
+ return Promise.resolve(app.info);
149
+ }
150
+ return this.waitForRegistration(applicationId, timeout);
115
151
  }
116
- async sendToApp(applicationId, method, params) {
152
+ async sendToApp(applicationId, method, params, waitTimeout) {
153
+ await this.waitForApp(applicationId, waitTimeout);
117
154
  const app = this.resolveTargetApp(applicationId);
118
155
  try {
119
156
  return await app.connection.send(method, params, this.requestTimeout);
@@ -1 +1 @@
1
- {"version":3,"file":"app-router.js","sourceRoot":"","sources":["../src/app-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { type JSONRPCRequest, McpError, type Result } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { AppConnections, ConnectionEvent, ProtocolConnection, RequestParams } from \"./transport.js\";\nimport {\n appNotFoundError,\n CONNECTION_CLOSED_CODE,\n connectionWriteFailedError,\n invalidRequestError,\n methodNotFoundError,\n noAppConnectedError,\n type ProtocolError,\n protocolErrorFrom,\n REQUEST_TIMEOUT_CODE,\n requestTimeoutError,\n} from \"./protocol/errors.js\";\nimport { type AppInfo, RegisterParamsSchema } from \"./protocol/schemas.js\";\n\ntype AppRegisteredEvent = CustomEvent<AppInfo>;\ntype AppUnregisteredEvent = CustomEvent<string>;\n\ntype RegisteredApp = {\n info: AppInfo;\n connection: ProtocolConnection;\n};\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\nfunction appRegisteredEvent(info: AppInfo): AppRegisteredEvent {\n return new CustomEvent(\"appRegistered\", { detail: info });\n}\n\nfunction appUnregisteredEvent(applicationId: string): AppUnregisteredEvent {\n return new CustomEvent(\"appUnregistered\", { detail: applicationId });\n}\n\nclass AppRouter extends EventTarget {\n private static defaultWaitTimeout = 10_000;\n\n private apps: Map<string, RegisteredApp> = new Map();\n\n private connectionToApp: Map<string, string> = new Map();\n\n private requestTimeout: number;\n\n private connections: AppConnections;\n\n constructor(connections: AppConnections, options: { requestTimeout?: number } = {}) {\n super();\n this.connections = connections;\n this.requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.connections.onRequest = (connection, request) => this.handleRequest(connection, request);\n\n this.connections.addEventListener(\"disconnection\", (event) => {\n this.removeApp((event as ConnectionEvent).detail);\n });\n }\n\n private resolveTargetApp(applicationId: string | undefined): RegisteredApp {\n const app = applicationId ? this.apps.get(applicationId) : this.getDefaultApp();\n\n if (app) {\n return app;\n }\n\n if (applicationId) {\n throw appNotFoundError(applicationId);\n }\n\n throw noAppConnectedError();\n }\n\n private handleRequest(connection: ProtocolConnection, request: JSONRPCRequest): Promise<Result> {\n if (request.method === \"app.register\") {\n return Promise.resolve(this.handleRegister(connection, request));\n }\n\n if (request.method === \"app.unregister\") {\n this.removeApp(connection);\n\n return Promise.resolve({ success: true });\n }\n\n return Promise.reject(methodNotFoundError(request.method));\n }\n\n private handleRegister(connection: ProtocolConnection, request: JSONRPCRequest): Result {\n const parseResult = RegisterParamsSchema.safeParse(request.params);\n\n if (!parseResult.success) {\n throw invalidRequestError(parseResult.error.message);\n }\n\n const params = parseResult.data;\n\n const appInfo: AppInfo = {\n applicationId: params.applicationId,\n pid: params.pid,\n ...(params.projectRoot !== undefined && { projectRoot: params.projectRoot }),\n };\n\n this.apps.set(params.applicationId, { info: appInfo, connection });\n this.connectionToApp.set(connection.id, params.applicationId);\n this.dispatchEvent(appRegisteredEvent(appInfo));\n\n return { success: true };\n }\n\n private toAppError(app: RegisteredApp, error: McpError): ProtocolError {\n if (error.code === CONNECTION_CLOSED_CODE) {\n this.removeApp(app.connection);\n\n return connectionWriteFailedError(app.info.applicationId);\n }\n\n if (error.code === REQUEST_TIMEOUT_CODE) {\n return requestTimeoutError(this.requestTimeout);\n }\n\n return protocolErrorFrom(error);\n }\n\n private removeApp(connection: ProtocolConnection): void {\n const applicationId = this.connectionToApp.get(connection.id);\n this.connectionToApp.delete(connection.id);\n\n if (applicationId === undefined) {\n return;\n }\n\n if (this.apps.get(applicationId)?.connection !== connection) {\n return;\n }\n\n this.apps.delete(applicationId);\n this.dispatchEvent(appUnregisteredEvent(applicationId));\n }\n\n getApps(): AppInfo[] {\n return this.apps.values().map((app) => app.info).toArray();\n }\n\n hasConnectedApps(): boolean {\n return this.apps.size > 0;\n }\n\n getDefaultApp(): RegisteredApp | undefined {\n const first = this.apps.values().next();\n\n return first.done ? undefined : first.value;\n }\n\n getProjectRoot(): string | undefined {\n return this.getDefaultApp()?.info.projectRoot;\n }\n\n waitForApp(timeout: number = AppRouter.defaultWaitTimeout): Promise<AppInfo> {\n const defaultApp = this.getDefaultApp();\n\n if (defaultApp) {\n return Promise.resolve(defaultApp.info);\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.removeEventListener(\"appRegistered\", onRegister);\n\n reject(\n new Error(\n `Timeout waiting for app registration after ${String(timeout)}ms. ` +\n \"Make sure your GTKX app is running with 'gtkx dev'.\",\n ),\n );\n }, timeout);\n\n const onRegister = (event: Event): void => {\n clearTimeout(timeoutId);\n this.removeEventListener(\"appRegistered\", onRegister);\n resolve((event as AppRegisteredEvent).detail);\n };\n\n this.addEventListener(\"appRegistered\", onRegister);\n });\n }\n\n async sendToApp<T>(applicationId: string | undefined, method: string, params?: RequestParams): Promise<T> {\n const app = this.resolveTargetApp(applicationId);\n\n try {\n return await app.connection.send<T>(method, params, this.requestTimeout);\n } catch (error) {\n if (error instanceof McpError) {\n throw this.toAppError(app, error);\n }\n\n throw error;\n }\n }\n}\n\nexport { AppRouter, type AppRegisteredEvent, type AppUnregisteredEvent };\n"]}
1
+ {"version":3,"file":"app-router.js","sourceRoot":"","sources":["../src/app-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { type JSONRPCRequest, McpError, type Result } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { AppConnections, ConnectionEvent, ProtocolConnection, RequestParams } from \"./transport.js\";\nimport {\n appNotFoundError,\n CONNECTION_CLOSED_CODE,\n connectionWriteFailedError,\n invalidRequestError,\n methodNotFoundError,\n noAppConnectedError,\n type ProtocolError,\n protocolErrorFrom,\n REQUEST_TIMEOUT_CODE,\n requestTimeoutError,\n} from \"./protocol/errors.js\";\nimport { type AppInfo, RegisterParamsSchema } from \"./protocol/schemas.js\";\n\ntype AppRegisteredEvent = CustomEvent<AppInfo>;\ntype AppUnregisteredEvent = CustomEvent<string>;\ntype PendingAppWait = { reject: (error: Error) => void };\n\ntype RegisteredApp = {\n info: AppInfo;\n connection: ProtocolConnection;\n};\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\nconst routerStoppedError = (): Error => new Error(\"GTKX MCP server stopped while waiting for an application\");\n\nconst appWaitTimeoutError = (timeout: number): Error =>\n new Error(\n `Timeout waiting for app registration after ${String(timeout)}ms. ` +\n \"Make sure your GTKX app is running with 'gtkx dev'.\",\n );\n\nfunction appRegisteredEvent(info: AppInfo): AppRegisteredEvent {\n return new CustomEvent(\"appRegistered\", { detail: info });\n}\n\nfunction appUnregisteredEvent(applicationId: string): AppUnregisteredEvent {\n return new CustomEvent(\"appUnregistered\", { detail: applicationId });\n}\n\nclass AppRouter extends EventTarget {\n private static defaultWaitTimeout = 10_000;\n\n private apps: Map<string, RegisteredApp> = new Map();\n\n private connectionToApp: Map<string, string> = new Map();\n\n private requestTimeout: number;\n\n private connections: AppConnections;\n\n private pendingAppWaits: Set<PendingAppWait> = new Set();\n\n private isDisposed = false;\n\n constructor(connections: AppConnections, options: { requestTimeout?: number } = {}) {\n super();\n this.connections = connections;\n this.requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT_MS;\n this.connections.onRequest = (connection, request) => this.handleRequest(connection, request);\n\n this.connections.addEventListener(\"disconnection\", (event) => {\n this.removeApp((event as ConnectionEvent).detail);\n });\n }\n\n private resolveTargetApp(applicationId: string | undefined): RegisteredApp {\n const app = applicationId ? this.apps.get(applicationId) : this.getDefaultApp();\n\n if (app) {\n return app;\n }\n\n if (applicationId) {\n throw appNotFoundError(applicationId);\n }\n\n throw noAppConnectedError();\n }\n\n private handleRequest(connection: ProtocolConnection, request: JSONRPCRequest): Promise<Result> {\n if (this.isDisposed) {\n return Promise.reject(routerStoppedError());\n }\n\n if (request.method === \"app.register\") {\n return Promise.resolve(this.handleRegister(connection, request));\n }\n\n if (request.method === \"app.unregister\") {\n this.removeApp(connection);\n\n return Promise.resolve({ success: true });\n }\n\n return Promise.reject(methodNotFoundError(request.method));\n }\n\n private handleRegister(connection: ProtocolConnection, request: JSONRPCRequest): Result {\n const parseResult = RegisterParamsSchema.safeParse(request.params);\n\n if (!parseResult.success) {\n throw invalidRequestError(parseResult.error.message);\n }\n\n const params = parseResult.data;\n\n const appInfo: AppInfo = {\n applicationId: params.applicationId,\n pid: params.pid,\n ...(params.projectRoot !== undefined && { projectRoot: params.projectRoot }),\n };\n\n this.apps.set(params.applicationId, { info: appInfo, connection });\n this.connectionToApp.set(connection.id, params.applicationId);\n this.dispatchEvent(appRegisteredEvent(appInfo));\n\n return { success: true };\n }\n\n private toAppError(app: RegisteredApp, error: McpError): ProtocolError {\n if (error.code === CONNECTION_CLOSED_CODE) {\n this.removeApp(app.connection);\n\n return connectionWriteFailedError(app.info.applicationId);\n }\n\n if (error.code === REQUEST_TIMEOUT_CODE) {\n return requestTimeoutError(this.requestTimeout);\n }\n\n return protocolErrorFrom(error);\n }\n\n private removeApp(connection: ProtocolConnection): void {\n const applicationId = this.connectionToApp.get(connection.id);\n this.connectionToApp.delete(connection.id);\n\n if (applicationId === undefined) {\n return;\n }\n\n if (this.apps.get(applicationId)?.connection !== connection) {\n return;\n }\n\n this.apps.delete(applicationId);\n this.dispatchEvent(appUnregisteredEvent(applicationId));\n }\n\n private async waitForRegistration(applicationId: string | undefined, timeout: number): Promise<AppInfo> {\n const controller = new AbortController();\n const { promise, reject, resolve } = Promise.withResolvers<AppInfo>();\n const rejectWait = (error: Error): void => {\n controller.abort();\n reject(error);\n };\n const pendingWait: PendingAppWait = { reject: rejectWait };\n const timeoutId = setTimeout(() => {\n rejectWait(appWaitTimeoutError(timeout));\n }, timeout);\n\n this.addEventListener(\n \"appRegistered\",\n (event) => {\n const info = (event as AppRegisteredEvent).detail;\n\n if (applicationId === undefined || info.applicationId === applicationId) {\n resolve(info);\n }\n },\n { signal: controller.signal },\n );\n this.pendingAppWaits.add(pendingWait);\n\n try {\n return await promise;\n } finally {\n clearTimeout(timeoutId);\n controller.abort();\n this.pendingAppWaits.delete(pendingWait);\n }\n }\n\n getApps(): AppInfo[] {\n return this.apps.values().map((app) => app.info).toArray();\n }\n\n hasConnectedApps(): boolean {\n return this.apps.size > 0;\n }\n\n getDefaultApp(): RegisteredApp | undefined {\n const first = this.apps.values().next();\n\n return first.done ? undefined : first.value;\n }\n\n getProjectRoot(): string | undefined {\n return this.getDefaultApp()?.info.projectRoot;\n }\n\n dispose(): void {\n if (this.isDisposed) {\n return;\n }\n\n this.isDisposed = true;\n const error = routerStoppedError();\n\n for (const pendingWait of this.pendingAppWaits) {\n pendingWait.reject(error);\n }\n }\n\n waitForApp(applicationId?: string, timeout: number = AppRouter.defaultWaitTimeout): Promise<AppInfo> {\n if (this.isDisposed) {\n return Promise.reject(routerStoppedError());\n }\n\n const app = applicationId === undefined ? this.getDefaultApp() : this.apps.get(applicationId);\n\n if (app) {\n return Promise.resolve(app.info);\n }\n\n return this.waitForRegistration(applicationId, timeout);\n }\n\n async sendToApp<T>(\n applicationId: string | undefined,\n method: string,\n params?: RequestParams,\n waitTimeout?: number,\n ): Promise<T> {\n await this.waitForApp(applicationId, waitTimeout);\n const app = this.resolveTargetApp(applicationId);\n\n try {\n return await app.connection.send<T>(method, params, this.requestTimeout);\n } catch (error) {\n if (error instanceof McpError) {\n throw this.toAppError(app, error);\n }\n\n throw error;\n }\n }\n}\n\nexport { AppRouter, type AppRegisteredEvent, type AppUnregisteredEvent };\n"]}
@@ -1,5 +1,6 @@
1
1
  export { invalidRequestError, isConnectionClosedError, methodNotFoundError, propertyNotFoundError, widgetNotFoundError, } from "./protocol/errors.js";
2
- export { DEFAULT_SOCKET_PATH, DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, type ParamsSchema, type SerializedProperty, type SerializedWidget, type ServerInitiatedMethod, type ServerRequestParams, ServerRequestParamsSchemas, } from "./protocol/schemas.js";
2
+ export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, type ParamsSchema, type SerializedProperty, type SerializedWidget, type ServerInitiatedMethod, type ServerRequestParams, ServerRequestParamsSchemas, } from "./protocol/schemas.js";
3
+ export { MCP_SOCKET_PATH_ENV, resolveMcpSocketPath, } from "./socket-path.js";
3
4
  export { ProtocolConnection } from "./transport.js";
4
5
  export type { JSONRPCRequest, Result } from "@modelcontextprotocol/sdk/types.js";
5
6
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,0BAA0B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,0BAA0B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACH,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC"}
package/dist/internal.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { invalidRequestError, isConnectionClosedError, methodNotFoundError, propertyNotFoundError, widgetNotFoundError, } from "./protocol/errors.js";
2
- export { DEFAULT_SOCKET_PATH, DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, ServerRequestParamsSchemas, } from "./protocol/schemas.js";
2
+ export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, ServerRequestParamsSchemas, } from "./protocol/schemas.js";
3
+ export { MCP_SOCKET_PATH_ENV, resolveMcpSocketPath, } from "./socket-path.js";
3
4
  export { ProtocolConnection } from "./transport.js";
4
5
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EAMnB,0BAA0B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export {\n invalidRequestError,\n isConnectionClosedError,\n methodNotFoundError,\n propertyNotFoundError,\n widgetNotFoundError,\n} from \"./protocol/errors.js\";\nexport {\n DEFAULT_SOCKET_PATH,\n DEFAULT_SUBTREE_DEPTH,\n MAX_SUBTREE_WIDGETS,\n type ParamsSchema,\n type SerializedProperty,\n type SerializedWidget,\n type ServerInitiatedMethod,\n type ServerRequestParams,\n ServerRequestParamsSchemas,\n} from \"./protocol/schemas.js\";\nexport { ProtocolConnection } from \"./transport.js\";\nexport type { JSONRPCRequest, Result } from \"@modelcontextprotocol/sdk/types.js\";\n"]}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EAMnB,0BAA0B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACH,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export {\n invalidRequestError,\n isConnectionClosedError,\n methodNotFoundError,\n propertyNotFoundError,\n widgetNotFoundError,\n} from \"./protocol/errors.js\";\nexport {\n DEFAULT_SUBTREE_DEPTH,\n MAX_SUBTREE_WIDGETS,\n type ParamsSchema,\n type SerializedProperty,\n type SerializedWidget,\n type ServerInitiatedMethod,\n type ServerRequestParams,\n ServerRequestParamsSchemas,\n} from \"./protocol/schemas.js\";\nexport {\n MCP_SOCKET_PATH_ENV,\n resolveMcpSocketPath,\n} from \"./socket-path.js\";\nexport { ProtocolConnection } from \"./transport.js\";\nexport type { JSONRPCRequest, Result } from \"@modelcontextprotocol/sdk/types.js\";\n"]}
@@ -84,6 +84,5 @@ declare const ServerRequestParamsSchemas: {
84
84
  "widget.fireEvent": typeof fireEventParams;
85
85
  "widget.screenshot": typeof screenshotParams;
86
86
  };
87
- declare const DEFAULT_SOCKET_PATH: string;
88
- export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, RegisterParamsSchema, widgetIdParams, widgetPropsParams, treeParams, queryParams, typeParams, fireEventParams, screenshotParams, ServerRequestParamsSchemas, DEFAULT_SOCKET_PATH, type SerializedWidget, type SerializedProperty, type AppInfo, type ServerRequestParams, type ParamsSchema, type ServerInitiatedMethod, };
87
+ export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, RegisterParamsSchema, widgetIdParams, widgetPropsParams, treeParams, queryParams, typeParams, fireEventParams, screenshotParams, ServerRequestParamsSchemas, type SerializedWidget, type SerializedProperty, type AppInfo, type ServerRequestParams, type ParamsSchema, type ServerInitiatedMethod, };
89
88
  //# sourceMappingURL=schemas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/protocol/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/protocol/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,KAAK,gBAAgB,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,OAAO,GAAG;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,mBAAmB,CAAC,MAAM,SAAS,MAAM,OAAO,0BAA0B,IAAI,CAAC,CAAC,KAAK,CACtF,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAC9C,CAAC;AAEF,KAAK,YAAY,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAC9C,KAAK,qBAAqB,GAAG,MAAM,OAAO,0BAA0B,CAAC;AAErE,QAAA,MAAM,oBAAoB,EAAE,CAAC,CAAC,SAAS,CACnC;IACI,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,GAAG,EAAE,CAAC,CAAC,SAAS,CAAC;IACjB,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CAC3C,CAKH,CAAC;AAEH,QAAA,MAAM,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAgB,CAAC;AAErE,QAAA,MAAM,cAAc,EAAE,CAAC,CAAC,SAAS,CAAC;IAAE,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAA;CAAE,CAEzD,CAAC;AAEH,QAAA,MAAM,qBAAqB,IAAI,CAAC;AAChC,QAAA,MAAM,mBAAmB,KAAK,CAAC;AAE/B,QAAA,MAAM,iBAAiB,EAAE,CAAC,CAAC,SAAS,CAChC;IACI,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC;IACtB,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACnD,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CACxC,CAKH,CAAC;AAEH,QAAA,MAAM,UAAU,EAAE,CAAC,CAAC,SAAS,CACzB;IAAE,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;CAAE,CAI9E,CAAC;AAEH,QAAA,MAAM,kBAAkB,EAAE,CAAC,CAAC,SAAS,CACjC;IAAE,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAAC,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;CAAE,CAK/G,CAAC;AAEH,QAAA,MAAM,WAAW,EAAE,CAAC,CAAC,SAAS,CAC1B;IACI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACpF,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC;CACrD,CAKH,CAAC;AAEH,QAAA,MAAM,UAAU,EAAE,CAAC,CAAC,SAAS,CACzB;IAAE,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;CAAE,CACG,CAAC;AAExF,QAAA,MAAM,eAAe,EAAE,CAAC,CAAC,SAAS,CAC9B;IAAE,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;CAAE,CACA,CAAC;AAElG,QAAA,MAAM,gBAAgB,EAAE,CAAC,CAAC,SAAS,CAC/B;IAAE,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;CAAE,CAI5E,CAAC;AAEH,QAAA,MAAM,0BAA0B,EAAE;IAC9B,gBAAgB,EAAE,OAAO,WAAW,CAAC;IACrC,gBAAgB,EAAE,OAAO,UAAU,CAAC;IACpC,cAAc,EAAE,OAAO,WAAW,CAAC;IACnC,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,aAAa,EAAE,OAAO,UAAU,CAAC;IACjC,kBAAkB,EAAE,OAAO,eAAe,CAAC;IAC3C,mBAAmB,EAAE,OAAO,gBAAgB,CAAC;CAUhD,CAAC;AAEF,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,qBAAqB,GAC7B,CAAC"}
@@ -1,5 +1,3 @@
1
- import { tmpdir } from "node:os";
2
- import { join } from "node:path";
3
1
  import { z } from "zod";
4
2
  const RegisterParamsSchema = z.object({
5
3
  applicationId: z.string(),
@@ -47,9 +45,5 @@ const ServerRequestParamsSchemas = {
47
45
  "widget.fireEvent": fireEventParams,
48
46
  "widget.screenshot": screenshotParams,
49
47
  };
50
- const DEFAULT_SOCKET_PATH = join(getRuntimeDir(), "gtkx-mcp.sock");
51
- function getRuntimeDir() {
52
- return process.env.XDG_RUNTIME_DIR ?? tmpdir();
53
- }
54
- export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, RegisterParamsSchema, widgetIdParams, widgetPropsParams, treeParams, queryParams, typeParams, fireEventParams, screenshotParams, ServerRequestParamsSchemas, DEFAULT_SOCKET_PATH, };
48
+ export { DEFAULT_SUBTREE_DEPTH, MAX_SUBTREE_WIDGETS, RegisterParamsSchema, widgetIdParams, widgetPropsParams, treeParams, queryParams, typeParams, fireEventParams, screenshotParams, ServerRequestParamsSchemas, };
55
49
  //# sourceMappingURL=schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/protocol/schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\n\ntype SerializedWidget = {\n id: string;\n type: string;\n role: string;\n name: string | null;\n text: string | null;\n isSensitive: boolean;\n isVisible: boolean;\n cssClasses: string[];\n children: SerializedWidget[];\n hiddenChildren?: number;\n};\n\ntype SerializedProperty = {\n type: string;\n value: string | number | boolean | string[] | null;\n widgetId?: string;\n note?: string;\n};\n\ntype AppInfo = {\n applicationId: string;\n pid: number;\n projectRoot?: string;\n};\n\ntype ServerRequestParams<Method extends keyof typeof ServerRequestParamsSchemas> = z.infer<\n (typeof ServerRequestParamsSchemas)[Method]\n>;\n\ntype ParamsSchema<Output> = z.ZodType<Output>;\ntype ServerInitiatedMethod = keyof typeof ServerRequestParamsSchemas;\n\nconst RegisterParamsSchema: z.ZodObject<\n {\n applicationId: z.ZodString;\n pid: z.ZodNumber;\n projectRoot: z.ZodOptional<z.ZodString>;\n }\n> = z.object({\n applicationId: z.string(),\n pid: z.number(),\n projectRoot: z.string().optional(),\n});\n\nconst emptyParams: z.ZodObject<Record<string, never>> = z.object({});\n\nconst widgetIdParams: z.ZodObject<{ widgetId: z.ZodString }> = z.object({\n widgetId: z.string(),\n});\n\nconst DEFAULT_SUBTREE_DEPTH = 8;\nconst MAX_SUBTREE_WIDGETS = 30;\n\nconst widgetPropsParams: z.ZodObject<\n {\n widgetId: z.ZodString;\n properties: z.ZodOptional<z.ZodArray<z.ZodString>>;\n maxDepth: z.ZodOptional<z.ZodNumber>;\n }\n> = z.object({\n widgetId: z.string(),\n properties: z.array(z.string()).optional(),\n maxDepth: z.number().int().nonnegative().optional(),\n});\n\nconst treeParams: z.ZodObject<\n { rootId: z.ZodOptional<z.ZodString>; maxDepth: z.ZodOptional<z.ZodNumber> }\n> = z.object({\n rootId: z.string().optional(),\n maxDepth: z.number().int().nonnegative().optional(),\n});\n\nconst queryOptionsSchema: z.ZodObject<\n { name: z.ZodOptional<z.ZodString>; exact: z.ZodOptional<z.ZodBoolean>; timeout: z.ZodOptional<z.ZodNumber> }\n> = z.object({\n name: z.string().optional(),\n exact: z.boolean().optional(),\n timeout: z.number().optional(),\n});\n\nconst queryParams: z.ZodObject<\n {\n by: z.ZodEnum<{ role: \"role\"; text: \"text\"; name: \"name\"; labelText: \"labelText\" }>;\n value: z.ZodUnion<[z.ZodString, z.ZodNumber]>;\n options: z.ZodOptional<typeof queryOptionsSchema>;\n }\n> = z.object({\n by: z.enum([\"role\", \"text\", \"name\", \"labelText\"]),\n value: z.union([z.string(), z.number()]),\n options: queryOptionsSchema.optional(),\n});\n\nconst typeParams: z.ZodObject<\n { widgetId: z.ZodString; text: z.ZodString; clear: z.ZodOptional<z.ZodBoolean> }\n> = z.object({ widgetId: z.string(), text: z.string(), clear: z.boolean().optional() });\n\nconst fireEventParams: z.ZodObject<\n { widgetId: z.ZodString; signal: z.ZodString; args: z.ZodOptional<z.ZodArray<z.ZodUnknown>> }\n> = z.object({ widgetId: z.string(), signal: z.string(), args: z.array(z.unknown()).optional() });\n\nconst screenshotParams: z.ZodObject<\n { windowId: z.ZodOptional<z.ZodString>; path: z.ZodOptional<z.ZodString> }\n> = z.object({\n windowId: z.string().optional(),\n path: z.string().optional(),\n});\n\nconst ServerRequestParamsSchemas: {\n \"app.getWindows\": typeof emptyParams;\n \"widget.getTree\": typeof treeParams;\n \"widget.query\": typeof queryParams;\n \"widget.getProps\": typeof widgetPropsParams;\n \"widget.click\": typeof widgetIdParams;\n \"widget.type\": typeof typeParams;\n \"widget.fireEvent\": typeof fireEventParams;\n \"widget.screenshot\": typeof screenshotParams;\n} = {\n \"app.getWindows\": emptyParams,\n \"widget.getTree\": treeParams,\n \"widget.query\": queryParams,\n \"widget.getProps\": widgetPropsParams,\n \"widget.click\": widgetIdParams,\n \"widget.type\": typeParams,\n \"widget.fireEvent\": fireEventParams,\n \"widget.screenshot\": screenshotParams,\n};\n\nconst DEFAULT_SOCKET_PATH: string = join(getRuntimeDir(), \"gtkx-mcp.sock\");\n\nfunction getRuntimeDir(): string {\n return process.env.XDG_RUNTIME_DIR ?? tmpdir();\n}\n\nexport {\n DEFAULT_SUBTREE_DEPTH,\n MAX_SUBTREE_WIDGETS,\n RegisterParamsSchema,\n widgetIdParams,\n widgetPropsParams,\n treeParams,\n queryParams,\n typeParams,\n fireEventParams,\n screenshotParams,\n ServerRequestParamsSchemas,\n DEFAULT_SOCKET_PATH,\n type SerializedWidget,\n type SerializedProperty,\n type AppInfo,\n type ServerRequestParams,\n type ParamsSchema,\n type ServerInitiatedMethod,\n};\n"]}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/protocol/schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\ntype SerializedWidget = {\n id: string;\n type: string;\n role: string;\n name: string | null;\n text: string | null;\n isSensitive: boolean;\n isVisible: boolean;\n cssClasses: string[];\n children: SerializedWidget[];\n hiddenChildren?: number;\n};\n\ntype SerializedProperty = {\n type: string;\n value: string | number | boolean | string[] | null;\n widgetId?: string;\n note?: string;\n};\n\ntype AppInfo = {\n applicationId: string;\n pid: number;\n projectRoot?: string;\n};\n\ntype ServerRequestParams<Method extends keyof typeof ServerRequestParamsSchemas> = z.infer<\n (typeof ServerRequestParamsSchemas)[Method]\n>;\n\ntype ParamsSchema<Output> = z.ZodType<Output>;\ntype ServerInitiatedMethod = keyof typeof ServerRequestParamsSchemas;\n\nconst RegisterParamsSchema: z.ZodObject<\n {\n applicationId: z.ZodString;\n pid: z.ZodNumber;\n projectRoot: z.ZodOptional<z.ZodString>;\n }\n> = z.object({\n applicationId: z.string(),\n pid: z.number(),\n projectRoot: z.string().optional(),\n});\n\nconst emptyParams: z.ZodObject<Record<string, never>> = z.object({});\n\nconst widgetIdParams: z.ZodObject<{ widgetId: z.ZodString }> = z.object({\n widgetId: z.string(),\n});\n\nconst DEFAULT_SUBTREE_DEPTH = 8;\nconst MAX_SUBTREE_WIDGETS = 30;\n\nconst widgetPropsParams: z.ZodObject<\n {\n widgetId: z.ZodString;\n properties: z.ZodOptional<z.ZodArray<z.ZodString>>;\n maxDepth: z.ZodOptional<z.ZodNumber>;\n }\n> = z.object({\n widgetId: z.string(),\n properties: z.array(z.string()).optional(),\n maxDepth: z.number().int().nonnegative().optional(),\n});\n\nconst treeParams: z.ZodObject<\n { rootId: z.ZodOptional<z.ZodString>; maxDepth: z.ZodOptional<z.ZodNumber> }\n> = z.object({\n rootId: z.string().optional(),\n maxDepth: z.number().int().nonnegative().optional(),\n});\n\nconst queryOptionsSchema: z.ZodObject<\n { name: z.ZodOptional<z.ZodString>; exact: z.ZodOptional<z.ZodBoolean>; timeout: z.ZodOptional<z.ZodNumber> }\n> = z.object({\n name: z.string().optional(),\n exact: z.boolean().optional(),\n timeout: z.number().optional(),\n});\n\nconst queryParams: z.ZodObject<\n {\n by: z.ZodEnum<{ role: \"role\"; text: \"text\"; name: \"name\"; labelText: \"labelText\" }>;\n value: z.ZodUnion<[z.ZodString, z.ZodNumber]>;\n options: z.ZodOptional<typeof queryOptionsSchema>;\n }\n> = z.object({\n by: z.enum([\"role\", \"text\", \"name\", \"labelText\"]),\n value: z.union([z.string(), z.number()]),\n options: queryOptionsSchema.optional(),\n});\n\nconst typeParams: z.ZodObject<\n { widgetId: z.ZodString; text: z.ZodString; clear: z.ZodOptional<z.ZodBoolean> }\n> = z.object({ widgetId: z.string(), text: z.string(), clear: z.boolean().optional() });\n\nconst fireEventParams: z.ZodObject<\n { widgetId: z.ZodString; signal: z.ZodString; args: z.ZodOptional<z.ZodArray<z.ZodUnknown>> }\n> = z.object({ widgetId: z.string(), signal: z.string(), args: z.array(z.unknown()).optional() });\n\nconst screenshotParams: z.ZodObject<\n { windowId: z.ZodOptional<z.ZodString>; path: z.ZodOptional<z.ZodString> }\n> = z.object({\n windowId: z.string().optional(),\n path: z.string().optional(),\n});\n\nconst ServerRequestParamsSchemas: {\n \"app.getWindows\": typeof emptyParams;\n \"widget.getTree\": typeof treeParams;\n \"widget.query\": typeof queryParams;\n \"widget.getProps\": typeof widgetPropsParams;\n \"widget.click\": typeof widgetIdParams;\n \"widget.type\": typeof typeParams;\n \"widget.fireEvent\": typeof fireEventParams;\n \"widget.screenshot\": typeof screenshotParams;\n} = {\n \"app.getWindows\": emptyParams,\n \"widget.getTree\": treeParams,\n \"widget.query\": queryParams,\n \"widget.getProps\": widgetPropsParams,\n \"widget.click\": widgetIdParams,\n \"widget.type\": typeParams,\n \"widget.fireEvent\": fireEventParams,\n \"widget.screenshot\": screenshotParams,\n};\n\nexport {\n DEFAULT_SUBTREE_DEPTH,\n MAX_SUBTREE_WIDGETS,\n RegisterParamsSchema,\n widgetIdParams,\n widgetPropsParams,\n treeParams,\n queryParams,\n typeParams,\n fireEventParams,\n screenshotParams,\n ServerRequestParamsSchemas,\n type SerializedWidget,\n type SerializedProperty,\n type AppInfo,\n type ServerRequestParams,\n type ParamsSchema,\n type ServerInitiatedMethod,\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAsCjF,KAAK,aAAa,GAAG;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAmBF,QAAA,MAAM,GAAG,EAAE,MAA4B,CAAC;AA0axC,QAAA,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,KAAG,aAgBzC,CAAC;AAEF,iBAAe,IAAI,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;AAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,YAAY,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAsCjF,KAAK,aAAa,GAAG;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAqBF,QAAA,MAAM,GAAG,EAAE,MAA4B,CAAC;AA0exC,QAAA,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,KAAG,aAgBzC,CAAC;AAEF,iBAAe,IAAI,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;AAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,IAAI,YAAY,EAAE,eAAe,EAAE,CAAC"}
package/dist/server.js CHANGED
@@ -8,8 +8,9 @@ import { z } from "zod";
8
8
  import packageManifest from "../package.json" with { type: "json" };
9
9
  import { AppRouter } from "./app-router.js";
10
10
  import { ConnectionRegistry } from "./connection-registry.js";
11
- import { DEFAULT_SOCKET_PATH, DEFAULT_SUBTREE_DEPTH, fireEventParams, MAX_SUBTREE_WIDGETS, queryParams, screenshotParams, treeParams, typeParams, widgetIdParams, widgetPropsParams, } from "./protocol/schemas.js";
11
+ import { DEFAULT_SUBTREE_DEPTH, fireEventParams, MAX_SUBTREE_WIDGETS, queryParams, screenshotParams, treeParams, typeParams, widgetIdParams, widgetPropsParams, } from "./protocol/schemas.js";
12
12
  import { buildReferenceTools, createReferenceProvider, registerReferenceResources, } from "./reference.js";
13
+ import { resolveMcpSocketAddress } from "./socket-path.js";
13
14
  import { SocketServer } from "./socket-server.js";
14
15
  import { selectTools } from "./tool-filter.js";
15
16
  import { defineTool, imageContent, registerTool, textContent, textError } from "./tool.js";
@@ -18,17 +19,23 @@ const log = createLogger("mcp");
18
19
  const DEFAULT_SETTINGS = { tools: [], isReadOnly: false };
19
20
  const INSTRUCTIONS = "The widget tools drive a GTKX app running under `gtkx dev`: they read " +
20
21
  "its live widget tree, query it by accessible role and name, click and type, and capture screenshots. " +
21
- "They fail until an app is running, so start `gtkx dev` first. The reference tools answer from the " +
22
+ "They wait briefly for a starting app, so start `gtkx dev` before or alongside a widget request. " +
23
+ "The reference tools answer from the " +
22
24
  "bindings generated for a specific project, so they describe that project's GIR libraries rather than " +
23
25
  "GTK in general; prefer them over recalled GTK knowledge, which is usually C, PyGObject or GJS and " +
24
26
  "does not apply here.\n\n" +
25
27
  "Widget IDs are valid only while the widget is mounted. After a dialog closes, a list re-renders, or " +
26
28
  "fast refresh patches a component, re-read the tree or re-run the query instead of reusing an ID.";
27
- const APPLICATION_ID_DESCRIPTION = "Application ID to query. If not specified, uses the first connected app.";
29
+ const APPLICATION_ID_DESCRIPTION = "Application ID to query. If not specified, uses the first connected app. The tool waits briefly for the " +
30
+ "requested app to register.";
31
+ const APP_TIMEOUT_DESCRIPTION = "Milliseconds to wait for the requested app to register (default: 10000).";
28
32
  const WIDGET_ID_DESCRIPTION = "Widget ID obtained from `gtkx_get_widget_tree`, `gtkx_query_widgets`, or `gtkx_get_widget_props`. " +
29
33
  "IDs are scoped to a single app. An ID stays valid for as long as its widget is mounted and stops " +
30
34
  "resolving once the widget is unmounted.";
31
- const applicationIdShape = { applicationId: z.string().optional().describe(APPLICATION_ID_DESCRIPTION) };
35
+ const applicationIdShape = {
36
+ applicationId: z.string().optional().describe(APPLICATION_ID_DESCRIPTION),
37
+ appTimeout: z.number().int().nonnegative().optional().describe(APP_TIMEOUT_DESCRIPTION),
38
+ };
32
39
  const widgetIdShape = {
33
40
  ...applicationIdShape,
34
41
  ...describeParams(widgetIdParams.shape, { widgetId: WIDGET_ID_DESCRIPTION }),
@@ -137,7 +144,7 @@ const listAppsTool = (appRouter) => defineTool({
137
144
  inputSchema: listAppsShape,
138
145
  handler: async ({ waitForApps, timeout }) => {
139
146
  if (waitForApps && !appRouter.hasConnectedApps()) {
140
- await appRouter.waitForApp(timeout);
147
+ await appRouter.waitForApp(undefined, timeout);
141
148
  }
142
149
  const apps = appRouter.getApps();
143
150
  const appsWithWindows = await Promise.all(apps.map((app) => appWithWindows(appRouter, app)));
@@ -165,8 +172,8 @@ const screenshotTool = (appRouter) => defineTool({
165
172
  "the PNG to `path` on the app's machine. You can't target widgets from a screenshot; use " +
166
173
  "`gtkx_get_widget_tree` to find widget IDs for interaction.",
167
174
  inputSchema: screenshotShape,
168
- handler: async ({ applicationId, returnImage, ...params }) => {
169
- const result = await appRouter.sendToApp(applicationId, "widget.screenshot", params);
175
+ handler: async ({ applicationId, appTimeout, returnImage, ...params }) => {
176
+ const result = await appRouter.sendToApp(applicationId, "widget.screenshot", params, appTimeout);
170
177
  return screenshotResult(result, returnImage !== false);
171
178
  },
172
179
  });
@@ -187,8 +194,8 @@ const widgetPropsTool = (appRouter) => defineTool({
187
194
  "a property the widget does not have fails; a value that cannot be marshalled carries a `note` " +
188
195
  "instead.",
189
196
  inputSchema: widgetPropsShape,
190
- handler: async ({ applicationId, ...params }) => {
191
- const result = await appRouter.sendToApp(applicationId, "widget.getProps", params);
197
+ handler: async ({ applicationId, appTimeout, ...params }) => {
198
+ const result = await appRouter.sendToApp(applicationId, "widget.getProps", params, appTimeout);
192
199
  return textContent(JSON.stringify(result, null, 2));
193
200
  },
194
201
  });
@@ -203,11 +210,11 @@ function buildInspectionTools(appRouter) {
203
210
  "types, roles, and properties. For large apps, pass `maxDepth` for a shallow overview and/or " +
204
211
  "`rootId` to render just one subtree instead of the whole (possibly truncated) tree.",
205
212
  inputSchema: treeShape,
206
- handler: async ({ applicationId, rootId, maxDepth }) => {
213
+ handler: async ({ applicationId, appTimeout, rootId, maxDepth }) => {
207
214
  const result = await appRouter.sendToApp(applicationId, "widget.getTree", {
208
215
  rootId,
209
216
  maxDepth,
210
- });
217
+ }, appTimeout);
211
218
  return textContent(result.tree);
212
219
  },
213
220
  }),
@@ -220,8 +227,8 @@ function buildInspectionTools(appRouter) {
220
227
  "children carries `hiddenChildren`, the count of its direct children left out. Read a " +
221
228
  "match's subtree with `gtkx_get_widget_props` or `gtkx_get_widget_tree`.",
222
229
  inputSchema: queryWidgetsShape,
223
- handler: async ({ applicationId, ...params }) => {
224
- const result = await appRouter.sendToApp(applicationId, "widget.query", params);
230
+ handler: async ({ applicationId, appTimeout, ...params }) => {
231
+ const result = await appRouter.sendToApp(applicationId, "widget.query", params, appTimeout);
225
232
  return textContent(JSON.stringify(result, null, 2));
226
233
  },
227
234
  }),
@@ -239,8 +246,8 @@ function buildInteractionTools(appRouter) {
239
246
  "buttons, checkboxes, switches, list and grid rows, tree expanders, and column headers: a " +
240
247
  "row is selected, an expander toggles its row's expansion, and a header sorts its column.",
241
248
  inputSchema: widgetIdShape,
242
- handler: async ({ applicationId, ...params }) => {
243
- await appRouter.sendToApp(applicationId, "widget.click", params);
249
+ handler: async ({ applicationId, appTimeout, ...params }) => {
250
+ await appRouter.sendToApp(applicationId, "widget.click", params, appTimeout);
244
251
  return textContent("Clicked");
245
252
  },
246
253
  }),
@@ -250,8 +257,8 @@ function buildInteractionTools(appRouter) {
250
257
  kind: "action",
251
258
  description: "Type text into an editable widget like Entry or TextView",
252
259
  inputSchema: typeShape,
253
- handler: async ({ applicationId, ...params }) => {
254
- await appRouter.sendToApp(applicationId, "widget.type", params);
260
+ handler: async ({ applicationId, appTimeout, ...params }) => {
261
+ await appRouter.sendToApp(applicationId, "widget.type", params, appTimeout);
255
262
  return textContent("Typed text");
256
263
  },
257
264
  }),
@@ -261,8 +268,8 @@ function buildInteractionTools(appRouter) {
261
268
  kind: "action",
262
269
  description: "Emit a GTK4 signal on a widget. Use this for custom interactions.",
263
270
  inputSchema: fireEventShape,
264
- handler: async ({ applicationId, ...params }) => {
265
- const result = await appRouter.sendToApp(applicationId, "widget.fireEvent", params);
271
+ handler: async ({ applicationId, appTimeout, ...params }) => {
272
+ const result = await appRouter.sendToApp(applicationId, "widget.fireEvent", params, appTimeout);
266
273
  return textContent(JSON.stringify(result, null, 2));
267
274
  },
268
275
  }),
@@ -280,34 +287,74 @@ const registerTools = (mcpServer, appRouter, provider, settings) => {
280
287
  registerTool(mcpServer, tool);
281
288
  }
282
289
  };
283
- async function stopServer(state) {
284
- if (state.isStopped) {
285
- return;
290
+ const stoppedServerError = () => new Error("createMcpServer: a stopped server cannot be started again");
291
+ const wasStopRequested = (state) => state.isStopRequested;
292
+ function stopServer(state) {
293
+ if (state.shutdown !== null) {
294
+ return state.shutdown;
286
295
  }
287
- state.isStopped = true;
288
- await state.socketServer.stop();
289
- await state.mcpServer.close();
296
+ state.isStopRequested = true;
297
+ state.appRouter.dispose();
298
+ const startup = state.startup;
299
+ const shutdown = (async () => {
300
+ if (startup !== null) {
301
+ await Promise.allSettled([startup]);
302
+ }
303
+ await state.socketServer.stop();
304
+ await state.mcpServer.close();
305
+ })();
306
+ state.shutdown = shutdown;
307
+ return shutdown;
290
308
  }
291
- async function startServer(state) {
292
- if (state.isStopped) {
293
- throw new Error("createMcpServer: a stopped server cannot be started again");
309
+ function startServer(state) {
310
+ if (wasStopRequested(state)) {
311
+ return Promise.reject(stoppedServerError());
294
312
  }
295
- await state.socketServer.start();
296
- if (state.isStarted) {
297
- return;
313
+ if (state.startup !== null) {
314
+ return state.startup;
298
315
  }
299
- state.isStarted = true;
300
- log.info(`socket server listening on ${state.socketPath}`);
301
- await connectStdio(state.mcpServer, () => stopServer(state));
316
+ const startup = (async () => {
317
+ try {
318
+ await state.socketServer.start();
319
+ if (wasStopRequested(state)) {
320
+ return;
321
+ }
322
+ log.info(`socket server listening on ${state.socketPath}`);
323
+ await connectStdio(state.mcpServer, () => stopServer(state));
324
+ }
325
+ catch (error) {
326
+ if (!wasStopRequested(state)) {
327
+ state.isStopRequested = true;
328
+ state.appRouter.dispose();
329
+ await state.socketServer.stop();
330
+ await state.mcpServer.close();
331
+ }
332
+ throw error;
333
+ }
334
+ })();
335
+ state.startup = startup;
336
+ return startup;
302
337
  }
303
- const createServerHandle = (socketServer, mcpServer, socketPath) => {
304
- const state = { socketServer, mcpServer, socketPath, isStopped: false, isStarted: false };
338
+ const createServerHandle = (socketServer, mcpServer, appRouter, socketPath) => {
339
+ const state = {
340
+ socketServer,
341
+ mcpServer,
342
+ appRouter,
343
+ socketPath,
344
+ isStopRequested: false,
345
+ startup: null,
346
+ shutdown: null,
347
+ };
305
348
  return { start: () => startServer(state), stop: () => stopServer(state) };
306
349
  };
307
350
  const createMcpServer = (options) => {
308
- const socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;
351
+ const socketAddress = resolveMcpSocketAddress(options.socketPath);
352
+ const socketPath = socketAddress.path;
353
+ if (socketAddress.fallbackDirectory !== null) {
354
+ log.warn(`MCP socket path exceeds the safe Unix byte budget; using private fallback ${socketPath}`);
355
+ }
309
356
  const registry = new ConnectionRegistry();
310
- const socketServer = new SocketServer(registry, socketPath);
357
+ const socketServer = new SocketServer(registry, socketAddress);
311
358
  const appRouter = new AppRouter(registry);
312
359
  registry.addEventListener("error", logSocketError);
313
360
  appRouter.addEventListener("appRegistered", (event) => {
@@ -321,7 +368,7 @@ const createMcpServer = (options) => {
321
368
  const referenceProvider = createReferenceProvider({ getAppRoot: () => appRouter.getProjectRoot() });
322
369
  registerTools(mcpServer, appRouter, referenceProvider, options.settings ?? DEFAULT_SETTINGS);
323
370
  registerReferenceResources(mcpServer, referenceProvider);
324
- return createServerHandle(socketServer, mcpServer, socketPath);
371
+ return createServerHandle(socketServer, mcpServer, appRouter, socketPath);
325
372
  };
326
373
  const configuredSettings = async (cwd) => {
327
374
  try {