@runpod/mcp-server 1.3.0 → 1.4.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.
package/dist/stdio.cjs CHANGED
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
9
16
  var __copyProps = (to, from, except, desc) => {
10
17
  if (from && typeof from === "object" || typeof from === "function") {
11
18
  for (let key of __getOwnPropNames(from))
@@ -23,13 +30,425 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
30
  mod
24
31
  ));
25
32
 
33
+ // src/install/clients.ts
34
+ function localServerConfig(apiKey, serverProperty) {
35
+ const config = {
36
+ command: "npx",
37
+ args: ["-y", NPM_PACKAGE],
38
+ env: { RUNPOD_API_KEY: apiKey }
39
+ };
40
+ return serverProperty === "servers" ? { type: "stdio", ...config } : config;
41
+ }
42
+ function hostedServerConfig(strategy, serverProperty, url) {
43
+ if (strategy === "mcp-remote") {
44
+ return { command: "npx", args: ["-y", "mcp-remote", url] };
45
+ }
46
+ return serverProperty === "servers" ? { type: "http", url } : { url };
47
+ }
48
+ function upsertJsonServer(configPath, serverProperty, value) {
49
+ try {
50
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
51
+ const content = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf8") : "";
52
+ const edits = jsonc.modify(content, [serverProperty, SERVER_NAME2], value, {
53
+ formattingOptions: { tabSize: 2, insertSpaces: true }
54
+ });
55
+ fs.writeFileSync(configPath, jsonc.applyEdits(content, edits), "utf8");
56
+ return { success: true };
57
+ } catch (error) {
58
+ return { success: false, message: errMessage(error) };
59
+ }
60
+ }
61
+ function removeJsonServer(configPath, serverProperty) {
62
+ try {
63
+ if (!fs.existsSync(configPath)) {
64
+ return { success: true, message: "nothing to remove" };
65
+ }
66
+ const content = fs.readFileSync(configPath, "utf8");
67
+ const edits = jsonc.modify(
68
+ content,
69
+ [serverProperty, SERVER_NAME2],
70
+ void 0,
71
+ { formattingOptions: { tabSize: 2, insertSpaces: true } }
72
+ );
73
+ fs.writeFileSync(configPath, jsonc.applyEdits(content, edits), "utf8");
74
+ return { success: true };
75
+ } catch (error) {
76
+ return { success: false, message: errMessage(error) };
77
+ }
78
+ }
79
+ function errMessage(error) {
80
+ return error instanceof Error ? error.message : String(error);
81
+ }
82
+ function exists(p2) {
83
+ try {
84
+ return fs.existsSync(p2);
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+ function jsonClient(opts) {
90
+ const serverProperty = opts.serverProperty ?? "mcpServers";
91
+ const hostedStrategy = opts.hostedStrategy ?? "http";
92
+ return {
93
+ id: opts.id,
94
+ name: opts.name,
95
+ detect: () => Promise.resolve(
96
+ (opts.detectPaths?.() ?? [path.dirname(opts.configPath())]).some(exists)
97
+ ),
98
+ add: (mode) => {
99
+ const value = mode.kind === "local" ? localServerConfig(mode.apiKey, serverProperty) : hostedServerConfig(hostedStrategy, serverProperty, mode.url);
100
+ return Promise.resolve(
101
+ upsertJsonServer(opts.configPath(), serverProperty, value)
102
+ );
103
+ },
104
+ remove: () => Promise.resolve(removeJsonServer(opts.configPath(), serverProperty)),
105
+ describeTarget: () => opts.configPath()
106
+ };
107
+ }
108
+ function findClaudeBinary() {
109
+ const candidates = [
110
+ path.join(os.homedir(), ".claude", "local", "claude"),
111
+ "/usr/local/bin/claude",
112
+ "/opt/homebrew/bin/claude"
113
+ ];
114
+ for (const candidate of candidates) {
115
+ if (exists(candidate)) return candidate;
116
+ }
117
+ try {
118
+ (0, import_child_process.execSync)("command -v claude", { stdio: "pipe" });
119
+ return "claude";
120
+ } catch {
121
+ return null;
122
+ }
123
+ }
124
+ function runClaude(binary, args) {
125
+ try {
126
+ (0, import_child_process.execFileSync)(binary, args, { stdio: "pipe" });
127
+ return { success: true };
128
+ } catch (error) {
129
+ const message = errMessage(error);
130
+ if (message.includes("already exists")) {
131
+ return { success: true, message: "already configured" };
132
+ }
133
+ return { success: false, message };
134
+ }
135
+ }
136
+ function claudeDesktopConfigPath() {
137
+ if (process.platform === "win32") {
138
+ return path.join(appData, "Claude", "claude_desktop_config.json");
139
+ }
140
+ return path.join(
141
+ home,
142
+ "Library",
143
+ "Application Support",
144
+ "Claude",
145
+ "claude_desktop_config.json"
146
+ );
147
+ }
148
+ function vsCodeConfigPath() {
149
+ if (process.platform === "win32") {
150
+ return path.join(appData, "Code", "User", "mcp.json");
151
+ }
152
+ if (process.platform === "darwin") {
153
+ return path.join(
154
+ home,
155
+ "Library",
156
+ "Application Support",
157
+ "Code",
158
+ "User",
159
+ "mcp.json"
160
+ );
161
+ }
162
+ return path.join(home, ".config", "Code", "User", "mcp.json");
163
+ }
164
+ var fs, os, path, import_child_process, jsonc, SERVER_NAME2, NPM_PACKAGE, HOSTED_URL, claudeCodeClient, home, appData, CLIENTS;
165
+ var init_clients = __esm({
166
+ "src/install/clients.ts"() {
167
+ "use strict";
168
+ fs = __toESM(require("fs"), 1);
169
+ os = __toESM(require("os"), 1);
170
+ path = __toESM(require("path"), 1);
171
+ import_child_process = require("child_process");
172
+ jsonc = __toESM(require("jsonc-parser"), 1);
173
+ SERVER_NAME2 = "runpod";
174
+ NPM_PACKAGE = "@runpod/mcp-server@latest";
175
+ HOSTED_URL = process.env.RUNPOD_MCP_URL ?? "https://mcp.getrunpod.io/";
176
+ claudeCodeClient = {
177
+ id: "claude-code",
178
+ name: "Claude Code",
179
+ detect: () => Promise.resolve(findClaudeBinary() !== null),
180
+ add: (mode) => {
181
+ const binary = findClaudeBinary();
182
+ if (!binary) {
183
+ return Promise.resolve({
184
+ success: false,
185
+ message: "claude CLI not found"
186
+ });
187
+ }
188
+ const args = mode.kind === "local" ? [
189
+ "mcp",
190
+ "add",
191
+ SERVER_NAME2,
192
+ "--scope",
193
+ "user",
194
+ "-e",
195
+ `RUNPOD_API_KEY=${mode.apiKey}`,
196
+ "--",
197
+ "npx",
198
+ "-y",
199
+ NPM_PACKAGE
200
+ ] : [
201
+ "mcp",
202
+ "add",
203
+ "--transport",
204
+ "http",
205
+ "--scope",
206
+ "user",
207
+ SERVER_NAME2,
208
+ mode.url
209
+ ];
210
+ return Promise.resolve(runClaude(binary, args));
211
+ },
212
+ remove: () => {
213
+ const binary = findClaudeBinary();
214
+ if (!binary) {
215
+ return Promise.resolve({
216
+ success: false,
217
+ message: "claude CLI not found"
218
+ });
219
+ }
220
+ try {
221
+ (0, import_child_process.execFileSync)(binary, ["mcp", "remove", "--scope", "user", SERVER_NAME2], {
222
+ stdio: "pipe"
223
+ });
224
+ return Promise.resolve({ success: true });
225
+ } catch (error) {
226
+ return Promise.resolve({ success: true, message: errMessage(error) });
227
+ }
228
+ },
229
+ describeTarget: () => "Claude Code user config (via `claude mcp` CLI)"
230
+ };
231
+ home = os.homedir();
232
+ appData = process.env.APPDATA ?? path.join(home, "AppData", "Roaming");
233
+ CLIENTS = [
234
+ claudeCodeClient,
235
+ jsonClient({
236
+ id: "cursor",
237
+ name: "Cursor",
238
+ configPath: () => path.join(home, ".cursor", "mcp.json")
239
+ }),
240
+ jsonClient({
241
+ id: "windsurf",
242
+ name: "Windsurf",
243
+ // Windsurf is stdio-only, so it reaches the hosted server via mcp-remote.
244
+ hostedStrategy: "mcp-remote",
245
+ configPath: () => path.join(home, ".codeium", "windsurf", "mcp_config.json")
246
+ }),
247
+ jsonClient({
248
+ id: "claude-desktop",
249
+ name: "Claude Desktop",
250
+ // Claude Desktop config files are stdio-only; use the mcp-remote bridge.
251
+ hostedStrategy: "mcp-remote",
252
+ configPath: claudeDesktopConfigPath,
253
+ // Detect by the application/support directory, which exists once the app runs.
254
+ detectPaths: () => [path.dirname(claudeDesktopConfigPath())]
255
+ }),
256
+ jsonClient({
257
+ id: "vscode",
258
+ name: "Visual Studio Code",
259
+ serverProperty: "servers",
260
+ configPath: vsCodeConfigPath,
261
+ detectPaths: () => [path.dirname(vsCodeConfigPath())]
262
+ })
263
+ ];
264
+ }
265
+ });
266
+
267
+ // src/install/wizard.ts
268
+ var wizard_exports = {};
269
+ __export(wizard_exports, {
270
+ runWizard: () => runWizard
271
+ });
272
+ function openBrowser(url) {
273
+ try {
274
+ if (process.platform === "darwin") {
275
+ (0, import_child_process2.execFileSync)("open", [url], { stdio: "ignore" });
276
+ } else if (process.platform === "win32") {
277
+ (0, import_child_process2.execFileSync)("cmd", ["/c", "start", "", url], { stdio: "ignore" });
278
+ } else {
279
+ (0, import_child_process2.execFileSync)("xdg-open", [url], { stdio: "ignore" });
280
+ }
281
+ } catch {
282
+ }
283
+ }
284
+ async function verifyApiKey(apiKey) {
285
+ try {
286
+ const base = process.env.RUNPOD_REST_API_URL ?? "https://rest.runpod.io/v1";
287
+ const response = await fetch(`${base}/pods`, {
288
+ headers: { Authorization: `Bearer ${apiKey}` }
289
+ });
290
+ if (response.ok) return true;
291
+ if (response.status === 401 || response.status === 403) return false;
292
+ return null;
293
+ } catch {
294
+ return null;
295
+ }
296
+ }
297
+ function bail(message = "Cancelled.") {
298
+ p.cancel(message);
299
+ process.exit(0);
300
+ }
301
+ async function promptForApiKey() {
302
+ const fromEnv = process.env.RUNPOD_API_KEY;
303
+ if (fromEnv) {
304
+ const useEnv = await p.confirm({
305
+ message: "Use the RUNPOD_API_KEY from your environment?"
306
+ });
307
+ if (p.isCancel(useEnv)) bail();
308
+ if (useEnv) return fromEnv;
309
+ }
310
+ const create = await p.confirm({
311
+ message: "Open the Runpod console to create or copy an API key?"
312
+ });
313
+ if (p.isCancel(create)) bail();
314
+ if (create) {
315
+ openBrowser(API_KEYS_URL);
316
+ p.log.info(`Opening ${API_KEYS_URL}`);
317
+ }
318
+ const apiKey = await p.password({
319
+ message: "Paste your Runpod API key",
320
+ validate: (value) => !value || value.trim().length === 0 ? "API key cannot be empty" : void 0
321
+ });
322
+ if (p.isCancel(apiKey)) bail();
323
+ return apiKey.trim();
324
+ }
325
+ async function selectClients(detected, verb) {
326
+ const options = CLIENTS.map((client) => ({
327
+ value: client.id,
328
+ label: client.name,
329
+ hint: detected.get(client.id) ? "detected" : void 0
330
+ }));
331
+ const selected = await p.multiselect({
332
+ message: `Which agents should we ${verb}?`,
333
+ options,
334
+ // Pre-select detected clients so the common case is a single Enter press.
335
+ initialValues: CLIENTS.filter((c) => detected.get(c.id)).map((c) => c.id),
336
+ required: true
337
+ });
338
+ if (p.isCancel(selected)) bail();
339
+ return CLIENTS.filter((c) => selected.includes(c.id));
340
+ }
341
+ async function detectAll() {
342
+ const entries = await Promise.all(
343
+ CLIENTS.map(async (c) => [c.id, await c.detect()])
344
+ );
345
+ return new Map(entries);
346
+ }
347
+ async function selectMode() {
348
+ const kind = await p.select({
349
+ message: "How do you want to connect to Runpod?",
350
+ options: [
351
+ {
352
+ value: "hosted",
353
+ label: "Sign in with Runpod (recommended)",
354
+ hint: "hosted, OAuth, no API key stored"
355
+ },
356
+ {
357
+ value: "local",
358
+ label: "Run locally with an API key",
359
+ hint: "runs on this machine via npx"
360
+ }
361
+ ],
362
+ initialValue: "hosted"
363
+ });
364
+ if (p.isCancel(kind)) bail();
365
+ if (kind === "hosted") {
366
+ return { kind: "hosted", url: HOSTED_URL };
367
+ }
368
+ const apiKey = await promptForApiKey();
369
+ const verifySpinner = p.spinner();
370
+ verifySpinner.start("Verifying API key");
371
+ const valid = await verifyApiKey(apiKey);
372
+ if (valid === true) {
373
+ verifySpinner.stop("API key verified.");
374
+ } else if (valid === false) {
375
+ verifySpinner.stop("API key rejected by Runpod.");
376
+ const proceed = await p.confirm({
377
+ message: "The key did not authenticate. Continue anyway?",
378
+ initialValue: false
379
+ });
380
+ if (p.isCancel(proceed) || !proceed) bail();
381
+ } else {
382
+ verifySpinner.stop("Could not verify the key (offline?). Continuing.");
383
+ }
384
+ return { kind: "local", apiKey };
385
+ }
386
+ async function runAdd() {
387
+ const detected = await detectAll();
388
+ const clients = await selectClients(detected, "set up");
389
+ const mode = await selectMode();
390
+ const results = [];
391
+ for (const client of clients) {
392
+ const spinner2 = p.spinner();
393
+ spinner2.start(`Configuring ${client.name}`);
394
+ const result = await client.add(mode);
395
+ if (result.success) {
396
+ spinner2.stop(`${client.name} configured.`);
397
+ results.push(`\u2713 ${client.name} \u2014 ${client.describeTarget()}`);
398
+ } else {
399
+ spinner2.stop(`${client.name} failed.`);
400
+ results.push(`\u2717 ${client.name} \u2014 ${result.message ?? "unknown error"}`);
401
+ }
402
+ }
403
+ p.note(results.join("\n"), "Results");
404
+ p.outro(
405
+ mode.kind === "hosted" ? 'Restart your agent, then complete "Sign in with Runpod" when it connects.' : "Restart your agent (or reconnect MCP) to load the Runpod tools."
406
+ );
407
+ }
408
+ async function runRemove() {
409
+ const detected = await detectAll();
410
+ const clients = await selectClients(detected, "remove Runpod from");
411
+ const results = [];
412
+ for (const client of clients) {
413
+ const spinner2 = p.spinner();
414
+ spinner2.start(`Removing from ${client.name}`);
415
+ const result = await client.remove();
416
+ spinner2.stop(
417
+ result.success ? `${client.name} cleaned up.` : `${client.name} failed.`
418
+ );
419
+ results.push(
420
+ `${result.success ? "\u2713" : "\u2717"} ${client.name}${result.message ? ` \u2014 ${result.message}` : ""}`
421
+ );
422
+ }
423
+ p.note(results.join("\n"), "Results");
424
+ p.outro("Done.");
425
+ }
426
+ async function runWizard(subcommand2) {
427
+ p.intro("Runpod MCP server installer");
428
+ if (subcommand2 === "remove") {
429
+ await runRemove();
430
+ } else {
431
+ await runAdd();
432
+ }
433
+ }
434
+ var import_child_process2, p, API_KEYS_URL;
435
+ var init_wizard = __esm({
436
+ "src/install/wizard.ts"() {
437
+ "use strict";
438
+ import_child_process2 = require("child_process");
439
+ p = __toESM(require("@clack/prompts"), 1);
440
+ init_clients();
441
+ API_KEYS_URL = "https://www.runpod.io/console/user/settings";
442
+ }
443
+ });
444
+
26
445
  // src/stdio.ts
27
446
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
28
447
 
29
448
  // src/server.ts
30
449
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
31
450
  var SERVER_NAME = "Runpod API Server";
32
- var SERVER_VERSION = true ? "1.3.0" : "dev";
451
+ var SERVER_VERSION = true ? "1.4.0" : "dev";
33
452
  function createServer(version = SERVER_VERSION) {
34
453
  return new import_mcp.McpServer({
35
454
  name: SERVER_NAME,
@@ -42,19 +461,78 @@ function createServer(version = SERVER_VERSION) {
42
461
  }
43
462
 
44
463
  // src/tools.ts
45
- var import_zod = require("zod");
464
+ var import_zod2 = require("zod");
46
465
  var import_node_fetch = __toESM(require("node-fetch"), 1);
47
466
  var import_node_crypto = require("crypto");
467
+
468
+ // src/pagination.ts
469
+ var import_zod = require("zod");
470
+ var DEFAULT_LIST_LIMIT = 20;
471
+ var MAX_LIST_LIMIT = 100;
472
+ var listPaginationParams = {
473
+ limit: import_zod.z.number().int().positive().max(MAX_LIST_LIMIT).optional().describe(
474
+ `Maximum number of items to return (default ${DEFAULT_LIST_LIMIT}, max ${MAX_LIST_LIMIT}). Use the returned nextCursor to fetch the next page.`
475
+ ),
476
+ cursor: import_zod.z.string().optional().describe(
477
+ "Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning."
478
+ )
479
+ };
480
+ function decodeCursorOffset(cursor) {
481
+ if (!cursor) return 0;
482
+ try {
483
+ const decoded = Buffer.from(cursor, "base64").toString("utf8");
484
+ const offset = Number.parseInt(decoded, 10);
485
+ return Number.isFinite(offset) && offset >= 0 ? offset : 0;
486
+ } catch {
487
+ return 0;
488
+ }
489
+ }
490
+ function encodeCursorOffset(offset) {
491
+ return Buffer.from(String(offset), "utf8").toString("base64");
492
+ }
493
+ function capListResult(result, options) {
494
+ const limit = Math.min(options.limit ?? DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT);
495
+ const offset = decodeCursorOffset(options.cursor);
496
+ if (!Array.isArray(result)) {
497
+ return {
498
+ content: [
499
+ { type: "text", text: JSON.stringify(result, null, 2) }
500
+ ]
501
+ };
502
+ }
503
+ const total = result.length;
504
+ const page = result.slice(offset, offset + limit);
505
+ const nextOffset = offset + page.length;
506
+ const hasMore = nextOffset < total;
507
+ const envelope = {
508
+ items: page,
509
+ pagination: {
510
+ total,
511
+ returned: page.length,
512
+ offset,
513
+ truncated: hasMore,
514
+ nextCursor: hasMore ? encodeCursorOffset(nextOffset) : null,
515
+ note: hasMore ? `Showing ${page.length} of ${total}. Pass cursor=nextCursor to fetch more, or narrow the query with filters.` : void 0
516
+ }
517
+ };
518
+ return {
519
+ content: [
520
+ { type: "text", text: JSON.stringify(envelope, null, 2) }
521
+ ]
522
+ };
523
+ }
524
+
525
+ // src/tools.ts
48
526
  var API_BASE_URL = process.env.RUNPOD_REST_API_URL ?? "https://rest.runpod.io/v1";
49
527
  var SERVERLESS_API_BASE_URL = process.env.RUNPOD_SERVERLESS_API_URL ?? "https://api.runpod.ai/v2";
50
528
  var GRAPHQL_URL = process.env.RUNPOD_PUBLIC_GRAPHQL_URL ?? "https://api.runpod.io/graphql";
51
- var MCP_SERVER_VERSION = true ? "1.3.0" : "dev";
529
+ var MCP_SERVER_VERSION = true ? "1.4.0" : "dev";
52
530
  var SESSION_ID = (0, import_node_crypto.randomUUID)();
53
531
  function sanitizeUaToken(value) {
54
532
  return value.replace(/[()<>@,;:\\"/[\]?={}\s]/g, "_").slice(0, 64);
55
533
  }
56
- function trackingHeaders(server2, ctx) {
57
- const info = server2.server.getClientVersion();
534
+ function trackingHeaders(server, ctx) {
535
+ const info = server.server.getClientVersion();
58
536
  const fallbackName = ctx.clientUserAgent || "unknown";
59
537
  const name = sanitizeUaToken(info?.name || fallbackName);
60
538
  const version = sanitizeUaToken(info?.version || "unknown");
@@ -118,8 +596,8 @@ function createRunpodRequest(apiKey, tracking) {
118
596
  };
119
597
  }
120
598
  function createServerlessRequest(apiKey, tracking) {
121
- return async function serverlessRequest(endpointId, path, method = "GET", body) {
122
- const url = `${SERVERLESS_API_BASE_URL}/${endpointId}${path}`;
599
+ return async function serverlessRequest(endpointId, path2, method = "GET", body) {
600
+ const url = `${SERVERLESS_API_BASE_URL}/${endpointId}${path2}`;
123
601
  const headers = {
124
602
  Authorization: `Bearer ${apiKey}`,
125
603
  "Content-Type": "application/json",
@@ -151,20 +629,20 @@ function createServerlessRequest(apiKey, tracking) {
151
629
  }
152
630
  };
153
631
  }
154
- function registerTools(server2, ctx) {
155
- const tracking = () => trackingHeaders(server2, ctx);
632
+ function registerTools(server, ctx) {
633
+ const tracking = () => trackingHeaders(server, ctx);
156
634
  const runpodRequest = createRunpodRequest(ctx.apiKey, tracking);
157
635
  const serverlessRequest = createServerlessRequest(ctx.apiKey, tracking);
158
- server2.tool(
636
+ server.tool(
159
637
  "list-gpu-types",
160
638
  {
161
- minMemoryGb: import_zod.z.number().optional().describe("Filter to GPUs with at least this much VRAM in GB"),
162
- secureCloudOnly: import_zod.z.boolean().optional().describe("Filter to only GPUs available in secure cloud"),
163
- communityCloudOnly: import_zod.z.boolean().optional().describe("Filter to only GPUs available in community cloud"),
164
- searchTerm: import_zod.z.string().optional().describe(
639
+ minMemoryGb: import_zod2.z.number().optional().describe("Filter to GPUs with at least this much VRAM in GB"),
640
+ secureCloudOnly: import_zod2.z.boolean().optional().describe("Filter to only GPUs available in secure cloud"),
641
+ communityCloudOnly: import_zod2.z.boolean().optional().describe("Filter to only GPUs available in community cloud"),
642
+ searchTerm: import_zod2.z.string().optional().describe(
165
643
  "Search term to filter GPUs by name (e.g., 'A100', 'RTX 4090')"
166
644
  ),
167
- includeUnavailable: import_zod.z.boolean().optional().describe(
645
+ includeUnavailable: import_zod2.z.boolean().optional().describe(
168
646
  "Include GPUs that are currently out of stock. Default is false"
169
647
  )
170
648
  },
@@ -241,10 +719,10 @@ function registerTools(server2, ctx) {
241
719
  };
242
720
  }
243
721
  );
244
- server2.tool(
722
+ server.tool(
245
723
  "list-data-centers",
246
724
  {
247
- region: import_zod.z.string().optional().describe(
725
+ region: import_zod2.z.string().optional().describe(
248
726
  "Filter by region/location (e.g., 'United States', 'Europe', 'Canada')"
249
727
  )
250
728
  },
@@ -278,15 +756,16 @@ function registerTools(server2, ctx) {
278
756
  };
279
757
  }
280
758
  );
281
- server2.tool(
759
+ server.tool(
282
760
  "list-pods",
283
761
  {
284
- computeType: import_zod.z.enum(["GPU", "CPU"]).optional().describe("Filter to only GPU or only CPU Pods"),
285
- gpuTypeId: import_zod.z.array(import_zod.z.string()).optional().describe("Filter to Pods with any of the listed GPU types"),
286
- dataCenterId: import_zod.z.array(import_zod.z.string()).optional().describe("Filter to Pods in any of the provided data centers"),
287
- name: import_zod.z.string().optional().describe("Filter to Pods with the provided name"),
288
- includeMachine: import_zod.z.boolean().optional().describe("Include information about the machine"),
289
- includeNetworkVolume: import_zod.z.boolean().optional().describe("Include information about attached network volumes")
762
+ ...listPaginationParams,
763
+ computeType: import_zod2.z.enum(["GPU", "CPU"]).optional().describe("Filter to only GPU or only CPU Pods"),
764
+ gpuTypeId: import_zod2.z.array(import_zod2.z.string()).optional().describe("Filter to Pods with any of the listed GPU types"),
765
+ dataCenterId: import_zod2.z.array(import_zod2.z.string()).optional().describe("Filter to Pods in any of the provided data centers"),
766
+ name: import_zod2.z.string().optional().describe("Filter to Pods with the provided name"),
767
+ includeMachine: import_zod2.z.boolean().optional().describe("Include information about the machine"),
768
+ includeNetworkVolume: import_zod2.z.boolean().optional().describe("Include information about attached network volumes")
290
769
  },
291
770
  async (params) => {
292
771
  const queryParams = new URLSearchParams();
@@ -310,22 +789,18 @@ function registerTools(server2, ctx) {
310
789
  );
311
790
  const queryString = queryParams.toString() ? `?${queryParams.toString()}` : "";
312
791
  const result = await runpodRequest(`/pods${queryString}`);
313
- return {
314
- content: [
315
- {
316
- type: "text",
317
- text: JSON.stringify(result, null, 2)
318
- }
319
- ]
320
- };
792
+ return capListResult(result, {
793
+ limit: params.limit,
794
+ cursor: params.cursor
795
+ });
321
796
  }
322
797
  );
323
- server2.tool(
798
+ server.tool(
324
799
  "get-pod",
325
800
  {
326
- podId: import_zod.z.string().describe("ID of the pod to retrieve"),
327
- includeMachine: import_zod.z.boolean().optional().describe("Include information about the machine"),
328
- includeNetworkVolume: import_zod.z.boolean().optional().describe("Include information about attached network volumes")
801
+ podId: import_zod2.z.string().describe("ID of the pod to retrieve"),
802
+ includeMachine: import_zod2.z.boolean().optional().describe("Include information about the machine"),
803
+ includeNetworkVolume: import_zod2.z.boolean().optional().describe("Include information about attached network volumes")
329
804
  },
330
805
  async (params) => {
331
806
  const queryParams = new URLSearchParams();
@@ -348,21 +823,21 @@ function registerTools(server2, ctx) {
348
823
  };
349
824
  }
350
825
  );
351
- server2.tool(
826
+ server.tool(
352
827
  "create-pod",
353
828
  'Create a new GPU/CPU pod on Runpod. If the user does not specify an image, recommend the "Runpod Pytorch 2.8.0" image (runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404) as the default \u2014 it has the most up-to-date CUDA and PyTorch versions.',
354
829
  {
355
- name: import_zod.z.string().optional().describe("Name for the pod"),
356
- imageName: import_zod.z.string().describe("Docker image to use"),
357
- cloudType: import_zod.z.enum(["SECURE", "COMMUNITY"]).optional().describe("SECURE or COMMUNITY cloud"),
358
- gpuTypeIds: import_zod.z.array(import_zod.z.string()).optional().describe("List of acceptable GPU types"),
359
- gpuCount: import_zod.z.number().optional().describe("Number of GPUs"),
360
- containerDiskInGb: import_zod.z.number().optional().describe("Container disk size in GB"),
361
- volumeInGb: import_zod.z.number().optional().describe("Volume size in GB"),
362
- volumeMountPath: import_zod.z.string().optional().describe("Path to mount the volume"),
363
- ports: import_zod.z.array(import_zod.z.string()).optional().describe("Ports to expose (e.g., '8888/http', '22/tcp')"),
364
- env: import_zod.z.record(import_zod.z.string()).optional().describe("Environment variables"),
365
- dataCenterIds: import_zod.z.array(import_zod.z.string()).optional().describe("List of data centers")
830
+ name: import_zod2.z.string().optional().describe("Name for the pod"),
831
+ imageName: import_zod2.z.string().describe("Docker image to use"),
832
+ cloudType: import_zod2.z.enum(["SECURE", "COMMUNITY"]).optional().describe("SECURE or COMMUNITY cloud"),
833
+ gpuTypeIds: import_zod2.z.array(import_zod2.z.string()).optional().describe("List of acceptable GPU types"),
834
+ gpuCount: import_zod2.z.number().optional().describe("Number of GPUs"),
835
+ containerDiskInGb: import_zod2.z.number().optional().describe("Container disk size in GB"),
836
+ volumeInGb: import_zod2.z.number().optional().describe("Volume size in GB"),
837
+ volumeMountPath: import_zod2.z.string().optional().describe("Path to mount the volume"),
838
+ ports: import_zod2.z.array(import_zod2.z.string()).optional().describe("Ports to expose (e.g., '8888/http', '22/tcp')"),
839
+ env: import_zod2.z.record(import_zod2.z.string()).optional().describe("Environment variables"),
840
+ dataCenterIds: import_zod2.z.array(import_zod2.z.string()).optional().describe("List of data centers")
366
841
  },
367
842
  async (params) => {
368
843
  const result = await runpodRequest("/pods", "POST", params);
@@ -376,17 +851,17 @@ function registerTools(server2, ctx) {
376
851
  };
377
852
  }
378
853
  );
379
- server2.tool(
854
+ server.tool(
380
855
  "update-pod",
381
856
  {
382
- podId: import_zod.z.string().describe("ID of the pod to update"),
383
- name: import_zod.z.string().optional().describe("New name for the pod"),
384
- imageName: import_zod.z.string().optional().describe("New Docker image"),
385
- containerDiskInGb: import_zod.z.number().optional().describe("New container disk size in GB"),
386
- volumeInGb: import_zod.z.number().optional().describe("New volume size in GB"),
387
- volumeMountPath: import_zod.z.string().optional().describe("New path to mount the volume"),
388
- ports: import_zod.z.array(import_zod.z.string()).optional().describe("New ports to expose"),
389
- env: import_zod.z.record(import_zod.z.string()).optional().describe("New environment variables")
857
+ podId: import_zod2.z.string().describe("ID of the pod to update"),
858
+ name: import_zod2.z.string().optional().describe("New name for the pod"),
859
+ imageName: import_zod2.z.string().optional().describe("New Docker image"),
860
+ containerDiskInGb: import_zod2.z.number().optional().describe("New container disk size in GB"),
861
+ volumeInGb: import_zod2.z.number().optional().describe("New volume size in GB"),
862
+ volumeMountPath: import_zod2.z.string().optional().describe("New path to mount the volume"),
863
+ ports: import_zod2.z.array(import_zod2.z.string()).optional().describe("New ports to expose"),
864
+ env: import_zod2.z.record(import_zod2.z.string()).optional().describe("New environment variables")
390
865
  },
391
866
  async (params) => {
392
867
  const { podId, ...updateParams } = params;
@@ -405,10 +880,10 @@ function registerTools(server2, ctx) {
405
880
  };
406
881
  }
407
882
  );
408
- server2.tool(
883
+ server.tool(
409
884
  "start-pod",
410
885
  {
411
- podId: import_zod.z.string().describe("ID of the pod to start")
886
+ podId: import_zod2.z.string().describe("ID of the pod to start")
412
887
  },
413
888
  async (params) => {
414
889
  const result = await runpodRequest(`/pods/${params.podId}/start`, "POST");
@@ -422,10 +897,10 @@ function registerTools(server2, ctx) {
422
897
  };
423
898
  }
424
899
  );
425
- server2.tool(
900
+ server.tool(
426
901
  "stop-pod",
427
902
  {
428
- podId: import_zod.z.string().describe("ID of the pod to stop")
903
+ podId: import_zod2.z.string().describe("ID of the pod to stop")
429
904
  },
430
905
  async (params) => {
431
906
  const result = await runpodRequest(`/pods/${params.podId}/stop`, "POST");
@@ -439,10 +914,10 @@ function registerTools(server2, ctx) {
439
914
  };
440
915
  }
441
916
  );
442
- server2.tool(
917
+ server.tool(
443
918
  "delete-pod",
444
919
  {
445
- podId: import_zod.z.string().describe("ID of the pod to delete")
920
+ podId: import_zod2.z.string().describe("ID of the pod to delete")
446
921
  },
447
922
  async (params) => {
448
923
  const result = await runpodRequest(`/pods/${params.podId}`, "DELETE");
@@ -456,11 +931,12 @@ function registerTools(server2, ctx) {
456
931
  };
457
932
  }
458
933
  );
459
- server2.tool(
934
+ server.tool(
460
935
  "list-endpoints",
461
936
  {
462
- includeTemplate: import_zod.z.boolean().optional().describe("Include template information"),
463
- includeWorkers: import_zod.z.boolean().optional().describe("Include information about workers")
937
+ ...listPaginationParams,
938
+ includeTemplate: import_zod2.z.boolean().optional().describe("Include template information"),
939
+ includeWorkers: import_zod2.z.boolean().optional().describe("Include information about workers")
464
940
  },
465
941
  async (params) => {
466
942
  const queryParams = new URLSearchParams();
@@ -473,22 +949,18 @@ function registerTools(server2, ctx) {
473
949
  queryParams.append("includeWorkers", params.includeWorkers.toString());
474
950
  const queryString = queryParams.toString() ? `?${queryParams.toString()}` : "";
475
951
  const result = await runpodRequest(`/endpoints${queryString}`);
476
- return {
477
- content: [
478
- {
479
- type: "text",
480
- text: JSON.stringify(result, null, 2)
481
- }
482
- ]
483
- };
952
+ return capListResult(result, {
953
+ limit: params.limit,
954
+ cursor: params.cursor
955
+ });
484
956
  }
485
957
  );
486
- server2.tool(
958
+ server.tool(
487
959
  "get-endpoint",
488
960
  {
489
- endpointId: import_zod.z.string().describe("ID of the endpoint to retrieve"),
490
- includeTemplate: import_zod.z.boolean().optional().describe("Include template information"),
491
- includeWorkers: import_zod.z.boolean().optional().describe("Include information about workers")
961
+ endpointId: import_zod2.z.string().describe("ID of the endpoint to retrieve"),
962
+ includeTemplate: import_zod2.z.boolean().optional().describe("Include template information"),
963
+ includeWorkers: import_zod2.z.boolean().optional().describe("Include information about workers")
492
964
  },
493
965
  async (params) => {
494
966
  const queryParams = new URLSearchParams();
@@ -513,17 +985,17 @@ function registerTools(server2, ctx) {
513
985
  };
514
986
  }
515
987
  );
516
- server2.tool(
988
+ server.tool(
517
989
  "create-endpoint",
518
990
  {
519
- name: import_zod.z.string().optional().describe("Name for the endpoint"),
520
- templateId: import_zod.z.string().describe("Template ID to use"),
521
- computeType: import_zod.z.enum(["GPU", "CPU"]).optional().describe("GPU or CPU endpoint"),
522
- gpuTypeIds: import_zod.z.array(import_zod.z.string()).optional().describe("List of acceptable GPU types"),
523
- gpuCount: import_zod.z.number().optional().describe("Number of GPUs per worker"),
524
- workersMin: import_zod.z.number().optional().describe("Minimum number of workers"),
525
- workersMax: import_zod.z.number().optional().describe("Maximum number of workers"),
526
- dataCenterIds: import_zod.z.array(import_zod.z.string()).optional().describe("List of data centers")
991
+ name: import_zod2.z.string().optional().describe("Name for the endpoint"),
992
+ templateId: import_zod2.z.string().describe("Template ID to use"),
993
+ computeType: import_zod2.z.enum(["GPU", "CPU"]).optional().describe("GPU or CPU endpoint"),
994
+ gpuTypeIds: import_zod2.z.array(import_zod2.z.string()).optional().describe("List of acceptable GPU types"),
995
+ gpuCount: import_zod2.z.number().optional().describe("Number of GPUs per worker"),
996
+ workersMin: import_zod2.z.number().optional().describe("Minimum number of workers"),
997
+ workersMax: import_zod2.z.number().optional().describe("Maximum number of workers"),
998
+ dataCenterIds: import_zod2.z.array(import_zod2.z.string()).optional().describe("List of data centers")
527
999
  },
528
1000
  async (params) => {
529
1001
  const result = await runpodRequest("/endpoints", "POST", params);
@@ -537,16 +1009,16 @@ function registerTools(server2, ctx) {
537
1009
  };
538
1010
  }
539
1011
  );
540
- server2.tool(
1012
+ server.tool(
541
1013
  "update-endpoint",
542
1014
  {
543
- endpointId: import_zod.z.string().describe("ID of the endpoint to update"),
544
- name: import_zod.z.string().optional().describe("New name for the endpoint"),
545
- workersMin: import_zod.z.number().optional().describe("New minimum number of workers"),
546
- workersMax: import_zod.z.number().optional().describe("New maximum number of workers"),
547
- idleTimeout: import_zod.z.number().optional().describe("New idle timeout in seconds"),
548
- scalerType: import_zod.z.enum(["QUEUE_DELAY", "REQUEST_COUNT"]).optional().describe("Scaler type"),
549
- scalerValue: import_zod.z.number().optional().describe("Scaler value")
1015
+ endpointId: import_zod2.z.string().describe("ID of the endpoint to update"),
1016
+ name: import_zod2.z.string().optional().describe("New name for the endpoint"),
1017
+ workersMin: import_zod2.z.number().optional().describe("New minimum number of workers"),
1018
+ workersMax: import_zod2.z.number().optional().describe("New maximum number of workers"),
1019
+ idleTimeout: import_zod2.z.number().optional().describe("New idle timeout in seconds"),
1020
+ scalerType: import_zod2.z.enum(["QUEUE_DELAY", "REQUEST_COUNT"]).optional().describe("Scaler type"),
1021
+ scalerValue: import_zod2.z.number().optional().describe("Scaler value")
550
1022
  },
551
1023
  async (params) => {
552
1024
  const { endpointId, ...updateParams } = params;
@@ -565,10 +1037,10 @@ function registerTools(server2, ctx) {
565
1037
  };
566
1038
  }
567
1039
  );
568
- server2.tool(
1040
+ server.tool(
569
1041
  "delete-endpoint",
570
1042
  {
571
- endpointId: import_zod.z.string().describe("ID of the endpoint to delete")
1043
+ endpointId: import_zod2.z.string().describe("ID of the endpoint to delete")
572
1044
  },
573
1045
  async (params) => {
574
1046
  const result = await runpodRequest(
@@ -585,26 +1057,26 @@ function registerTools(server2, ctx) {
585
1057
  };
586
1058
  }
587
1059
  );
588
- const endpointIdSchema = import_zod.z.string().regex(/^[a-zA-Z0-9_-]+$/, "Invalid endpoint ID format");
589
- const jobIdSchema = import_zod.z.string().regex(/^[a-zA-Z0-9_-]+$/, "Invalid job ID format");
590
- const inputSchema = import_zod.z.record(import_zod.z.unknown()).describe(
1060
+ const endpointIdSchema = import_zod2.z.string().regex(/^[a-zA-Z0-9_-]+$/, "Invalid endpoint ID format");
1061
+ const jobIdSchema = import_zod2.z.string().regex(/^[a-zA-Z0-9_-]+$/, "Invalid job ID format");
1062
+ const inputSchema = import_zod2.z.record(import_zod2.z.unknown()).describe(
591
1063
  "Input payload for the worker handler. The expected fields depend on the deployed model or worker."
592
1064
  );
593
- const webhookSchema = import_zod.z.string().url().optional().describe(
1065
+ const webhookSchema = import_zod2.z.string().url().optional().describe(
594
1066
  "Webhook URL to receive job completion notifications instead of polling"
595
1067
  );
596
- const policySchema = import_zod.z.object({
597
- executionTimeout: import_zod.z.number().optional().describe("Maximum execution time in milliseconds"),
598
- lowPriority: import_zod.z.boolean().optional().describe("Submit as a low-priority job"),
599
- ttl: import_zod.z.number().optional().describe("Time-to-live for the job result in milliseconds")
1068
+ const policySchema = import_zod2.z.object({
1069
+ executionTimeout: import_zod2.z.number().optional().describe("Maximum execution time in milliseconds"),
1070
+ lowPriority: import_zod2.z.boolean().optional().describe("Submit as a low-priority job"),
1071
+ ttl: import_zod2.z.number().optional().describe("Time-to-live for the job result in milliseconds")
600
1072
  }).optional().describe("Execution policy options");
601
- const s3ConfigSchema = import_zod.z.object({
602
- accessId: import_zod.z.string().describe("S3 access key ID"),
603
- accessSecret: import_zod.z.string().describe("S3 secret access key"),
604
- bucketName: import_zod.z.string().describe("S3 bucket name"),
605
- endpointUrl: import_zod.z.string().describe("S3 endpoint URL")
1073
+ const s3ConfigSchema = import_zod2.z.object({
1074
+ accessId: import_zod2.z.string().describe("S3 access key ID"),
1075
+ accessSecret: import_zod2.z.string().describe("S3 secret access key"),
1076
+ bucketName: import_zod2.z.string().describe("S3 bucket name"),
1077
+ endpointUrl: import_zod2.z.string().describe("S3 endpoint URL")
606
1078
  }).optional().describe("S3-compatible storage config for large outputs");
607
- server2.tool(
1079
+ server.tool(
608
1080
  "run-endpoint",
609
1081
  "Submit an asynchronous job to a Serverless endpoint. Returns a job ID immediately \u2014 use get-job-status to poll for results. Async results are available for 30 minutes after completion.",
610
1082
  {
@@ -634,7 +1106,7 @@ function registerTools(server2, ctx) {
634
1106
  };
635
1107
  }
636
1108
  );
637
- server2.tool(
1109
+ server.tool(
638
1110
  "runsync-endpoint",
639
1111
  "Submit a synchronous job to a Serverless endpoint and wait for the result. Best for tasks completing within 90 seconds. If processing exceeds 90 seconds, the response returns a job ID to poll with get-job-status. Max payload: 20 MB. Results expire after 1 minute. Use the wait parameter to extend the server-side wait up to 5 minutes (300000 ms).",
640
1112
  {
@@ -642,7 +1114,7 @@ function registerTools(server2, ctx) {
642
1114
  "ID of the Serverless endpoint to run synchronously"
643
1115
  ),
644
1116
  input: inputSchema,
645
- wait: import_zod.z.number().min(1e3).max(3e5).optional().describe(
1117
+ wait: import_zod2.z.number().min(1e3).max(3e5).optional().describe(
646
1118
  "How long in milliseconds the server should wait for a result before returning a job ID to poll (1000\u2013300000). Defaults to 90000 (90 seconds)."
647
1119
  ),
648
1120
  webhook: webhookSchema,
@@ -651,10 +1123,10 @@ function registerTools(server2, ctx) {
651
1123
  },
652
1124
  async (params) => {
653
1125
  const { endpointId, wait, ...body } = params;
654
- const path = wait ? `/runsync?wait=${wait}` : "/runsync";
1126
+ const path2 = wait ? `/runsync?wait=${wait}` : "/runsync";
655
1127
  const result = await serverlessRequest(
656
1128
  endpointId,
657
- path,
1129
+ path2,
658
1130
  "POST",
659
1131
  body
660
1132
  );
@@ -668,7 +1140,7 @@ function registerTools(server2, ctx) {
668
1140
  };
669
1141
  }
670
1142
  );
671
- server2.tool(
1143
+ server.tool(
672
1144
  "get-job-status",
673
1145
  "Check the status of an asynchronous Serverless job. Returns the current status and output when complete. Job statuses: IN_QUEUE, IN_PROGRESS, COMPLETED, FAILED, CANCELLED, TIMED_OUT.",
674
1146
  {
@@ -692,7 +1164,7 @@ function registerTools(server2, ctx) {
692
1164
  };
693
1165
  }
694
1166
  );
695
- server2.tool(
1167
+ server.tool(
696
1168
  "stream-job",
697
1169
  "Retrieve all streaming output from a Serverless job by polling until the job reaches a terminal state. The worker must support streaming output. Polls /stream/{jobId} repeatedly and collects every chunk until status is COMPLETED, FAILED, CANCELLED, or TIMED_OUT.",
698
1170
  {
@@ -760,7 +1232,7 @@ function registerTools(server2, ctx) {
760
1232
  };
761
1233
  }
762
1234
  );
763
- server2.tool(
1235
+ server.tool(
764
1236
  "cancel-job",
765
1237
  "Cancel a Serverless job that is queued or in progress.",
766
1238
  {
@@ -785,7 +1257,7 @@ function registerTools(server2, ctx) {
785
1257
  };
786
1258
  }
787
1259
  );
788
- server2.tool(
1260
+ server.tool(
789
1261
  "retry-job",
790
1262
  "Retry a failed or timed-out Serverless job. Only works for jobs with FAILED or TIMED_OUT status. The previous output is removed and the job is requeued.",
791
1263
  {
@@ -810,7 +1282,7 @@ function registerTools(server2, ctx) {
810
1282
  };
811
1283
  }
812
1284
  );
813
- server2.tool(
1285
+ server.tool(
814
1286
  "endpoint-health",
815
1287
  "Get the health and operational status of a Serverless endpoint, including worker counts and job statistics.",
816
1288
  {
@@ -830,7 +1302,7 @@ function registerTools(server2, ctx) {
830
1302
  };
831
1303
  }
832
1304
  );
833
- server2.tool(
1305
+ server.tool(
834
1306
  "purge-endpoint-queue",
835
1307
  "Remove all pending jobs from a Serverless endpoint queue. Only affects queued jobs \u2014 in-progress jobs continue running. Use this for error recovery or clearing outdated requests.",
836
1308
  {
@@ -854,13 +1326,14 @@ function registerTools(server2, ctx) {
854
1326
  };
855
1327
  }
856
1328
  );
857
- server2.tool(
1329
+ server.tool(
858
1330
  "list-templates",
859
1331
  `List available templates. By default returns only the user's own templates. Use includeRunpodTemplates to also include official Runpod templates. The recommended default template for new pods is "Runpod Pytorch 2.8.0" (ID: runpod-torch-v280) \u2014 it has the latest CUDA and PyTorch versions.`,
860
1332
  {
861
- includeRunpodTemplates: import_zod.z.boolean().optional().describe("Include official Runpod templates in the response"),
862
- includePublicTemplates: import_zod.z.boolean().optional().describe("Include community-made public templates in the response"),
863
- includeEndpointBoundTemplates: import_zod.z.boolean().optional().describe(
1333
+ ...listPaginationParams,
1334
+ includeRunpodTemplates: import_zod2.z.boolean().optional().describe("Include official Runpod templates in the response"),
1335
+ includePublicTemplates: import_zod2.z.boolean().optional().describe("Include community-made public templates in the response"),
1336
+ includeEndpointBoundTemplates: import_zod2.z.boolean().optional().describe(
864
1337
  "Include templates bound to Serverless endpoints in the response"
865
1338
  )
866
1339
  },
@@ -876,20 +1349,16 @@ function registerTools(server2, ctx) {
876
1349
  const result = await runpodRequest(
877
1350
  `/templates${query ? `?${query}` : ""}`
878
1351
  );
879
- return {
880
- content: [
881
- {
882
- type: "text",
883
- text: JSON.stringify(result, null, 2)
884
- }
885
- ]
886
- };
1352
+ return capListResult(result, {
1353
+ limit: params.limit,
1354
+ cursor: params.cursor
1355
+ });
887
1356
  }
888
1357
  );
889
- server2.tool(
1358
+ server.tool(
890
1359
  "get-template",
891
1360
  {
892
- templateId: import_zod.z.string().describe("ID of the template to retrieve")
1361
+ templateId: import_zod2.z.string().describe("ID of the template to retrieve")
893
1362
  },
894
1363
  async (params) => {
895
1364
  const result = await runpodRequest(`/templates/${params.templateId}`);
@@ -903,20 +1372,23 @@ function registerTools(server2, ctx) {
903
1372
  };
904
1373
  }
905
1374
  );
906
- server2.tool(
1375
+ server.tool(
907
1376
  "create-template",
908
1377
  {
909
- name: import_zod.z.string().describe("Name for the template"),
910
- imageName: import_zod.z.string().describe("Docker image to use"),
911
- isServerless: import_zod.z.boolean().optional().describe("Is this a serverless template"),
912
- ports: import_zod.z.array(import_zod.z.string()).optional().describe("Ports to expose"),
913
- dockerEntrypoint: import_zod.z.array(import_zod.z.string()).optional().describe("Docker entrypoint commands"),
914
- dockerStartCmd: import_zod.z.array(import_zod.z.string()).optional().describe("Docker start commands"),
915
- env: import_zod.z.record(import_zod.z.string()).optional().describe("Environment variables"),
916
- containerDiskInGb: import_zod.z.number().optional().describe("Container disk size in GB"),
917
- volumeInGb: import_zod.z.number().optional().describe("Volume size in GB"),
918
- volumeMountPath: import_zod.z.string().optional().describe("Path to mount the volume"),
919
- readme: import_zod.z.string().optional().describe("README content in markdown format")
1378
+ name: import_zod2.z.string().describe("Name for the template"),
1379
+ imageName: import_zod2.z.string().describe("Docker image to use"),
1380
+ isServerless: import_zod2.z.boolean().optional().describe("Is this a serverless template"),
1381
+ ports: import_zod2.z.array(import_zod2.z.string()).optional().describe("Ports to expose"),
1382
+ dockerEntrypoint: import_zod2.z.array(import_zod2.z.string()).optional().describe("Docker entrypoint commands"),
1383
+ dockerStartCmd: import_zod2.z.array(import_zod2.z.string()).optional().describe("Docker start commands"),
1384
+ env: import_zod2.z.record(import_zod2.z.string()).optional().describe("Environment variables"),
1385
+ containerDiskInGb: import_zod2.z.number().optional().describe("Container disk size in GB"),
1386
+ volumeInGb: import_zod2.z.number().optional().describe("Volume size in GB"),
1387
+ volumeMountPath: import_zod2.z.string().optional().describe("Path to mount the volume"),
1388
+ readme: import_zod2.z.string().optional().describe("README content in markdown format"),
1389
+ containerRegistryAuthId: import_zod2.z.string().optional().describe(
1390
+ "ID of a container registry credential (from create-container-registry-auth / list-container-registry-auths) used to pull a private image. Required when imageName points at a private registry; without it serverless workers fail the image pull."
1391
+ )
920
1392
  },
921
1393
  async (params) => {
922
1394
  const result = await runpodRequest("/templates", "POST", params);
@@ -930,15 +1402,18 @@ function registerTools(server2, ctx) {
930
1402
  };
931
1403
  }
932
1404
  );
933
- server2.tool(
1405
+ server.tool(
934
1406
  "update-template",
935
1407
  {
936
- templateId: import_zod.z.string().describe("ID of the template to update"),
937
- name: import_zod.z.string().optional().describe("New name for the template"),
938
- imageName: import_zod.z.string().optional().describe("New Docker image"),
939
- ports: import_zod.z.array(import_zod.z.string()).optional().describe("New ports to expose"),
940
- env: import_zod.z.record(import_zod.z.string()).optional().describe("New environment variables"),
941
- readme: import_zod.z.string().optional().describe("New README content in markdown format")
1408
+ templateId: import_zod2.z.string().describe("ID of the template to update"),
1409
+ name: import_zod2.z.string().optional().describe("New name for the template"),
1410
+ imageName: import_zod2.z.string().optional().describe("New Docker image"),
1411
+ ports: import_zod2.z.array(import_zod2.z.string()).optional().describe("New ports to expose"),
1412
+ env: import_zod2.z.record(import_zod2.z.string()).optional().describe("New environment variables"),
1413
+ readme: import_zod2.z.string().optional().describe("New README content in markdown format"),
1414
+ containerRegistryAuthId: import_zod2.z.string().optional().describe(
1415
+ "ID of a container registry credential (from create-container-registry-auth / list-container-registry-auths) used to pull a private image. Set this to attach a credential to a template referencing a private registry."
1416
+ )
942
1417
  },
943
1418
  async (params) => {
944
1419
  const { templateId, ...updateParams } = params;
@@ -957,10 +1432,10 @@ function registerTools(server2, ctx) {
957
1432
  };
958
1433
  }
959
1434
  );
960
- server2.tool(
1435
+ server.tool(
961
1436
  "delete-template",
962
1437
  {
963
- templateId: import_zod.z.string().describe("ID of the template to delete")
1438
+ templateId: import_zod2.z.string().describe("ID of the template to delete")
964
1439
  },
965
1440
  async (params) => {
966
1441
  const result = await runpodRequest(
@@ -977,21 +1452,17 @@ function registerTools(server2, ctx) {
977
1452
  };
978
1453
  }
979
1454
  );
980
- server2.tool("list-network-volumes", {}, async () => {
1455
+ server.tool("list-network-volumes", listPaginationParams, async (params) => {
981
1456
  const result = await runpodRequest("/networkvolumes");
982
- return {
983
- content: [
984
- {
985
- type: "text",
986
- text: JSON.stringify(result, null, 2)
987
- }
988
- ]
989
- };
1457
+ return capListResult(result, {
1458
+ limit: params.limit,
1459
+ cursor: params.cursor
1460
+ });
990
1461
  });
991
- server2.tool(
1462
+ server.tool(
992
1463
  "get-network-volume",
993
1464
  {
994
- networkVolumeId: import_zod.z.string().describe("ID of the network volume to retrieve")
1465
+ networkVolumeId: import_zod2.z.string().describe("ID of the network volume to retrieve")
995
1466
  },
996
1467
  async (params) => {
997
1468
  const result = await runpodRequest(
@@ -1007,12 +1478,12 @@ function registerTools(server2, ctx) {
1007
1478
  };
1008
1479
  }
1009
1480
  );
1010
- server2.tool(
1481
+ server.tool(
1011
1482
  "create-network-volume",
1012
1483
  {
1013
- name: import_zod.z.string().describe("Name for the network volume"),
1014
- size: import_zod.z.number().describe("Size in GB (1-4000)"),
1015
- dataCenterId: import_zod.z.string().describe("Data center ID")
1484
+ name: import_zod2.z.string().describe("Name for the network volume"),
1485
+ size: import_zod2.z.number().describe("Size in GB (1-4000)"),
1486
+ dataCenterId: import_zod2.z.string().describe("Data center ID")
1016
1487
  },
1017
1488
  async (params) => {
1018
1489
  const result = await runpodRequest("/networkvolumes", "POST", params);
@@ -1026,12 +1497,12 @@ function registerTools(server2, ctx) {
1026
1497
  };
1027
1498
  }
1028
1499
  );
1029
- server2.tool(
1500
+ server.tool(
1030
1501
  "update-network-volume",
1031
1502
  {
1032
- networkVolumeId: import_zod.z.string().describe("ID of the network volume to update"),
1033
- name: import_zod.z.string().optional().describe("New name for the network volume"),
1034
- size: import_zod.z.number().optional().describe("New size in GB (must be larger than current)")
1503
+ networkVolumeId: import_zod2.z.string().describe("ID of the network volume to update"),
1504
+ name: import_zod2.z.string().optional().describe("New name for the network volume"),
1505
+ size: import_zod2.z.number().optional().describe("New size in GB (must be larger than current)")
1035
1506
  },
1036
1507
  async (params) => {
1037
1508
  const { networkVolumeId, ...updateParams } = params;
@@ -1050,10 +1521,10 @@ function registerTools(server2, ctx) {
1050
1521
  };
1051
1522
  }
1052
1523
  );
1053
- server2.tool(
1524
+ server.tool(
1054
1525
  "delete-network-volume",
1055
1526
  {
1056
- networkVolumeId: import_zod.z.string().describe("ID of the network volume to delete")
1527
+ networkVolumeId: import_zod2.z.string().describe("ID of the network volume to delete")
1057
1528
  },
1058
1529
  async (params) => {
1059
1530
  const result = await runpodRequest(
@@ -1070,21 +1541,21 @@ function registerTools(server2, ctx) {
1070
1541
  };
1071
1542
  }
1072
1543
  );
1073
- server2.tool("list-container-registry-auths", {}, async () => {
1074
- const result = await runpodRequest("/containerregistryauth");
1075
- return {
1076
- content: [
1077
- {
1078
- type: "text",
1079
- text: JSON.stringify(result, null, 2)
1080
- }
1081
- ]
1082
- };
1083
- });
1084
- server2.tool(
1544
+ server.tool(
1545
+ "list-container-registry-auths",
1546
+ listPaginationParams,
1547
+ async (params) => {
1548
+ const result = await runpodRequest("/containerregistryauth");
1549
+ return capListResult(result, {
1550
+ limit: params.limit,
1551
+ cursor: params.cursor
1552
+ });
1553
+ }
1554
+ );
1555
+ server.tool(
1085
1556
  "get-container-registry-auth",
1086
1557
  {
1087
- containerRegistryAuthId: import_zod.z.string().describe("ID of the container registry auth to retrieve")
1558
+ containerRegistryAuthId: import_zod2.z.string().describe("ID of the container registry auth to retrieve")
1088
1559
  },
1089
1560
  async (params) => {
1090
1561
  const result = await runpodRequest(
@@ -1100,12 +1571,12 @@ function registerTools(server2, ctx) {
1100
1571
  };
1101
1572
  }
1102
1573
  );
1103
- server2.tool(
1574
+ server.tool(
1104
1575
  "create-container-registry-auth",
1105
1576
  {
1106
- name: import_zod.z.string().describe("Name for the container registry auth"),
1107
- username: import_zod.z.string().describe("Registry username"),
1108
- password: import_zod.z.string().describe("Registry password")
1577
+ name: import_zod2.z.string().describe("Name for the container registry auth"),
1578
+ username: import_zod2.z.string().describe("Registry username"),
1579
+ password: import_zod2.z.string().describe("Registry password")
1109
1580
  },
1110
1581
  async (params) => {
1111
1582
  const result = await runpodRequest(
@@ -1123,10 +1594,10 @@ function registerTools(server2, ctx) {
1123
1594
  };
1124
1595
  }
1125
1596
  );
1126
- server2.tool(
1597
+ server.tool(
1127
1598
  "delete-container-registry-auth",
1128
1599
  {
1129
- containerRegistryAuthId: import_zod.z.string().describe("ID of the container registry auth to delete")
1600
+ containerRegistryAuthId: import_zod2.z.string().describe("ID of the container registry auth to delete")
1130
1601
  },
1131
1602
  async (params) => {
1132
1603
  const result = await runpodRequest(
@@ -1146,13 +1617,23 @@ function registerTools(server2, ctx) {
1146
1617
  }
1147
1618
 
1148
1619
  // src/stdio.ts
1149
- var API_KEY = process.env.RUNPOD_API_KEY;
1150
- if (!API_KEY) {
1151
- console.error("RUNPOD_API_KEY environment variable is required");
1152
- process.exit(1);
1620
+ var WIZARD_SUBCOMMANDS = ["add", "remove"];
1621
+ var subcommand = process.argv[2];
1622
+ var isWizardMode = WIZARD_SUBCOMMANDS.includes(subcommand);
1623
+ if (isWizardMode) {
1624
+ Promise.resolve().then(() => (init_wizard(), wizard_exports)).then(({ runWizard: runWizard2 }) => runWizard2(subcommand)).catch((error) => {
1625
+ console.error(error instanceof Error ? error.message : String(error));
1626
+ process.exit(1);
1627
+ });
1628
+ } else {
1629
+ const API_KEY = process.env.RUNPOD_API_KEY;
1630
+ if (!API_KEY) {
1631
+ console.error("RUNPOD_API_KEY environment variable is required");
1632
+ process.exit(1);
1633
+ }
1634
+ const server = createServer();
1635
+ registerTools(server, { apiKey: API_KEY, transport: "stdio" });
1636
+ const transport = new import_stdio.StdioServerTransport();
1637
+ server.connect(transport);
1153
1638
  }
1154
- var server = createServer();
1155
- registerTools(server, { apiKey: API_KEY, transport: "stdio" });
1156
- var transport = new import_stdio.StdioServerTransport();
1157
- server.connect(transport);
1158
1639
  //# sourceMappingURL=stdio.cjs.map