@wavespeed/mcp 1.0.9 → 1.0.11

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/README.md CHANGED
@@ -43,6 +43,30 @@ Some generations take minutes to hours. `run_model` waits up to `wait_seconds` (
43
43
 
44
44
  ## Setup
45
45
 
46
+ ### Remote (nothing to install)
47
+
48
+ The same server is hosted at:
49
+
50
+ ```text
51
+ https://api.wavespeed.ai/mcp
52
+ ```
53
+
54
+ - **Claude on the web / ChatGPT:** add a custom connector with that address and approve the connection on the WaveSpeed page that opens. Approving creates a dedicated API key (named `MCP · <app>`) that you can delete on the [API Keys](https://wavespeed.ai/accesskey) page to disconnect.
55
+ - **Claude Code:** `claude mcp add --transport http wavespeed https://api.wavespeed.ai/mcp`
56
+ - **Cursor:**
57
+ <a href="https://cursor.com/install-mcp?name=wavespeed&config=eyJ1cmwiOiJodHRwczovL2FwaS53YXZlc3BlZWQuYWkvbWNwIn0%3D">
58
+ <picture>
59
+ <source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/deeplink/mcp-install-light.svg">
60
+ <img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Add the hosted wavespeed MCP server to Cursor" height="32"/>
61
+ </picture>
62
+ </a>
63
+ - **VS Code:** `code --add-mcp '{"name":"wavespeed","type":"http","url":"https://api.wavespeed.ai/mcp"}'`
64
+ - **Any other client that sends request headers:** point it at the URL with `Authorization: Bearer <your API key>`.
65
+
66
+ The hosted server has the same tools except for files: it cannot read files on your computer, so pass public URLs, or use `create_upload` from a tool that can send HTTP requests (it returns a temporary upload address and the `download_url` to use as an input). Full guide: [wavespeed.ai/docs/mcp](https://wavespeed.ai/docs/mcp).
67
+
68
+ ### Local (npx)
69
+
46
70
  Auth resolves from `WAVESPEED_API_KEY`, or from the CLI's stored login (`wavespeed login`) — one login covers both tools. Keys: [wavespeed.ai/accesskey](https://wavespeed.ai/accesskey).
47
71
 
48
72
  **Claude Code**
package/dist/lib/api.js CHANGED
@@ -77,9 +77,12 @@ function authHeaders() {
77
77
  }
78
78
  return { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() };
79
79
  }
80
- // A hung socket would otherwise stall the tool call until the client gives
81
- // up. 30s is far above a healthy read, so it only trips on a dead connection.
82
- const GET_TIMEOUT_MS = 30_000;
80
+ // Per-request timeouts (no overall cap). A hung socket would otherwise stall
81
+ // the tool call. Read-only GETs are far below 30s in practice (result p99.9
82
+ // < 1s); the async submit gets more headroom because a timeout there is an
83
+ // ambiguous outcome, not a clean failure.
84
+ export const GET_TIMEOUT_MS = 30_000;
85
+ export const SUBMIT_TIMEOUT_MS = 60_000;
83
86
  async function apiGetOnce(apiPath) {
84
87
  const res = await fetch(`${getBaseUrl()}${apiPath}`, {
85
88
  headers: authHeaders(),
@@ -119,11 +122,12 @@ async function apiGet(apiPath, opts = {}) {
119
122
  }
120
123
  }
121
124
  }
122
- async function apiPost(apiPath, body) {
125
+ async function apiPost(apiPath, body, opts = {}) {
123
126
  const res = await fetch(`${getBaseUrl()}${apiPath}`, {
124
127
  method: 'POST',
125
128
  headers: { ...authHeaders(), 'Content-Type': 'application/json' },
126
129
  body: JSON.stringify(body),
130
+ signal: opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined,
127
131
  });
128
132
  if (!res.ok)
129
133
  throw await httpError(res, 'POST', apiPath);
@@ -168,7 +172,16 @@ export async function fetchPricing(modelId, inputs) {
168
172
  * mid-generation must never orphan a paid task.
169
173
  */
170
174
  export async function submitPrediction(model, input) {
171
- return apiPost(`/api/v3/${model}`, { ...input });
175
+ try {
176
+ return await apiPost(`/api/v3/${model}`, { ...input }, { timeoutMs: SUBMIT_TIMEOUT_MS });
177
+ }
178
+ catch (err) {
179
+ // Never retried: the server may already have created (and billed) the task.
180
+ if (err?.name === 'TimeoutError') {
181
+ throw new Error(`Submission outcome unknown: no response within ${SUBMIT_TIMEOUT_MS / 1000}s. The task may have been created and billed — do not resubmit blindly; if you have a prediction id, check it with get_prediction.`);
182
+ }
183
+ throw err;
184
+ }
172
185
  }
173
186
  // The message always carries the task id and says the task was not declared
174
187
  // failed — a status read that dies after submit must not look like a lost
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavespeed/mcp",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
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": {
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "@modelcontextprotocol/sdk": "^1.12.0",
42
- "wavespeed": "^0.3.2",
42
+ "wavespeed": "^0.3.4",
43
43
  "zod": "^3.24.0"
44
44
  },
45
45
  "devDependencies": {