clay-server 2.34.0-beta.4 → 2.34.0-beta.5

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: mergeMcpServers(getMcpServers(), getRemoteMcpServers) || undefined,
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.
@@ -648,7 +648,7 @@ function cleanupWorker(worker) {
648
648
  // in-process QueryHandle. This allows processQueryStream to iterate a worker
649
649
  // query identically to an in-process query.
650
650
 
651
- function createWorkerQueryHandle(worker, canUseTool, onElicitation) {
651
+ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool) {
652
652
  // Async iterable state
653
653
  var iterQueue = [];
654
654
  var iterWaiting = null;
@@ -741,6 +741,20 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation) {
741
741
  }
742
742
  break;
743
743
 
744
+ case "mcp_tool_call":
745
+ if (callMcpTool) {
746
+ callMcpTool(msg.serverName, msg.toolName, msg.args || {}).then(function(result) {
747
+ worker.send({ type: "mcp_tool_result", requestId: msg.requestId, result: result });
748
+ }).catch(function(e) {
749
+ worker.send({
750
+ type: "mcp_tool_result",
751
+ requestId: msg.requestId,
752
+ error: (e && e.message) ? e.message : String(e),
753
+ });
754
+ });
755
+ }
756
+ break;
757
+
744
758
  case "context_usage":
745
759
  case "model_changed":
746
760
  case "effort_changed":
@@ -1231,7 +1245,7 @@ function createClaudeAdapter(opts) {
1231
1245
  }
1232
1246
 
1233
1247
  // Create the worker query handle (sets up message handler on worker)
1234
- var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation);
1248
+ var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation, queryOpts.callMcpTool);
1235
1249
 
1236
1250
  // Wait for worker to be ready before sending query_start
1237
1251
  if (!reusingWorker) {
@@ -1254,7 +1268,7 @@ function createClaudeAdapter(opts) {
1254
1268
  if (claudeOpts.allowDangerouslySkipPermissions) queryOptions.allowDangerouslySkipPermissions = true;
1255
1269
  if (claudeOpts.settings) queryOptions.settings = claudeOpts.settings;
1256
1270
 
1257
- if (queryOpts.toolServers) queryOptions.mcpServers = queryOpts.toolServers;
1271
+ if (queryOpts.toolServerDescriptors) queryOptions.mcpServerDescriptors = queryOpts.toolServerDescriptors;
1258
1272
  if (queryOpts.model) queryOptions.model = queryOpts.model;
1259
1273
  if (queryOpts.effort) queryOptions.effort = queryOpts.effort;
1260
1274
  if (queryOpts.resumeSessionId) queryOptions.resume = queryOpts.resumeSessionId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.34.0-beta.4",
3
+ "version": "2.34.0-beta.5",
4
4
  "description": "Self-hosted Claude Code in your browser. Multi-session, multi-user, push notifications.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",