@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/http.mjs CHANGED
@@ -257,6 +257,12 @@ var generatedTools = [
257
257
  path: "/v2/clusters",
258
258
  params: [],
259
259
  hasBody: true,
260
+ annotations: {
261
+ readOnlyHint: false,
262
+ destructiveHint: false,
263
+ idempotentHint: false,
264
+ openWorldHint: true
265
+ },
260
266
  inputSchema: {
261
267
  type: "object",
262
268
  properties: {
@@ -268,12 +274,34 @@ var generatedTools = [
268
274
  $defs: {
269
275
  BaseContainerConfig: {
270
276
  type: "object",
271
- 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",
277
+ 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",
272
278
  properties: {
273
279
  args: {
274
280
  type: "string",
275
- description: "Arguments passed to the container entrypoint",
276
- examples: [""]
281
+ 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',
282
+ examples: [
283
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
284
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
285
+ ""
286
+ ]
287
+ },
288
+ cmd: {
289
+ type: "array",
290
+ items: {
291
+ type: "string"
292
+ },
293
+ 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",
294
+ examples: [
295
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
296
+ ]
297
+ },
298
+ entrypoint: {
299
+ type: "array",
300
+ items: {
301
+ type: "string"
302
+ },
303
+ 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",
304
+ examples: [["/bin/bash", "-c"]]
277
305
  },
278
306
  disk: {
279
307
  type: "integer",
@@ -349,7 +377,7 @@ var generatedTools = [
349
377
  {
350
378
  type: "object",
351
379
  required: ["name", "type", "compute"],
352
- 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",
380
+ 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",
353
381
  properties: {
354
382
  compute: {
355
383
  $ref: "#/$defs/ClusterCompute"
@@ -362,6 +390,12 @@ var generatedTools = [
362
390
  type: {
363
391
  $ref: "#/$defs/ClusterType"
364
392
  },
393
+ templateId: {
394
+ type: "string",
395
+ minLength: 1,
396
+ 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",
397
+ examples: ["30zmvf89kd"]
398
+ },
365
399
  dataCenterIds: {
366
400
  type: "array",
367
401
  items: {
@@ -453,6 +487,12 @@ var generatedTools = [
453
487
  path: "/v2/registries/delegations",
454
488
  params: [],
455
489
  hasBody: true,
490
+ annotations: {
491
+ readOnlyHint: false,
492
+ destructiveHint: false,
493
+ idempotentHint: false,
494
+ openWorldHint: true
495
+ },
456
496
  inputSchema: {
457
497
  type: "object",
458
498
  properties: {
@@ -492,6 +532,12 @@ var generatedTools = [
492
532
  path: "/v2/serverless",
493
533
  params: [],
494
534
  hasBody: true,
535
+ annotations: {
536
+ readOnlyHint: false,
537
+ destructiveHint: false,
538
+ idempotentHint: false,
539
+ openWorldHint: true
540
+ },
495
541
  inputSchema: {
496
542
  type: "object",
497
543
  properties: {
@@ -503,12 +549,34 @@ var generatedTools = [
503
549
  $defs: {
504
550
  BaseContainerConfig: {
505
551
  type: "object",
506
- 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",
552
+ 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",
507
553
  properties: {
508
554
  args: {
509
555
  type: "string",
510
- description: "Arguments passed to the container entrypoint",
511
- examples: [""]
556
+ 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',
557
+ examples: [
558
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
559
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
560
+ ""
561
+ ]
562
+ },
563
+ cmd: {
564
+ type: "array",
565
+ items: {
566
+ type: "string"
567
+ },
568
+ 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",
569
+ examples: [
570
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
571
+ ]
572
+ },
573
+ entrypoint: {
574
+ type: "array",
575
+ items: {
576
+ type: "string"
577
+ },
578
+ 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",
579
+ examples: [["/bin/bash", "-c"]]
512
580
  },
513
581
  disk: {
514
582
  type: "integer",
@@ -567,7 +635,7 @@ var generatedTools = [
567
635
  pools: {
568
636
  type: "array",
569
637
  minItems: 1,
570
- 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",
638
+ 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',
571
639
  items: {
572
640
  type: "string"
573
641
  },
@@ -871,6 +939,12 @@ var generatedTools = [
871
939
  path: "/v2/network-volumes",
872
940
  params: [],
873
941
  hasBody: true,
942
+ annotations: {
943
+ readOnlyHint: false,
944
+ destructiveHint: false,
945
+ idempotentHint: false,
946
+ openWorldHint: true
947
+ },
874
948
  inputSchema: {
875
949
  type: "object",
876
950
  properties: {
@@ -930,6 +1004,12 @@ var generatedTools = [
930
1004
  path: "/v2/pods",
931
1005
  params: [],
932
1006
  hasBody: true,
1007
+ annotations: {
1008
+ readOnlyHint: false,
1009
+ destructiveHint: false,
1010
+ idempotentHint: false,
1011
+ openWorldHint: true
1012
+ },
933
1013
  inputSchema: {
934
1014
  type: "object",
935
1015
  properties: {
@@ -941,12 +1021,34 @@ var generatedTools = [
941
1021
  $defs: {
942
1022
  BaseContainerConfig: {
943
1023
  type: "object",
944
- 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",
1024
+ 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",
945
1025
  properties: {
946
1026
  args: {
947
1027
  type: "string",
948
- description: "Arguments passed to the container entrypoint",
949
- examples: [""]
1028
+ 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',
1029
+ examples: [
1030
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1031
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1032
+ ""
1033
+ ]
1034
+ },
1035
+ cmd: {
1036
+ type: "array",
1037
+ items: {
1038
+ type: "string"
1039
+ },
1040
+ 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",
1041
+ examples: [
1042
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1043
+ ]
1044
+ },
1045
+ entrypoint: {
1046
+ type: "array",
1047
+ items: {
1048
+ type: "string"
1049
+ },
1050
+ 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",
1051
+ examples: [["/bin/bash", "-c"]]
950
1052
  },
951
1053
  disk: {
952
1054
  type: "integer",
@@ -1232,6 +1334,12 @@ var generatedTools = [
1232
1334
  path: "/v2/registries",
1233
1335
  params: [],
1234
1336
  hasBody: true,
1337
+ annotations: {
1338
+ readOnlyHint: false,
1339
+ destructiveHint: false,
1340
+ idempotentHint: false,
1341
+ openWorldHint: true
1342
+ },
1235
1343
  inputSchema: {
1236
1344
  type: "object",
1237
1345
  properties: {
@@ -1249,16 +1357,19 @@ var generatedTools = [
1249
1357
  name: {
1250
1358
  type: "string",
1251
1359
  minLength: 1,
1360
+ maxLength: 191,
1252
1361
  examples: ["my-private-registry"]
1253
1362
  },
1254
1363
  password: {
1255
1364
  type: "string",
1256
1365
  minLength: 1,
1366
+ maxLength: 16384,
1257
1367
  description: "Registry password (write-only, not returned in responses)"
1258
1368
  },
1259
1369
  username: {
1260
1370
  type: "string",
1261
1371
  minLength: 1,
1372
+ maxLength: 191,
1262
1373
  description: "Registry username (write-only, not returned in responses)"
1263
1374
  }
1264
1375
  }
@@ -1266,6 +1377,59 @@ var generatedTools = [
1266
1377
  }
1267
1378
  }
1268
1379
  },
1380
+ {
1381
+ name: "create-secret",
1382
+ operationId: "createSecret",
1383
+ 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.",
1384
+ method: "POST",
1385
+ path: "/v2/account/secrets",
1386
+ params: [],
1387
+ hasBody: true,
1388
+ annotations: {
1389
+ readOnlyHint: false,
1390
+ destructiveHint: false,
1391
+ idempotentHint: false,
1392
+ openWorldHint: true
1393
+ },
1394
+ inputSchema: {
1395
+ type: "object",
1396
+ properties: {
1397
+ body: {
1398
+ $ref: "#/$defs/CreateSecretRequest"
1399
+ }
1400
+ },
1401
+ required: ["body"],
1402
+ $defs: {
1403
+ CreateSecretRequest: {
1404
+ type: "object",
1405
+ additionalProperties: false,
1406
+ required: ["name", "value"],
1407
+ properties: {
1408
+ name: {
1409
+ type: "string",
1410
+ minLength: 1,
1411
+ maxLength: 191,
1412
+ pattern: "^[a-zA-Z_][a-zA-Z0-9_.\\-/]*$",
1413
+ 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).",
1414
+ examples: ["hf-token"]
1415
+ },
1416
+ value: {
1417
+ type: "string",
1418
+ minLength: 1,
1419
+ maxLength: 16777216,
1420
+ 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)."
1421
+ },
1422
+ description: {
1423
+ type: "string",
1424
+ maxLength: 65535,
1425
+ description: "Optional human-readable description, at most 65,535 bytes of UTF-8 text.",
1426
+ examples: ["Hugging Face read token"]
1427
+ }
1428
+ }
1429
+ }
1430
+ }
1431
+ }
1432
+ },
1269
1433
  {
1270
1434
  name: "create-template",
1271
1435
  operationId: "createTemplate",
@@ -1274,6 +1438,12 @@ var generatedTools = [
1274
1438
  path: "/v2/templates",
1275
1439
  params: [],
1276
1440
  hasBody: true,
1441
+ annotations: {
1442
+ readOnlyHint: false,
1443
+ destructiveHint: false,
1444
+ idempotentHint: false,
1445
+ openWorldHint: true
1446
+ },
1277
1447
  inputSchema: {
1278
1448
  type: "object",
1279
1449
  properties: {
@@ -1285,12 +1455,34 @@ var generatedTools = [
1285
1455
  $defs: {
1286
1456
  BaseContainerConfig: {
1287
1457
  type: "object",
1288
- 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",
1458
+ 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",
1289
1459
  properties: {
1290
1460
  args: {
1291
1461
  type: "string",
1292
- description: "Arguments passed to the container entrypoint",
1293
- examples: [""]
1462
+ 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',
1463
+ examples: [
1464
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1465
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1466
+ ""
1467
+ ]
1468
+ },
1469
+ cmd: {
1470
+ type: "array",
1471
+ items: {
1472
+ type: "string"
1473
+ },
1474
+ 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",
1475
+ examples: [
1476
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1477
+ ]
1478
+ },
1479
+ entrypoint: {
1480
+ type: "array",
1481
+ items: {
1482
+ type: "string"
1483
+ },
1484
+ 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",
1485
+ examples: [["/bin/bash", "-c"]]
1294
1486
  },
1295
1487
  disk: {
1296
1488
  type: "integer",
@@ -1453,6 +1645,12 @@ var generatedTools = [
1453
1645
  }
1454
1646
  ],
1455
1647
  hasBody: false,
1648
+ annotations: {
1649
+ readOnlyHint: false,
1650
+ destructiveHint: true,
1651
+ idempotentHint: true,
1652
+ openWorldHint: true
1653
+ },
1456
1654
  inputSchema: {
1457
1655
  type: "object",
1458
1656
  properties: {
@@ -1477,6 +1675,12 @@ var generatedTools = [
1477
1675
  }
1478
1676
  ],
1479
1677
  hasBody: false,
1678
+ annotations: {
1679
+ readOnlyHint: false,
1680
+ destructiveHint: true,
1681
+ idempotentHint: true,
1682
+ openWorldHint: true
1683
+ },
1480
1684
  inputSchema: {
1481
1685
  type: "object",
1482
1686
  properties: {
@@ -1501,6 +1705,12 @@ var generatedTools = [
1501
1705
  }
1502
1706
  ],
1503
1707
  hasBody: false,
1708
+ annotations: {
1709
+ readOnlyHint: false,
1710
+ destructiveHint: true,
1711
+ idempotentHint: true,
1712
+ openWorldHint: true
1713
+ },
1504
1714
  inputSchema: {
1505
1715
  type: "object",
1506
1716
  properties: {
@@ -1525,6 +1735,12 @@ var generatedTools = [
1525
1735
  }
1526
1736
  ],
1527
1737
  hasBody: false,
1738
+ annotations: {
1739
+ readOnlyHint: false,
1740
+ destructiveHint: true,
1741
+ idempotentHint: true,
1742
+ openWorldHint: true
1743
+ },
1528
1744
  inputSchema: {
1529
1745
  type: "object",
1530
1746
  properties: {
@@ -1549,6 +1765,12 @@ var generatedTools = [
1549
1765
  }
1550
1766
  ],
1551
1767
  hasBody: false,
1768
+ annotations: {
1769
+ readOnlyHint: false,
1770
+ destructiveHint: true,
1771
+ idempotentHint: true,
1772
+ openWorldHint: true
1773
+ },
1552
1774
  inputSchema: {
1553
1775
  type: "object",
1554
1776
  properties: {
@@ -1559,6 +1781,36 @@ var generatedTools = [
1559
1781
  required: ["id"]
1560
1782
  }
1561
1783
  },
1784
+ {
1785
+ name: "delete-secret",
1786
+ operationId: "deleteSecret",
1787
+ description: "Delete a secret. Permanently deletes a secret. Environment variables referencing the deleted secret's name will no longer resolve to a value.",
1788
+ method: "DELETE",
1789
+ path: "/v2/account/secrets/{id}",
1790
+ params: [
1791
+ {
1792
+ name: "id",
1793
+ location: "path"
1794
+ }
1795
+ ],
1796
+ hasBody: false,
1797
+ annotations: {
1798
+ readOnlyHint: false,
1799
+ destructiveHint: true,
1800
+ idempotentHint: true,
1801
+ openWorldHint: true
1802
+ },
1803
+ inputSchema: {
1804
+ type: "object",
1805
+ properties: {
1806
+ id: {
1807
+ type: "string",
1808
+ description: "Secret identifier"
1809
+ }
1810
+ },
1811
+ required: ["id"]
1812
+ }
1813
+ },
1562
1814
  {
1563
1815
  name: "delete-template",
1564
1816
  operationId: "deleteTemplate",
@@ -1572,6 +1824,12 @@ var generatedTools = [
1572
1824
  }
1573
1825
  ],
1574
1826
  hasBody: false,
1827
+ annotations: {
1828
+ readOnlyHint: false,
1829
+ destructiveHint: true,
1830
+ idempotentHint: true,
1831
+ openWorldHint: true
1832
+ },
1575
1833
  inputSchema: {
1576
1834
  type: "object",
1577
1835
  properties: {
@@ -1595,6 +1853,12 @@ var generatedTools = [
1595
1853
  }
1596
1854
  ],
1597
1855
  hasBody: false,
1856
+ annotations: {
1857
+ readOnlyHint: true,
1858
+ destructiveHint: false,
1859
+ idempotentHint: true,
1860
+ openWorldHint: true
1861
+ },
1598
1862
  inputSchema: {
1599
1863
  type: "object",
1600
1864
  properties: {
@@ -1633,6 +1897,12 @@ var generatedTools = [
1633
1897
  }
1634
1898
  ],
1635
1899
  hasBody: false,
1900
+ annotations: {
1901
+ readOnlyHint: true,
1902
+ destructiveHint: false,
1903
+ idempotentHint: true,
1904
+ openWorldHint: true
1905
+ },
1636
1906
  inputSchema: {
1637
1907
  type: "object",
1638
1908
  properties: {
@@ -1694,6 +1964,12 @@ var generatedTools = [
1694
1964
  }
1695
1965
  ],
1696
1966
  hasBody: false,
1967
+ annotations: {
1968
+ readOnlyHint: true,
1969
+ destructiveHint: false,
1970
+ idempotentHint: true,
1971
+ openWorldHint: true
1972
+ },
1697
1973
  inputSchema: {
1698
1974
  type: "object",
1699
1975
  properties: {
@@ -1732,6 +2008,12 @@ var generatedTools = [
1732
2008
  }
1733
2009
  ],
1734
2010
  hasBody: false,
2011
+ annotations: {
2012
+ readOnlyHint: true,
2013
+ destructiveHint: false,
2014
+ idempotentHint: true,
2015
+ openWorldHint: true
2016
+ },
1735
2017
  inputSchema: {
1736
2018
  type: "object",
1737
2019
  properties: {
@@ -1746,7 +2028,7 @@ var generatedTools = [
1746
2028
  {
1747
2029
  name: "get-endpoint-build",
1748
2030
  operationId: "getEndpointBuild",
1749
- 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.",
2031
+ 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.",
1750
2032
  method: "GET",
1751
2033
  path: "/v2/serverless/{id}/builds/{buildId}",
1752
2034
  params: [
@@ -1760,6 +2042,12 @@ var generatedTools = [
1760
2042
  }
1761
2043
  ],
1762
2044
  hasBody: false,
2045
+ annotations: {
2046
+ readOnlyHint: true,
2047
+ destructiveHint: false,
2048
+ idempotentHint: true,
2049
+ openWorldHint: true
2050
+ },
1763
2051
  inputSchema: {
1764
2052
  type: "object",
1765
2053
  properties: {
@@ -1820,6 +2108,12 @@ var generatedTools = [
1820
2108
  }
1821
2109
  ],
1822
2110
  hasBody: false,
2111
+ annotations: {
2112
+ readOnlyHint: true,
2113
+ destructiveHint: false,
2114
+ idempotentHint: true,
2115
+ openWorldHint: true
2116
+ },
1823
2117
  inputSchema: {
1824
2118
  type: "object",
1825
2119
  properties: {
@@ -1906,6 +2200,12 @@ var generatedTools = [
1906
2200
  }
1907
2201
  ],
1908
2202
  hasBody: false,
2203
+ annotations: {
2204
+ readOnlyHint: true,
2205
+ destructiveHint: false,
2206
+ idempotentHint: true,
2207
+ openWorldHint: true
2208
+ },
1909
2209
  inputSchema: {
1910
2210
  type: "object",
1911
2211
  properties: {
@@ -1930,6 +2230,12 @@ var generatedTools = [
1930
2230
  }
1931
2231
  ],
1932
2232
  hasBody: false,
2233
+ annotations: {
2234
+ readOnlyHint: true,
2235
+ destructiveHint: false,
2236
+ idempotentHint: true,
2237
+ openWorldHint: true
2238
+ },
1933
2239
  inputSchema: {
1934
2240
  type: "object",
1935
2241
  properties: {
@@ -1954,6 +2260,12 @@ var generatedTools = [
1954
2260
  }
1955
2261
  ],
1956
2262
  hasBody: false,
2263
+ annotations: {
2264
+ readOnlyHint: true,
2265
+ destructiveHint: false,
2266
+ idempotentHint: true,
2267
+ openWorldHint: true
2268
+ },
1957
2269
  inputSchema: {
1958
2270
  type: "object",
1959
2271
  properties: {
@@ -1964,6 +2276,36 @@ var generatedTools = [
1964
2276
  required: ["id"]
1965
2277
  }
1966
2278
  },
2279
+ {
2280
+ name: "get-secret",
2281
+ operationId: "getSecret",
2282
+ description: "Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.",
2283
+ method: "GET",
2284
+ path: "/v2/account/secrets/{id}",
2285
+ params: [
2286
+ {
2287
+ name: "id",
2288
+ location: "path"
2289
+ }
2290
+ ],
2291
+ hasBody: false,
2292
+ annotations: {
2293
+ readOnlyHint: true,
2294
+ destructiveHint: false,
2295
+ idempotentHint: true,
2296
+ openWorldHint: true
2297
+ },
2298
+ inputSchema: {
2299
+ type: "object",
2300
+ properties: {
2301
+ id: {
2302
+ type: "string",
2303
+ description: "Secret identifier"
2304
+ }
2305
+ },
2306
+ required: ["id"]
2307
+ }
2308
+ },
1967
2309
  {
1968
2310
  name: "get-ssh-keys",
1969
2311
  operationId: "getSshKeys",
@@ -1972,6 +2314,12 @@ var generatedTools = [
1972
2314
  path: "/v2/account/ssh-keys",
1973
2315
  params: [],
1974
2316
  hasBody: false,
2317
+ annotations: {
2318
+ readOnlyHint: true,
2319
+ destructiveHint: false,
2320
+ idempotentHint: true,
2321
+ openWorldHint: true
2322
+ },
1975
2323
  inputSchema: {
1976
2324
  type: "object",
1977
2325
  properties: {}
@@ -1990,6 +2338,12 @@ var generatedTools = [
1990
2338
  }
1991
2339
  ],
1992
2340
  hasBody: false,
2341
+ annotations: {
2342
+ readOnlyHint: true,
2343
+ destructiveHint: false,
2344
+ idempotentHint: true,
2345
+ openWorldHint: true
2346
+ },
1993
2347
  inputSchema: {
1994
2348
  type: "object",
1995
2349
  properties: {
@@ -2025,6 +2379,12 @@ var generatedTools = [
2025
2379
  }
2026
2380
  ],
2027
2381
  hasBody: false,
2382
+ annotations: {
2383
+ readOnlyHint: true,
2384
+ destructiveHint: false,
2385
+ idempotentHint: true,
2386
+ openWorldHint: true
2387
+ },
2028
2388
  inputSchema: {
2029
2389
  type: "object",
2030
2390
  properties: {
@@ -2095,6 +2455,12 @@ var generatedTools = [
2095
2455
  }
2096
2456
  ],
2097
2457
  hasBody: false,
2458
+ annotations: {
2459
+ readOnlyHint: true,
2460
+ destructiveHint: false,
2461
+ idempotentHint: true,
2462
+ openWorldHint: true
2463
+ },
2098
2464
  inputSchema: {
2099
2465
  type: "object",
2100
2466
  properties: {
@@ -2153,6 +2519,12 @@ var generatedTools = [
2153
2519
  }
2154
2520
  ],
2155
2521
  hasBody: false,
2522
+ annotations: {
2523
+ readOnlyHint: true,
2524
+ destructiveHint: false,
2525
+ idempotentHint: true,
2526
+ openWorldHint: true
2527
+ },
2156
2528
  inputSchema: {
2157
2529
  type: "object",
2158
2530
  properties: {
@@ -2172,6 +2544,12 @@ var generatedTools = [
2172
2544
  path: "/v2/clusters",
2173
2545
  params: [],
2174
2546
  hasBody: false,
2547
+ annotations: {
2548
+ readOnlyHint: true,
2549
+ destructiveHint: false,
2550
+ idempotentHint: true,
2551
+ openWorldHint: true
2552
+ },
2175
2553
  inputSchema: {
2176
2554
  type: "object",
2177
2555
  properties: {}
@@ -2200,6 +2578,12 @@ var generatedTools = [
2200
2578
  }
2201
2579
  ],
2202
2580
  hasBody: false,
2581
+ annotations: {
2582
+ readOnlyHint: true,
2583
+ destructiveHint: false,
2584
+ idempotentHint: true,
2585
+ openWorldHint: true
2586
+ },
2203
2587
  inputSchema: {
2204
2588
  type: "object",
2205
2589
  properties: {
@@ -2272,6 +2656,12 @@ var generatedTools = [
2272
2656
  }
2273
2657
  ],
2274
2658
  hasBody: false,
2659
+ annotations: {
2660
+ readOnlyHint: true,
2661
+ destructiveHint: false,
2662
+ idempotentHint: true,
2663
+ openWorldHint: true
2664
+ },
2275
2665
  inputSchema: {
2276
2666
  type: "object",
2277
2667
  properties: {
@@ -2368,6 +2758,12 @@ var generatedTools = [
2368
2758
  path: "/v2/registries/delegations",
2369
2759
  params: [],
2370
2760
  hasBody: false,
2761
+ annotations: {
2762
+ readOnlyHint: true,
2763
+ destructiveHint: false,
2764
+ idempotentHint: true,
2765
+ openWorldHint: true
2766
+ },
2371
2767
  inputSchema: {
2372
2768
  type: "object",
2373
2769
  properties: {}
@@ -2398,6 +2794,12 @@ var generatedTools = [
2398
2794
  }
2399
2795
  ],
2400
2796
  hasBody: false,
2797
+ annotations: {
2798
+ readOnlyHint: true,
2799
+ destructiveHint: false,
2800
+ idempotentHint: true,
2801
+ openWorldHint: true
2802
+ },
2401
2803
  inputSchema: {
2402
2804
  type: "object",
2403
2805
  properties: {
@@ -2442,22 +2844,47 @@ var generatedTools = [
2442
2844
  {
2443
2845
  name: "list-endpoint-builds",
2444
2846
  operationId: "listEndpointBuilds",
2445
- 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`.",
2847
+ 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`.",
2446
2848
  method: "GET",
2447
2849
  path: "/v2/serverless/{id}/builds",
2448
2850
  params: [
2449
2851
  {
2450
2852
  name: "id",
2451
2853
  location: "path"
2854
+ },
2855
+ {
2856
+ name: "cursor",
2857
+ location: "query"
2858
+ },
2859
+ {
2860
+ name: "limit",
2861
+ location: "query"
2452
2862
  }
2453
2863
  ],
2454
2864
  hasBody: false,
2865
+ annotations: {
2866
+ readOnlyHint: true,
2867
+ destructiveHint: false,
2868
+ idempotentHint: true,
2869
+ openWorldHint: true
2870
+ },
2455
2871
  inputSchema: {
2456
2872
  type: "object",
2457
2873
  properties: {
2458
2874
  id: {
2459
2875
  type: "string",
2460
2876
  description: "Serverless endpoint identifier"
2877
+ },
2878
+ cursor: {
2879
+ type: "string",
2880
+ minLength: 1,
2881
+ 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"
2882
+ },
2883
+ limit: {
2884
+ type: "integer",
2885
+ minimum: 1,
2886
+ maximum: 100,
2887
+ description: "Page size, 1\u2013100. Defaults to 100 when omitted."
2461
2888
  }
2462
2889
  },
2463
2890
  required: ["id"]
@@ -2466,22 +2893,47 @@ var generatedTools = [
2466
2893
  {
2467
2894
  name: "list-endpoint-releases",
2468
2895
  operationId: "listEndpointReleases",
2469
- 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).",
2896
+ 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.",
2470
2897
  method: "GET",
2471
2898
  path: "/v2/serverless/{id}/releases",
2472
2899
  params: [
2473
2900
  {
2474
2901
  name: "id",
2475
2902
  location: "path"
2903
+ },
2904
+ {
2905
+ name: "cursor",
2906
+ location: "query"
2907
+ },
2908
+ {
2909
+ name: "limit",
2910
+ location: "query"
2476
2911
  }
2477
2912
  ],
2478
2913
  hasBody: false,
2914
+ annotations: {
2915
+ readOnlyHint: true,
2916
+ destructiveHint: false,
2917
+ idempotentHint: true,
2918
+ openWorldHint: true
2919
+ },
2479
2920
  inputSchema: {
2480
2921
  type: "object",
2481
2922
  properties: {
2482
2923
  id: {
2483
2924
  type: "string",
2484
2925
  description: "Serverless endpoint identifier"
2926
+ },
2927
+ cursor: {
2928
+ type: "string",
2929
+ minLength: 1,
2930
+ 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"
2931
+ },
2932
+ limit: {
2933
+ type: "integer",
2934
+ minimum: 1,
2935
+ maximum: 1e3,
2936
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
2485
2937
  }
2486
2938
  },
2487
2939
  required: ["id"]
@@ -2500,6 +2952,12 @@ var generatedTools = [
2500
2952
  }
2501
2953
  ],
2502
2954
  hasBody: false,
2955
+ annotations: {
2956
+ readOnlyHint: true,
2957
+ destructiveHint: false,
2958
+ idempotentHint: true,
2959
+ openWorldHint: true
2960
+ },
2503
2961
  inputSchema: {
2504
2962
  type: "object",
2505
2963
  properties: {
@@ -2552,6 +3010,12 @@ var generatedTools = [
2552
3010
  }
2553
3011
  ],
2554
3012
  hasBody: false,
3013
+ annotations: {
3014
+ readOnlyHint: true,
3015
+ destructiveHint: false,
3016
+ idempotentHint: true,
3017
+ openWorldHint: true
3018
+ },
2555
3019
  inputSchema: {
2556
3020
  type: "object",
2557
3021
  properties: {
@@ -2650,6 +3114,12 @@ var generatedTools = [
2650
3114
  }
2651
3115
  ],
2652
3116
  hasBody: false,
3117
+ annotations: {
3118
+ readOnlyHint: true,
3119
+ destructiveHint: false,
3120
+ idempotentHint: true,
3121
+ openWorldHint: true
3122
+ },
2653
3123
  inputSchema: {
2654
3124
  type: "object",
2655
3125
  properties: {
@@ -2703,6 +3173,12 @@ var generatedTools = [
2703
3173
  path: "/v2/network-volumes",
2704
3174
  params: [],
2705
3175
  hasBody: false,
3176
+ annotations: {
3177
+ readOnlyHint: true,
3178
+ destructiveHint: false,
3179
+ idempotentHint: true,
3180
+ openWorldHint: true
3181
+ },
2706
3182
  inputSchema: {
2707
3183
  type: "object",
2708
3184
  properties: {}
@@ -2737,6 +3213,12 @@ var generatedTools = [
2737
3213
  }
2738
3214
  ],
2739
3215
  hasBody: false,
3216
+ annotations: {
3217
+ readOnlyHint: true,
3218
+ destructiveHint: false,
3219
+ idempotentHint: true,
3220
+ openWorldHint: true
3221
+ },
2740
3222
  inputSchema: {
2741
3223
  type: "object",
2742
3224
  properties: {
@@ -2785,16 +3267,30 @@ var generatedTools = [
2785
3267
  {
2786
3268
  name: "list-pods",
2787
3269
  operationId: "listPods",
2788
- 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).",
3270
+ 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.",
2789
3271
  method: "GET",
2790
3272
  path: "/v2/pods",
2791
3273
  params: [
2792
3274
  {
2793
3275
  name: "includeClusterPods",
2794
3276
  location: "query"
3277
+ },
3278
+ {
3279
+ name: "cursor",
3280
+ location: "query"
3281
+ },
3282
+ {
3283
+ name: "limit",
3284
+ location: "query"
2795
3285
  }
2796
3286
  ],
2797
3287
  hasBody: false,
3288
+ annotations: {
3289
+ readOnlyHint: true,
3290
+ destructiveHint: false,
3291
+ idempotentHint: true,
3292
+ openWorldHint: true
3293
+ },
2798
3294
  inputSchema: {
2799
3295
  type: "object",
2800
3296
  properties: {
@@ -2802,6 +3298,17 @@ var generatedTools = [
2802
3298
  type: "boolean",
2803
3299
  default: false,
2804
3300
  description: "Include cluster member pods in the result. Defaults to false."
3301
+ },
3302
+ cursor: {
3303
+ type: "string",
3304
+ minLength: 1,
3305
+ 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"
3306
+ },
3307
+ limit: {
3308
+ type: "integer",
3309
+ minimum: 1,
3310
+ maximum: 1e3,
3311
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
2805
3312
  }
2806
3313
  }
2807
3314
  }
@@ -2809,7 +3316,7 @@ var generatedTools = [
2809
3316
  {
2810
3317
  name: "list-public-templates",
2811
3318
  operationId: "listPublicTemplates",
2812
- 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.",
3319
+ 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`).",
2813
3320
  method: "GET",
2814
3321
  path: "/v2/catalog/templates",
2815
3322
  params: [
@@ -2819,6 +3326,12 @@ var generatedTools = [
2819
3326
  }
2820
3327
  ],
2821
3328
  hasBody: false,
3329
+ annotations: {
3330
+ readOnlyHint: true,
3331
+ destructiveHint: false,
3332
+ idempotentHint: true,
3333
+ openWorldHint: true
3334
+ },
2822
3335
  inputSchema: {
2823
3336
  type: "object",
2824
3337
  properties: {
@@ -2839,11 +3352,46 @@ var generatedTools = [
2839
3352
  path: "/v2/registries",
2840
3353
  params: [],
2841
3354
  hasBody: false,
3355
+ annotations: {
3356
+ readOnlyHint: true,
3357
+ destructiveHint: false,
3358
+ idempotentHint: true,
3359
+ openWorldHint: true
3360
+ },
2842
3361
  inputSchema: {
2843
3362
  type: "object",
2844
3363
  properties: {}
2845
3364
  }
2846
3365
  },
3366
+ {
3367
+ name: "list-secrets",
3368
+ operationId: "listSecrets",
3369
+ 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.",
3370
+ method: "GET",
3371
+ path: "/v2/account/secrets",
3372
+ params: [
3373
+ {
3374
+ name: "name",
3375
+ location: "query"
3376
+ }
3377
+ ],
3378
+ hasBody: false,
3379
+ annotations: {
3380
+ readOnlyHint: true,
3381
+ destructiveHint: false,
3382
+ idempotentHint: true,
3383
+ openWorldHint: true
3384
+ },
3385
+ inputSchema: {
3386
+ type: "object",
3387
+ properties: {
3388
+ name: {
3389
+ type: "string",
3390
+ description: "When provided, returns only the secret with this name (case-insensitive)."
3391
+ }
3392
+ }
3393
+ }
3394
+ },
2847
3395
  {
2848
3396
  name: "list-serverless-billing",
2849
3397
  operationId: "listServerlessBilling",
@@ -2873,6 +3421,12 @@ var generatedTools = [
2873
3421
  }
2874
3422
  ],
2875
3423
  hasBody: false,
3424
+ annotations: {
3425
+ readOnlyHint: true,
3426
+ destructiveHint: false,
3427
+ idempotentHint: true,
3428
+ openWorldHint: true
3429
+ },
2876
3430
  inputSchema: {
2877
3431
  type: "object",
2878
3432
  properties: {
@@ -2931,6 +3485,12 @@ var generatedTools = [
2931
3485
  }
2932
3486
  ],
2933
3487
  hasBody: true,
3488
+ annotations: {
3489
+ readOnlyHint: false,
3490
+ destructiveHint: true,
3491
+ idempotentHint: false,
3492
+ openWorldHint: true
3493
+ },
2934
3494
  inputSchema: {
2935
3495
  type: "object",
2936
3496
  properties: {
@@ -2974,6 +3534,12 @@ var generatedTools = [
2974
3534
  }
2975
3535
  ],
2976
3536
  hasBody: false,
3537
+ annotations: {
3538
+ readOnlyHint: false,
3539
+ destructiveHint: true,
3540
+ idempotentHint: true,
3541
+ openWorldHint: true
3542
+ },
2977
3543
  inputSchema: {
2978
3544
  type: "object",
2979
3545
  properties: {
@@ -2997,6 +3563,12 @@ var generatedTools = [
2997
3563
  }
2998
3564
  ],
2999
3565
  hasBody: true,
3566
+ annotations: {
3567
+ readOnlyHint: false,
3568
+ destructiveHint: false,
3569
+ idempotentHint: false,
3570
+ openWorldHint: true
3571
+ },
3000
3572
  inputSchema: {
3001
3573
  type: "object",
3002
3574
  properties: {
@@ -3039,6 +3611,12 @@ var generatedTools = [
3039
3611
  }
3040
3612
  ],
3041
3613
  hasBody: true,
3614
+ annotations: {
3615
+ readOnlyHint: false,
3616
+ destructiveHint: false,
3617
+ idempotentHint: false,
3618
+ openWorldHint: true
3619
+ },
3042
3620
  inputSchema: {
3043
3621
  type: "object",
3044
3622
  properties: {
@@ -3054,12 +3632,34 @@ var generatedTools = [
3054
3632
  $defs: {
3055
3633
  BaseContainerConfig: {
3056
3634
  type: "object",
3057
- 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",
3635
+ 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",
3058
3636
  properties: {
3059
3637
  args: {
3060
3638
  type: "string",
3061
- description: "Arguments passed to the container entrypoint",
3062
- examples: [""]
3639
+ 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',
3640
+ examples: [
3641
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
3642
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
3643
+ ""
3644
+ ]
3645
+ },
3646
+ cmd: {
3647
+ type: "array",
3648
+ items: {
3649
+ type: "string"
3650
+ },
3651
+ 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",
3652
+ examples: [
3653
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
3654
+ ]
3655
+ },
3656
+ entrypoint: {
3657
+ type: "array",
3658
+ items: {
3659
+ type: "string"
3660
+ },
3661
+ 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",
3662
+ examples: [["/bin/bash", "-c"]]
3063
3663
  },
3064
3664
  disk: {
3065
3665
  type: "integer",
@@ -3118,7 +3718,7 @@ var generatedTools = [
3118
3718
  pools: {
3119
3719
  type: "array",
3120
3720
  minItems: 1,
3121
- 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",
3721
+ 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',
3122
3722
  items: {
3123
3723
  type: "string"
3124
3724
  },
@@ -3363,6 +3963,12 @@ var generatedTools = [
3363
3963
  }
3364
3964
  ],
3365
3965
  hasBody: true,
3966
+ annotations: {
3967
+ readOnlyHint: false,
3968
+ destructiveHint: false,
3969
+ idempotentHint: false,
3970
+ openWorldHint: true
3971
+ },
3366
3972
  inputSchema: {
3367
3973
  type: "object",
3368
3974
  properties: {
@@ -3413,6 +4019,12 @@ var generatedTools = [
3413
4019
  }
3414
4020
  ],
3415
4021
  hasBody: true,
4022
+ annotations: {
4023
+ readOnlyHint: false,
4024
+ destructiveHint: false,
4025
+ idempotentHint: false,
4026
+ openWorldHint: true
4027
+ },
3416
4028
  inputSchema: {
3417
4029
  type: "object",
3418
4030
  properties: {
@@ -3428,12 +4040,34 @@ var generatedTools = [
3428
4040
  $defs: {
3429
4041
  BaseContainerConfig: {
3430
4042
  type: "object",
3431
- 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",
4043
+ 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",
3432
4044
  properties: {
3433
4045
  args: {
3434
4046
  type: "string",
3435
- description: "Arguments passed to the container entrypoint",
3436
- examples: [""]
4047
+ 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',
4048
+ examples: [
4049
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
4050
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
4051
+ ""
4052
+ ]
4053
+ },
4054
+ cmd: {
4055
+ type: "array",
4056
+ items: {
4057
+ type: "string"
4058
+ },
4059
+ 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",
4060
+ examples: [
4061
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
4062
+ ]
4063
+ },
4064
+ entrypoint: {
4065
+ type: "array",
4066
+ items: {
4067
+ type: "string"
4068
+ },
4069
+ 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",
4070
+ examples: [["/bin/bash", "-c"]]
3437
4071
  },
3438
4072
  disk: {
3439
4073
  type: "integer",
@@ -3576,6 +4210,60 @@ var generatedTools = [
3576
4210
  }
3577
4211
  }
3578
4212
  },
4213
+ {
4214
+ name: "update-secret",
4215
+ operationId: "updateSecret",
4216
+ 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.",
4217
+ method: "PATCH",
4218
+ path: "/v2/account/secrets/{id}",
4219
+ params: [
4220
+ {
4221
+ name: "id",
4222
+ location: "path"
4223
+ }
4224
+ ],
4225
+ hasBody: true,
4226
+ annotations: {
4227
+ readOnlyHint: false,
4228
+ destructiveHint: false,
4229
+ idempotentHint: false,
4230
+ openWorldHint: true
4231
+ },
4232
+ inputSchema: {
4233
+ type: "object",
4234
+ properties: {
4235
+ id: {
4236
+ type: "string",
4237
+ description: "Secret identifier"
4238
+ },
4239
+ body: {
4240
+ $ref: "#/$defs/UpdateSecretRequest"
4241
+ }
4242
+ },
4243
+ required: ["id", "body"],
4244
+ $defs: {
4245
+ UpdateSecretRequest: {
4246
+ type: "object",
4247
+ additionalProperties: false,
4248
+ minProperties: 1,
4249
+ description: "Only the provided fields are updated; at least one field is required.\nThe secret's `name` is immutable.\n",
4250
+ properties: {
4251
+ value: {
4252
+ type: "string",
4253
+ minLength: 1,
4254
+ maxLength: 16777216,
4255
+ 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)."
4256
+ },
4257
+ description: {
4258
+ type: "string",
4259
+ maxLength: 65535,
4260
+ description: 'New human-readable description, at most 65,535 bytes of UTF-8 text. Send `""` to clear.'
4261
+ }
4262
+ }
4263
+ }
4264
+ }
4265
+ }
4266
+ },
3579
4267
  {
3580
4268
  name: "update-ssh-keys",
3581
4269
  operationId: "updateSshKeys",
@@ -3584,6 +4272,12 @@ var generatedTools = [
3584
4272
  path: "/v2/account/ssh-keys",
3585
4273
  params: [],
3586
4274
  hasBody: true,
4275
+ annotations: {
4276
+ readOnlyHint: false,
4277
+ destructiveHint: true,
4278
+ idempotentHint: true,
4279
+ openWorldHint: true
4280
+ },
3587
4281
  inputSchema: {
3588
4282
  type: "object",
3589
4283
  properties: {
@@ -3629,6 +4323,12 @@ var generatedTools = [
3629
4323
  }
3630
4324
  ],
3631
4325
  hasBody: true,
4326
+ annotations: {
4327
+ readOnlyHint: false,
4328
+ destructiveHint: false,
4329
+ idempotentHint: false,
4330
+ openWorldHint: true
4331
+ },
3632
4332
  inputSchema: {
3633
4333
  type: "object",
3634
4334
  properties: {
@@ -3643,12 +4343,34 @@ var generatedTools = [
3643
4343
  $defs: {
3644
4344
  BaseContainerConfig: {
3645
4345
  type: "object",
3646
- 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",
4346
+ 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",
3647
4347
  properties: {
3648
4348
  args: {
3649
4349
  type: "string",
3650
- description: "Arguments passed to the container entrypoint",
3651
- examples: [""]
4350
+ 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',
4351
+ examples: [
4352
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
4353
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
4354
+ ""
4355
+ ]
4356
+ },
4357
+ cmd: {
4358
+ type: "array",
4359
+ items: {
4360
+ type: "string"
4361
+ },
4362
+ 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",
4363
+ examples: [
4364
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
4365
+ ]
4366
+ },
4367
+ entrypoint: {
4368
+ type: "array",
4369
+ items: {
4370
+ type: "string"
4371
+ },
4372
+ 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",
4373
+ examples: [["/bin/bash", "-c"]]
3652
4374
  },
3653
4375
  disk: {
3654
4376
  type: "integer",
@@ -3965,6 +4687,26 @@ var listPaginationProperties = {
3965
4687
  description: "Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning."
3966
4688
  }
3967
4689
  };
4690
+ function clampListLimit(limit) {
4691
+ const requested = Number(limit);
4692
+ return Math.min(
4693
+ Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
4694
+ MAX_LIST_LIMIT
4695
+ );
4696
+ }
4697
+ function serverPageQuery(args) {
4698
+ const cursor = typeof args.cursor === "string" && args.cursor !== "" ? args.cursor : void 0;
4699
+ return { limit: clampListLimit(args.limit), ...cursor ? { cursor } : {} };
4700
+ }
4701
+ function serverPagination(pagination, returned) {
4702
+ const hasNextPage = pagination?.hasNextPage === true;
4703
+ return {
4704
+ returned,
4705
+ hasNextPage,
4706
+ nextCursor: pagination?.nextCursor ?? null,
4707
+ ...hasNextPage ? { note: "More results exist. Pass cursor=nextCursor to fetch them." } : {}
4708
+ };
4709
+ }
3968
4710
  function decodeCursorOffset(cursor) {
3969
4711
  if (!cursor) return 0;
3970
4712
  try {
@@ -3980,11 +4722,7 @@ function encodeCursorOffset(offset) {
3980
4722
  return Buffer.from(String(offset), "utf8").toString("base64");
3981
4723
  }
3982
4724
  function capList(items, options, extra) {
3983
- const requested = Number(options.limit);
3984
- const limit = Math.min(
3985
- Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
3986
- MAX_LIST_LIMIT
3987
- );
4725
+ const limit = clampListLimit(options.limit);
3988
4726
  const offset = decodeCursorOffset(options.cursor);
3989
4727
  const total = items.length;
3990
4728
  const page = items.slice(offset, offset + limit);
@@ -4063,6 +4801,38 @@ async function runTool(body) {
4063
4801
  }
4064
4802
  }
4065
4803
 
4804
+ // src/specgen/tools/annotations.ts
4805
+ var readOnly = {
4806
+ readOnlyHint: true,
4807
+ destructiveHint: false,
4808
+ idempotentHint: true,
4809
+ openWorldHint: true
4810
+ };
4811
+ var bundledRead = {
4812
+ readOnlyHint: true,
4813
+ destructiveHint: false,
4814
+ idempotentHint: true,
4815
+ openWorldHint: false
4816
+ };
4817
+ var write = {
4818
+ readOnlyHint: false,
4819
+ destructiveHint: false,
4820
+ idempotentHint: false,
4821
+ openWorldHint: true
4822
+ };
4823
+ var idempotentWrite = {
4824
+ readOnlyHint: false,
4825
+ destructiveHint: false,
4826
+ idempotentHint: true,
4827
+ openWorldHint: true
4828
+ };
4829
+ var destructive = {
4830
+ readOnlyHint: false,
4831
+ destructiveHint: true,
4832
+ idempotentHint: true,
4833
+ openWorldHint: true
4834
+ };
4835
+
4066
4836
  // src/specgen/tools/capacity.ts
4067
4837
  var CUDA_VERSION_REGEX = /^\d{1,2}\.\d{1,2}$/;
4068
4838
  var MAX_PROBE_VERSIONS = 12;
@@ -4097,6 +4867,7 @@ function rankByStock(rows, stats, includeUnavailable) {
4097
4867
  }
4098
4868
  var getCapacity = {
4099
4869
  name: "get-capacity",
4870
+ annotations: readOnly,
4100
4871
  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.",
4101
4872
  inputSchema: {
4102
4873
  type: "object",
@@ -4297,6 +5068,7 @@ function formatGpuIds(gpu) {
4297
5068
  }
4298
5069
  var setEndpointGpus = {
4299
5070
  name: "set-endpoint-gpus",
5071
+ annotations: idempotentWrite,
4300
5072
  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.",
4301
5073
  inputSchema: {
4302
5074
  type: "object",
@@ -4490,6 +5262,7 @@ function randomSuffix() {
4490
5262
  }
4491
5263
  var listHubRepos = {
4492
5264
  name: "list-hub-repos",
5265
+ annotations: readOnly,
4493
5266
  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.",
4494
5267
  inputSchema: {
4495
5268
  type: "object",
@@ -4591,6 +5364,7 @@ var listHubRepos = {
4591
5364
  };
4592
5365
  var deployHubRepo = {
4593
5366
  name: "deploy-hub-repo",
5367
+ annotations: write,
4594
5368
  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).",
4595
5369
  inputSchema: {
4596
5370
  type: "object",
@@ -5048,6 +5822,7 @@ function validateWait(wait) {
5048
5822
  }
5049
5823
  var runEndpoint = {
5050
5824
  name: "run-endpoint",
5825
+ annotations: write,
5051
5826
  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.",
5052
5827
  inputSchema: {
5053
5828
  type: "object",
@@ -5077,6 +5852,7 @@ var runEndpoint = {
5077
5852
  };
5078
5853
  var runsyncEndpoint = {
5079
5854
  name: "runsync-endpoint",
5855
+ annotations: write,
5080
5856
  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)."),
5081
5857
  inputSchema: {
5082
5858
  type: "object",
@@ -5120,6 +5896,7 @@ var runsyncEndpoint = {
5120
5896
  };
5121
5897
  var getJobStatus = {
5122
5898
  name: "get-job-status",
5899
+ annotations: readOnly,
5123
5900
  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.",
5124
5901
  inputSchema: {
5125
5902
  type: "object",
@@ -5167,6 +5944,7 @@ var getJobStatus = {
5167
5944
  };
5168
5945
  var streamJob = {
5169
5946
  name: "stream-job",
5947
+ annotations: readOnly,
5170
5948
  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.`,
5171
5949
  inputSchema: {
5172
5950
  type: "object",
@@ -5197,6 +5975,7 @@ var streamJob = {
5197
5975
  };
5198
5976
  var cancelJob = {
5199
5977
  name: "cancel-job",
5978
+ annotations: destructive,
5200
5979
  description: "Cancel a Serverless job that is queued or in progress.",
5201
5980
  inputSchema: {
5202
5981
  type: "object",
@@ -5221,6 +6000,7 @@ var cancelJob = {
5221
6000
  };
5222
6001
  var retryJob = {
5223
6002
  name: "retry-job",
6003
+ annotations: write,
5224
6004
  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.",
5225
6005
  inputSchema: {
5226
6006
  type: "object",
@@ -5245,6 +6025,7 @@ var retryJob = {
5245
6025
  };
5246
6026
  var endpointHealth = {
5247
6027
  name: "endpoint-health",
6028
+ annotations: readOnly,
5248
6029
  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.",
5249
6030
  inputSchema: {
5250
6031
  type: "object",
@@ -5264,6 +6045,7 @@ var endpointHealth = {
5264
6045
  };
5265
6046
  var purgeEndpointQueue = {
5266
6047
  name: "purge-endpoint-queue",
6048
+ annotations: destructive,
5267
6049
  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.",
5268
6050
  inputSchema: {
5269
6051
  type: "object",
@@ -5299,13 +6081,16 @@ var jobTools = [
5299
6081
  // src/specgen/tools/list-endpoints.ts
5300
6082
  var listEndpoints = {
5301
6083
  name: "list-endpoints",
6084
+ annotations: readOnly,
5302
6085
  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.",
5303
6086
  inputSchema: {
5304
6087
  type: "object",
5305
6088
  properties: { ...listPaginationProperties }
5306
6089
  },
5307
6090
  async handler(ctx, args) {
5308
- const { data, error, response } = await ctx.sdk.GET("/v2/serverless");
6091
+ const { data, error, response } = await ctx.sdk.GET("/v2/serverless", {
6092
+ params: { query: serverPageQuery(args) }
6093
+ });
5309
6094
  if (!response.ok) return restError(response, error);
5310
6095
  if (!data || !Array.isArray(data.endpoints)) {
5311
6096
  return {
@@ -5330,10 +6115,10 @@ var listEndpoints = {
5330
6115
  return {
5331
6116
  ok: true,
5332
6117
  status: response.status,
5333
- payload: capList(trimmed, {
5334
- limit: args.limit,
5335
- cursor: args.cursor
5336
- })
6118
+ payload: {
6119
+ items: trimmed,
6120
+ pagination: serverPagination(data.pagination, trimmed.length)
6121
+ }
5337
6122
  };
5338
6123
  }
5339
6124
  };
@@ -5341,10 +6126,16 @@ var listEndpoints = {
5341
6126
  // src/specgen/tools/list-templates.ts
5342
6127
  var listTemplates = {
5343
6128
  name: "list-templates",
5344
- description: "List templates visible to the account. Returns id, name, image, and serverless flag per template; use get-template for full detail.",
5345
- inputSchema: { type: "object", properties: {} },
5346
- async handler(ctx) {
5347
- const { data, error, response } = await ctx.sdk.GET("/v2/templates");
6129
+ annotations: readOnly,
6130
+ 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.",
6131
+ inputSchema: {
6132
+ type: "object",
6133
+ properties: { ...listPaginationProperties }
6134
+ },
6135
+ async handler(ctx, args) {
6136
+ const { data, error, response } = await ctx.sdk.GET("/v2/templates", {
6137
+ params: { query: serverPageQuery(args) }
6138
+ });
5348
6139
  if (!response.ok) return restError(response, error);
5349
6140
  if (!data || !Array.isArray(data.templates)) {
5350
6141
  return {
@@ -5362,7 +6153,8 @@ var listTemplates = {
5362
6153
  name: template.name,
5363
6154
  image: template.image,
5364
6155
  serverless: template.serverless
5365
- }))
6156
+ })),
6157
+ pagination: serverPagination(data.pagination, data.templates.length)
5366
6158
  }
5367
6159
  };
5368
6160
  }
@@ -5385,7 +6177,7 @@ function authedGraphqlBase(env) {
5385
6177
  return pick(env.RUNPOD_AUTHED_GRAPHQL_URL, "https://api.runpod.io/graphql");
5386
6178
  }
5387
6179
 
5388
- // node_modules/.pnpm/@runpod+typescript-api-sdk@0.1.1/node_modules/@runpod/typescript-api-sdk/dist/index.js
6180
+ // node_modules/.pnpm/@runpod+typescript-api-sdk@0.2.0/node_modules/@runpod/typescript-api-sdk/dist/index.js
5389
6181
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
5390
6182
  var supportsRequestInitExt = () => {
5391
6183
  return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
@@ -6789,6 +7581,7 @@ function logParams(args) {
6789
7581
  }
6790
7582
  var streamPodLogs = {
6791
7583
  name: "stream-pod-logs",
7584
+ annotations: readOnly,
6792
7585
  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.",
6793
7586
  inputSchema: {
6794
7587
  type: "object",
@@ -6810,6 +7603,7 @@ var streamPodLogs = {
6810
7603
  };
6811
7604
  var streamWorkerLogs = {
6812
7605
  name: "stream-worker-logs",
7606
+ annotations: readOnly,
6813
7607
  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.",
6814
7608
  inputSchema: {
6815
7609
  type: "object",
@@ -6850,6 +7644,7 @@ function parseMetadata(metadata) {
6850
7644
  }
6851
7645
  var listPublicEndpoints = {
6852
7646
  name: "list-public-endpoints",
7647
+ annotations: readOnly,
6853
7648
  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.",
6854
7649
  inputSchema: {
6855
7650
  type: "object",
@@ -6948,9 +7743,321 @@ var listPublicEndpoints = {
6948
7743
  })
6949
7744
  };
6950
7745
 
7746
+ // src/specgen/tools/knowledge.ts
7747
+ import {
7748
+ loadKnowledge
7749
+ } from "@runpod/plugin-knowledge";
7750
+ var knowledge = loadKnowledge();
7751
+ var GUIDE_KINDS = ["skill", "reference", "golden-path"];
7752
+ var STOPWORDS = new Set(
7753
+ "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(
7754
+ " "
7755
+ )
7756
+ );
7757
+ var singular = (word) => {
7758
+ if (word.length > 4 && word.endsWith("ies")) return `${word.slice(0, -3)}y`;
7759
+ if (word.length > 3 && word.endsWith("s") && !word.endsWith("ss"))
7760
+ return word.slice(0, -1);
7761
+ return word;
7762
+ };
7763
+ var words = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 1 && !STOPWORDS.has(word)).map(singular);
7764
+ function editDistance(a, b, max) {
7765
+ if (Math.abs(a.length - b.length) > max) return max + 1;
7766
+ let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
7767
+ for (let i = 1; i <= a.length; i++) {
7768
+ const current = [i];
7769
+ for (let j = 1; j <= b.length; j++) {
7770
+ current[j] = Math.min(
7771
+ previous[j] + 1,
7772
+ current[j - 1] + 1,
7773
+ previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
7774
+ );
7775
+ }
7776
+ if (Math.min(...current) > max) return max + 1;
7777
+ previous = current;
7778
+ }
7779
+ return previous[b.length];
7780
+ }
7781
+ var typoBudget = (text) => text.length >= 8 ? 2 : text.length >= 4 ? 1 : 0;
7782
+ var oneTypo = (word, term) => term.length >= 5 && editDistance(word, term, 1) <= 1;
7783
+ var termMatches = (word, term) => word.startsWith(term) || oneTypo(word, term);
7784
+ var nameMatches = (name, term) => name === term || oneTypo(name, term);
7785
+ var guideSummary = ({
7786
+ id,
7787
+ kind,
7788
+ title,
7789
+ description,
7790
+ lanes,
7791
+ mcp,
7792
+ needs_shell,
7793
+ concepts
7794
+ }) => ({
7795
+ id,
7796
+ kind,
7797
+ title,
7798
+ description,
7799
+ lanes,
7800
+ mcp,
7801
+ needs_shell,
7802
+ concepts
7803
+ });
7804
+ function linkedGuides(conceptId) {
7805
+ const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));
7806
+ const seen = /* @__PURE__ */ new Set();
7807
+ const examples = [];
7808
+ const docs = [];
7809
+ for (const link of knowledge.links) {
7810
+ if (link.to !== conceptId || seen.has(link.from)) continue;
7811
+ seen.add(link.from);
7812
+ const guide = byId.get(link.from);
7813
+ if (!guide) continue;
7814
+ if (guide.kind === "golden-path")
7815
+ examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });
7816
+ else
7817
+ docs.push({
7818
+ id: guide.id,
7819
+ title: guide.title,
7820
+ ...link.rules ? { rules: link.rules } : {}
7821
+ });
7822
+ }
7823
+ return { examples, docs };
7824
+ }
7825
+ var conceptIndex = /* @__PURE__ */ new Map();
7826
+ for (const concept of knowledge.concepts) {
7827
+ for (const key of [concept.id, concept.name, ...concept.aliases]) {
7828
+ if (!conceptIndex.has(key.toLowerCase()))
7829
+ conceptIndex.set(key.toLowerCase(), concept);
7830
+ }
7831
+ }
7832
+ var conceptKey = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).map(singular).join(" ");
7833
+ var conceptKeyIndex = /* @__PURE__ */ new Map();
7834
+ for (const [key, concept] of conceptIndex) {
7835
+ if (!conceptKeyIndex.has(conceptKey(key)))
7836
+ conceptKeyIndex.set(conceptKey(key), concept);
7837
+ }
7838
+ function resolveConcept(input) {
7839
+ const exact = conceptIndex.get(input.trim().toLowerCase());
7840
+ if (exact) return { concept: exact };
7841
+ const key = conceptKey(input);
7842
+ const plural = conceptKeyIndex.get(key);
7843
+ if (plural) return { concept: plural, matchedAs: key };
7844
+ const budget = typoBudget(key);
7845
+ let best;
7846
+ let tied = false;
7847
+ for (const [candidate, concept] of conceptKeyIndex) {
7848
+ const distance = editDistance(key, candidate, budget);
7849
+ if (distance > budget) continue;
7850
+ if (!best || distance < best.distance) {
7851
+ best = { concept, key: candidate, distance };
7852
+ tied = false;
7853
+ } else if (distance === best.distance && concept.id !== best.concept.id) {
7854
+ tied = true;
7855
+ }
7856
+ }
7857
+ return best && !tied ? { concept: best.concept, matchedAs: best.key } : void 0;
7858
+ }
7859
+ var ruleIndex = /* @__PURE__ */ new Map();
7860
+ for (const concept of knowledge.concepts) {
7861
+ for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });
7862
+ }
7863
+ var source = {
7864
+ plugin_version: knowledge.version,
7865
+ plugin_commit: knowledge.commit
7866
+ };
7867
+ var listGuides = {
7868
+ name: "list-guides",
7869
+ annotations: bundledRead,
7870
+ 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.",
7871
+ inputSchema: {
7872
+ type: "object",
7873
+ properties: {
7874
+ kind: {
7875
+ type: "string",
7876
+ enum: [...GUIDE_KINDS],
7877
+ description: "Only this kind of guide."
7878
+ },
7879
+ query: {
7880
+ type: "string",
7881
+ description: "Words to match against the id, title and description."
7882
+ },
7883
+ concept: {
7884
+ type: "string",
7885
+ description: 'Only guides linked to this concept id, for example "network-volume".'
7886
+ }
7887
+ },
7888
+ additionalProperties: false
7889
+ },
7890
+ handler: async (_ctx, args) => {
7891
+ const kind = args.kind;
7892
+ const terms = words(String(args.query ?? ""));
7893
+ const concept = args.concept ? String(args.concept).trim() : void 0;
7894
+ const guides = knowledge.guides.filter((guide) => !kind || guide.kind === kind).filter((guide) => !concept || guide.concepts.includes(concept)).filter((guide) => {
7895
+ if (!terms.length) return true;
7896
+ const haystack = `${guide.id} ${guide.title} ${guide.description}`.toLowerCase();
7897
+ return terms.some((term) => haystack.includes(term));
7898
+ }).map(guideSummary);
7899
+ return ok({ ...source, count: guides.length, guides });
7900
+ }
7901
+ };
7902
+ var readGuide = {
7903
+ name: "read-guide",
7904
+ annotations: bundledRead,
7905
+ 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").',
7906
+ inputSchema: {
7907
+ type: "object",
7908
+ properties: {
7909
+ id: { type: "string", description: "The guide id from list-guides." }
7910
+ },
7911
+ required: ["id"],
7912
+ additionalProperties: false
7913
+ },
7914
+ handler: async (_ctx, args) => {
7915
+ const id = String(args.id).trim();
7916
+ const guide = knowledge.guides.find((candidate) => candidate.id === id);
7917
+ if (!guide) {
7918
+ const close = knowledge.guides.filter(
7919
+ (candidate) => candidate.id.includes(id) || id.includes(candidate.id)
7920
+ ).map((candidate) => candidate.id);
7921
+ return {
7922
+ ok: false,
7923
+ status: 404,
7924
+ payload: {
7925
+ error: `No guide with id "${id}".`,
7926
+ hint: close.length ? `Did you mean: ${close.join(", ")}?` : "Call list-guides for the ids."
7927
+ }
7928
+ };
7929
+ }
7930
+ return ok({
7931
+ ...source,
7932
+ ...guideSummary(guide),
7933
+ parent: guide.parent,
7934
+ path: guide.path,
7935
+ body: guide.body
7936
+ });
7937
+ }
7938
+ };
7939
+ var lookupConcept = {
7940
+ name: "lookup-concept",
7941
+ annotations: bundledRead,
7942
+ 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".',
7943
+ inputSchema: {
7944
+ type: "object",
7945
+ properties: {
7946
+ concept: {
7947
+ type: "string",
7948
+ description: 'An id, name or alias, such as "pod", "Network volume" or "volume disk".'
7949
+ }
7950
+ },
7951
+ required: ["concept"],
7952
+ additionalProperties: false
7953
+ },
7954
+ handler: async (_ctx, args) => {
7955
+ const resolved = resolveConcept(String(args.concept));
7956
+ if (!resolved) {
7957
+ const ref = conceptKey(String(args.concept));
7958
+ const close = [...conceptKeyIndex.keys()].filter(
7959
+ (key) => key.includes(ref) || editDistance(key, ref, typoBudget(ref) + 1) <= typoBudget(ref) + 1
7960
+ ).slice(0, 10);
7961
+ return {
7962
+ ok: false,
7963
+ status: 404,
7964
+ payload: {
7965
+ error: `No concept matches "${args.concept}".`,
7966
+ hint: close.length ? `Close matches: ${close.join(", ")}.` : "Try search-concepts with a few words instead."
7967
+ }
7968
+ };
7969
+ }
7970
+ const { concept, matchedAs } = resolved;
7971
+ const pointedAtBy = knowledge.concepts.flatMap((other) => [
7972
+ ...other.is_a === concept.id ? [{ concept: other.id, type: "is_a" }] : [],
7973
+ ...other.part_of === concept.id ? [{ concept: other.id, type: "part_of" }] : [],
7974
+ ...other.relations.filter((relation) => relation.target === concept.id).map((relation) => ({ concept: other.id, type: relation.type }))
7975
+ ]);
7976
+ const linkedRules = [...new Set(concept.rules.flatMap((rule) => rule.see))].map((id) => ruleIndex.get(id)).filter((entry) => entry !== void 0).map(({ rule, concept: owner }) => ({
7977
+ concept: owner.id,
7978
+ id: rule.id,
7979
+ statement: rule.statement.trim()
7980
+ }));
7981
+ return ok({
7982
+ ...source,
7983
+ ...matchedAs ? { matched_as: matchedAs } : {},
7984
+ ...concept,
7985
+ pointed_at_by: pointedAtBy,
7986
+ linked_rules: linkedRules,
7987
+ ...linkedGuides(concept.id)
7988
+ });
7989
+ }
7990
+ };
7991
+ var searchConcepts = {
7992
+ name: "search-concepts",
7993
+ annotations: bundledRead,
7994
+ 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.',
7995
+ inputSchema: {
7996
+ type: "object",
7997
+ properties: {
7998
+ query: {
7999
+ type: "string",
8000
+ description: "A few words describing the question."
8001
+ },
8002
+ limit: {
8003
+ type: "integer",
8004
+ minimum: 1,
8005
+ maximum: 25,
8006
+ description: "Most rules to return. Default 8."
8007
+ }
8008
+ },
8009
+ required: ["query"],
8010
+ additionalProperties: false
8011
+ },
8012
+ handler: async (_ctx, args) => {
8013
+ const terms = words(String(args.query));
8014
+ if (!terms.length) return badRequest("query needs at least one word.");
8015
+ const limit = Math.min(Math.max(Number(args.limit) || 8, 1), 25);
8016
+ const hits = [...ruleIndex.values()].map(({ rule, concept }) => {
8017
+ const statement = words(rule.statement);
8018
+ const names = words(
8019
+ [concept.id, concept.name, ...concept.aliases].join(" ")
8020
+ );
8021
+ const ruleId = words(rule.id);
8022
+ const score = terms.reduce(
8023
+ (total, term) => total + statement.filter((word) => termMatches(word, term)).length + (names.some((name) => nameMatches(name, term)) ? 3 : 0) + (ruleId.includes(term) ? 1 : 0),
8024
+ 0
8025
+ );
8026
+ const matched = terms.filter(
8027
+ (term) => statement.some((word) => termMatches(word, term)) || names.some((name) => nameMatches(name, term))
8028
+ ).length;
8029
+ return { rule, concept, score: score * matched };
8030
+ }).filter((hit) => hit.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map(({ rule, concept }) => ({
8031
+ concept: concept.id,
8032
+ concept_name: concept.name,
8033
+ id: rule.id,
8034
+ statement: rule.statement.trim(),
8035
+ status: rule.status,
8036
+ conflict: rule.conflict,
8037
+ evidence: rule.evidence
8038
+ }));
8039
+ return ok({ ...source, count: hits.length, rules: hits });
8040
+ }
8041
+ };
8042
+ var knowledgeTools = [
8043
+ listGuides,
8044
+ readGuide,
8045
+ lookupConcept,
8046
+ searchConcepts
8047
+ ];
8048
+ var GUIDE_URI_PREFIX = "runpod://guides/";
8049
+ var guideResources = knowledge.guides.map((guide) => ({
8050
+ uri: `${GUIDE_URI_PREFIX}${guide.id}`,
8051
+ name: guide.id,
8052
+ title: guide.title,
8053
+ description: guide.description,
8054
+ mimeType: "text/markdown",
8055
+ text: guide.body
8056
+ }));
8057
+
6951
8058
  // src/server.ts
6952
8059
  var SERVER_NAME = "Runpod API Server";
6953
- var SERVER_VERSION = true ? "4.0.0" : "dev";
8060
+ var SERVER_VERSION = true ? "4.1.0" : "dev";
6954
8061
 
6955
8062
  // src/specgen/analytics.ts
6956
8063
  import { createHmac } from "crypto";
@@ -7092,6 +8199,7 @@ function createAlpTools(opts) {
7092
8199
  // is ignored, never a 400 that derails the task the agent is actually on.
7093
8200
  lenientArguments: true,
7094
8201
  name: "report_feedback",
8202
+ annotations: write,
7095
8203
  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.",
7096
8204
  inputSchema: alpInputSchema(
7097
8205
  "The observation: what happened, what you expected, and the exact error or response text if you have it.",
@@ -7127,6 +8235,7 @@ function createAlpTools(opts) {
7127
8235
  // is ignored, never a 400 that derails the task the agent is actually on.
7128
8236
  lenientArguments: true,
7129
8237
  name: "save_to_journal",
8238
+ annotations: write,
7130
8239
  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.",
7131
8240
  inputSchema: alpInputSchema(
7132
8241
  "The learning, stated so a future agent can act on it: the situation, what turned out to be true, and how you verified it.",
@@ -7157,6 +8266,7 @@ function createAlpTools(opts) {
7157
8266
  // is ignored, never a 400 that derails the task the agent is actually on.
7158
8267
  lenientArguments: true,
7159
8268
  name: "ask_question",
8269
+ annotations: write,
7160
8270
  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.",
7161
8271
  inputSchema: alpInputSchema(
7162
8272
  "The question, with enough context that someone reading it later understands what you were blocked on.",
@@ -7181,6 +8291,7 @@ function createAlpTools(opts) {
7181
8291
  const readJournalTool = {
7182
8292
  lenientArguments: true,
7183
8293
  name: "read_journal",
8294
+ annotations: readOnly,
7184
8295
  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.",
7185
8296
  inputSchema: {
7186
8297
  type: "object",
@@ -7231,7 +8342,8 @@ var curatedTools = [
7231
8342
  getCapacity,
7232
8343
  ...hubTools,
7233
8344
  setEndpointGpus,
7234
- listPublicEndpoints
8345
+ listPublicEndpoints,
8346
+ ...knowledgeTools
7235
8347
  ];
7236
8348
  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.
7237
8349
 
@@ -7243,6 +8355,8 @@ Mutations cost money and bind to what this conversation created. State the hourl
7243
8355
 
7244
8356
  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.
7245
8357
 
8358
+ 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.
8359
+
7246
8360
  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.
7247
8361
 
7248
8362
  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.
@@ -7274,32 +8388,56 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
7274
8388
  };
7275
8389
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
7276
8390
  tools: [
7277
- ...servedCuratedTools.map(({ name, description, inputSchema }) => ({
7278
- name,
7279
- description,
7280
- inputSchema
7281
- })),
7282
- ...generatedTools.map(({ name, description, inputSchema }) => ({
7283
- name,
7284
- description,
7285
- inputSchema
7286
- }))
8391
+ ...servedCuratedTools.map(
8392
+ ({ name, description, inputSchema, annotations }) => ({
8393
+ name,
8394
+ description,
8395
+ inputSchema,
8396
+ annotations
8397
+ })
8398
+ ),
8399
+ ...generatedTools.map(
8400
+ ({ name, description, inputSchema, annotations }) => ({
8401
+ name,
8402
+ description,
8403
+ inputSchema,
8404
+ annotations
8405
+ })
8406
+ )
7287
8407
  ]
7288
8408
  }));
7289
8409
  const SKILL_URI_PREFIX = "runpod://skills/";
7290
8410
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
7291
- resources: skillDocs.map((skill) => ({
7292
- uri: `${SKILL_URI_PREFIX}${skill.name}`,
7293
- name: skill.name,
7294
- title: `Runpod skill: ${skill.name}`,
7295
- description: skill.description,
7296
- mimeType: "text/markdown"
7297
- }))
8411
+ resources: [
8412
+ ...skillDocs.map((skill) => ({
8413
+ uri: `${SKILL_URI_PREFIX}${skill.name}`,
8414
+ name: skill.name,
8415
+ title: `Runpod skill: ${skill.name}`,
8416
+ description: skill.description,
8417
+ mimeType: "text/markdown"
8418
+ })),
8419
+ ...guideResources.map(({ text: _text, ...resource }) => resource)
8420
+ ]
7298
8421
  }));
7299
8422
  server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
7300
8423
  resourceTemplates: []
7301
8424
  }));
7302
8425
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
8426
+ if (request.params.uri.startsWith(GUIDE_URI_PREFIX)) {
8427
+ const guide = guideResources.find(
8428
+ (candidate) => candidate.uri === request.params.uri
8429
+ );
8430
+ if (!guide) {
8431
+ throw new Error(
8432
+ `Unknown resource ${request.params.uri}. Call list-guides for the guide ids.`
8433
+ );
8434
+ }
8435
+ return {
8436
+ contents: [
8437
+ { uri: guide.uri, mimeType: "text/markdown", text: guide.text }
8438
+ ]
8439
+ };
8440
+ }
7303
8441
  const name = request.params.uri.startsWith(SKILL_URI_PREFIX) ? request.params.uri.slice(SKILL_URI_PREFIX.length) : void 0;
7304
8442
  const skill = skillDocs.find((candidate) => candidate.name === name);
7305
8443
  if (!skill) {