@contextual-io/cli 0.7.1 → 0.8.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.
@@ -0,0 +1,357 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { io } from "socket.io-client";
3
+ import { McpBindSessionFailure, McpBindSessionResponse, McpCommandStatus, McpListSessionsResponse, McpManifestResponse, McpToolError, McpToolRegistrySync, McpToolResult } from "../models/mcp.js";
4
+ import { McpDetachedPayload, McpSessionAvailablePayload, McpSessionUnavailablePayload, } from "./contracts.js";
5
+ const mcpNamespace = "/mcp";
6
+ const toSocketIoUrl = (routeUrl) => `${routeUrl.protocol}//${routeUrl.host}`;
7
+ const getConnectErrorMessage = (error) => {
8
+ const message = error.message || "Socket.IO connection failed";
9
+ const type = error.type ? ` (${error.type})` : "";
10
+ return `${message}${type}`;
11
+ };
12
+ export const getMcpSocketRoute = ({ url }) => {
13
+ let routeUrl;
14
+ try {
15
+ routeUrl = new URL(url);
16
+ }
17
+ catch {
18
+ throw new McpSocketBridgeError(`Invalid route URL '${url}'`, "INVALID_CONNECT_ROUTE");
19
+ }
20
+ if (routeUrl.protocol !== "http:" && routeUrl.protocol !== "https:") {
21
+ throw new McpSocketBridgeError(`Route URL must use http:// or https:// (received '${url}')`, "INVALID_CONNECT_ROUTE");
22
+ }
23
+ if (routeUrl.search || routeUrl.hash) {
24
+ throw new McpSocketBridgeError(`Websocket URL cannot include query string or hash (received '${url}')`, "INVALID_CONNECT_ROUTE");
25
+ }
26
+ const normalizedPathname = (routeUrl.pathname.length > 1 && routeUrl.pathname.endsWith("/")
27
+ ? routeUrl.pathname.slice(0, -1)
28
+ : routeUrl.pathname) || "/";
29
+ const path = normalizedPathname.endsWith(mcpNamespace)
30
+ ? normalizedPathname.slice(0, -mcpNamespace.length) || "/"
31
+ : normalizedPathname;
32
+ const connectUrl = toSocketIoUrl(routeUrl);
33
+ const namespaceUrl = new URL(mcpNamespace, `${connectUrl}/`).toString();
34
+ return {
35
+ connectUrl,
36
+ namespace: mcpNamespace,
37
+ namespaceUrl,
38
+ path,
39
+ url: routeUrl.toString(),
40
+ };
41
+ };
42
+ export class McpSocketBridgeError extends Error {
43
+ code;
44
+ constructor(message, code) {
45
+ super(message);
46
+ this.code = code;
47
+ this.name = "McpSocketBridgeError";
48
+ }
49
+ }
50
+ export class McpSocketBridge {
51
+ boundFlowId;
52
+ commandQueue = Promise.resolve();
53
+ handlers;
54
+ pendingCommands = new Map();
55
+ socket;
56
+ constructor(handlers = {}) {
57
+ this.handlers = handlers;
58
+ }
59
+ get isConnected() {
60
+ return this.socket?.connected ?? false;
61
+ }
62
+ async bindSession({ flowId }) {
63
+ const socket = this.requireSocket();
64
+ return new Promise((resolve, reject) => {
65
+ let settled = false;
66
+ const timer = setTimeout(() => {
67
+ if (settled)
68
+ return;
69
+ settled = true;
70
+ reject(new McpSocketBridgeError("Timed out waiting for bind response", "BIND_TIMEOUT"));
71
+ }, 60_000);
72
+ socket.emit("mcp-bind-session", { flowId }, (response) => {
73
+ if (settled)
74
+ return;
75
+ settled = true;
76
+ clearTimeout(timer);
77
+ const failure = McpBindSessionFailure.safeParse(response);
78
+ if (failure.success && failure.data.code) {
79
+ reject(new McpSocketBridgeError(failure.data.message, "BIND_FAILED"));
80
+ return;
81
+ }
82
+ const parsed = McpBindSessionResponse.safeParse(response);
83
+ if (!parsed.success) {
84
+ reject(new McpSocketBridgeError("Invalid bind-session response payload", "BIND_FAILED"));
85
+ return;
86
+ }
87
+ this.boundFlowId = parsed.data.flowId;
88
+ resolve(parsed.data);
89
+ });
90
+ });
91
+ }
92
+ async connect({ interfaceType, orgId, token, url }) {
93
+ if (this.socket) {
94
+ throw new McpSocketBridgeError("An MCP socket is already active", "ALREADY_CONNECTED");
95
+ }
96
+ const route = getMcpSocketRoute({ url });
97
+ const socket = io(route.namespaceUrl, {
98
+ auth: { token },
99
+ path: route.path,
100
+ query: { interfaceType, orgId },
101
+ reconnection: false,
102
+ transports: ["websocket", "polling"],
103
+ tryAllTransports: true,
104
+ });
105
+ return new Promise((resolve, reject) => {
106
+ let settled = false;
107
+ const cleanup = () => {
108
+ socket.off("connect", onConnect);
109
+ socket.off("connect_error", onConnectError);
110
+ };
111
+ const fail = (error) => {
112
+ if (settled)
113
+ return;
114
+ settled = true;
115
+ cleanup();
116
+ socket.removeAllListeners();
117
+ socket.disconnect();
118
+ reject(error);
119
+ };
120
+ const onConnect = () => {
121
+ if (settled)
122
+ return;
123
+ settled = true;
124
+ cleanup();
125
+ this.socket = socket;
126
+ this.bindPersistentListeners(socket);
127
+ resolve({ connectedAt: Date.now() });
128
+ };
129
+ const onConnectError = (error) => {
130
+ fail(new McpSocketBridgeError(getConnectErrorMessage(error), "CONNECT_ERROR"));
131
+ };
132
+ socket.on("connect", onConnect);
133
+ socket.on("connect_error", onConnectError);
134
+ });
135
+ }
136
+ async disconnect() {
137
+ if (!this.socket) {
138
+ return;
139
+ }
140
+ const { boundFlowId, socket } = this;
141
+ this.socket = undefined;
142
+ this.boundFlowId = undefined;
143
+ const disconnectInfo = boundFlowId ? await this.notifyRemoteDisconnect(socket) : undefined;
144
+ socket.removeAllListeners();
145
+ socket.disconnect();
146
+ this.rejectAllPendingCommands(new McpSocketBridgeError("Disconnected before command completion", "DISCONNECTED_DURING_COMMAND"));
147
+ return {
148
+ detachedAt: disconnectInfo?.detachedAt ?? Date.now(),
149
+ };
150
+ }
151
+ hasActiveSocket() {
152
+ return Boolean(this.socket);
153
+ }
154
+ async listSessions({ flowId, interfaceType }) {
155
+ const socket = this.requireSocket();
156
+ return new Promise((resolve, reject) => {
157
+ let settled = false;
158
+ const timer = setTimeout(() => {
159
+ if (settled)
160
+ return;
161
+ settled = true;
162
+ reject(new McpSocketBridgeError("Timed out waiting for session list", "LIST_SESSIONS_FAILED"));
163
+ }, 15_000);
164
+ socket.emit("mcp-list-sessions", {
165
+ interfaceType,
166
+ ...(flowId !== undefined && { flowId }),
167
+ }, (response) => {
168
+ if (settled)
169
+ return;
170
+ settled = true;
171
+ clearTimeout(timer);
172
+ const parsed = McpListSessionsResponse.safeParse(response);
173
+ if (!parsed.success) {
174
+ reject(new McpSocketBridgeError("Invalid list-sessions response payload", "LIST_SESSIONS_FAILED"));
175
+ return;
176
+ }
177
+ resolve(parsed.data);
178
+ });
179
+ });
180
+ }
181
+ async requestManifest(interfaceType) {
182
+ const socket = this.requireSocket();
183
+ return new Promise((resolve, reject) => {
184
+ let settled = false;
185
+ const timer = setTimeout(() => {
186
+ if (settled)
187
+ return;
188
+ settled = true;
189
+ reject(new McpSocketBridgeError("Timed out waiting for manifest response", "MANIFEST_TIMEOUT"));
190
+ }, 15_000);
191
+ socket.emit("mcp-request-manifest", { interfaceType }, (response) => {
192
+ if (settled)
193
+ return;
194
+ settled = true;
195
+ clearTimeout(timer);
196
+ const parsed = McpManifestResponse.safeParse(response);
197
+ if (!parsed.success) {
198
+ reject(new McpSocketBridgeError("Invalid manifest response payload", "MANIFEST_FETCH_FAILED"));
199
+ return;
200
+ }
201
+ resolve(parsed.data);
202
+ });
203
+ });
204
+ }
205
+ async runTool(params) {
206
+ return new Promise((resolve, reject) => {
207
+ this.commandQueue = this.commandQueue.then(() => this.executeToolCommand(params).then(resolve, reject));
208
+ });
209
+ }
210
+ async unbindSession() {
211
+ if (!this.boundFlowId) {
212
+ return;
213
+ }
214
+ const socket = this.requireSocket();
215
+ this.boundFlowId = undefined;
216
+ return new Promise((resolve) => {
217
+ let settled = false;
218
+ const timer = setTimeout(() => {
219
+ if (settled)
220
+ return;
221
+ settled = true;
222
+ resolve();
223
+ }, 5000);
224
+ socket.emit("mcp-unbind-session", {}, () => {
225
+ if (settled)
226
+ return;
227
+ settled = true;
228
+ clearTimeout(timer);
229
+ resolve();
230
+ });
231
+ });
232
+ }
233
+ bindPersistentListeners(socket) {
234
+ socket.on("mcp-tool-registry", (payload) => {
235
+ const parsed = McpToolRegistrySync.safeParse(payload);
236
+ if (!parsed.success) {
237
+ return;
238
+ }
239
+ this.handlers.onToolRegistrySync?.(parsed.data);
240
+ });
241
+ socket.on("mcp-command-status", (payload) => {
242
+ const parsed = McpCommandStatus.safeParse(payload);
243
+ if (!parsed.success) {
244
+ return;
245
+ }
246
+ this.handlers.onCommandStatus?.(parsed.data);
247
+ const pendingCommand = this.pendingCommands.get(parsed.data.commandId);
248
+ if (!pendingCommand) {
249
+ return;
250
+ }
251
+ if (parsed.data.status === "failed" || parsed.data.status === "timeout") {
252
+ this.pendingCommands.delete(parsed.data.commandId);
253
+ pendingCommand.reject(new McpSocketBridgeError(parsed.data.error?.message ?? parsed.data.progress?.message ?? `Tool command ${parsed.data.status}`, "MCP_ERROR"));
254
+ }
255
+ });
256
+ socket.on("mcp-tool-result", (payload) => {
257
+ const parsed = McpToolResult.safeParse(payload);
258
+ if (!parsed.success) {
259
+ return;
260
+ }
261
+ const pendingCommand = this.pendingCommands.get(parsed.data.commandId);
262
+ if (!pendingCommand) {
263
+ return;
264
+ }
265
+ this.pendingCommands.delete(parsed.data.commandId);
266
+ pendingCommand.resolve(parsed.data.result);
267
+ });
268
+ socket.on("mcp-tool-error", (payload) => {
269
+ const parsed = McpToolError.safeParse(payload);
270
+ if (!parsed.success) {
271
+ return;
272
+ }
273
+ this.rejectAllPendingCommands(new McpSocketBridgeError(parsed.data.message, "MCP_ERROR"));
274
+ });
275
+ socket.on("mcp-session-available", (payload) => {
276
+ const parsed = McpSessionAvailablePayload.safeParse(payload);
277
+ if (!parsed.success) {
278
+ return;
279
+ }
280
+ this.handlers.onSessionAvailable?.(parsed.data);
281
+ });
282
+ socket.on("mcp-session-unavailable", (payload) => {
283
+ const parsed = McpSessionUnavailablePayload.safeParse(payload);
284
+ if (!parsed.success) {
285
+ return;
286
+ }
287
+ this.handlers.onSessionUnavailable?.(parsed.data);
288
+ });
289
+ socket.on("mcp-detached", (payload) => {
290
+ const parsed = McpDetachedPayload.safeParse(payload);
291
+ if (parsed.success) {
292
+ this.handlers.onDetached?.(parsed.data);
293
+ }
294
+ this.boundFlowId = undefined;
295
+ this.rejectAllPendingCommands(new McpSocketBridgeError("Remote session detached", "DISCONNECTED_DURING_COMMAND"));
296
+ });
297
+ socket.on("disconnect", (reason) => {
298
+ if (this.socket?.id === socket.id) {
299
+ this.socket = undefined;
300
+ }
301
+ this.boundFlowId = undefined;
302
+ this.rejectAllPendingCommands(new McpSocketBridgeError(`Socket disconnected (${reason})`, "DISCONNECTED_DURING_COMMAND"));
303
+ this.handlers.onDisconnected?.(reason);
304
+ });
305
+ }
306
+ async executeToolCommand({ args, name, timeoutMs }) {
307
+ const socket = this.requireSocket();
308
+ const commandId = randomUUID();
309
+ return new Promise((resolve, reject) => {
310
+ this.pendingCommands.set(commandId, {
311
+ commandId,
312
+ reject,
313
+ resolve,
314
+ });
315
+ socket.emit("mcp-run-tool", {
316
+ commandId,
317
+ toolCall: {
318
+ args,
319
+ name,
320
+ ...(timeoutMs !== undefined && { timeoutMs }),
321
+ type: "mcp-tool",
322
+ },
323
+ });
324
+ });
325
+ }
326
+ notifyRemoteDisconnect(socket) {
327
+ return new Promise((resolve) => {
328
+ let settled = false;
329
+ const timer = setTimeout(() => {
330
+ if (settled)
331
+ return;
332
+ settled = true;
333
+ resolve({ detachedAt: Date.now() });
334
+ }, 1000);
335
+ socket.emit("mcp-disconnect-session", {}, (payload) => {
336
+ if (settled)
337
+ return;
338
+ settled = true;
339
+ clearTimeout(timer);
340
+ resolve(payload);
341
+ });
342
+ });
343
+ }
344
+ rejectAllPendingCommands(error) {
345
+ const pending = [...this.pendingCommands.values()];
346
+ this.pendingCommands.clear();
347
+ for (const command of pending) {
348
+ command.reject(error);
349
+ }
350
+ }
351
+ requireSocket() {
352
+ if (!this.socket) {
353
+ throw new McpSocketBridgeError("Cannot perform action without an active MCP socket", "NOT_CONNECTED");
354
+ }
355
+ return this.socket;
356
+ }
357
+ }
@@ -0,0 +1,288 @@
1
+ import { z } from "zod";
2
+ export declare const McpSessionId: z.ZodString;
3
+ export type McpSessionId = z.infer<typeof McpSessionId>;
4
+ export declare const McpDetachReason: z.ZodEnum<{
5
+ "target-disconnected": "target-disconnected";
6
+ "mcp-disconnected": "mcp-disconnected";
7
+ "manual-detach": "manual-detach";
8
+ }>;
9
+ export type McpDetachReason = z.infer<typeof McpDetachReason>;
10
+ export declare const McpBindFailureCode: z.ZodEnum<{
11
+ MCP_DISABLED: "MCP_DISABLED";
12
+ NO_ACTIVE_BROWSER: "NO_ACTIVE_BROWSER";
13
+ BIND_DENIED: "BIND_DENIED";
14
+ INTERNAL_ERROR: "INTERNAL_ERROR";
15
+ }>;
16
+ export type McpBindFailureCode = z.infer<typeof McpBindFailureCode>;
17
+ export declare const McpToolErrorCode: z.ZodEnum<{
18
+ INTERNAL_ERROR: "INTERNAL_ERROR";
19
+ NOT_ATTACHED: "NOT_ATTACHED";
20
+ UNKNOWN_TOOL: "UNKNOWN_TOOL";
21
+ COMMAND_IN_FLIGHT: "COMMAND_IN_FLIGHT";
22
+ TIMEOUT: "TIMEOUT";
23
+ UNAUTHORIZED: "UNAUTHORIZED";
24
+ }>;
25
+ export type McpToolErrorCode = z.infer<typeof McpToolErrorCode>;
26
+ export declare const JsonSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
27
+ export type JsonSchema = z.infer<typeof JsonSchema>;
28
+ export declare const McpToolDefinition: z.ZodObject<{
29
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
+ description: z.ZodString;
31
+ inputSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
32
+ name: z.ZodString;
33
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
+ title: z.ZodOptional<z.ZodString>;
35
+ }, z.core.$strip>;
36
+ export type McpToolDefinition = z.infer<typeof McpToolDefinition>;
37
+ export declare const McpClientPackageInfo: z.ZodObject<{
38
+ name: z.ZodOptional<z.ZodString>;
39
+ version: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>;
41
+ export type McpClientPackageInfo = z.infer<typeof McpClientPackageInfo>;
42
+ export declare const McpManifestRequest: z.ZodObject<{
43
+ interfaceType: z.ZodString;
44
+ }, z.core.$strip>;
45
+ export type McpManifestRequest = z.infer<typeof McpManifestRequest>;
46
+ export declare const McpManifestResponse: z.ZodObject<{
47
+ definitions: z.ZodArray<z.ZodObject<{
48
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
49
+ description: z.ZodString;
50
+ inputSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
51
+ name: z.ZodString;
52
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
53
+ title: z.ZodOptional<z.ZodString>;
54
+ }, z.core.$strip>>;
55
+ interfaceType: z.ZodString;
56
+ resolvedAt: z.ZodNumber;
57
+ tools: z.ZodArray<z.ZodString>;
58
+ }, z.core.$strip>;
59
+ export type McpManifestResponse = z.infer<typeof McpManifestResponse>;
60
+ export declare const McpFlowSession: z.ZodObject<{
61
+ flowId: z.ZodString;
62
+ flowName: z.ZodString;
63
+ }, z.core.$strip>;
64
+ export type McpFlowSession = z.infer<typeof McpFlowSession>;
65
+ export declare const McpListSessionsRequest: z.ZodObject<{
66
+ flowId: z.ZodOptional<z.ZodString>;
67
+ interfaceType: z.ZodString;
68
+ }, z.core.$strip>;
69
+ export type McpListSessionsRequest = z.infer<typeof McpListSessionsRequest>;
70
+ export declare const McpListSessionsResponse: z.ZodObject<{
71
+ sessions: z.ZodArray<z.ZodObject<{
72
+ flowId: z.ZodString;
73
+ flowName: z.ZodString;
74
+ }, z.core.$strip>>;
75
+ }, z.core.$strip>;
76
+ export type McpListSessionsResponse = z.infer<typeof McpListSessionsResponse>;
77
+ export declare const McpBindSessionRequest: z.ZodObject<{
78
+ flowId: z.ZodString;
79
+ }, z.core.$strip>;
80
+ export type McpBindSessionRequest = z.infer<typeof McpBindSessionRequest>;
81
+ export declare const McpBindSessionResponse: z.ZodObject<{
82
+ boundAt: z.ZodNumber;
83
+ flowId: z.ZodString;
84
+ flowName: z.ZodString;
85
+ }, z.core.$strip>;
86
+ export type McpBindSessionResponse = z.infer<typeof McpBindSessionResponse>;
87
+ export declare const McpBindSessionFailure: z.ZodObject<{
88
+ code: z.ZodEnum<{
89
+ MCP_DISABLED: "MCP_DISABLED";
90
+ NO_ACTIVE_BROWSER: "NO_ACTIVE_BROWSER";
91
+ BIND_DENIED: "BIND_DENIED";
92
+ INTERNAL_ERROR: "INTERNAL_ERROR";
93
+ }>;
94
+ message: z.ZodString;
95
+ sessions: z.ZodOptional<z.ZodArray<z.ZodObject<{
96
+ flowId: z.ZodString;
97
+ flowName: z.ZodString;
98
+ }, z.core.$strip>>>;
99
+ }, z.core.$strip>;
100
+ export type McpBindSessionFailure = z.infer<typeof McpBindSessionFailure>;
101
+ export declare const McpSessionControlRequest: z.ZodObject<{
102
+ mcpSessionId: z.ZodString;
103
+ }, z.core.$strip>;
104
+ export type McpSessionControlRequest = z.infer<typeof McpSessionControlRequest>;
105
+ export declare const McpSessionDisconnectAck: z.ZodObject<{
106
+ detachedAt: z.ZodOptional<z.ZodNumber>;
107
+ }, z.core.$strip>;
108
+ export type McpSessionDisconnectAck = z.infer<typeof McpSessionDisconnectAck>;
109
+ export declare const McpToolRegistrySync: z.ZodObject<{
110
+ action: z.ZodEnum<{
111
+ clear: "clear";
112
+ register: "register";
113
+ }>;
114
+ clientPackage: z.ZodOptional<z.ZodObject<{
115
+ name: z.ZodOptional<z.ZodString>;
116
+ version: z.ZodOptional<z.ZodString>;
117
+ }, z.core.$strip>>;
118
+ definitions: z.ZodArray<z.ZodObject<{
119
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
120
+ description: z.ZodString;
121
+ inputSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
122
+ name: z.ZodString;
123
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
124
+ title: z.ZodOptional<z.ZodString>;
125
+ }, z.core.$strip>>;
126
+ expertId: z.ZodOptional<z.ZodString>;
127
+ expertName: z.ZodOptional<z.ZodString>;
128
+ mcpSessionId: z.ZodString;
129
+ replace: z.ZodOptional<z.ZodBoolean>;
130
+ tools: z.ZodArray<z.ZodString>;
131
+ updatedAt: z.ZodNumber;
132
+ }, z.core.$strip>;
133
+ export type McpToolRegistrySync = z.infer<typeof McpToolRegistrySync>;
134
+ export declare const McpToolCall: z.ZodObject<{
135
+ args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
136
+ name: z.ZodString;
137
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
138
+ type: z.ZodLiteral<"mcp-tool">;
139
+ }, z.core.$strip>;
140
+ export type McpToolCall = z.infer<typeof McpToolCall>;
141
+ export declare const McpToolProgress: z.ZodObject<{
142
+ data: z.ZodOptional<z.ZodUnknown>;
143
+ message: z.ZodOptional<z.ZodString>;
144
+ percent: z.ZodOptional<z.ZodNumber>;
145
+ }, z.core.$strip>;
146
+ export type McpToolProgress = z.infer<typeof McpToolProgress>;
147
+ export declare const McpToolResult: z.ZodObject<{
148
+ commandId: z.ZodString;
149
+ result: z.ZodUnknown;
150
+ }, z.core.$strip>;
151
+ export type McpToolResult = z.infer<typeof McpToolResult>;
152
+ export declare const McpToolError: z.ZodObject<{
153
+ code: z.ZodOptional<z.ZodEnum<{
154
+ INTERNAL_ERROR: "INTERNAL_ERROR";
155
+ NOT_ATTACHED: "NOT_ATTACHED";
156
+ UNKNOWN_TOOL: "UNKNOWN_TOOL";
157
+ COMMAND_IN_FLIGHT: "COMMAND_IN_FLIGHT";
158
+ TIMEOUT: "TIMEOUT";
159
+ UNAUTHORIZED: "UNAUTHORIZED";
160
+ }>>;
161
+ data: z.ZodOptional<z.ZodUnknown>;
162
+ message: z.ZodString;
163
+ }, z.core.$strip>;
164
+ export type McpToolError = z.infer<typeof McpToolError>;
165
+ export declare const McpCommandStatusType: z.ZodEnum<{
166
+ failed: "failed";
167
+ progress: "progress";
168
+ accepted: "accepted";
169
+ dispatched: "dispatched";
170
+ completed: "completed";
171
+ timeout: "timeout";
172
+ }>;
173
+ export type McpCommandStatusType = z.infer<typeof McpCommandStatusType>;
174
+ export declare const McpCommandStatus: z.ZodObject<{
175
+ commandId: z.ZodString;
176
+ error: z.ZodOptional<z.ZodObject<{
177
+ code: z.ZodOptional<z.ZodEnum<{
178
+ INTERNAL_ERROR: "INTERNAL_ERROR";
179
+ NOT_ATTACHED: "NOT_ATTACHED";
180
+ UNKNOWN_TOOL: "UNKNOWN_TOOL";
181
+ COMMAND_IN_FLIGHT: "COMMAND_IN_FLIGHT";
182
+ TIMEOUT: "TIMEOUT";
183
+ UNAUTHORIZED: "UNAUTHORIZED";
184
+ }>>;
185
+ data: z.ZodOptional<z.ZodUnknown>;
186
+ message: z.ZodString;
187
+ }, z.core.$strip>>;
188
+ mcpSessionId: z.ZodString;
189
+ progress: z.ZodOptional<z.ZodObject<{
190
+ data: z.ZodOptional<z.ZodUnknown>;
191
+ message: z.ZodOptional<z.ZodString>;
192
+ percent: z.ZodOptional<z.ZodNumber>;
193
+ }, z.core.$strip>>;
194
+ status: z.ZodEnum<{
195
+ failed: "failed";
196
+ progress: "progress";
197
+ accepted: "accepted";
198
+ dispatched: "dispatched";
199
+ completed: "completed";
200
+ timeout: "timeout";
201
+ }>;
202
+ timestamp: z.ZodNumber;
203
+ toolName: z.ZodString;
204
+ }, z.core.$strip>;
205
+ export type McpCommandStatus = z.infer<typeof McpCommandStatus>;
206
+ export declare const McpCommandHistoryEntry: z.ZodObject<{
207
+ commandId: z.ZodString;
208
+ completedAt: z.ZodOptional<z.ZodNumber>;
209
+ createdAt: z.ZodNumber;
210
+ error: z.ZodOptional<z.ZodObject<{
211
+ code: z.ZodOptional<z.ZodEnum<{
212
+ INTERNAL_ERROR: "INTERNAL_ERROR";
213
+ NOT_ATTACHED: "NOT_ATTACHED";
214
+ UNKNOWN_TOOL: "UNKNOWN_TOOL";
215
+ COMMAND_IN_FLIGHT: "COMMAND_IN_FLIGHT";
216
+ TIMEOUT: "TIMEOUT";
217
+ UNAUTHORIZED: "UNAUTHORIZED";
218
+ }>>;
219
+ data: z.ZodOptional<z.ZodUnknown>;
220
+ message: z.ZodString;
221
+ }, z.core.$strip>>;
222
+ mcpSessionId: z.ZodString;
223
+ progress: z.ZodOptional<z.ZodObject<{
224
+ data: z.ZodOptional<z.ZodUnknown>;
225
+ message: z.ZodOptional<z.ZodString>;
226
+ percent: z.ZodOptional<z.ZodNumber>;
227
+ }, z.core.$strip>>;
228
+ result: z.ZodOptional<z.ZodUnknown>;
229
+ status: z.ZodEnum<{
230
+ failed: "failed";
231
+ progress: "progress";
232
+ accepted: "accepted";
233
+ dispatched: "dispatched";
234
+ completed: "completed";
235
+ timeout: "timeout";
236
+ }>;
237
+ toolCall: z.ZodOptional<z.ZodObject<{
238
+ args: z.ZodRecord<z.ZodString, z.ZodUnknown>;
239
+ name: z.ZodString;
240
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
241
+ type: z.ZodLiteral<"mcp-tool">;
242
+ }, z.core.$strip>>;
243
+ toolName: z.ZodString;
244
+ updatedAt: z.ZodNumber;
245
+ }, z.core.$strip>;
246
+ export type McpCommandHistoryEntry = z.infer<typeof McpCommandHistoryEntry>;
247
+ export type McpToSolutionAiSocketMap = {
248
+ "mcp-bind-session": (messageParams: McpBindSessionRequest, callback: (messageParams: McpBindSessionFailure | McpBindSessionResponse) => void) => void;
249
+ "mcp-disconnect-session": (messageParams: Partial<McpSessionControlRequest>, callback: (messageParams: McpSessionDisconnectAck) => void) => void;
250
+ "mcp-list-sessions": (messageParams: McpListSessionsRequest, callback: (messageParams: McpListSessionsResponse) => void) => void;
251
+ "mcp-request-manifest": (messageParams: McpManifestRequest, callback: (messageParams: McpManifestResponse) => void) => void;
252
+ "mcp-run-tool": (messageParams: {
253
+ commandId?: string;
254
+ toolCall: McpToolCall;
255
+ }) => void;
256
+ "mcp-unbind-session": (messageParams: Partial<McpSessionControlRequest>, callback: (messageParams: McpSessionDisconnectAck) => void) => void;
257
+ };
258
+ export type SolutionAiToMcpSocketMap = {
259
+ "mcp-command-status": (messageParams: McpCommandStatus) => void;
260
+ "mcp-detached": (messageParams: {
261
+ detachedAt: number;
262
+ mcpSessionId: string;
263
+ reason: McpDetachReason;
264
+ }) => void;
265
+ "mcp-error": (messageParams: {
266
+ error: string;
267
+ }) => void;
268
+ "mcp-session-available": (messageParams: {
269
+ flowId: string;
270
+ flowName: string;
271
+ }) => void;
272
+ "mcp-session-unavailable": (messageParams: {
273
+ flowId: string;
274
+ reason: string;
275
+ }) => void;
276
+ "mcp-tool-accepted": (messageParams: {
277
+ commandId: string;
278
+ toolName: string;
279
+ }) => void;
280
+ "mcp-tool-error": (messageParams: {
281
+ commandId?: string;
282
+ error: Omit<McpToolError, "code"> & {
283
+ code: NonNullable<McpToolError["code"]>;
284
+ };
285
+ }) => void;
286
+ "mcp-tool-registry": (messageParams: McpToolRegistrySync) => void;
287
+ "mcp-tool-result": (messageParams: McpToolResult) => void;
288
+ };