clay-server 2.34.0-beta.4 → 2.34.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/sdk-bridge.js
CHANGED
|
@@ -1227,11 +1227,13 @@ function createSDKBridge(opts) {
|
|
|
1227
1227
|
}
|
|
1228
1228
|
|
|
1229
1229
|
var codexConfig = getCodexConfig(sm);
|
|
1230
|
+
var mergedMcpServers = mergeMcpServers(getMcpServers(), getRemoteMcpServers) || undefined;
|
|
1230
1231
|
var queryOpts = {
|
|
1231
1232
|
cwd: cwd,
|
|
1232
1233
|
model: queryModel,
|
|
1233
1234
|
effort: ls.effort || sm.currentEffort || undefined,
|
|
1234
|
-
toolServers:
|
|
1235
|
+
toolServers: mergedMcpServers,
|
|
1236
|
+
toolServerDescriptors: extractMcpDescriptors(mergedMcpServers) || undefined,
|
|
1235
1237
|
resumeSessionId: session.cliSessionId || undefined,
|
|
1236
1238
|
abortController: linuxUser ? undefined : session.abortController,
|
|
1237
1239
|
canUseTool: function(toolName, input, toolOpts) {
|
|
@@ -1240,6 +1242,9 @@ function createSDKBridge(opts) {
|
|
|
1240
1242
|
onElicitation: function(request, elicitOpts) {
|
|
1241
1243
|
return handleElicitation(session, request, elicitOpts);
|
|
1242
1244
|
},
|
|
1245
|
+
callMcpTool: function(serverName, toolName, args) {
|
|
1246
|
+
return callMcpToolHandler(mergedMcpServers, serverName, toolName, args);
|
|
1247
|
+
},
|
|
1243
1248
|
adapterOptions: {
|
|
1244
1249
|
CLAUDE: claudeOpts,
|
|
1245
1250
|
CODEX: {
|
|
@@ -31,6 +31,7 @@ var abortController = null;
|
|
|
31
31
|
var pendingPermissions = {}; // requestId -> resolve
|
|
32
32
|
var pendingAskUser = {}; // toolUseId -> resolve
|
|
33
33
|
var pendingElicitations = {}; // requestId -> resolve
|
|
34
|
+
var pendingMcpToolCalls = {}; // requestId -> { resolve, reject }
|
|
34
35
|
var conn = null;
|
|
35
36
|
var buffer = "";
|
|
36
37
|
|
|
@@ -81,6 +82,90 @@ function getSDK() {
|
|
|
81
82
|
return sdkModule;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
function buildZodShape(z, inputSchema) {
|
|
86
|
+
if (!inputSchema || !inputSchema.properties) return {};
|
|
87
|
+
var shape = {};
|
|
88
|
+
var props = inputSchema.properties;
|
|
89
|
+
var required = inputSchema.required || [];
|
|
90
|
+
var keys = Object.keys(props);
|
|
91
|
+
|
|
92
|
+
for (var i = 0; i < keys.length; i++) {
|
|
93
|
+
var key = keys[i];
|
|
94
|
+
var prop = props[key];
|
|
95
|
+
var field;
|
|
96
|
+
|
|
97
|
+
if (prop.type === "number" || prop.type === "integer") {
|
|
98
|
+
field = z.number();
|
|
99
|
+
} else if (prop.type === "boolean") {
|
|
100
|
+
field = z.boolean();
|
|
101
|
+
} else if (prop.type === "array") {
|
|
102
|
+
field = z.array(z.any());
|
|
103
|
+
} else if (prop.type === "object") {
|
|
104
|
+
field = z.record(z.any());
|
|
105
|
+
} else if (prop.enum) {
|
|
106
|
+
field = z.enum(prop.enum);
|
|
107
|
+
} else {
|
|
108
|
+
field = z.string();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (prop.description) field = field.describe(prop.description);
|
|
112
|
+
if (required.indexOf(key) === -1) field = field.optional();
|
|
113
|
+
shape[key] = field;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return shape;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function createWorkerMcpToolHandler(serverName, toolName) {
|
|
120
|
+
return function(args) {
|
|
121
|
+
var requestId = crypto.randomUUID();
|
|
122
|
+
sendToDaemon({
|
|
123
|
+
type: "mcp_tool_call",
|
|
124
|
+
requestId: requestId,
|
|
125
|
+
serverName: serverName,
|
|
126
|
+
toolName: toolName,
|
|
127
|
+
args: args || {},
|
|
128
|
+
});
|
|
129
|
+
return new Promise(function(resolve, reject) {
|
|
130
|
+
pendingMcpToolCalls[requestId] = { resolve: resolve, reject: reject };
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function buildMcpServersFromDescriptors(descriptors, sdk) {
|
|
136
|
+
if (!descriptors || !descriptors.length) return null;
|
|
137
|
+
var z;
|
|
138
|
+
try { z = require("zod").z; } catch (e) {
|
|
139
|
+
try { z = require("zod"); } catch (e2) { return null; }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
var servers = {};
|
|
143
|
+
for (var i = 0; i < descriptors.length; i++) {
|
|
144
|
+
var descriptor = descriptors[i];
|
|
145
|
+
if (!descriptor || !descriptor.serverName || !descriptor.tools || !descriptor.tools.length) continue;
|
|
146
|
+
var tools = [];
|
|
147
|
+
for (var j = 0; j < descriptor.tools.length; j++) {
|
|
148
|
+
var toolDescriptor = descriptor.tools[j];
|
|
149
|
+
if (!toolDescriptor || !toolDescriptor.name) continue;
|
|
150
|
+
tools.push(sdk.tool(
|
|
151
|
+
toolDescriptor.name,
|
|
152
|
+
toolDescriptor.description || toolDescriptor.name,
|
|
153
|
+
buildZodShape(z, toolDescriptor.inputSchema),
|
|
154
|
+
createWorkerMcpToolHandler(descriptor.serverName, toolDescriptor.name)
|
|
155
|
+
));
|
|
156
|
+
}
|
|
157
|
+
if (tools.length > 0) {
|
|
158
|
+
servers[descriptor.serverName] = sdk.createSdkMcpServer({
|
|
159
|
+
name: descriptor.serverName,
|
|
160
|
+
version: "1.0.0",
|
|
161
|
+
tools: tools,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return Object.keys(servers).length > 0 ? servers : null;
|
|
167
|
+
}
|
|
168
|
+
|
|
84
169
|
// --- IPC helpers ---
|
|
85
170
|
function sendToDaemon(msg) {
|
|
86
171
|
if (!conn || conn.destroyed) return;
|
|
@@ -127,6 +212,9 @@ function handleMessage(msg) {
|
|
|
127
212
|
case "elicitation_response":
|
|
128
213
|
handleElicitationResponse(msg);
|
|
129
214
|
break;
|
|
215
|
+
case "mcp_tool_result":
|
|
216
|
+
handleMcpToolResult(msg);
|
|
217
|
+
break;
|
|
130
218
|
case "warmup":
|
|
131
219
|
handleWarmup(msg);
|
|
132
220
|
break;
|
|
@@ -208,6 +296,17 @@ function handleElicitationResponse(msg) {
|
|
|
208
296
|
}
|
|
209
297
|
}
|
|
210
298
|
|
|
299
|
+
function handleMcpToolResult(msg) {
|
|
300
|
+
var pending = pendingMcpToolCalls[msg.requestId];
|
|
301
|
+
if (!pending) return;
|
|
302
|
+
delete pendingMcpToolCalls[msg.requestId];
|
|
303
|
+
if (msg.error) {
|
|
304
|
+
pending.reject(new Error(msg.error));
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
pending.resolve(msg.result);
|
|
308
|
+
}
|
|
309
|
+
|
|
211
310
|
// --- Query handling ---
|
|
212
311
|
async function handleQueryStart(msg) {
|
|
213
312
|
var t0 = msg._perfT0 || Date.now();
|
|
@@ -238,6 +337,15 @@ async function handleQueryStart(msg) {
|
|
|
238
337
|
options.abortController = abortController;
|
|
239
338
|
options.debug = true;
|
|
240
339
|
options.debugFile = "/tmp/clay-cli-debug-" + process.pid + ".log";
|
|
340
|
+
if (options.mcpServerDescriptors && options.mcpServerDescriptors.length) {
|
|
341
|
+
try {
|
|
342
|
+
var mcpServers = buildMcpServersFromDescriptors(options.mcpServerDescriptors, sdk);
|
|
343
|
+
if (mcpServers) options.mcpServers = mcpServers;
|
|
344
|
+
} catch (e) {
|
|
345
|
+
console.error("[sdk-worker] Failed to build MCP servers:", e.message || e);
|
|
346
|
+
}
|
|
347
|
+
delete options.mcpServerDescriptors;
|
|
348
|
+
}
|
|
241
349
|
// Override CLI subprocess spawn to inject NODE_OPTIONS for IPv4-first DNS.
|
|
242
350
|
// The SDK constructs its own env for the CLI process, so worker env vars
|
|
243
351
|
// like NODE_OPTIONS are not inherited. We intercept the spawn to fix this.
|
|
@@ -600,7 +600,7 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
600
600
|
worker.send = function(msg) {
|
|
601
601
|
if (!worker.connection || worker.connection.destroyed) return;
|
|
602
602
|
try {
|
|
603
|
-
worker.connection.write(JSON.stringify(msg) + "\n");
|
|
603
|
+
worker.connection.write(JSON.stringify(serializeWorkerValue(msg)) + "\n");
|
|
604
604
|
} catch (e) {
|
|
605
605
|
console.error("[yoke/claude] Failed to send to worker:", e.message);
|
|
606
606
|
}
|
|
@@ -643,12 +643,45 @@ function cleanupWorker(worker) {
|
|
|
643
643
|
worker.ready = false;
|
|
644
644
|
}
|
|
645
645
|
|
|
646
|
+
function serializeWorkerValue(value, seen) {
|
|
647
|
+
if (value == null) return value;
|
|
648
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
649
|
+
if (typeof value === "bigint") return String(value);
|
|
650
|
+
if (typeof value === "function" || typeof value === "symbol" || typeof value === "undefined") return undefined;
|
|
651
|
+
if (value instanceof Date) return value.toISOString();
|
|
652
|
+
if (Buffer.isBuffer(value)) return value.toString("base64");
|
|
653
|
+
|
|
654
|
+
if (!seen) seen = new WeakSet();
|
|
655
|
+
if (typeof value === "object") {
|
|
656
|
+
if (seen.has(value)) return undefined;
|
|
657
|
+
seen.add(value);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
if (Array.isArray(value)) {
|
|
661
|
+
var arr = [];
|
|
662
|
+
for (var i = 0; i < value.length; i++) {
|
|
663
|
+
var item = serializeWorkerValue(value[i], seen);
|
|
664
|
+
if (item !== undefined) arr.push(item);
|
|
665
|
+
}
|
|
666
|
+
return arr;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
var out = {};
|
|
670
|
+
var keys = Object.keys(value);
|
|
671
|
+
for (var j = 0; j < keys.length; j++) {
|
|
672
|
+
var key = keys[j];
|
|
673
|
+
var child = serializeWorkerValue(value[key], seen);
|
|
674
|
+
if (child !== undefined) out[key] = child;
|
|
675
|
+
}
|
|
676
|
+
return out;
|
|
677
|
+
}
|
|
678
|
+
|
|
646
679
|
// --- Worker QueryHandle ---
|
|
647
680
|
// Wraps worker IPC into the same async iterable + control interface as the
|
|
648
681
|
// in-process QueryHandle. This allows processQueryStream to iterate a worker
|
|
649
682
|
// query identically to an in-process query.
|
|
650
683
|
|
|
651
|
-
function createWorkerQueryHandle(worker, canUseTool, onElicitation) {
|
|
684
|
+
function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool) {
|
|
652
685
|
// Async iterable state
|
|
653
686
|
var iterQueue = [];
|
|
654
687
|
var iterWaiting = null;
|
|
@@ -741,6 +774,20 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation) {
|
|
|
741
774
|
}
|
|
742
775
|
break;
|
|
743
776
|
|
|
777
|
+
case "mcp_tool_call":
|
|
778
|
+
if (callMcpTool) {
|
|
779
|
+
callMcpTool(msg.serverName, msg.toolName, msg.args || {}).then(function(result) {
|
|
780
|
+
worker.send({ type: "mcp_tool_result", requestId: msg.requestId, result: result });
|
|
781
|
+
}).catch(function(e) {
|
|
782
|
+
worker.send({
|
|
783
|
+
type: "mcp_tool_result",
|
|
784
|
+
requestId: msg.requestId,
|
|
785
|
+
error: (e && e.message) ? e.message : String(e),
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
break;
|
|
790
|
+
|
|
744
791
|
case "context_usage":
|
|
745
792
|
case "model_changed":
|
|
746
793
|
case "effort_changed":
|
|
@@ -1231,7 +1278,7 @@ function createClaudeAdapter(opts) {
|
|
|
1231
1278
|
}
|
|
1232
1279
|
|
|
1233
1280
|
// Create the worker query handle (sets up message handler on worker)
|
|
1234
|
-
var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation);
|
|
1281
|
+
var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation, queryOpts.callMcpTool);
|
|
1235
1282
|
|
|
1236
1283
|
// Wait for worker to be ready before sending query_start
|
|
1237
1284
|
if (!reusingWorker) {
|
|
@@ -1254,7 +1301,7 @@ function createClaudeAdapter(opts) {
|
|
|
1254
1301
|
if (claudeOpts.allowDangerouslySkipPermissions) queryOptions.allowDangerouslySkipPermissions = true;
|
|
1255
1302
|
if (claudeOpts.settings) queryOptions.settings = claudeOpts.settings;
|
|
1256
1303
|
|
|
1257
|
-
if (queryOpts.
|
|
1304
|
+
if (queryOpts.toolServerDescriptors) queryOptions.mcpServerDescriptors = queryOpts.toolServerDescriptors;
|
|
1258
1305
|
if (queryOpts.model) queryOptions.model = queryOpts.model;
|
|
1259
1306
|
if (queryOpts.effort) queryOptions.effort = queryOpts.effort;
|
|
1260
1307
|
if (queryOpts.resumeSessionId) queryOptions.resume = queryOpts.resumeSessionId;
|