@runpod/mcp-server 4.0.0 → 4.1.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
@@ -975,7 +975,7 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
975
975
 
976
976
  // src/server.ts
977
977
  var SERVER_NAME = "Runpod API Server";
978
- var SERVER_VERSION = true ? "4.0.0" : "dev";
978
+ var SERVER_VERSION = true ? "4.1.0" : "dev";
979
979
 
980
980
  // src/specgen/server.ts
981
981
  var import_server3 = require("@modelcontextprotocol/sdk/server/index.js");
@@ -1227,6 +1227,12 @@ var generatedTools = [
1227
1227
  path: "/v2/clusters",
1228
1228
  params: [],
1229
1229
  hasBody: true,
1230
+ annotations: {
1231
+ readOnlyHint: false,
1232
+ destructiveHint: false,
1233
+ idempotentHint: false,
1234
+ openWorldHint: true
1235
+ },
1230
1236
  inputSchema: {
1231
1237
  type: "object",
1232
1238
  properties: {
@@ -1238,12 +1244,34 @@ var generatedTools = [
1238
1244
  $defs: {
1239
1245
  BaseContainerConfig: {
1240
1246
  type: "object",
1241
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
1247
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
1242
1248
  properties: {
1243
1249
  args: {
1244
1250
  type: "string",
1245
- description: "Arguments passed to the container entrypoint",
1246
- examples: [""]
1251
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
1252
+ examples: [
1253
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1254
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1255
+ ""
1256
+ ]
1257
+ },
1258
+ cmd: {
1259
+ type: "array",
1260
+ items: {
1261
+ type: "string"
1262
+ },
1263
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
1264
+ examples: [
1265
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1266
+ ]
1267
+ },
1268
+ entrypoint: {
1269
+ type: "array",
1270
+ items: {
1271
+ type: "string"
1272
+ },
1273
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
1274
+ examples: [["/bin/bash", "-c"]]
1247
1275
  },
1248
1276
  disk: {
1249
1277
  type: "integer",
@@ -1319,7 +1347,7 @@ var generatedTools = [
1319
1347
  {
1320
1348
  type: "object",
1321
1349
  required: ["name", "type", "compute"],
1322
- description: "Request body for creating a cluster. `compute` defines the\nhomogeneous pod shape; the container configuration (image, env, ports,\n\u2026) applies to every pod and can be spread from a template response.\nPrivate registries are not yet supported for clusters \u2014 there is no\n`registry` field here, unlike the other create requests.\n",
1350
+ description: "Request body for creating a cluster. `compute` defines the\nhomogeneous pod shape; the container configuration (image, env, ports,\n\u2026) applies to every pod. Pass `templateId` to provision every member\npod from a pod template instead of inline container fields \u2014 the\ntemplate also supplies the container registry credential, the only\nprivate-image path for clusters (a bare `registry` property on this\nbody is rejected).\n",
1323
1351
  properties: {
1324
1352
  compute: {
1325
1353
  $ref: "#/$defs/ClusterCompute"
@@ -1332,6 +1360,12 @@ var generatedTools = [
1332
1360
  type: {
1333
1361
  $ref: "#/$defs/ClusterType"
1334
1362
  },
1363
+ templateId: {
1364
+ type: "string",
1365
+ minLength: 1,
1366
+ description: "ID of a pod template to provision every member pod from. The\ntemplate supplies the container settings (image, args, disk,\nenv, ports) and the container registry credential for private\nimages \u2014 the only private-image path for clusters. Mutually\nexclusive with `image`, `args`, `entrypoint`, `cmd`, `disk`,\n`env`, `ports`, and `mounts` (rejected with 400). The cluster\nretains the link: the `template` response field is set. Must be\na non-serverless pod template accessible to the caller.\n",
1367
+ examples: ["30zmvf89kd"]
1368
+ },
1335
1369
  dataCenterIds: {
1336
1370
  type: "array",
1337
1371
  items: {
@@ -1423,6 +1457,12 @@ var generatedTools = [
1423
1457
  path: "/v2/registries/delegations",
1424
1458
  params: [],
1425
1459
  hasBody: true,
1460
+ annotations: {
1461
+ readOnlyHint: false,
1462
+ destructiveHint: false,
1463
+ idempotentHint: false,
1464
+ openWorldHint: true
1465
+ },
1426
1466
  inputSchema: {
1427
1467
  type: "object",
1428
1468
  properties: {
@@ -1462,6 +1502,12 @@ var generatedTools = [
1462
1502
  path: "/v2/serverless",
1463
1503
  params: [],
1464
1504
  hasBody: true,
1505
+ annotations: {
1506
+ readOnlyHint: false,
1507
+ destructiveHint: false,
1508
+ idempotentHint: false,
1509
+ openWorldHint: true
1510
+ },
1465
1511
  inputSchema: {
1466
1512
  type: "object",
1467
1513
  properties: {
@@ -1473,12 +1519,34 @@ var generatedTools = [
1473
1519
  $defs: {
1474
1520
  BaseContainerConfig: {
1475
1521
  type: "object",
1476
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
1522
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
1477
1523
  properties: {
1478
1524
  args: {
1479
1525
  type: "string",
1480
- description: "Arguments passed to the container entrypoint",
1481
- examples: [""]
1526
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
1527
+ examples: [
1528
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1529
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1530
+ ""
1531
+ ]
1532
+ },
1533
+ cmd: {
1534
+ type: "array",
1535
+ items: {
1536
+ type: "string"
1537
+ },
1538
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
1539
+ examples: [
1540
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1541
+ ]
1542
+ },
1543
+ entrypoint: {
1544
+ type: "array",
1545
+ items: {
1546
+ type: "string"
1547
+ },
1548
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
1549
+ examples: [["/bin/bash", "-c"]]
1482
1550
  },
1483
1551
  disk: {
1484
1552
  type: "integer",
@@ -1537,7 +1605,7 @@ var generatedTools = [
1537
1605
  pools: {
1538
1606
  type: "array",
1539
1607
  minItems: 1,
1540
- description: "Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\n`pool`). Workers are placed on whichever listed pool has capacity.\nNarrow a pool down to specific cards with `excludedTypes`.\n",
1608
+ description: 'Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\n`pool`). Workers are placed on whichever listed pool has capacity.\nNarrow a pool down to specific cards with `excludedTypes`.\n\nOn `PATCH`, `pools` and `excludedTypes` are one selection and are\nreplaced together, so sending `pools` by itself **clears the\nexclusions**. Two cases:\n\n- **Changing pools, keeping exclusions** \u2014 send both fields in one\n request: `{"gpu": {"pools": ["ADA_24"], "excludedTypes":\n ["NVIDIA L40"]}}`. `GET` the endpoint first to read the current\n `excludedTypes` and resend the ones that still apply to the new\n pools; an exclusion naming a type outside `pools` is a 400.\n- **Changing only `count` or a CUDA constraint** \u2014 omit `pools`:\n `{"gpu": {"minCudaVersion": "12.4"}}`. The pool list and the\n exclusions are both left exactly as they are.\n\n`excludedTypes` documents the full rule.\n',
1541
1609
  items: {
1542
1610
  type: "string"
1543
1611
  },
@@ -1841,6 +1909,12 @@ var generatedTools = [
1841
1909
  path: "/v2/network-volumes",
1842
1910
  params: [],
1843
1911
  hasBody: true,
1912
+ annotations: {
1913
+ readOnlyHint: false,
1914
+ destructiveHint: false,
1915
+ idempotentHint: false,
1916
+ openWorldHint: true
1917
+ },
1844
1918
  inputSchema: {
1845
1919
  type: "object",
1846
1920
  properties: {
@@ -1900,6 +1974,12 @@ var generatedTools = [
1900
1974
  path: "/v2/pods",
1901
1975
  params: [],
1902
1976
  hasBody: true,
1977
+ annotations: {
1978
+ readOnlyHint: false,
1979
+ destructiveHint: false,
1980
+ idempotentHint: false,
1981
+ openWorldHint: true
1982
+ },
1903
1983
  inputSchema: {
1904
1984
  type: "object",
1905
1985
  properties: {
@@ -1911,12 +1991,34 @@ var generatedTools = [
1911
1991
  $defs: {
1912
1992
  BaseContainerConfig: {
1913
1993
  type: "object",
1914
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
1994
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
1915
1995
  properties: {
1916
1996
  args: {
1917
1997
  type: "string",
1918
- description: "Arguments passed to the container entrypoint",
1919
- examples: [""]
1998
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
1999
+ examples: [
2000
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
2001
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
2002
+ ""
2003
+ ]
2004
+ },
2005
+ cmd: {
2006
+ type: "array",
2007
+ items: {
2008
+ type: "string"
2009
+ },
2010
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
2011
+ examples: [
2012
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
2013
+ ]
2014
+ },
2015
+ entrypoint: {
2016
+ type: "array",
2017
+ items: {
2018
+ type: "string"
2019
+ },
2020
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
2021
+ examples: [["/bin/bash", "-c"]]
1920
2022
  },
1921
2023
  disk: {
1922
2024
  type: "integer",
@@ -2202,6 +2304,12 @@ var generatedTools = [
2202
2304
  path: "/v2/registries",
2203
2305
  params: [],
2204
2306
  hasBody: true,
2307
+ annotations: {
2308
+ readOnlyHint: false,
2309
+ destructiveHint: false,
2310
+ idempotentHint: false,
2311
+ openWorldHint: true
2312
+ },
2205
2313
  inputSchema: {
2206
2314
  type: "object",
2207
2315
  properties: {
@@ -2219,16 +2327,19 @@ var generatedTools = [
2219
2327
  name: {
2220
2328
  type: "string",
2221
2329
  minLength: 1,
2330
+ maxLength: 191,
2222
2331
  examples: ["my-private-registry"]
2223
2332
  },
2224
2333
  password: {
2225
2334
  type: "string",
2226
2335
  minLength: 1,
2336
+ maxLength: 16384,
2227
2337
  description: "Registry password (write-only, not returned in responses)"
2228
2338
  },
2229
2339
  username: {
2230
2340
  type: "string",
2231
2341
  minLength: 1,
2342
+ maxLength: 191,
2232
2343
  description: "Registry username (write-only, not returned in responses)"
2233
2344
  }
2234
2345
  }
@@ -2236,6 +2347,59 @@ var generatedTools = [
2236
2347
  }
2237
2348
  }
2238
2349
  },
2350
+ {
2351
+ name: "create-secret",
2352
+ operationId: "createSecret",
2353
+ description: "Create a secret. Stores a new account-scoped encrypted string. `name` must be unique across the account's secrets and is immutable; `value` is write-only and can never be read back through the API. Use the secret from pods, serverless endpoints, and templates by setting an environment variable's value to `{{ RUNPOD_SECRET_<name> }}` \u2014 Runpod substitutes the stored value when the pod or worker boots. Returns `201` with the created secret's metadata, or `409` when the name is already taken.",
2354
+ method: "POST",
2355
+ path: "/v2/account/secrets",
2356
+ params: [],
2357
+ hasBody: true,
2358
+ annotations: {
2359
+ readOnlyHint: false,
2360
+ destructiveHint: false,
2361
+ idempotentHint: false,
2362
+ openWorldHint: true
2363
+ },
2364
+ inputSchema: {
2365
+ type: "object",
2366
+ properties: {
2367
+ body: {
2368
+ $ref: "#/$defs/CreateSecretRequest"
2369
+ }
2370
+ },
2371
+ required: ["body"],
2372
+ $defs: {
2373
+ CreateSecretRequest: {
2374
+ type: "object",
2375
+ additionalProperties: false,
2376
+ required: ["name", "value"],
2377
+ properties: {
2378
+ name: {
2379
+ type: "string",
2380
+ minLength: 1,
2381
+ maxLength: 191,
2382
+ pattern: "^[a-zA-Z_][a-zA-Z0-9_.\\-/]*$",
2383
+ description: "Unique name for the secret \u2014 referenced from environment variables as `{{ RUNPOD_SECRET_<name> }}`; immutable after creation. Maximum 191 characters, must start with a letter or underscore, and may contain letters, digits, and `_.-/`. Names beginning with the reserved prefix `RUNPOD` are rejected (case-insensitive).",
2384
+ examples: ["hf-token"]
2385
+ },
2386
+ value: {
2387
+ type: "string",
2388
+ minLength: 1,
2389
+ maxLength: 16777216,
2390
+ description: "The secret value. Write-only \u2014 never returned by the API. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes)."
2391
+ },
2392
+ description: {
2393
+ type: "string",
2394
+ maxLength: 65535,
2395
+ description: "Optional human-readable description, at most 65,535 bytes of UTF-8 text.",
2396
+ examples: ["Hugging Face read token"]
2397
+ }
2398
+ }
2399
+ }
2400
+ }
2401
+ }
2402
+ },
2239
2403
  {
2240
2404
  name: "create-template",
2241
2405
  operationId: "createTemplate",
@@ -2244,6 +2408,12 @@ var generatedTools = [
2244
2408
  path: "/v2/templates",
2245
2409
  params: [],
2246
2410
  hasBody: true,
2411
+ annotations: {
2412
+ readOnlyHint: false,
2413
+ destructiveHint: false,
2414
+ idempotentHint: false,
2415
+ openWorldHint: true
2416
+ },
2247
2417
  inputSchema: {
2248
2418
  type: "object",
2249
2419
  properties: {
@@ -2255,12 +2425,34 @@ var generatedTools = [
2255
2425
  $defs: {
2256
2426
  BaseContainerConfig: {
2257
2427
  type: "object",
2258
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
2428
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
2259
2429
  properties: {
2260
2430
  args: {
2261
2431
  type: "string",
2262
- description: "Arguments passed to the container entrypoint",
2263
- examples: [""]
2432
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
2433
+ examples: [
2434
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
2435
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
2436
+ ""
2437
+ ]
2438
+ },
2439
+ cmd: {
2440
+ type: "array",
2441
+ items: {
2442
+ type: "string"
2443
+ },
2444
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
2445
+ examples: [
2446
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
2447
+ ]
2448
+ },
2449
+ entrypoint: {
2450
+ type: "array",
2451
+ items: {
2452
+ type: "string"
2453
+ },
2454
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
2455
+ examples: [["/bin/bash", "-c"]]
2264
2456
  },
2265
2457
  disk: {
2266
2458
  type: "integer",
@@ -2423,6 +2615,12 @@ var generatedTools = [
2423
2615
  }
2424
2616
  ],
2425
2617
  hasBody: false,
2618
+ annotations: {
2619
+ readOnlyHint: false,
2620
+ destructiveHint: true,
2621
+ idempotentHint: true,
2622
+ openWorldHint: true
2623
+ },
2426
2624
  inputSchema: {
2427
2625
  type: "object",
2428
2626
  properties: {
@@ -2447,6 +2645,12 @@ var generatedTools = [
2447
2645
  }
2448
2646
  ],
2449
2647
  hasBody: false,
2648
+ annotations: {
2649
+ readOnlyHint: false,
2650
+ destructiveHint: true,
2651
+ idempotentHint: true,
2652
+ openWorldHint: true
2653
+ },
2450
2654
  inputSchema: {
2451
2655
  type: "object",
2452
2656
  properties: {
@@ -2471,6 +2675,12 @@ var generatedTools = [
2471
2675
  }
2472
2676
  ],
2473
2677
  hasBody: false,
2678
+ annotations: {
2679
+ readOnlyHint: false,
2680
+ destructiveHint: true,
2681
+ idempotentHint: true,
2682
+ openWorldHint: true
2683
+ },
2474
2684
  inputSchema: {
2475
2685
  type: "object",
2476
2686
  properties: {
@@ -2495,6 +2705,12 @@ var generatedTools = [
2495
2705
  }
2496
2706
  ],
2497
2707
  hasBody: false,
2708
+ annotations: {
2709
+ readOnlyHint: false,
2710
+ destructiveHint: true,
2711
+ idempotentHint: true,
2712
+ openWorldHint: true
2713
+ },
2498
2714
  inputSchema: {
2499
2715
  type: "object",
2500
2716
  properties: {
@@ -2519,6 +2735,12 @@ var generatedTools = [
2519
2735
  }
2520
2736
  ],
2521
2737
  hasBody: false,
2738
+ annotations: {
2739
+ readOnlyHint: false,
2740
+ destructiveHint: true,
2741
+ idempotentHint: true,
2742
+ openWorldHint: true
2743
+ },
2522
2744
  inputSchema: {
2523
2745
  type: "object",
2524
2746
  properties: {
@@ -2529,6 +2751,36 @@ var generatedTools = [
2529
2751
  required: ["id"]
2530
2752
  }
2531
2753
  },
2754
+ {
2755
+ name: "delete-secret",
2756
+ operationId: "deleteSecret",
2757
+ description: "Delete a secret. Permanently deletes a secret. Environment variables referencing the deleted secret's name will no longer resolve to a value.",
2758
+ method: "DELETE",
2759
+ path: "/v2/account/secrets/{id}",
2760
+ params: [
2761
+ {
2762
+ name: "id",
2763
+ location: "path"
2764
+ }
2765
+ ],
2766
+ hasBody: false,
2767
+ annotations: {
2768
+ readOnlyHint: false,
2769
+ destructiveHint: true,
2770
+ idempotentHint: true,
2771
+ openWorldHint: true
2772
+ },
2773
+ inputSchema: {
2774
+ type: "object",
2775
+ properties: {
2776
+ id: {
2777
+ type: "string",
2778
+ description: "Secret identifier"
2779
+ }
2780
+ },
2781
+ required: ["id"]
2782
+ }
2783
+ },
2532
2784
  {
2533
2785
  name: "delete-template",
2534
2786
  operationId: "deleteTemplate",
@@ -2542,6 +2794,12 @@ var generatedTools = [
2542
2794
  }
2543
2795
  ],
2544
2796
  hasBody: false,
2797
+ annotations: {
2798
+ readOnlyHint: false,
2799
+ destructiveHint: true,
2800
+ idempotentHint: true,
2801
+ openWorldHint: true
2802
+ },
2545
2803
  inputSchema: {
2546
2804
  type: "object",
2547
2805
  properties: {
@@ -2565,6 +2823,12 @@ var generatedTools = [
2565
2823
  }
2566
2824
  ],
2567
2825
  hasBody: false,
2826
+ annotations: {
2827
+ readOnlyHint: true,
2828
+ destructiveHint: false,
2829
+ idempotentHint: true,
2830
+ openWorldHint: true
2831
+ },
2568
2832
  inputSchema: {
2569
2833
  type: "object",
2570
2834
  properties: {
@@ -2603,6 +2867,12 @@ var generatedTools = [
2603
2867
  }
2604
2868
  ],
2605
2869
  hasBody: false,
2870
+ annotations: {
2871
+ readOnlyHint: true,
2872
+ destructiveHint: false,
2873
+ idempotentHint: true,
2874
+ openWorldHint: true
2875
+ },
2606
2876
  inputSchema: {
2607
2877
  type: "object",
2608
2878
  properties: {
@@ -2664,6 +2934,12 @@ var generatedTools = [
2664
2934
  }
2665
2935
  ],
2666
2936
  hasBody: false,
2937
+ annotations: {
2938
+ readOnlyHint: true,
2939
+ destructiveHint: false,
2940
+ idempotentHint: true,
2941
+ openWorldHint: true
2942
+ },
2667
2943
  inputSchema: {
2668
2944
  type: "object",
2669
2945
  properties: {
@@ -2702,6 +2978,12 @@ var generatedTools = [
2702
2978
  }
2703
2979
  ],
2704
2980
  hasBody: false,
2981
+ annotations: {
2982
+ readOnlyHint: true,
2983
+ destructiveHint: false,
2984
+ idempotentHint: true,
2985
+ openWorldHint: true
2986
+ },
2705
2987
  inputSchema: {
2706
2988
  type: "object",
2707
2989
  properties: {
@@ -2716,7 +2998,7 @@ var generatedTools = [
2716
2998
  {
2717
2999
  name: "get-endpoint-build",
2718
3000
  operationId: "getEndpointBuild",
2719
- description: "Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age \u2014 unlike the list, which is capped to recent history.",
3001
+ description: "Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age \u2014 no need to page through `GET /v2/serverless/{id}/builds` to reach it.",
2720
3002
  method: "GET",
2721
3003
  path: "/v2/serverless/{id}/builds/{buildId}",
2722
3004
  params: [
@@ -2730,6 +3012,12 @@ var generatedTools = [
2730
3012
  }
2731
3013
  ],
2732
3014
  hasBody: false,
3015
+ annotations: {
3016
+ readOnlyHint: true,
3017
+ destructiveHint: false,
3018
+ idempotentHint: true,
3019
+ openWorldHint: true
3020
+ },
2733
3021
  inputSchema: {
2734
3022
  type: "object",
2735
3023
  properties: {
@@ -2790,6 +3078,12 @@ var generatedTools = [
2790
3078
  }
2791
3079
  ],
2792
3080
  hasBody: false,
3081
+ annotations: {
3082
+ readOnlyHint: true,
3083
+ destructiveHint: false,
3084
+ idempotentHint: true,
3085
+ openWorldHint: true
3086
+ },
2793
3087
  inputSchema: {
2794
3088
  type: "object",
2795
3089
  properties: {
@@ -2876,6 +3170,12 @@ var generatedTools = [
2876
3170
  }
2877
3171
  ],
2878
3172
  hasBody: false,
3173
+ annotations: {
3174
+ readOnlyHint: true,
3175
+ destructiveHint: false,
3176
+ idempotentHint: true,
3177
+ openWorldHint: true
3178
+ },
2879
3179
  inputSchema: {
2880
3180
  type: "object",
2881
3181
  properties: {
@@ -2900,6 +3200,12 @@ var generatedTools = [
2900
3200
  }
2901
3201
  ],
2902
3202
  hasBody: false,
3203
+ annotations: {
3204
+ readOnlyHint: true,
3205
+ destructiveHint: false,
3206
+ idempotentHint: true,
3207
+ openWorldHint: true
3208
+ },
2903
3209
  inputSchema: {
2904
3210
  type: "object",
2905
3211
  properties: {
@@ -2924,6 +3230,12 @@ var generatedTools = [
2924
3230
  }
2925
3231
  ],
2926
3232
  hasBody: false,
3233
+ annotations: {
3234
+ readOnlyHint: true,
3235
+ destructiveHint: false,
3236
+ idempotentHint: true,
3237
+ openWorldHint: true
3238
+ },
2927
3239
  inputSchema: {
2928
3240
  type: "object",
2929
3241
  properties: {
@@ -2934,6 +3246,36 @@ var generatedTools = [
2934
3246
  required: ["id"]
2935
3247
  }
2936
3248
  },
3249
+ {
3250
+ name: "get-secret",
3251
+ operationId: "getSecret",
3252
+ description: "Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.",
3253
+ method: "GET",
3254
+ path: "/v2/account/secrets/{id}",
3255
+ params: [
3256
+ {
3257
+ name: "id",
3258
+ location: "path"
3259
+ }
3260
+ ],
3261
+ hasBody: false,
3262
+ annotations: {
3263
+ readOnlyHint: true,
3264
+ destructiveHint: false,
3265
+ idempotentHint: true,
3266
+ openWorldHint: true
3267
+ },
3268
+ inputSchema: {
3269
+ type: "object",
3270
+ properties: {
3271
+ id: {
3272
+ type: "string",
3273
+ description: "Secret identifier"
3274
+ }
3275
+ },
3276
+ required: ["id"]
3277
+ }
3278
+ },
2937
3279
  {
2938
3280
  name: "get-ssh-keys",
2939
3281
  operationId: "getSshKeys",
@@ -2942,6 +3284,12 @@ var generatedTools = [
2942
3284
  path: "/v2/account/ssh-keys",
2943
3285
  params: [],
2944
3286
  hasBody: false,
3287
+ annotations: {
3288
+ readOnlyHint: true,
3289
+ destructiveHint: false,
3290
+ idempotentHint: true,
3291
+ openWorldHint: true
3292
+ },
2945
3293
  inputSchema: {
2946
3294
  type: "object",
2947
3295
  properties: {}
@@ -2960,6 +3308,12 @@ var generatedTools = [
2960
3308
  }
2961
3309
  ],
2962
3310
  hasBody: false,
3311
+ annotations: {
3312
+ readOnlyHint: true,
3313
+ destructiveHint: false,
3314
+ idempotentHint: true,
3315
+ openWorldHint: true
3316
+ },
2963
3317
  inputSchema: {
2964
3318
  type: "object",
2965
3319
  properties: {
@@ -2995,6 +3349,12 @@ var generatedTools = [
2995
3349
  }
2996
3350
  ],
2997
3351
  hasBody: false,
3352
+ annotations: {
3353
+ readOnlyHint: true,
3354
+ destructiveHint: false,
3355
+ idempotentHint: true,
3356
+ openWorldHint: true
3357
+ },
2998
3358
  inputSchema: {
2999
3359
  type: "object",
3000
3360
  properties: {
@@ -3065,6 +3425,12 @@ var generatedTools = [
3065
3425
  }
3066
3426
  ],
3067
3427
  hasBody: false,
3428
+ annotations: {
3429
+ readOnlyHint: true,
3430
+ destructiveHint: false,
3431
+ idempotentHint: true,
3432
+ openWorldHint: true
3433
+ },
3068
3434
  inputSchema: {
3069
3435
  type: "object",
3070
3436
  properties: {
@@ -3123,6 +3489,12 @@ var generatedTools = [
3123
3489
  }
3124
3490
  ],
3125
3491
  hasBody: false,
3492
+ annotations: {
3493
+ readOnlyHint: true,
3494
+ destructiveHint: false,
3495
+ idempotentHint: true,
3496
+ openWorldHint: true
3497
+ },
3126
3498
  inputSchema: {
3127
3499
  type: "object",
3128
3500
  properties: {
@@ -3142,6 +3514,12 @@ var generatedTools = [
3142
3514
  path: "/v2/clusters",
3143
3515
  params: [],
3144
3516
  hasBody: false,
3517
+ annotations: {
3518
+ readOnlyHint: true,
3519
+ destructiveHint: false,
3520
+ idempotentHint: true,
3521
+ openWorldHint: true
3522
+ },
3145
3523
  inputSchema: {
3146
3524
  type: "object",
3147
3525
  properties: {}
@@ -3170,6 +3548,12 @@ var generatedTools = [
3170
3548
  }
3171
3549
  ],
3172
3550
  hasBody: false,
3551
+ annotations: {
3552
+ readOnlyHint: true,
3553
+ destructiveHint: false,
3554
+ idempotentHint: true,
3555
+ openWorldHint: true
3556
+ },
3173
3557
  inputSchema: {
3174
3558
  type: "object",
3175
3559
  properties: {
@@ -3242,6 +3626,12 @@ var generatedTools = [
3242
3626
  }
3243
3627
  ],
3244
3628
  hasBody: false,
3629
+ annotations: {
3630
+ readOnlyHint: true,
3631
+ destructiveHint: false,
3632
+ idempotentHint: true,
3633
+ openWorldHint: true
3634
+ },
3245
3635
  inputSchema: {
3246
3636
  type: "object",
3247
3637
  properties: {
@@ -3338,6 +3728,12 @@ var generatedTools = [
3338
3728
  path: "/v2/registries/delegations",
3339
3729
  params: [],
3340
3730
  hasBody: false,
3731
+ annotations: {
3732
+ readOnlyHint: true,
3733
+ destructiveHint: false,
3734
+ idempotentHint: true,
3735
+ openWorldHint: true
3736
+ },
3341
3737
  inputSchema: {
3342
3738
  type: "object",
3343
3739
  properties: {}
@@ -3368,6 +3764,12 @@ var generatedTools = [
3368
3764
  }
3369
3765
  ],
3370
3766
  hasBody: false,
3767
+ annotations: {
3768
+ readOnlyHint: true,
3769
+ destructiveHint: false,
3770
+ idempotentHint: true,
3771
+ openWorldHint: true
3772
+ },
3371
3773
  inputSchema: {
3372
3774
  type: "object",
3373
3775
  properties: {
@@ -3412,22 +3814,47 @@ var generatedTools = [
3412
3814
  {
3413
3815
  name: "list-endpoint-builds",
3414
3816
  operationId: "listEndpointBuilds",
3415
- description: "List serverless endpoint builds. Returns the endpoint's GitHub build history, newest first (Runpod GitHub-build integration). At most the 100 most recent builds are returned; any older build can still be fetched by id via `GET /v2/serverless/{id}/builds/{buildId}`. Stream a build's logs via `/v2/serverless/{id}/builds/{buildId}/logs`.",
3817
+ description: "List serverless endpoint builds. Returns the endpoint's GitHub build history, newest first (Runpod GitHub-build integration), cursor-paginated; an omitted `limit` defaults to 100, so a bare request returns at most the 100 most recent builds. Any build can also be fetched by id via `GET /v2/serverless/{id}/builds/{buildId}`. Stream a build's logs via `/v2/serverless/{id}/builds/{buildId}/logs`.",
3416
3818
  method: "GET",
3417
3819
  path: "/v2/serverless/{id}/builds",
3418
3820
  params: [
3419
3821
  {
3420
3822
  name: "id",
3421
3823
  location: "path"
3824
+ },
3825
+ {
3826
+ name: "cursor",
3827
+ location: "query"
3828
+ },
3829
+ {
3830
+ name: "limit",
3831
+ location: "query"
3422
3832
  }
3423
3833
  ],
3424
3834
  hasBody: false,
3835
+ annotations: {
3836
+ readOnlyHint: true,
3837
+ destructiveHint: false,
3838
+ idempotentHint: true,
3839
+ openWorldHint: true
3840
+ },
3425
3841
  inputSchema: {
3426
3842
  type: "object",
3427
3843
  properties: {
3428
3844
  id: {
3429
3845
  type: "string",
3430
3846
  description: "Serverless endpoint identifier"
3847
+ },
3848
+ cursor: {
3849
+ type: "string",
3850
+ minLength: 1,
3851
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\n"
3852
+ },
3853
+ limit: {
3854
+ type: "integer",
3855
+ minimum: 1,
3856
+ maximum: 100,
3857
+ description: "Page size, 1\u2013100. Defaults to 100 when omitted."
3431
3858
  }
3432
3859
  },
3433
3860
  required: ["id"]
@@ -3436,22 +3863,47 @@ var generatedTools = [
3436
3863
  {
3437
3864
  name: "list-endpoint-releases",
3438
3865
  operationId: "listEndpointReleases",
3439
- description: "List serverless endpoint releases. Returns the endpoint's release history (newest first) plus a rollout summary of how many workers are running the current version. Each release is a versioned configuration snapshot with a `diff` of what changed; build-driven releases carry a `buildId` (fetch build detail via the builds sub-routes).",
3866
+ description: "List serverless endpoint releases. Returns the endpoint's release history (newest first) plus a rollout summary of how many workers are running the current version. Each release is a versioned configuration snapshot with a `diff` of what changed; build-driven releases carry a `buildId` (fetch build detail via the builds sub-routes). Releases are cursor-paginated newest-first; an omitted `limit` defaults to 1000. The rollout summary always describes the endpoint's current state, independent of the page requested.",
3440
3867
  method: "GET",
3441
3868
  path: "/v2/serverless/{id}/releases",
3442
3869
  params: [
3443
3870
  {
3444
3871
  name: "id",
3445
3872
  location: "path"
3873
+ },
3874
+ {
3875
+ name: "cursor",
3876
+ location: "query"
3877
+ },
3878
+ {
3879
+ name: "limit",
3880
+ location: "query"
3446
3881
  }
3447
3882
  ],
3448
3883
  hasBody: false,
3884
+ annotations: {
3885
+ readOnlyHint: true,
3886
+ destructiveHint: false,
3887
+ idempotentHint: true,
3888
+ openWorldHint: true
3889
+ },
3449
3890
  inputSchema: {
3450
3891
  type: "object",
3451
3892
  properties: {
3452
3893
  id: {
3453
3894
  type: "string",
3454
3895
  description: "Serverless endpoint identifier"
3896
+ },
3897
+ cursor: {
3898
+ type: "string",
3899
+ minLength: 1,
3900
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\n"
3901
+ },
3902
+ limit: {
3903
+ type: "integer",
3904
+ minimum: 1,
3905
+ maximum: 1e3,
3906
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3455
3907
  }
3456
3908
  },
3457
3909
  required: ["id"]
@@ -3470,6 +3922,12 @@ var generatedTools = [
3470
3922
  }
3471
3923
  ],
3472
3924
  hasBody: false,
3925
+ annotations: {
3926
+ readOnlyHint: true,
3927
+ destructiveHint: false,
3928
+ idempotentHint: true,
3929
+ openWorldHint: true
3930
+ },
3473
3931
  inputSchema: {
3474
3932
  type: "object",
3475
3933
  properties: {
@@ -3522,6 +3980,12 @@ var generatedTools = [
3522
3980
  }
3523
3981
  ],
3524
3982
  hasBody: false,
3983
+ annotations: {
3984
+ readOnlyHint: true,
3985
+ destructiveHint: false,
3986
+ idempotentHint: true,
3987
+ openWorldHint: true
3988
+ },
3525
3989
  inputSchema: {
3526
3990
  type: "object",
3527
3991
  properties: {
@@ -3620,6 +4084,12 @@ var generatedTools = [
3620
4084
  }
3621
4085
  ],
3622
4086
  hasBody: false,
4087
+ annotations: {
4088
+ readOnlyHint: true,
4089
+ destructiveHint: false,
4090
+ idempotentHint: true,
4091
+ openWorldHint: true
4092
+ },
3623
4093
  inputSchema: {
3624
4094
  type: "object",
3625
4095
  properties: {
@@ -3673,6 +4143,12 @@ var generatedTools = [
3673
4143
  path: "/v2/network-volumes",
3674
4144
  params: [],
3675
4145
  hasBody: false,
4146
+ annotations: {
4147
+ readOnlyHint: true,
4148
+ destructiveHint: false,
4149
+ idempotentHint: true,
4150
+ openWorldHint: true
4151
+ },
3676
4152
  inputSchema: {
3677
4153
  type: "object",
3678
4154
  properties: {}
@@ -3707,6 +4183,12 @@ var generatedTools = [
3707
4183
  }
3708
4184
  ],
3709
4185
  hasBody: false,
4186
+ annotations: {
4187
+ readOnlyHint: true,
4188
+ destructiveHint: false,
4189
+ idempotentHint: true,
4190
+ openWorldHint: true
4191
+ },
3710
4192
  inputSchema: {
3711
4193
  type: "object",
3712
4194
  properties: {
@@ -3755,16 +4237,30 @@ var generatedTools = [
3755
4237
  {
3756
4238
  name: "list-pods",
3757
4239
  operationId: "listPods",
3758
- description: "List pods. Returns pods owned by the authenticated user. Cluster member pods are excluded by default; set `includeClusterPods=true` to include them (each carries a non-null `cluster` membership block).",
4240
+ description: "List pods. Returns pods owned by the authenticated user. Cluster member pods are excluded by default; set `includeClusterPods=true` to include them (each carries a non-null `cluster` membership block). Results are cursor-paginated newest-first; an omitted `limit` defaults to 1000. When cluster member pods are excluded, the exclusion applies to each page after it is cut, so a page may hold fewer than `limit` pods \u2014 follow `pagination.nextCursor` until `hasNextPage` is false rather than counting items.",
3759
4241
  method: "GET",
3760
4242
  path: "/v2/pods",
3761
4243
  params: [
3762
4244
  {
3763
4245
  name: "includeClusterPods",
3764
4246
  location: "query"
4247
+ },
4248
+ {
4249
+ name: "cursor",
4250
+ location: "query"
4251
+ },
4252
+ {
4253
+ name: "limit",
4254
+ location: "query"
3765
4255
  }
3766
4256
  ],
3767
4257
  hasBody: false,
4258
+ annotations: {
4259
+ readOnlyHint: true,
4260
+ destructiveHint: false,
4261
+ idempotentHint: true,
4262
+ openWorldHint: true
4263
+ },
3768
4264
  inputSchema: {
3769
4265
  type: "object",
3770
4266
  properties: {
@@ -3772,6 +4268,17 @@ var generatedTools = [
3772
4268
  type: "boolean",
3773
4269
  default: false,
3774
4270
  description: "Include cluster member pods in the result. Defaults to false."
4271
+ },
4272
+ cursor: {
4273
+ type: "string",
4274
+ minLength: 1,
4275
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\n"
4276
+ },
4277
+ limit: {
4278
+ type: "integer",
4279
+ minimum: 1,
4280
+ maximum: 1e3,
4281
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3775
4282
  }
3776
4283
  }
3777
4284
  }
@@ -3779,7 +4286,7 @@ var generatedTools = [
3779
4286
  {
3780
4287
  name: "list-public-templates",
3781
4288
  operationId: "listPublicTemplates",
3782
- description: "List public templates. Returns the public template catalog. `source` selects which slice: `official` (the default) is Runpod-curated templates, `verified` is community templates Runpod has verified, and `community` is everything else other users have shared publicly. Both pod and serverless templates appear \u2014 use each entry's `serverless` flag to tell them apart. `registry` is always null for templates you don't own. Your own templates (public or private) are managed under `/v2/templates`; fetch any individual template \u2014 catalog or owned \u2014 via `/v2/templates/{id}`. At most 100 templates are returned. Pagination is not yet supported.",
4289
+ description: "List public templates. Returns the public template catalog. `source` selects which slice: `official` (the default) is Runpod-curated templates, `verified` is community templates Runpod has verified, and `community` is everything else other users have shared publicly. Both pod and serverless templates appear \u2014 use each entry's `serverless` flag to tell them apart. `registry` is always null for templates you don't own. Your own templates (public or private) are managed under `/v2/templates`; fetch any individual template \u2014 catalog or owned \u2014 via `/v2/templates/{id}`. At most 100 templates are returned. Cursor pagination is not yet supported here; `pagination` is always the exhausted marker (`nextCursor: null`, `hasNextPage: false`).",
3783
4290
  method: "GET",
3784
4291
  path: "/v2/catalog/templates",
3785
4292
  params: [
@@ -3789,6 +4296,12 @@ var generatedTools = [
3789
4296
  }
3790
4297
  ],
3791
4298
  hasBody: false,
4299
+ annotations: {
4300
+ readOnlyHint: true,
4301
+ destructiveHint: false,
4302
+ idempotentHint: true,
4303
+ openWorldHint: true
4304
+ },
3792
4305
  inputSchema: {
3793
4306
  type: "object",
3794
4307
  properties: {
@@ -3809,11 +4322,46 @@ var generatedTools = [
3809
4322
  path: "/v2/registries",
3810
4323
  params: [],
3811
4324
  hasBody: false,
4325
+ annotations: {
4326
+ readOnlyHint: true,
4327
+ destructiveHint: false,
4328
+ idempotentHint: true,
4329
+ openWorldHint: true
4330
+ },
3812
4331
  inputSchema: {
3813
4332
  type: "object",
3814
4333
  properties: {}
3815
4334
  }
3816
4335
  },
4336
+ {
4337
+ name: "list-secrets",
4338
+ operationId: "listSecrets",
4339
+ description: "List secrets. Returns the account's secrets \u2014 encrypted strings referenced from pod, serverless, and template environment variables with the `{{ RUNPOD_SECRET_<name> }}` placeholder syntax, substituted with the secret's value when the pod or worker boots. Secret values are write-only and are never returned.",
4340
+ method: "GET",
4341
+ path: "/v2/account/secrets",
4342
+ params: [
4343
+ {
4344
+ name: "name",
4345
+ location: "query"
4346
+ }
4347
+ ],
4348
+ hasBody: false,
4349
+ annotations: {
4350
+ readOnlyHint: true,
4351
+ destructiveHint: false,
4352
+ idempotentHint: true,
4353
+ openWorldHint: true
4354
+ },
4355
+ inputSchema: {
4356
+ type: "object",
4357
+ properties: {
4358
+ name: {
4359
+ type: "string",
4360
+ description: "When provided, returns only the secret with this name (case-insensitive)."
4361
+ }
4362
+ }
4363
+ }
4364
+ },
3817
4365
  {
3818
4366
  name: "list-serverless-billing",
3819
4367
  operationId: "listServerlessBilling",
@@ -3843,6 +4391,12 @@ var generatedTools = [
3843
4391
  }
3844
4392
  ],
3845
4393
  hasBody: false,
4394
+ annotations: {
4395
+ readOnlyHint: true,
4396
+ destructiveHint: false,
4397
+ idempotentHint: true,
4398
+ openWorldHint: true
4399
+ },
3846
4400
  inputSchema: {
3847
4401
  type: "object",
3848
4402
  properties: {
@@ -3901,6 +4455,12 @@ var generatedTools = [
3901
4455
  }
3902
4456
  ],
3903
4457
  hasBody: true,
4458
+ annotations: {
4459
+ readOnlyHint: false,
4460
+ destructiveHint: true,
4461
+ idempotentHint: false,
4462
+ openWorldHint: true
4463
+ },
3904
4464
  inputSchema: {
3905
4465
  type: "object",
3906
4466
  properties: {
@@ -3944,6 +4504,12 @@ var generatedTools = [
3944
4504
  }
3945
4505
  ],
3946
4506
  hasBody: false,
4507
+ annotations: {
4508
+ readOnlyHint: false,
4509
+ destructiveHint: true,
4510
+ idempotentHint: true,
4511
+ openWorldHint: true
4512
+ },
3947
4513
  inputSchema: {
3948
4514
  type: "object",
3949
4515
  properties: {
@@ -3967,6 +4533,12 @@ var generatedTools = [
3967
4533
  }
3968
4534
  ],
3969
4535
  hasBody: true,
4536
+ annotations: {
4537
+ readOnlyHint: false,
4538
+ destructiveHint: false,
4539
+ idempotentHint: false,
4540
+ openWorldHint: true
4541
+ },
3970
4542
  inputSchema: {
3971
4543
  type: "object",
3972
4544
  properties: {
@@ -4009,6 +4581,12 @@ var generatedTools = [
4009
4581
  }
4010
4582
  ],
4011
4583
  hasBody: true,
4584
+ annotations: {
4585
+ readOnlyHint: false,
4586
+ destructiveHint: false,
4587
+ idempotentHint: false,
4588
+ openWorldHint: true
4589
+ },
4012
4590
  inputSchema: {
4013
4591
  type: "object",
4014
4592
  properties: {
@@ -4024,12 +4602,34 @@ var generatedTools = [
4024
4602
  $defs: {
4025
4603
  BaseContainerConfig: {
4026
4604
  type: "object",
4027
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
4605
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
4028
4606
  properties: {
4029
4607
  args: {
4030
4608
  type: "string",
4031
- description: "Arguments passed to the container entrypoint",
4032
- examples: [""]
4609
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
4610
+ examples: [
4611
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
4612
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
4613
+ ""
4614
+ ]
4615
+ },
4616
+ cmd: {
4617
+ type: "array",
4618
+ items: {
4619
+ type: "string"
4620
+ },
4621
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
4622
+ examples: [
4623
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
4624
+ ]
4625
+ },
4626
+ entrypoint: {
4627
+ type: "array",
4628
+ items: {
4629
+ type: "string"
4630
+ },
4631
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
4632
+ examples: [["/bin/bash", "-c"]]
4033
4633
  },
4034
4634
  disk: {
4035
4635
  type: "integer",
@@ -4088,7 +4688,7 @@ var generatedTools = [
4088
4688
  pools: {
4089
4689
  type: "array",
4090
4690
  minItems: 1,
4091
- description: "Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\n`pool`). Workers are placed on whichever listed pool has capacity.\nNarrow a pool down to specific cards with `excludedTypes`.\n",
4691
+ description: 'Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\n`pool`). Workers are placed on whichever listed pool has capacity.\nNarrow a pool down to specific cards with `excludedTypes`.\n\nOn `PATCH`, `pools` and `excludedTypes` are one selection and are\nreplaced together, so sending `pools` by itself **clears the\nexclusions**. Two cases:\n\n- **Changing pools, keeping exclusions** \u2014 send both fields in one\n request: `{"gpu": {"pools": ["ADA_24"], "excludedTypes":\n ["NVIDIA L40"]}}`. `GET` the endpoint first to read the current\n `excludedTypes` and resend the ones that still apply to the new\n pools; an exclusion naming a type outside `pools` is a 400.\n- **Changing only `count` or a CUDA constraint** \u2014 omit `pools`:\n `{"gpu": {"minCudaVersion": "12.4"}}`. The pool list and the\n exclusions are both left exactly as they are.\n\n`excludedTypes` documents the full rule.\n',
4092
4692
  items: {
4093
4693
  type: "string"
4094
4694
  },
@@ -4333,6 +4933,12 @@ var generatedTools = [
4333
4933
  }
4334
4934
  ],
4335
4935
  hasBody: true,
4936
+ annotations: {
4937
+ readOnlyHint: false,
4938
+ destructiveHint: false,
4939
+ idempotentHint: false,
4940
+ openWorldHint: true
4941
+ },
4336
4942
  inputSchema: {
4337
4943
  type: "object",
4338
4944
  properties: {
@@ -4383,6 +4989,12 @@ var generatedTools = [
4383
4989
  }
4384
4990
  ],
4385
4991
  hasBody: true,
4992
+ annotations: {
4993
+ readOnlyHint: false,
4994
+ destructiveHint: false,
4995
+ idempotentHint: false,
4996
+ openWorldHint: true
4997
+ },
4386
4998
  inputSchema: {
4387
4999
  type: "object",
4388
5000
  properties: {
@@ -4398,12 +5010,34 @@ var generatedTools = [
4398
5010
  $defs: {
4399
5011
  BaseContainerConfig: {
4400
5012
  type: "object",
4401
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
5013
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
4402
5014
  properties: {
4403
5015
  args: {
4404
5016
  type: "string",
4405
- description: "Arguments passed to the container entrypoint",
4406
- examples: [""]
5017
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
5018
+ examples: [
5019
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
5020
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
5021
+ ""
5022
+ ]
5023
+ },
5024
+ cmd: {
5025
+ type: "array",
5026
+ items: {
5027
+ type: "string"
5028
+ },
5029
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
5030
+ examples: [
5031
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
5032
+ ]
5033
+ },
5034
+ entrypoint: {
5035
+ type: "array",
5036
+ items: {
5037
+ type: "string"
5038
+ },
5039
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
5040
+ examples: [["/bin/bash", "-c"]]
4407
5041
  },
4408
5042
  disk: {
4409
5043
  type: "integer",
@@ -4546,6 +5180,60 @@ var generatedTools = [
4546
5180
  }
4547
5181
  }
4548
5182
  },
5183
+ {
5184
+ name: "update-secret",
5185
+ operationId: "updateSecret",
5186
+ description: "Update a secret. Rotates a secret's value and/or updates its description. Only the provided fields are changed and at least one field is required; the `name` is immutable. Pods and workers receive the new value at their next boot \u2014 running instances keep the value they were started with. When both fields are sent, the value is applied first, then the description. The two updates are not atomic: if the description update fails after the value was rotated, the response is an error but the new value has already taken effect. Send the fields in separate requests when that partial outcome matters.",
5187
+ method: "PATCH",
5188
+ path: "/v2/account/secrets/{id}",
5189
+ params: [
5190
+ {
5191
+ name: "id",
5192
+ location: "path"
5193
+ }
5194
+ ],
5195
+ hasBody: true,
5196
+ annotations: {
5197
+ readOnlyHint: false,
5198
+ destructiveHint: false,
5199
+ idempotentHint: false,
5200
+ openWorldHint: true
5201
+ },
5202
+ inputSchema: {
5203
+ type: "object",
5204
+ properties: {
5205
+ id: {
5206
+ type: "string",
5207
+ description: "Secret identifier"
5208
+ },
5209
+ body: {
5210
+ $ref: "#/$defs/UpdateSecretRequest"
5211
+ }
5212
+ },
5213
+ required: ["id", "body"],
5214
+ $defs: {
5215
+ UpdateSecretRequest: {
5216
+ type: "object",
5217
+ additionalProperties: false,
5218
+ minProperties: 1,
5219
+ description: "Only the provided fields are updated; at least one field is required.\nThe secret's `name` is immutable.\n",
5220
+ properties: {
5221
+ value: {
5222
+ type: "string",
5223
+ minLength: 1,
5224
+ maxLength: 16777216,
5225
+ description: "New secret value, replacing the current one. Write-only. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes)."
5226
+ },
5227
+ description: {
5228
+ type: "string",
5229
+ maxLength: 65535,
5230
+ description: 'New human-readable description, at most 65,535 bytes of UTF-8 text. Send `""` to clear.'
5231
+ }
5232
+ }
5233
+ }
5234
+ }
5235
+ }
5236
+ },
4549
5237
  {
4550
5238
  name: "update-ssh-keys",
4551
5239
  operationId: "updateSshKeys",
@@ -4554,6 +5242,12 @@ var generatedTools = [
4554
5242
  path: "/v2/account/ssh-keys",
4555
5243
  params: [],
4556
5244
  hasBody: true,
5245
+ annotations: {
5246
+ readOnlyHint: false,
5247
+ destructiveHint: true,
5248
+ idempotentHint: true,
5249
+ openWorldHint: true
5250
+ },
4557
5251
  inputSchema: {
4558
5252
  type: "object",
4559
5253
  properties: {
@@ -4599,6 +5293,12 @@ var generatedTools = [
4599
5293
  }
4600
5294
  ],
4601
5295
  hasBody: true,
5296
+ annotations: {
5297
+ readOnlyHint: false,
5298
+ destructiveHint: false,
5299
+ idempotentHint: false,
5300
+ openWorldHint: true
5301
+ },
4602
5302
  inputSchema: {
4603
5303
  type: "object",
4604
5304
  properties: {
@@ -4613,12 +5313,34 @@ var generatedTools = [
4613
5313
  $defs: {
4614
5314
  BaseContainerConfig: {
4615
5315
  type: "object",
4616
- description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support private registries (clusters, until the upstream input accepts a registry credential).\n",
5316
+ description: "Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters \u2014 there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\n",
4617
5317
  properties: {
4618
5318
  args: {
4619
5319
  type: "string",
4620
- description: "Arguments passed to the container entrypoint",
4621
- examples: [""]
5320
+ description: 'The container\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\n\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\'s "Container start command" field writes. A JSON object of the form `{"entrypoint":[...],"cmd":[...]}` sets either or both explicitly.\n\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `""` to clear, omit to leave unchanged.\n',
5321
+ examples: [
5322
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
5323
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
5324
+ ""
5325
+ ]
5326
+ },
5327
+ cmd: {
5328
+ type: "array",
5329
+ items: {
5330
+ type: "string"
5331
+ },
5332
+ description: "Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
5333
+ examples: [
5334
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
5335
+ ]
5336
+ },
5337
+ entrypoint: {
5338
+ type: "array",
5339
+ items: {
5340
+ type: "string"
5341
+ },
5342
+ description: "Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\n",
5343
+ examples: [["/bin/bash", "-c"]]
4622
5344
  },
4623
5345
  disk: {
4624
5346
  type: "integer",
@@ -4935,6 +5657,26 @@ var listPaginationProperties = {
4935
5657
  description: "Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning."
4936
5658
  }
4937
5659
  };
5660
+ function clampListLimit(limit) {
5661
+ const requested = Number(limit);
5662
+ return Math.min(
5663
+ Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
5664
+ MAX_LIST_LIMIT
5665
+ );
5666
+ }
5667
+ function serverPageQuery(args) {
5668
+ const cursor = typeof args.cursor === "string" && args.cursor !== "" ? args.cursor : void 0;
5669
+ return { limit: clampListLimit(args.limit), ...cursor ? { cursor } : {} };
5670
+ }
5671
+ function serverPagination(pagination, returned) {
5672
+ const hasNextPage = pagination?.hasNextPage === true;
5673
+ return {
5674
+ returned,
5675
+ hasNextPage,
5676
+ nextCursor: pagination?.nextCursor ?? null,
5677
+ ...hasNextPage ? { note: "More results exist. Pass cursor=nextCursor to fetch them." } : {}
5678
+ };
5679
+ }
4938
5680
  function decodeCursorOffset(cursor) {
4939
5681
  if (!cursor) return 0;
4940
5682
  try {
@@ -4950,11 +5692,7 @@ function encodeCursorOffset(offset) {
4950
5692
  return Buffer.from(String(offset), "utf8").toString("base64");
4951
5693
  }
4952
5694
  function capList(items, options, extra) {
4953
- const requested = Number(options.limit);
4954
- const limit = Math.min(
4955
- Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
4956
- MAX_LIST_LIMIT
4957
- );
5695
+ const limit = clampListLimit(options.limit);
4958
5696
  const offset = decodeCursorOffset(options.cursor);
4959
5697
  const total = items.length;
4960
5698
  const page = items.slice(offset, offset + limit);
@@ -5033,6 +5771,38 @@ async function runTool(body) {
5033
5771
  }
5034
5772
  }
5035
5773
 
5774
+ // src/specgen/tools/annotations.ts
5775
+ var readOnly = {
5776
+ readOnlyHint: true,
5777
+ destructiveHint: false,
5778
+ idempotentHint: true,
5779
+ openWorldHint: true
5780
+ };
5781
+ var bundledRead = {
5782
+ readOnlyHint: true,
5783
+ destructiveHint: false,
5784
+ idempotentHint: true,
5785
+ openWorldHint: false
5786
+ };
5787
+ var write = {
5788
+ readOnlyHint: false,
5789
+ destructiveHint: false,
5790
+ idempotentHint: false,
5791
+ openWorldHint: true
5792
+ };
5793
+ var idempotentWrite = {
5794
+ readOnlyHint: false,
5795
+ destructiveHint: false,
5796
+ idempotentHint: true,
5797
+ openWorldHint: true
5798
+ };
5799
+ var destructive = {
5800
+ readOnlyHint: false,
5801
+ destructiveHint: true,
5802
+ idempotentHint: true,
5803
+ openWorldHint: true
5804
+ };
5805
+
5036
5806
  // src/specgen/tools/capacity.ts
5037
5807
  var CUDA_VERSION_REGEX = /^\d{1,2}\.\d{1,2}$/;
5038
5808
  var MAX_PROBE_VERSIONS = 12;
@@ -5067,6 +5837,7 @@ function rankByStock(rows, stats, includeUnavailable) {
5067
5837
  }
5068
5838
  var getCapacity = {
5069
5839
  name: "get-capacity",
5840
+ annotations: readOnly,
5070
5841
  description: "GPU capacity across host CUDA versions, as a matrix. Use this to choose an endpoint's allowedCudaVersions/minCudaVersion (or diagnose/widen a capacity-starved one) and to distinguish capacity problems from compatibility problems. Default mode is one call returning, per GPU type, overall stock plus AVAILABLE/UNAVAILABLE per host-reported CUDA version. Pass cudaVersions to deep-probe instead: one stock lookup per listed version, returning graded stock (High/Medium/Low/Out) and the lowest on-demand price per version; a probe that fails transiently reports a per-version error instead of failing the call. Nothing is hidden by default \u2014 set includeUnavailable:false to drop GPUs with no stock on any listed version. Credential-free public catalog data. Stock is live, so page cursors can shift between calls.",
5071
5842
  inputSchema: {
5072
5843
  type: "object",
@@ -5267,6 +6038,7 @@ function formatGpuIds(gpu) {
5267
6038
  }
5268
6039
  var setEndpointGpus = {
5269
6040
  name: "set-endpoint-gpus",
6041
+ annotations: idempotentWrite,
5270
6042
  description: "Set which GPUs a Serverless endpoint's workers run on \u2014 including pinning specific GPU SKUs. Provide either a raw gpuIds string, or pools plus optional excludeGpuTypeIds (GPU type ids from list-gpu-types) and the exclusion string is built for you: a pool allows every SKU in it, and excluding all but one SKU pins that SKU exactly. Updates only GPU settings through REST v2, preserving other endpoint settings. create-endpoint/update-endpoint also support gpu.excludedTypes.",
5271
6043
  inputSchema: {
5272
6044
  type: "object",
@@ -5460,6 +6232,7 @@ function randomSuffix() {
5460
6232
  }
5461
6233
  var listHubRepos = {
5462
6234
  name: "list-hub-repos",
6235
+ annotations: readOnly,
5463
6236
  description: "List repos published to the Runpod Hub (prebuilt Serverless workers and Pod templates, e.g. vLLM, ComfyUI). Public catalog \u2014 no auth required. Each result includes the currently listed release with its hubReleaseId and prebuilt image name. Results are sorted by deploy count (most popular first). Set includeConfig:true to also return the release config (hardware requirements and environment-variable schema) \u2014 it is large, so prefer requesting it for a single repo via the repoOwner/searchTerm filters.",
5464
6237
  inputSchema: {
5465
6238
  type: "object",
@@ -5561,6 +6334,7 @@ var listHubRepos = {
5561
6334
  };
5562
6335
  var deployHubRepo = {
5563
6336
  name: "deploy-hub-repo",
6337
+ annotations: write,
5564
6338
  description: "Deploy a Runpod Hub repo's listed release as a new Serverless endpoint (the same as clicking Deploy on the Hub). Identify the repo by `repo` (\"owner/name\" from list-hub-repos) or by `hubReleaseId`. The release supplies the prebuilt image, container disk, CUDA constraints, and env-var defaults; pass `env` to override or fill in values (required keys without a default must be provided \u2014 check list-hub-repos with includeConfig:true for the schema). GPU selection comes from the release config when it specifies one; otherwise pass gpuIds (GPU pool names, e.g. 'ADA_24' or 'ADA_80_PRO,AMPERE_80'). Uses the authenticated GraphQL API (no REST home for Hub deploys yet).",
5565
6339
  inputSchema: {
5566
6340
  type: "object",
@@ -6018,6 +6792,7 @@ function validateWait(wait) {
6018
6792
  }
6019
6793
  var runEndpoint = {
6020
6794
  name: "run-endpoint",
6795
+ annotations: write,
6021
6796
  description: "Submit an asynchronous job to a Serverless endpoint. Returns a job ID immediately \u2014 use get-job-status to poll for results (pass its `wait` to block through a cold start instead of tight-looping). Async results are available for 30 minutes after completion.",
6022
6797
  inputSchema: {
6023
6798
  type: "object",
@@ -6047,6 +6822,7 @@ var runEndpoint = {
6047
6822
  };
6048
6823
  var runsyncEndpoint = {
6049
6824
  name: "runsync-endpoint",
6825
+ annotations: write,
6050
6826
  description: "Submit a synchronous job to a Serverless endpoint and wait for the result. Best for fast tasks: if the job outlives the wait, the response returns a job ID and a non-terminal status (IN_QUEUE or IN_PROGRESS) to poll with get-job-status. Max payload 20 MB; results expire after 1 minute. The wait parameter extends the server-side wait" + (HOSTED ? ` \u2014 this server runs behind a 60-second gateway deadline, so waits clamp to ${HTTP_LONG_POLL_BUDGET_MS} ms, which is also the effective default. For longer jobs use run-endpoint + get-job-status.` : " to up to 5 minutes (300000 ms); it defaults to 90000 (90 seconds)."),
6051
6827
  inputSchema: {
6052
6828
  type: "object",
@@ -6090,6 +6866,7 @@ var runsyncEndpoint = {
6090
6866
  };
6091
6867
  var getJobStatus = {
6092
6868
  name: "get-job-status",
6869
+ annotations: readOnly,
6093
6870
  description: "Check the status of a Serverless job. Returns the current status and output when complete. Job statuses: IN_QUEUE, IN_PROGRESS, COMPLETED, FAILED, CANCELLED, TIMED_OUT. Pass `wait` (milliseconds, up to " + STATUS_WAIT_MAX_MS + ") to BLOCK server-side, polling until the job reaches a terminal status or the budget expires \u2014 use it to ride out a cold start (a first job on a fresh worker pulls the image and loads the model, commonly 1\u20135+ minutes) in a single call instead of returning on the first IN_QUEUE and tight-looping the tool. Without `wait` it returns the current status immediately (a single check). If the budget expires before a terminal status, it returns the latest non-terminal status with pollingTimedOut:true \u2014 call again (with `wait`) to keep blocking. IMPORTANT: a job stuck IN_QUEUE does not necessarily mean a capacity shortage \u2014 a worker may have spun up and crash-looped. When the job is IN_QUEUE this tool attaches a workerHealth summary and a hint. To dig deeper call list-endpoint-workers, then read stream-worker-logs regardless of the status a worker reports: a container failing to start loops while its worker still shows RUNNING or THROTTLED and unhealthy stays 0, so UNHEALTHY is one symptom of a crash loop and not a test for it. The logs are the authority.",
6094
6871
  inputSchema: {
6095
6872
  type: "object",
@@ -6137,6 +6914,7 @@ var getJobStatus = {
6137
6914
  };
6138
6915
  var streamJob = {
6139
6916
  name: "stream-job",
6917
+ annotations: readOnly,
6140
6918
  description: `Retrieve streaming output from a Serverless job. The worker must support streaming output. Polls /stream/{jobId} and collects chunks until the status is COMPLETED, FAILED, CANCELLED, or TIMED_OUT, for up to ${formatBudget(STREAM_BUDGET_MS)}. If the budget expires first, returns the chunks collected so far with pollingTimedOut: true \u2014 call stream-job again to resume where it left off, or get-job-status to check without streaming.`,
6141
6919
  inputSchema: {
6142
6920
  type: "object",
@@ -6167,6 +6945,7 @@ var streamJob = {
6167
6945
  };
6168
6946
  var cancelJob = {
6169
6947
  name: "cancel-job",
6948
+ annotations: destructive,
6170
6949
  description: "Cancel a Serverless job that is queued or in progress.",
6171
6950
  inputSchema: {
6172
6951
  type: "object",
@@ -6191,6 +6970,7 @@ var cancelJob = {
6191
6970
  };
6192
6971
  var retryJob = {
6193
6972
  name: "retry-job",
6973
+ annotations: write,
6194
6974
  description: "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.",
6195
6975
  inputSchema: {
6196
6976
  type: "object",
@@ -6215,6 +6995,7 @@ var retryJob = {
6215
6995
  };
6216
6996
  var endpointHealth = {
6217
6997
  name: "endpoint-health",
6998
+ annotations: readOnly,
6218
6999
  description: "Get the endpoint-level health rollup for a Serverless endpoint: worker counts by state plus job queue statistics. This is the runtime plane's own /health view and it can lag or disagree with the per-worker truth \u2014 when a job is stuck IN_QUEUE, prefer list-endpoint-workers over this rollup for per-worker state \u2014 but treat neither as the authority on crash loops, because a container failing to start loops while its worker reports RUNNING or THROTTLED and unhealthy stays 0; stream-worker-logs is what settles it, and note that get-job-status already attaches that worker summary and a hint on every IN_QUEUE result. Zero workers here means the endpoint is waiting for GPU capacity.",
6219
7000
  inputSchema: {
6220
7001
  type: "object",
@@ -6234,6 +7015,7 @@ var endpointHealth = {
6234
7015
  };
6235
7016
  var purgeEndpointQueue = {
6236
7017
  name: "purge-endpoint-queue",
7018
+ annotations: destructive,
6237
7019
  description: "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.",
6238
7020
  inputSchema: {
6239
7021
  type: "object",
@@ -6269,13 +7051,16 @@ var jobTools = [
6269
7051
  // src/specgen/tools/list-endpoints.ts
6270
7052
  var listEndpoints = {
6271
7053
  name: "list-endpoints",
7054
+ annotations: readOnly,
6272
7055
  description: "List serverless endpoints owned by the account (trimmed: id, name, image, compute config, worker counts, scaling, data centers per endpoint \u2014 env vars and request URLs are omitted; use get-endpoint for the full object). Returns a page; pass cursor=nextCursor for more.",
6273
7056
  inputSchema: {
6274
7057
  type: "object",
6275
7058
  properties: { ...listPaginationProperties }
6276
7059
  },
6277
7060
  async handler(ctx, args) {
6278
- const { data, error, response } = await ctx.sdk.GET("/v2/serverless");
7061
+ const { data, error, response } = await ctx.sdk.GET("/v2/serverless", {
7062
+ params: { query: serverPageQuery(args) }
7063
+ });
6279
7064
  if (!response.ok) return restError(response, error);
6280
7065
  if (!data || !Array.isArray(data.endpoints)) {
6281
7066
  return {
@@ -6300,10 +7085,10 @@ var listEndpoints = {
6300
7085
  return {
6301
7086
  ok: true,
6302
7087
  status: response.status,
6303
- payload: capList(trimmed, {
6304
- limit: args.limit,
6305
- cursor: args.cursor
6306
- })
7088
+ payload: {
7089
+ items: trimmed,
7090
+ pagination: serverPagination(data.pagination, trimmed.length)
7091
+ }
6307
7092
  };
6308
7093
  }
6309
7094
  };
@@ -6311,10 +7096,16 @@ var listEndpoints = {
6311
7096
  // src/specgen/tools/list-templates.ts
6312
7097
  var listTemplates = {
6313
7098
  name: "list-templates",
6314
- description: "List templates visible to the account. Returns id, name, image, and serverless flag per template; use get-template for full detail.",
6315
- inputSchema: { type: "object", properties: {} },
6316
- async handler(ctx) {
6317
- const { data, error, response } = await ctx.sdk.GET("/v2/templates");
7099
+ annotations: readOnly,
7100
+ description: "List templates visible to the account. Returns id, name, image, and serverless flag per template; use get-template for full detail. Returns 20 templates per page by default. To find a template, follow `pagination.nextCursor` until `hasNextPage` is false: a name missing from one page may be on a later one.",
7101
+ inputSchema: {
7102
+ type: "object",
7103
+ properties: { ...listPaginationProperties }
7104
+ },
7105
+ async handler(ctx, args) {
7106
+ const { data, error, response } = await ctx.sdk.GET("/v2/templates", {
7107
+ params: { query: serverPageQuery(args) }
7108
+ });
6318
7109
  if (!response.ok) return restError(response, error);
6319
7110
  if (!data || !Array.isArray(data.templates)) {
6320
7111
  return {
@@ -6332,7 +7123,8 @@ var listTemplates = {
6332
7123
  name: template.name,
6333
7124
  image: template.image,
6334
7125
  serverless: template.serverless
6335
- }))
7126
+ })),
7127
+ pagination: serverPagination(data.pagination, data.templates.length)
6336
7128
  }
6337
7129
  };
6338
7130
  }
@@ -6341,7 +7133,7 @@ var listTemplates = {
6341
7133
  // src/specgen/tools/logs.ts
6342
7134
  init_hosts();
6343
7135
 
6344
- // node_modules/.pnpm/@runpod+typescript-api-sdk@0.1.1/node_modules/@runpod/typescript-api-sdk/dist/index.js
7136
+ // node_modules/.pnpm/@runpod+typescript-api-sdk@0.2.0/node_modules/@runpod/typescript-api-sdk/dist/index.js
6345
7137
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
6346
7138
  var supportsRequestInitExt = () => {
6347
7139
  return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
@@ -7745,6 +8537,7 @@ function logParams(args) {
7745
8537
  }
7746
8538
  var streamPodLogs = {
7747
8539
  name: "stream-pod-logs",
8540
+ annotations: readOnly,
7748
8541
  description: "Read a bounded snapshot of a Pod's logs (container and/or system source). Holds the live stream open for maxWaitMs and returns the parsed log lines; `truncated: true` means the byte cap cut the output. Use `since` to resume from a timestamp.",
7749
8542
  inputSchema: {
7750
8543
  type: "object",
@@ -7766,6 +8559,7 @@ var streamPodLogs = {
7766
8559
  };
7767
8560
  var streamWorkerLogs = {
7768
8561
  name: "stream-worker-logs",
8562
+ annotations: readOnly,
7769
8563
  description: "Read a bounded snapshot of a Serverless worker's logs (container and/or system source). Holds the live stream open for maxWaitMs and returns the parsed log lines; `truncated: true` means the byte cap cut the output. Get worker IDs from list-endpoint-workers. Use this whenever a job stays IN_QUEUE while workers exist, whatever status they report \u2014 a crash-looping container often still shows RUNNING or THROTTLED with unhealthy 0, so these logs, not the worker status, are what identify a crash loop.",
7770
8564
  inputSchema: {
7771
8565
  type: "object",
@@ -7806,6 +8600,7 @@ function parseMetadata(metadata) {
7806
8600
  }
7807
8601
  var listPublicEndpoints = {
7808
8602
  name: "list-public-endpoints",
8603
+ annotations: readOnly,
7809
8604
  description: "List Runpod Public Endpoints \u2014 managed, pay-per-use model APIs (text, image, video, audio) that require no deployment. Public catalog, no auth required. Each result includes the endpointId to call with run-endpoint/runsync-endpoint (or via https://api.runpod.ai/v2/{endpointId}), the model name, modality, owner, and pricing. Only live endpoints are returned by default; set includeOffline:true to also list ones that are not currently live.",
7810
8605
  inputSchema: {
7811
8606
  type: "object",
@@ -7904,6 +8699,316 @@ var listPublicEndpoints = {
7904
8699
  })
7905
8700
  };
7906
8701
 
8702
+ // src/specgen/tools/knowledge.ts
8703
+ var import_plugin_knowledge = require("@runpod/plugin-knowledge");
8704
+ var knowledge = (0, import_plugin_knowledge.loadKnowledge)();
8705
+ var GUIDE_KINDS = ["skill", "reference", "golden-path"];
8706
+ var STOPWORDS = new Set(
8707
+ "a an and are as at be by can do does for from how i in is it my of on or the to what when why with you your".split(
8708
+ " "
8709
+ )
8710
+ );
8711
+ var singular = (word) => {
8712
+ if (word.length > 4 && word.endsWith("ies")) return `${word.slice(0, -3)}y`;
8713
+ if (word.length > 3 && word.endsWith("s") && !word.endsWith("ss"))
8714
+ return word.slice(0, -1);
8715
+ return word;
8716
+ };
8717
+ var words = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 1 && !STOPWORDS.has(word)).map(singular);
8718
+ function editDistance(a, b, max) {
8719
+ if (Math.abs(a.length - b.length) > max) return max + 1;
8720
+ let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
8721
+ for (let i = 1; i <= a.length; i++) {
8722
+ const current = [i];
8723
+ for (let j = 1; j <= b.length; j++) {
8724
+ current[j] = Math.min(
8725
+ previous[j] + 1,
8726
+ current[j - 1] + 1,
8727
+ previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
8728
+ );
8729
+ }
8730
+ if (Math.min(...current) > max) return max + 1;
8731
+ previous = current;
8732
+ }
8733
+ return previous[b.length];
8734
+ }
8735
+ var typoBudget = (text) => text.length >= 8 ? 2 : text.length >= 4 ? 1 : 0;
8736
+ var oneTypo = (word, term) => term.length >= 5 && editDistance(word, term, 1) <= 1;
8737
+ var termMatches = (word, term) => word.startsWith(term) || oneTypo(word, term);
8738
+ var nameMatches = (name, term) => name === term || oneTypo(name, term);
8739
+ var guideSummary = ({
8740
+ id,
8741
+ kind,
8742
+ title,
8743
+ description,
8744
+ lanes,
8745
+ mcp,
8746
+ needs_shell,
8747
+ concepts
8748
+ }) => ({
8749
+ id,
8750
+ kind,
8751
+ title,
8752
+ description,
8753
+ lanes,
8754
+ mcp,
8755
+ needs_shell,
8756
+ concepts
8757
+ });
8758
+ function linkedGuides(conceptId) {
8759
+ const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));
8760
+ const seen = /* @__PURE__ */ new Set();
8761
+ const examples = [];
8762
+ const docs = [];
8763
+ for (const link of knowledge.links) {
8764
+ if (link.to !== conceptId || seen.has(link.from)) continue;
8765
+ seen.add(link.from);
8766
+ const guide = byId.get(link.from);
8767
+ if (!guide) continue;
8768
+ if (guide.kind === "golden-path")
8769
+ examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });
8770
+ else
8771
+ docs.push({
8772
+ id: guide.id,
8773
+ title: guide.title,
8774
+ ...link.rules ? { rules: link.rules } : {}
8775
+ });
8776
+ }
8777
+ return { examples, docs };
8778
+ }
8779
+ var conceptIndex = /* @__PURE__ */ new Map();
8780
+ for (const concept of knowledge.concepts) {
8781
+ for (const key of [concept.id, concept.name, ...concept.aliases]) {
8782
+ if (!conceptIndex.has(key.toLowerCase()))
8783
+ conceptIndex.set(key.toLowerCase(), concept);
8784
+ }
8785
+ }
8786
+ var conceptKey = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).map(singular).join(" ");
8787
+ var conceptKeyIndex = /* @__PURE__ */ new Map();
8788
+ for (const [key, concept] of conceptIndex) {
8789
+ if (!conceptKeyIndex.has(conceptKey(key)))
8790
+ conceptKeyIndex.set(conceptKey(key), concept);
8791
+ }
8792
+ function resolveConcept(input) {
8793
+ const exact = conceptIndex.get(input.trim().toLowerCase());
8794
+ if (exact) return { concept: exact };
8795
+ const key = conceptKey(input);
8796
+ const plural = conceptKeyIndex.get(key);
8797
+ if (plural) return { concept: plural, matchedAs: key };
8798
+ const budget = typoBudget(key);
8799
+ let best;
8800
+ let tied = false;
8801
+ for (const [candidate, concept] of conceptKeyIndex) {
8802
+ const distance = editDistance(key, candidate, budget);
8803
+ if (distance > budget) continue;
8804
+ if (!best || distance < best.distance) {
8805
+ best = { concept, key: candidate, distance };
8806
+ tied = false;
8807
+ } else if (distance === best.distance && concept.id !== best.concept.id) {
8808
+ tied = true;
8809
+ }
8810
+ }
8811
+ return best && !tied ? { concept: best.concept, matchedAs: best.key } : void 0;
8812
+ }
8813
+ var ruleIndex = /* @__PURE__ */ new Map();
8814
+ for (const concept of knowledge.concepts) {
8815
+ for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });
8816
+ }
8817
+ var source = {
8818
+ plugin_version: knowledge.version,
8819
+ plugin_commit: knowledge.commit
8820
+ };
8821
+ var listGuides = {
8822
+ name: "list-guides",
8823
+ annotations: bundledRead,
8824
+ description: "List the official Runpod guides: skills (how to work with each tool), reference docs (how Runpod works), and golden paths (live-verified end-to-end walkthroughs such as a dev pod, a Whisper endpoint or a fine-tune-to-serverless pipeline). Read one with read-guide. For a golden path, mcp says whether an agent with only these MCP tools can finish it: full (follow it with tool calls), partial (use it for the plan and facts; name the step the user must run in a terminal), none (reference only). Skills and reference docs have mcp null. concepts lists the concept ids it works with (see lookup-concept). Filter with kind, query or concept.",
8825
+ inputSchema: {
8826
+ type: "object",
8827
+ properties: {
8828
+ kind: {
8829
+ type: "string",
8830
+ enum: [...GUIDE_KINDS],
8831
+ description: "Only this kind of guide."
8832
+ },
8833
+ query: {
8834
+ type: "string",
8835
+ description: "Words to match against the id, title and description."
8836
+ },
8837
+ concept: {
8838
+ type: "string",
8839
+ description: 'Only guides linked to this concept id, for example "network-volume".'
8840
+ }
8841
+ },
8842
+ additionalProperties: false
8843
+ },
8844
+ handler: async (_ctx, args) => {
8845
+ const kind = args.kind;
8846
+ const terms = words(String(args.query ?? ""));
8847
+ const concept = args.concept ? String(args.concept).trim() : void 0;
8848
+ const guides = knowledge.guides.filter((guide) => !kind || guide.kind === kind).filter((guide) => !concept || guide.concepts.includes(concept)).filter((guide) => {
8849
+ if (!terms.length) return true;
8850
+ const haystack = `${guide.id} ${guide.title} ${guide.description}`.toLowerCase();
8851
+ return terms.some((term) => haystack.includes(term));
8852
+ }).map(guideSummary);
8853
+ return ok({ ...source, count: guides.length, guides });
8854
+ }
8855
+ };
8856
+ var readGuide = {
8857
+ name: "read-guide",
8858
+ annotations: bundledRead,
8859
+ description: 'Read one official Runpod guide in full, by the id list-guides returns (for example "runpod-usage/storage" or "golden-path/06-dev-pod").',
8860
+ inputSchema: {
8861
+ type: "object",
8862
+ properties: {
8863
+ id: { type: "string", description: "The guide id from list-guides." }
8864
+ },
8865
+ required: ["id"],
8866
+ additionalProperties: false
8867
+ },
8868
+ handler: async (_ctx, args) => {
8869
+ const id = String(args.id).trim();
8870
+ const guide = knowledge.guides.find((candidate) => candidate.id === id);
8871
+ if (!guide) {
8872
+ const close = knowledge.guides.filter(
8873
+ (candidate) => candidate.id.includes(id) || id.includes(candidate.id)
8874
+ ).map((candidate) => candidate.id);
8875
+ return {
8876
+ ok: false,
8877
+ status: 404,
8878
+ payload: {
8879
+ error: `No guide with id "${id}".`,
8880
+ hint: close.length ? `Did you mean: ${close.join(", ")}?` : "Call list-guides for the ids."
8881
+ }
8882
+ };
8883
+ }
8884
+ return ok({
8885
+ ...source,
8886
+ ...guideSummary(guide),
8887
+ parent: guide.parent,
8888
+ path: guide.path,
8889
+ body: guide.body
8890
+ });
8891
+ }
8892
+ };
8893
+ var lookupConcept = {
8894
+ name: "lookup-concept",
8895
+ annotations: bundledRead,
8896
+ description: 'Look up one Runpod concept (pod, network volume, machine, worker, template, \u2026) by id, name or alias; case, plurals and small typos are tolerated, and `matched_as` shows the key used when the match was not exact. Returns its summary, fields, states, relations and rules, each rule with the public source it comes from, the concepts that point at it, and the linked guides: examples (golden paths that use it, with their mcp level) and docs (skills and reference docs that explain it). Use it for exact facts, for example "is a volume disk tied to one machine" or "what happens to a stopped pod\'s GPU".',
8897
+ inputSchema: {
8898
+ type: "object",
8899
+ properties: {
8900
+ concept: {
8901
+ type: "string",
8902
+ description: 'An id, name or alias, such as "pod", "Network volume" or "volume disk".'
8903
+ }
8904
+ },
8905
+ required: ["concept"],
8906
+ additionalProperties: false
8907
+ },
8908
+ handler: async (_ctx, args) => {
8909
+ const resolved = resolveConcept(String(args.concept));
8910
+ if (!resolved) {
8911
+ const ref = conceptKey(String(args.concept));
8912
+ const close = [...conceptKeyIndex.keys()].filter(
8913
+ (key) => key.includes(ref) || editDistance(key, ref, typoBudget(ref) + 1) <= typoBudget(ref) + 1
8914
+ ).slice(0, 10);
8915
+ return {
8916
+ ok: false,
8917
+ status: 404,
8918
+ payload: {
8919
+ error: `No concept matches "${args.concept}".`,
8920
+ hint: close.length ? `Close matches: ${close.join(", ")}.` : "Try search-concepts with a few words instead."
8921
+ }
8922
+ };
8923
+ }
8924
+ const { concept, matchedAs } = resolved;
8925
+ const pointedAtBy = knowledge.concepts.flatMap((other) => [
8926
+ ...other.is_a === concept.id ? [{ concept: other.id, type: "is_a" }] : [],
8927
+ ...other.part_of === concept.id ? [{ concept: other.id, type: "part_of" }] : [],
8928
+ ...other.relations.filter((relation) => relation.target === concept.id).map((relation) => ({ concept: other.id, type: relation.type }))
8929
+ ]);
8930
+ const linkedRules = [...new Set(concept.rules.flatMap((rule) => rule.see))].map((id) => ruleIndex.get(id)).filter((entry) => entry !== void 0).map(({ rule, concept: owner }) => ({
8931
+ concept: owner.id,
8932
+ id: rule.id,
8933
+ statement: rule.statement.trim()
8934
+ }));
8935
+ return ok({
8936
+ ...source,
8937
+ ...matchedAs ? { matched_as: matchedAs } : {},
8938
+ ...concept,
8939
+ pointed_at_by: pointedAtBy,
8940
+ linked_rules: linkedRules,
8941
+ ...linkedGuides(concept.id)
8942
+ });
8943
+ }
8944
+ };
8945
+ var searchConcepts = {
8946
+ name: "search-concepts",
8947
+ annotations: bundledRead,
8948
+ description: 'Search the rules of the Runpod concept graph by words, for example "restart stopped pod no gpu" or "network volume data center". Returns the best-matching rules with their concept and public evidence. Follow up with lookup-concept for the full concept.',
8949
+ inputSchema: {
8950
+ type: "object",
8951
+ properties: {
8952
+ query: {
8953
+ type: "string",
8954
+ description: "A few words describing the question."
8955
+ },
8956
+ limit: {
8957
+ type: "integer",
8958
+ minimum: 1,
8959
+ maximum: 25,
8960
+ description: "Most rules to return. Default 8."
8961
+ }
8962
+ },
8963
+ required: ["query"],
8964
+ additionalProperties: false
8965
+ },
8966
+ handler: async (_ctx, args) => {
8967
+ const terms = words(String(args.query));
8968
+ if (!terms.length) return badRequest("query needs at least one word.");
8969
+ const limit = Math.min(Math.max(Number(args.limit) || 8, 1), 25);
8970
+ const hits = [...ruleIndex.values()].map(({ rule, concept }) => {
8971
+ const statement = words(rule.statement);
8972
+ const names = words(
8973
+ [concept.id, concept.name, ...concept.aliases].join(" ")
8974
+ );
8975
+ const ruleId = words(rule.id);
8976
+ const score = terms.reduce(
8977
+ (total, term) => total + statement.filter((word) => termMatches(word, term)).length + (names.some((name) => nameMatches(name, term)) ? 3 : 0) + (ruleId.includes(term) ? 1 : 0),
8978
+ 0
8979
+ );
8980
+ const matched = terms.filter(
8981
+ (term) => statement.some((word) => termMatches(word, term)) || names.some((name) => nameMatches(name, term))
8982
+ ).length;
8983
+ return { rule, concept, score: score * matched };
8984
+ }).filter((hit) => hit.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map(({ rule, concept }) => ({
8985
+ concept: concept.id,
8986
+ concept_name: concept.name,
8987
+ id: rule.id,
8988
+ statement: rule.statement.trim(),
8989
+ status: rule.status,
8990
+ conflict: rule.conflict,
8991
+ evidence: rule.evidence
8992
+ }));
8993
+ return ok({ ...source, count: hits.length, rules: hits });
8994
+ }
8995
+ };
8996
+ var knowledgeTools = [
8997
+ listGuides,
8998
+ readGuide,
8999
+ lookupConcept,
9000
+ searchConcepts
9001
+ ];
9002
+ var GUIDE_URI_PREFIX = "runpod://guides/";
9003
+ var guideResources = knowledge.guides.map((guide) => ({
9004
+ uri: `${GUIDE_URI_PREFIX}${guide.id}`,
9005
+ name: guide.id,
9006
+ title: guide.title,
9007
+ description: guide.description,
9008
+ mimeType: "text/markdown",
9009
+ text: guide.body
9010
+ }));
9011
+
7907
9012
  // src/specgen/analytics.ts
7908
9013
  var import_node_crypto = require("crypto");
7909
9014
  var CAPTURE_TIMEOUT_MS = 3e3;
@@ -8322,6 +9427,7 @@ function createAlpTools(opts) {
8322
9427
  // is ignored, never a 400 that derails the task the agent is actually on.
8323
9428
  lenientArguments: true,
8324
9429
  name: "report_feedback",
9430
+ annotations: write,
8325
9431
  description: "Report a problem or friction with Runpod or these tools: a wrong result, a confusing error, a docs gap, an API behavior that surprised you. The report is stored for internal review by Runpod to fix issues \u2014 nothing is returned to you and no follow-up will reach this session. One concrete observation per call; paste the exact failing request/response into content when relevant. Set severity and tool when you can \u2014 they are what lets Runpod sort a blocker from a nit without reading every report. Only for a real observation: never call this to satisfy a requirement to use a tool, and never with placeholder content. Never include API keys or secrets.",
8326
9432
  inputSchema: alpInputSchema(
8327
9433
  "The observation: what happened, what you expected, and the exact error or response text if you have it.",
@@ -8357,6 +9463,7 @@ function createAlpTools(opts) {
8357
9463
  // is ignored, never a 400 that derails the task the agent is actually on.
8358
9464
  lenientArguments: true,
8359
9465
  name: "save_to_journal",
9466
+ annotations: write,
8360
9467
  description: "Save something you learned about using Runpod that a future session would benefit from (e.g. 'image X needs CUDA 12.8', 'endpoint type cannot be changed after create'). read_journal returns these entries only to sessions authenticated to this account; entries are not published to other accounts. Runpod stores and reviews submissions to improve agent workflows. Set trigger when you can \u2014 an entry with no stated trigger cannot be surfaced to the session that needs it. Never include API keys or secrets.",
8361
9468
  inputSchema: alpInputSchema(
8362
9469
  "The learning, stated so a future agent can act on it: the situation, what turned out to be true, and how you verified it.",
@@ -8387,6 +9494,7 @@ function createAlpTools(opts) {
8387
9494
  // is ignored, never a 400 that derails the task the agent is actually on.
8388
9495
  lenientArguments: true,
8389
9496
  name: "ask_question",
9497
+ annotations: write,
8390
9498
  description: "Record a question about Runpod that you could not answer with the available tools, skills, and docs. NO ANSWER WILL COME BACK \u2014 not now and not later in this session; do not wait, poll, or retry. Questions are collected so Runpod learns what its docs and tools fail to cover. Ask when genuinely stuck (it costs one call and improves what future agents get), then consult the runpod://skills/ resources and continue with your best judgment. Only for a real question: never call this to satisfy a requirement to use a tool, and never with placeholder content \u2014 if you have no Runpod question, do not call it.",
8391
9499
  inputSchema: alpInputSchema(
8392
9500
  "The question, with enough context that someone reading it later understands what you were blocked on.",
@@ -8411,6 +9519,7 @@ function createAlpTools(opts) {
8411
9519
  const readJournalTool = {
8412
9520
  lenientArguments: true,
8413
9521
  name: "read_journal",
9522
+ annotations: readOnly,
8414
9523
  description: "Read back this account's private journal: the lessons earlier sessions on this account saved with save_to_journal, newest first. Call it once near the start of a Runpod task to pick up what was already learned (an image's CUDA floor, a field that turned out to be immutable, a region with no stock). Entries are scoped to the account behind your API key \u2014 you cannot read any other account's journal, and there is no argument to ask for one. Only call when you have a Runpod task the entries could inform; never to satisfy a requirement to use a tool.",
8415
9524
  inputSchema: {
8416
9525
  type: "object",
@@ -8461,7 +9570,8 @@ var curatedTools = [
8461
9570
  getCapacity,
8462
9571
  ...hubTools,
8463
9572
  setEndpointGpus,
8464
- listPublicEndpoints
9573
+ listPublicEndpoints,
9574
+ ...knowledgeTools
8465
9575
  ];
8466
9576
  var SERVER_INSTRUCTIONS = `These tools cover the Runpod v2 REST surface: compute catalog (GPUs, CPUs, data centers, capacity), pods, serverless endpoints and jobs, templates, network volumes, container registries, billing, public endpoints, and the Hub.
8467
9577
 
@@ -8473,6 +9583,8 @@ Mutations cost money and bind to what this conversation created. State the hourl
8473
9583
 
8474
9584
  These tools manage infrastructure only. They do not do SSH sessions, file transfer to or from pods, local image builds, or interactive terminals \u2014 say plainly when a task needs one of those and name the real path (the Runpod console, runpodctl) instead of improvising.
8475
9585
 
9586
+ OFFICIAL GUIDES AND FACTS. list-guides and read-guide serve the official Runpod plugin's skills, reference docs and live-verified golden paths, so you have them even without the plugin installed. For a multi-step or billable task, look for a matching golden path first. lookup-concept and search-concepts answer exact questions about how Runpod works (what a stopped pod keeps, where a volume lives) with the public source for each fact.
9587
+
8476
9588
  SKILLS \u2014 READ BEFORE ACTING. This server publishes its task playbooks as MCP resources under runpod://skills/. Before the FIRST Runpod tool call of a session, read runpod://skills/runpod (the router): it maps the request to a journey skill \u2014 deploying an endpoint reads runpod://skills/serverless-deploy, diagnosing a broken pod reads runpod://skills/pod-doctor, cost questions read runpod://skills/cost-audit, and so on \u2014 and each journey skill carries the procedure, pitfalls, and report format for that task. A reply produced without the routed skill loaded is out of contract. List them all with resources/list.
8477
9589
 
8478
9590
  THE OFFICIAL RUNPOD PLUGIN. Runpod ships an agent plugin that covers the lanes these resources do not: the runpodctl and flash CLIs, image builds and model downloads, the official pod templates, and verified end-to-end golden paths. Check once per session whether skills named runpod, runpod-usage, or runpodctl are available to you \u2014 read what you already have, never shell out to look. If they are there, prefer them for procedure and lane choice and treat runpod://skills/ as the fallback. If you do not see them, recommend the plugin to the user, and recommend updating to the latest if what they have is missing something you need. Point them at https://github.com/runpod/runpod-plugins-official \u2014 its README carries the install, update, and clone commands for each client, so read it yourself when you need the exact one rather than guessing a command. This is a recommendation, never a prerequisite: make it once, briefly, and get on with the task. Either way this server is the source of truth for its OWN tool surface: the live tool schemas and the runpod:// resources override any Runpod tool list written down elsewhere, the plugin's included.
@@ -8504,32 +9616,56 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
8504
9616
  };
8505
9617
  server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({
8506
9618
  tools: [
8507
- ...servedCuratedTools.map(({ name, description, inputSchema }) => ({
8508
- name,
8509
- description,
8510
- inputSchema
8511
- })),
8512
- ...generatedTools.map(({ name, description, inputSchema }) => ({
8513
- name,
8514
- description,
8515
- inputSchema
8516
- }))
9619
+ ...servedCuratedTools.map(
9620
+ ({ name, description, inputSchema, annotations }) => ({
9621
+ name,
9622
+ description,
9623
+ inputSchema,
9624
+ annotations
9625
+ })
9626
+ ),
9627
+ ...generatedTools.map(
9628
+ ({ name, description, inputSchema, annotations }) => ({
9629
+ name,
9630
+ description,
9631
+ inputSchema,
9632
+ annotations
9633
+ })
9634
+ )
8517
9635
  ]
8518
9636
  }));
8519
9637
  const SKILL_URI_PREFIX = "runpod://skills/";
8520
9638
  server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => ({
8521
- resources: skillDocs.map((skill) => ({
8522
- uri: `${SKILL_URI_PREFIX}${skill.name}`,
8523
- name: skill.name,
8524
- title: `Runpod skill: ${skill.name}`,
8525
- description: skill.description,
8526
- mimeType: "text/markdown"
8527
- }))
9639
+ resources: [
9640
+ ...skillDocs.map((skill) => ({
9641
+ uri: `${SKILL_URI_PREFIX}${skill.name}`,
9642
+ name: skill.name,
9643
+ title: `Runpod skill: ${skill.name}`,
9644
+ description: skill.description,
9645
+ mimeType: "text/markdown"
9646
+ })),
9647
+ ...guideResources.map(({ text: _text, ...resource }) => resource)
9648
+ ]
8528
9649
  }));
8529
9650
  server.setRequestHandler(import_types.ListResourceTemplatesRequestSchema, async () => ({
8530
9651
  resourceTemplates: []
8531
9652
  }));
8532
9653
  server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
9654
+ if (request.params.uri.startsWith(GUIDE_URI_PREFIX)) {
9655
+ const guide = guideResources.find(
9656
+ (candidate) => candidate.uri === request.params.uri
9657
+ );
9658
+ if (!guide) {
9659
+ throw new Error(
9660
+ `Unknown resource ${request.params.uri}. Call list-guides for the guide ids.`
9661
+ );
9662
+ }
9663
+ return {
9664
+ contents: [
9665
+ { uri: guide.uri, mimeType: "text/markdown", text: guide.text }
9666
+ ]
9667
+ };
9668
+ }
8533
9669
  const name = request.params.uri.startsWith(SKILL_URI_PREFIX) ? request.params.uri.slice(SKILL_URI_PREFIX.length) : void 0;
8534
9670
  const skill = skillDocs.find((candidate) => candidate.name === name);
8535
9671
  if (!skill) {