@wavespeed/mcp 1.2.2 → 1.2.3

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.
@@ -56,7 +56,7 @@
56
56
  // A small MCP Apps view (https://modelcontextprotocol.io/seps/1865-mcp-apps-interactive-user-interfaces-for-mcp):
57
57
  // it speaks JSON-RPC to the host over postMessage and shows what the tool returned.
58
58
  var PROTOCOL = "2026-01-26";
59
- var nextId = 1, pending = {}, args = {}, current = null, pollToken = 0, started = 0, ticker = null;
59
+ var nextId = 1, pending = {}, args = {}, current = null, pollToken = 0, started = 0, ticker = null, hostCaps = null;
60
60
  var $ = function (id) { return document.getElementById(id); };
61
61
 
62
62
  function send(msg) { try { window.parent.postMessage(msg, "*"); } catch (e) {} }
@@ -78,7 +78,11 @@
78
78
  var p = pending[m.id];
79
79
  if (!p) return;
80
80
  delete pending[m.id];
81
- if (m.error) p.reject(new Error(m.error.message || "error")); else p.resolve(m.result);
81
+ if (m.error) {
82
+ var err = new Error(m.error.message || "error");
83
+ err.code = m.error.code;
84
+ p.reject(err);
85
+ } else p.resolve(m.result);
82
86
  return;
83
87
  }
84
88
  if (m.method === "ui/notifications/tool-input") { args = (m.params && m.params.arguments) || {}; showPrompt(); }
@@ -251,7 +255,9 @@
251
255
  var label = el("span", "", "Generating…");
252
256
  w.appendChild(label); body.appendChild(w);
253
257
  started = started || Date.now();
254
- var tick = function () { var s = Math.round((Date.now() - started) / 1000); label.textContent = "Generating… " + s + " s. Video can take a few minutes."; };
258
+ // Only a video run says it can take minutes; images and audio finish much sooner.
259
+ var isVideo = /video|t2v|i2v/i.test(String(d.model || ""));
260
+ var tick = function () { var s = Math.round((Date.now() - started) / 1000); label.textContent = "Generating… " + s + " s." + (isVideo ? " Video can take a few minutes." : ""); };
255
261
  tick(); ticker = setInterval(tick, 1000);
256
262
  setState(d.status);
257
263
  } else if (d.note) {
@@ -272,6 +278,28 @@
272
278
  resize();
273
279
  }
274
280
 
281
+ // The card can no longer follow the run (the host refused its tool call, or it gave up): stop the timer and
282
+ // the spinner so it does not look as if it is still generating, and say where the result will appear.
283
+ function stopFollowing(message) {
284
+ clearInterval(ticker);
285
+ var body = $("body");
286
+ if (!(current && (current.outputs || []).length)) {
287
+ body.textContent = "";
288
+ body.appendChild(el("p", "", "Started. This card stops here; the result appears when the assistant checks on the run."));
289
+ setState("submitted");
290
+ }
291
+ $("note").textContent = message; $("note").hidden = false; resize();
292
+ }
293
+
294
+ // Say what actually went wrong when the host refused the card's tool call, so it can be told apart from a timeout.
295
+ function whyNot(err) {
296
+ if (window.console) console.warn("wavespeed-result: get_prediction failed", err, "hostCapabilities:", hostCaps);
297
+ if (err && err.message === "timeout") return "no answer from this chat in 130 seconds";
298
+ var said = "this chat said: " + ((err && err.message) || "error") + (err && err.code !== undefined ? " [" + err.code + "]" : "");
299
+ if (hostCaps && !hostCaps.serverTools) said += "; it does not declare tool calls for cards";
300
+ return said;
301
+ }
302
+
275
303
  // Keep asking the server while the run is going: this is what turns a video's wait into a card that fills in.
276
304
  function poll(id, token) {
277
305
  var asked = 0;
@@ -286,16 +314,15 @@
286
314
  try { d = JSON.parse(text); } catch (e) {}
287
315
  }
288
316
  if (res && res.isError && !(d && d.error)) d = { error: ((res.content || [])[0] || {}).text || "The run failed." };
289
- if (!d) { $("note").textContent = "Still running. Ask the assistant to check on it."; $("note").hidden = false; return; }
317
+ if (!d) { stopFollowing("Still running. Ask the assistant to check on it."); return; }
290
318
  if (d.error || d.done || ["completed", "failed", "cancelled", "timeout", "deleted"].indexOf(d.status) >= 0) {
291
319
  if (d.status && d.status !== "completed" && !d.error) d.error = "Prediction " + d.status + (d.error ? ": " + d.error : "");
292
320
  current = d; render(d); return;
293
321
  }
294
- if (asked < 80) again(); else { $("note").textContent = "Still running on the server. Ask the assistant to check on it."; $("note").hidden = false; }
295
- }).catch(function () {
322
+ if (asked < 80) again(); else stopFollowing("Still running on the server. Ask the assistant to check on it.");
323
+ }).catch(function (err) {
296
324
  if (token !== pollToken) return;
297
- $("note").textContent = "This chat cannot refresh the card by itself. Ask the assistant to check on the run.";
298
- $("note").hidden = false; resize();
325
+ stopFollowing("The card could not check on the run (" + whyNot(err) + "). Ask the assistant to check on it.");
299
326
  });
300
327
  })();
301
328
  }
@@ -311,7 +338,7 @@
311
338
 
312
339
  // Handshake with the host, then wait for tool-input and tool-result.
313
340
  request("ui/initialize", { protocolVersion: PROTOCOL, appInfo: { name: "wavespeed-result", version: "1.0.0" }, appCapabilities: {} })
314
- .then(function (r) { if (r && r.hostContext) applyContext(r.hostContext); notify("ui/notifications/initialized", {}); })
341
+ .then(function (r) { hostCaps = (r && r.hostCapabilities) || {}; if (r && r.hostContext) applyContext(r.hostContext); notify("ui/notifications/initialized", {}); })
315
342
  .catch(function () { notify("ui/notifications/initialized", {}); });
316
343
 
317
344
  // ChatGPT's own bridge, when the host offers it instead of the standard messages.
package/dist/server.js CHANGED
@@ -160,7 +160,16 @@ function ok(payload) {
160
160
  return res;
161
161
  }
162
162
  export function createServer() {
163
- const server = new McpServer({ name: 'wavespeed', version: PKG_VERSION }, {
163
+ const server = new McpServer({
164
+ name: 'wavespeed',
165
+ title: 'WaveSpeed',
166
+ version: PKG_VERSION,
167
+ websiteUrl: 'https://wavespeed.ai',
168
+ icons: [
169
+ { src: 'https://wavespeed.ai/favicon.svg', mimeType: 'image/svg+xml', sizes: ['any'] },
170
+ { src: 'https://wavespeed.ai/apple-touch-icon.png', mimeType: 'image/png', sizes: ['192x192'] },
171
+ ],
172
+ }, {
164
173
  instructions: [
165
174
  'WaveSpeed AI media generation (image, video, audio, 3D).',
166
175
  'Pattern: list_models to find a model, get_model_schema to see its',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavespeed/mcp",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "WaveSpeed MCP server — run any model on the live WaveSpeed catalog (image, video, audio, 3D) with schema introspection, local-file upload, and price quotes.",
5
5
  "type": "module",
6
6
  "bin": {