@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.cjs CHANGED
@@ -278,6 +278,12 @@ var generatedTools = [
278
278
  path: "/v2/clusters",
279
279
  params: [],
280
280
  hasBody: true,
281
+ annotations: {
282
+ readOnlyHint: false,
283
+ destructiveHint: false,
284
+ idempotentHint: false,
285
+ openWorldHint: true
286
+ },
281
287
  inputSchema: {
282
288
  type: "object",
283
289
  properties: {
@@ -289,12 +295,34 @@ var generatedTools = [
289
295
  $defs: {
290
296
  BaseContainerConfig: {
291
297
  type: "object",
292
- 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",
298
+ 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",
293
299
  properties: {
294
300
  args: {
295
301
  type: "string",
296
- description: "Arguments passed to the container entrypoint",
297
- examples: [""]
302
+ 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',
303
+ examples: [
304
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
305
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
306
+ ""
307
+ ]
308
+ },
309
+ cmd: {
310
+ type: "array",
311
+ items: {
312
+ type: "string"
313
+ },
314
+ 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",
315
+ examples: [
316
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
317
+ ]
318
+ },
319
+ entrypoint: {
320
+ type: "array",
321
+ items: {
322
+ type: "string"
323
+ },
324
+ 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",
325
+ examples: [["/bin/bash", "-c"]]
298
326
  },
299
327
  disk: {
300
328
  type: "integer",
@@ -370,7 +398,7 @@ var generatedTools = [
370
398
  {
371
399
  type: "object",
372
400
  required: ["name", "type", "compute"],
373
- 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",
401
+ 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",
374
402
  properties: {
375
403
  compute: {
376
404
  $ref: "#/$defs/ClusterCompute"
@@ -383,6 +411,12 @@ var generatedTools = [
383
411
  type: {
384
412
  $ref: "#/$defs/ClusterType"
385
413
  },
414
+ templateId: {
415
+ type: "string",
416
+ minLength: 1,
417
+ 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",
418
+ examples: ["30zmvf89kd"]
419
+ },
386
420
  dataCenterIds: {
387
421
  type: "array",
388
422
  items: {
@@ -474,6 +508,12 @@ var generatedTools = [
474
508
  path: "/v2/registries/delegations",
475
509
  params: [],
476
510
  hasBody: true,
511
+ annotations: {
512
+ readOnlyHint: false,
513
+ destructiveHint: false,
514
+ idempotentHint: false,
515
+ openWorldHint: true
516
+ },
477
517
  inputSchema: {
478
518
  type: "object",
479
519
  properties: {
@@ -513,6 +553,12 @@ var generatedTools = [
513
553
  path: "/v2/serverless",
514
554
  params: [],
515
555
  hasBody: true,
556
+ annotations: {
557
+ readOnlyHint: false,
558
+ destructiveHint: false,
559
+ idempotentHint: false,
560
+ openWorldHint: true
561
+ },
516
562
  inputSchema: {
517
563
  type: "object",
518
564
  properties: {
@@ -524,12 +570,34 @@ var generatedTools = [
524
570
  $defs: {
525
571
  BaseContainerConfig: {
526
572
  type: "object",
527
- 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",
573
+ 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",
528
574
  properties: {
529
575
  args: {
530
576
  type: "string",
531
- description: "Arguments passed to the container entrypoint",
532
- examples: [""]
577
+ 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',
578
+ examples: [
579
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
580
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
581
+ ""
582
+ ]
583
+ },
584
+ cmd: {
585
+ type: "array",
586
+ items: {
587
+ type: "string"
588
+ },
589
+ 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",
590
+ examples: [
591
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
592
+ ]
593
+ },
594
+ entrypoint: {
595
+ type: "array",
596
+ items: {
597
+ type: "string"
598
+ },
599
+ 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",
600
+ examples: [["/bin/bash", "-c"]]
533
601
  },
534
602
  disk: {
535
603
  type: "integer",
@@ -588,7 +656,7 @@ var generatedTools = [
588
656
  pools: {
589
657
  type: "array",
590
658
  minItems: 1,
591
- 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",
659
+ 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',
592
660
  items: {
593
661
  type: "string"
594
662
  },
@@ -892,6 +960,12 @@ var generatedTools = [
892
960
  path: "/v2/network-volumes",
893
961
  params: [],
894
962
  hasBody: true,
963
+ annotations: {
964
+ readOnlyHint: false,
965
+ destructiveHint: false,
966
+ idempotentHint: false,
967
+ openWorldHint: true
968
+ },
895
969
  inputSchema: {
896
970
  type: "object",
897
971
  properties: {
@@ -951,6 +1025,12 @@ var generatedTools = [
951
1025
  path: "/v2/pods",
952
1026
  params: [],
953
1027
  hasBody: true,
1028
+ annotations: {
1029
+ readOnlyHint: false,
1030
+ destructiveHint: false,
1031
+ idempotentHint: false,
1032
+ openWorldHint: true
1033
+ },
954
1034
  inputSchema: {
955
1035
  type: "object",
956
1036
  properties: {
@@ -962,12 +1042,34 @@ var generatedTools = [
962
1042
  $defs: {
963
1043
  BaseContainerConfig: {
964
1044
  type: "object",
965
- 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",
1045
+ 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",
966
1046
  properties: {
967
1047
  args: {
968
1048
  type: "string",
969
- description: "Arguments passed to the container entrypoint",
970
- examples: [""]
1049
+ 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',
1050
+ examples: [
1051
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1052
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1053
+ ""
1054
+ ]
1055
+ },
1056
+ cmd: {
1057
+ type: "array",
1058
+ items: {
1059
+ type: "string"
1060
+ },
1061
+ 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",
1062
+ examples: [
1063
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1064
+ ]
1065
+ },
1066
+ entrypoint: {
1067
+ type: "array",
1068
+ items: {
1069
+ type: "string"
1070
+ },
1071
+ 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",
1072
+ examples: [["/bin/bash", "-c"]]
971
1073
  },
972
1074
  disk: {
973
1075
  type: "integer",
@@ -1253,6 +1355,12 @@ var generatedTools = [
1253
1355
  path: "/v2/registries",
1254
1356
  params: [],
1255
1357
  hasBody: true,
1358
+ annotations: {
1359
+ readOnlyHint: false,
1360
+ destructiveHint: false,
1361
+ idempotentHint: false,
1362
+ openWorldHint: true
1363
+ },
1256
1364
  inputSchema: {
1257
1365
  type: "object",
1258
1366
  properties: {
@@ -1270,16 +1378,19 @@ var generatedTools = [
1270
1378
  name: {
1271
1379
  type: "string",
1272
1380
  minLength: 1,
1381
+ maxLength: 191,
1273
1382
  examples: ["my-private-registry"]
1274
1383
  },
1275
1384
  password: {
1276
1385
  type: "string",
1277
1386
  minLength: 1,
1387
+ maxLength: 16384,
1278
1388
  description: "Registry password (write-only, not returned in responses)"
1279
1389
  },
1280
1390
  username: {
1281
1391
  type: "string",
1282
1392
  minLength: 1,
1393
+ maxLength: 191,
1283
1394
  description: "Registry username (write-only, not returned in responses)"
1284
1395
  }
1285
1396
  }
@@ -1287,6 +1398,59 @@ var generatedTools = [
1287
1398
  }
1288
1399
  }
1289
1400
  },
1401
+ {
1402
+ name: "create-secret",
1403
+ operationId: "createSecret",
1404
+ 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.",
1405
+ method: "POST",
1406
+ path: "/v2/account/secrets",
1407
+ params: [],
1408
+ hasBody: true,
1409
+ annotations: {
1410
+ readOnlyHint: false,
1411
+ destructiveHint: false,
1412
+ idempotentHint: false,
1413
+ openWorldHint: true
1414
+ },
1415
+ inputSchema: {
1416
+ type: "object",
1417
+ properties: {
1418
+ body: {
1419
+ $ref: "#/$defs/CreateSecretRequest"
1420
+ }
1421
+ },
1422
+ required: ["body"],
1423
+ $defs: {
1424
+ CreateSecretRequest: {
1425
+ type: "object",
1426
+ additionalProperties: false,
1427
+ required: ["name", "value"],
1428
+ properties: {
1429
+ name: {
1430
+ type: "string",
1431
+ minLength: 1,
1432
+ maxLength: 191,
1433
+ pattern: "^[a-zA-Z_][a-zA-Z0-9_.\\-/]*$",
1434
+ 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).",
1435
+ examples: ["hf-token"]
1436
+ },
1437
+ value: {
1438
+ type: "string",
1439
+ minLength: 1,
1440
+ maxLength: 16777216,
1441
+ 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)."
1442
+ },
1443
+ description: {
1444
+ type: "string",
1445
+ maxLength: 65535,
1446
+ description: "Optional human-readable description, at most 65,535 bytes of UTF-8 text.",
1447
+ examples: ["Hugging Face read token"]
1448
+ }
1449
+ }
1450
+ }
1451
+ }
1452
+ }
1453
+ },
1290
1454
  {
1291
1455
  name: "create-template",
1292
1456
  operationId: "createTemplate",
@@ -1295,6 +1459,12 @@ var generatedTools = [
1295
1459
  path: "/v2/templates",
1296
1460
  params: [],
1297
1461
  hasBody: true,
1462
+ annotations: {
1463
+ readOnlyHint: false,
1464
+ destructiveHint: false,
1465
+ idempotentHint: false,
1466
+ openWorldHint: true
1467
+ },
1298
1468
  inputSchema: {
1299
1469
  type: "object",
1300
1470
  properties: {
@@ -1306,12 +1476,34 @@ var generatedTools = [
1306
1476
  $defs: {
1307
1477
  BaseContainerConfig: {
1308
1478
  type: "object",
1309
- 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",
1479
+ 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",
1310
1480
  properties: {
1311
1481
  args: {
1312
1482
  type: "string",
1313
- description: "Arguments passed to the container entrypoint",
1314
- examples: [""]
1483
+ 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',
1484
+ examples: [
1485
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
1486
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
1487
+ ""
1488
+ ]
1489
+ },
1490
+ cmd: {
1491
+ type: "array",
1492
+ items: {
1493
+ type: "string"
1494
+ },
1495
+ 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",
1496
+ examples: [
1497
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
1498
+ ]
1499
+ },
1500
+ entrypoint: {
1501
+ type: "array",
1502
+ items: {
1503
+ type: "string"
1504
+ },
1505
+ 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",
1506
+ examples: [["/bin/bash", "-c"]]
1315
1507
  },
1316
1508
  disk: {
1317
1509
  type: "integer",
@@ -1474,6 +1666,12 @@ var generatedTools = [
1474
1666
  }
1475
1667
  ],
1476
1668
  hasBody: false,
1669
+ annotations: {
1670
+ readOnlyHint: false,
1671
+ destructiveHint: true,
1672
+ idempotentHint: true,
1673
+ openWorldHint: true
1674
+ },
1477
1675
  inputSchema: {
1478
1676
  type: "object",
1479
1677
  properties: {
@@ -1498,6 +1696,12 @@ var generatedTools = [
1498
1696
  }
1499
1697
  ],
1500
1698
  hasBody: false,
1699
+ annotations: {
1700
+ readOnlyHint: false,
1701
+ destructiveHint: true,
1702
+ idempotentHint: true,
1703
+ openWorldHint: true
1704
+ },
1501
1705
  inputSchema: {
1502
1706
  type: "object",
1503
1707
  properties: {
@@ -1522,6 +1726,12 @@ var generatedTools = [
1522
1726
  }
1523
1727
  ],
1524
1728
  hasBody: false,
1729
+ annotations: {
1730
+ readOnlyHint: false,
1731
+ destructiveHint: true,
1732
+ idempotentHint: true,
1733
+ openWorldHint: true
1734
+ },
1525
1735
  inputSchema: {
1526
1736
  type: "object",
1527
1737
  properties: {
@@ -1546,6 +1756,12 @@ var generatedTools = [
1546
1756
  }
1547
1757
  ],
1548
1758
  hasBody: false,
1759
+ annotations: {
1760
+ readOnlyHint: false,
1761
+ destructiveHint: true,
1762
+ idempotentHint: true,
1763
+ openWorldHint: true
1764
+ },
1549
1765
  inputSchema: {
1550
1766
  type: "object",
1551
1767
  properties: {
@@ -1570,6 +1786,12 @@ var generatedTools = [
1570
1786
  }
1571
1787
  ],
1572
1788
  hasBody: false,
1789
+ annotations: {
1790
+ readOnlyHint: false,
1791
+ destructiveHint: true,
1792
+ idempotentHint: true,
1793
+ openWorldHint: true
1794
+ },
1573
1795
  inputSchema: {
1574
1796
  type: "object",
1575
1797
  properties: {
@@ -1580,6 +1802,36 @@ var generatedTools = [
1580
1802
  required: ["id"]
1581
1803
  }
1582
1804
  },
1805
+ {
1806
+ name: "delete-secret",
1807
+ operationId: "deleteSecret",
1808
+ description: "Delete a secret. Permanently deletes a secret. Environment variables referencing the deleted secret's name will no longer resolve to a value.",
1809
+ method: "DELETE",
1810
+ path: "/v2/account/secrets/{id}",
1811
+ params: [
1812
+ {
1813
+ name: "id",
1814
+ location: "path"
1815
+ }
1816
+ ],
1817
+ hasBody: false,
1818
+ annotations: {
1819
+ readOnlyHint: false,
1820
+ destructiveHint: true,
1821
+ idempotentHint: true,
1822
+ openWorldHint: true
1823
+ },
1824
+ inputSchema: {
1825
+ type: "object",
1826
+ properties: {
1827
+ id: {
1828
+ type: "string",
1829
+ description: "Secret identifier"
1830
+ }
1831
+ },
1832
+ required: ["id"]
1833
+ }
1834
+ },
1583
1835
  {
1584
1836
  name: "delete-template",
1585
1837
  operationId: "deleteTemplate",
@@ -1593,6 +1845,12 @@ var generatedTools = [
1593
1845
  }
1594
1846
  ],
1595
1847
  hasBody: false,
1848
+ annotations: {
1849
+ readOnlyHint: false,
1850
+ destructiveHint: true,
1851
+ idempotentHint: true,
1852
+ openWorldHint: true
1853
+ },
1596
1854
  inputSchema: {
1597
1855
  type: "object",
1598
1856
  properties: {
@@ -1616,6 +1874,12 @@ var generatedTools = [
1616
1874
  }
1617
1875
  ],
1618
1876
  hasBody: false,
1877
+ annotations: {
1878
+ readOnlyHint: true,
1879
+ destructiveHint: false,
1880
+ idempotentHint: true,
1881
+ openWorldHint: true
1882
+ },
1619
1883
  inputSchema: {
1620
1884
  type: "object",
1621
1885
  properties: {
@@ -1654,6 +1918,12 @@ var generatedTools = [
1654
1918
  }
1655
1919
  ],
1656
1920
  hasBody: false,
1921
+ annotations: {
1922
+ readOnlyHint: true,
1923
+ destructiveHint: false,
1924
+ idempotentHint: true,
1925
+ openWorldHint: true
1926
+ },
1657
1927
  inputSchema: {
1658
1928
  type: "object",
1659
1929
  properties: {
@@ -1715,6 +1985,12 @@ var generatedTools = [
1715
1985
  }
1716
1986
  ],
1717
1987
  hasBody: false,
1988
+ annotations: {
1989
+ readOnlyHint: true,
1990
+ destructiveHint: false,
1991
+ idempotentHint: true,
1992
+ openWorldHint: true
1993
+ },
1718
1994
  inputSchema: {
1719
1995
  type: "object",
1720
1996
  properties: {
@@ -1753,6 +2029,12 @@ var generatedTools = [
1753
2029
  }
1754
2030
  ],
1755
2031
  hasBody: false,
2032
+ annotations: {
2033
+ readOnlyHint: true,
2034
+ destructiveHint: false,
2035
+ idempotentHint: true,
2036
+ openWorldHint: true
2037
+ },
1756
2038
  inputSchema: {
1757
2039
  type: "object",
1758
2040
  properties: {
@@ -1767,7 +2049,7 @@ var generatedTools = [
1767
2049
  {
1768
2050
  name: "get-endpoint-build",
1769
2051
  operationId: "getEndpointBuild",
1770
- 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.",
2052
+ 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.",
1771
2053
  method: "GET",
1772
2054
  path: "/v2/serverless/{id}/builds/{buildId}",
1773
2055
  params: [
@@ -1781,6 +2063,12 @@ var generatedTools = [
1781
2063
  }
1782
2064
  ],
1783
2065
  hasBody: false,
2066
+ annotations: {
2067
+ readOnlyHint: true,
2068
+ destructiveHint: false,
2069
+ idempotentHint: true,
2070
+ openWorldHint: true
2071
+ },
1784
2072
  inputSchema: {
1785
2073
  type: "object",
1786
2074
  properties: {
@@ -1841,6 +2129,12 @@ var generatedTools = [
1841
2129
  }
1842
2130
  ],
1843
2131
  hasBody: false,
2132
+ annotations: {
2133
+ readOnlyHint: true,
2134
+ destructiveHint: false,
2135
+ idempotentHint: true,
2136
+ openWorldHint: true
2137
+ },
1844
2138
  inputSchema: {
1845
2139
  type: "object",
1846
2140
  properties: {
@@ -1927,6 +2221,12 @@ var generatedTools = [
1927
2221
  }
1928
2222
  ],
1929
2223
  hasBody: false,
2224
+ annotations: {
2225
+ readOnlyHint: true,
2226
+ destructiveHint: false,
2227
+ idempotentHint: true,
2228
+ openWorldHint: true
2229
+ },
1930
2230
  inputSchema: {
1931
2231
  type: "object",
1932
2232
  properties: {
@@ -1951,6 +2251,12 @@ var generatedTools = [
1951
2251
  }
1952
2252
  ],
1953
2253
  hasBody: false,
2254
+ annotations: {
2255
+ readOnlyHint: true,
2256
+ destructiveHint: false,
2257
+ idempotentHint: true,
2258
+ openWorldHint: true
2259
+ },
1954
2260
  inputSchema: {
1955
2261
  type: "object",
1956
2262
  properties: {
@@ -1975,6 +2281,12 @@ var generatedTools = [
1975
2281
  }
1976
2282
  ],
1977
2283
  hasBody: false,
2284
+ annotations: {
2285
+ readOnlyHint: true,
2286
+ destructiveHint: false,
2287
+ idempotentHint: true,
2288
+ openWorldHint: true
2289
+ },
1978
2290
  inputSchema: {
1979
2291
  type: "object",
1980
2292
  properties: {
@@ -1985,6 +2297,36 @@ var generatedTools = [
1985
2297
  required: ["id"]
1986
2298
  }
1987
2299
  },
2300
+ {
2301
+ name: "get-secret",
2302
+ operationId: "getSecret",
2303
+ description: "Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.",
2304
+ method: "GET",
2305
+ path: "/v2/account/secrets/{id}",
2306
+ params: [
2307
+ {
2308
+ name: "id",
2309
+ location: "path"
2310
+ }
2311
+ ],
2312
+ hasBody: false,
2313
+ annotations: {
2314
+ readOnlyHint: true,
2315
+ destructiveHint: false,
2316
+ idempotentHint: true,
2317
+ openWorldHint: true
2318
+ },
2319
+ inputSchema: {
2320
+ type: "object",
2321
+ properties: {
2322
+ id: {
2323
+ type: "string",
2324
+ description: "Secret identifier"
2325
+ }
2326
+ },
2327
+ required: ["id"]
2328
+ }
2329
+ },
1988
2330
  {
1989
2331
  name: "get-ssh-keys",
1990
2332
  operationId: "getSshKeys",
@@ -1993,6 +2335,12 @@ var generatedTools = [
1993
2335
  path: "/v2/account/ssh-keys",
1994
2336
  params: [],
1995
2337
  hasBody: false,
2338
+ annotations: {
2339
+ readOnlyHint: true,
2340
+ destructiveHint: false,
2341
+ idempotentHint: true,
2342
+ openWorldHint: true
2343
+ },
1996
2344
  inputSchema: {
1997
2345
  type: "object",
1998
2346
  properties: {}
@@ -2011,6 +2359,12 @@ var generatedTools = [
2011
2359
  }
2012
2360
  ],
2013
2361
  hasBody: false,
2362
+ annotations: {
2363
+ readOnlyHint: true,
2364
+ destructiveHint: false,
2365
+ idempotentHint: true,
2366
+ openWorldHint: true
2367
+ },
2014
2368
  inputSchema: {
2015
2369
  type: "object",
2016
2370
  properties: {
@@ -2046,6 +2400,12 @@ var generatedTools = [
2046
2400
  }
2047
2401
  ],
2048
2402
  hasBody: false,
2403
+ annotations: {
2404
+ readOnlyHint: true,
2405
+ destructiveHint: false,
2406
+ idempotentHint: true,
2407
+ openWorldHint: true
2408
+ },
2049
2409
  inputSchema: {
2050
2410
  type: "object",
2051
2411
  properties: {
@@ -2116,6 +2476,12 @@ var generatedTools = [
2116
2476
  }
2117
2477
  ],
2118
2478
  hasBody: false,
2479
+ annotations: {
2480
+ readOnlyHint: true,
2481
+ destructiveHint: false,
2482
+ idempotentHint: true,
2483
+ openWorldHint: true
2484
+ },
2119
2485
  inputSchema: {
2120
2486
  type: "object",
2121
2487
  properties: {
@@ -2174,6 +2540,12 @@ var generatedTools = [
2174
2540
  }
2175
2541
  ],
2176
2542
  hasBody: false,
2543
+ annotations: {
2544
+ readOnlyHint: true,
2545
+ destructiveHint: false,
2546
+ idempotentHint: true,
2547
+ openWorldHint: true
2548
+ },
2177
2549
  inputSchema: {
2178
2550
  type: "object",
2179
2551
  properties: {
@@ -2193,6 +2565,12 @@ var generatedTools = [
2193
2565
  path: "/v2/clusters",
2194
2566
  params: [],
2195
2567
  hasBody: false,
2568
+ annotations: {
2569
+ readOnlyHint: true,
2570
+ destructiveHint: false,
2571
+ idempotentHint: true,
2572
+ openWorldHint: true
2573
+ },
2196
2574
  inputSchema: {
2197
2575
  type: "object",
2198
2576
  properties: {}
@@ -2221,6 +2599,12 @@ var generatedTools = [
2221
2599
  }
2222
2600
  ],
2223
2601
  hasBody: false,
2602
+ annotations: {
2603
+ readOnlyHint: true,
2604
+ destructiveHint: false,
2605
+ idempotentHint: true,
2606
+ openWorldHint: true
2607
+ },
2224
2608
  inputSchema: {
2225
2609
  type: "object",
2226
2610
  properties: {
@@ -2293,6 +2677,12 @@ var generatedTools = [
2293
2677
  }
2294
2678
  ],
2295
2679
  hasBody: false,
2680
+ annotations: {
2681
+ readOnlyHint: true,
2682
+ destructiveHint: false,
2683
+ idempotentHint: true,
2684
+ openWorldHint: true
2685
+ },
2296
2686
  inputSchema: {
2297
2687
  type: "object",
2298
2688
  properties: {
@@ -2389,6 +2779,12 @@ var generatedTools = [
2389
2779
  path: "/v2/registries/delegations",
2390
2780
  params: [],
2391
2781
  hasBody: false,
2782
+ annotations: {
2783
+ readOnlyHint: true,
2784
+ destructiveHint: false,
2785
+ idempotentHint: true,
2786
+ openWorldHint: true
2787
+ },
2392
2788
  inputSchema: {
2393
2789
  type: "object",
2394
2790
  properties: {}
@@ -2419,6 +2815,12 @@ var generatedTools = [
2419
2815
  }
2420
2816
  ],
2421
2817
  hasBody: false,
2818
+ annotations: {
2819
+ readOnlyHint: true,
2820
+ destructiveHint: false,
2821
+ idempotentHint: true,
2822
+ openWorldHint: true
2823
+ },
2422
2824
  inputSchema: {
2423
2825
  type: "object",
2424
2826
  properties: {
@@ -2463,22 +2865,47 @@ var generatedTools = [
2463
2865
  {
2464
2866
  name: "list-endpoint-builds",
2465
2867
  operationId: "listEndpointBuilds",
2466
- 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`.",
2868
+ 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`.",
2467
2869
  method: "GET",
2468
2870
  path: "/v2/serverless/{id}/builds",
2469
2871
  params: [
2470
2872
  {
2471
2873
  name: "id",
2472
2874
  location: "path"
2875
+ },
2876
+ {
2877
+ name: "cursor",
2878
+ location: "query"
2879
+ },
2880
+ {
2881
+ name: "limit",
2882
+ location: "query"
2473
2883
  }
2474
2884
  ],
2475
2885
  hasBody: false,
2886
+ annotations: {
2887
+ readOnlyHint: true,
2888
+ destructiveHint: false,
2889
+ idempotentHint: true,
2890
+ openWorldHint: true
2891
+ },
2476
2892
  inputSchema: {
2477
2893
  type: "object",
2478
2894
  properties: {
2479
2895
  id: {
2480
2896
  type: "string",
2481
2897
  description: "Serverless endpoint identifier"
2898
+ },
2899
+ cursor: {
2900
+ type: "string",
2901
+ minLength: 1,
2902
+ 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"
2903
+ },
2904
+ limit: {
2905
+ type: "integer",
2906
+ minimum: 1,
2907
+ maximum: 100,
2908
+ description: "Page size, 1\u2013100. Defaults to 100 when omitted."
2482
2909
  }
2483
2910
  },
2484
2911
  required: ["id"]
@@ -2487,22 +2914,47 @@ var generatedTools = [
2487
2914
  {
2488
2915
  name: "list-endpoint-releases",
2489
2916
  operationId: "listEndpointReleases",
2490
- 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).",
2917
+ 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.",
2491
2918
  method: "GET",
2492
2919
  path: "/v2/serverless/{id}/releases",
2493
2920
  params: [
2494
2921
  {
2495
2922
  name: "id",
2496
2923
  location: "path"
2924
+ },
2925
+ {
2926
+ name: "cursor",
2927
+ location: "query"
2928
+ },
2929
+ {
2930
+ name: "limit",
2931
+ location: "query"
2497
2932
  }
2498
2933
  ],
2499
2934
  hasBody: false,
2935
+ annotations: {
2936
+ readOnlyHint: true,
2937
+ destructiveHint: false,
2938
+ idempotentHint: true,
2939
+ openWorldHint: true
2940
+ },
2500
2941
  inputSchema: {
2501
2942
  type: "object",
2502
2943
  properties: {
2503
2944
  id: {
2504
2945
  type: "string",
2505
2946
  description: "Serverless endpoint identifier"
2947
+ },
2948
+ cursor: {
2949
+ type: "string",
2950
+ minLength: 1,
2951
+ 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"
2952
+ },
2953
+ limit: {
2954
+ type: "integer",
2955
+ minimum: 1,
2956
+ maximum: 1e3,
2957
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
2506
2958
  }
2507
2959
  },
2508
2960
  required: ["id"]
@@ -2521,6 +2973,12 @@ var generatedTools = [
2521
2973
  }
2522
2974
  ],
2523
2975
  hasBody: false,
2976
+ annotations: {
2977
+ readOnlyHint: true,
2978
+ destructiveHint: false,
2979
+ idempotentHint: true,
2980
+ openWorldHint: true
2981
+ },
2524
2982
  inputSchema: {
2525
2983
  type: "object",
2526
2984
  properties: {
@@ -2573,6 +3031,12 @@ var generatedTools = [
2573
3031
  }
2574
3032
  ],
2575
3033
  hasBody: false,
3034
+ annotations: {
3035
+ readOnlyHint: true,
3036
+ destructiveHint: false,
3037
+ idempotentHint: true,
3038
+ openWorldHint: true
3039
+ },
2576
3040
  inputSchema: {
2577
3041
  type: "object",
2578
3042
  properties: {
@@ -2671,6 +3135,12 @@ var generatedTools = [
2671
3135
  }
2672
3136
  ],
2673
3137
  hasBody: false,
3138
+ annotations: {
3139
+ readOnlyHint: true,
3140
+ destructiveHint: false,
3141
+ idempotentHint: true,
3142
+ openWorldHint: true
3143
+ },
2674
3144
  inputSchema: {
2675
3145
  type: "object",
2676
3146
  properties: {
@@ -2724,6 +3194,12 @@ var generatedTools = [
2724
3194
  path: "/v2/network-volumes",
2725
3195
  params: [],
2726
3196
  hasBody: false,
3197
+ annotations: {
3198
+ readOnlyHint: true,
3199
+ destructiveHint: false,
3200
+ idempotentHint: true,
3201
+ openWorldHint: true
3202
+ },
2727
3203
  inputSchema: {
2728
3204
  type: "object",
2729
3205
  properties: {}
@@ -2758,6 +3234,12 @@ var generatedTools = [
2758
3234
  }
2759
3235
  ],
2760
3236
  hasBody: false,
3237
+ annotations: {
3238
+ readOnlyHint: true,
3239
+ destructiveHint: false,
3240
+ idempotentHint: true,
3241
+ openWorldHint: true
3242
+ },
2761
3243
  inputSchema: {
2762
3244
  type: "object",
2763
3245
  properties: {
@@ -2806,16 +3288,30 @@ var generatedTools = [
2806
3288
  {
2807
3289
  name: "list-pods",
2808
3290
  operationId: "listPods",
2809
- 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).",
3291
+ 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.",
2810
3292
  method: "GET",
2811
3293
  path: "/v2/pods",
2812
3294
  params: [
2813
3295
  {
2814
3296
  name: "includeClusterPods",
2815
3297
  location: "query"
3298
+ },
3299
+ {
3300
+ name: "cursor",
3301
+ location: "query"
3302
+ },
3303
+ {
3304
+ name: "limit",
3305
+ location: "query"
2816
3306
  }
2817
3307
  ],
2818
3308
  hasBody: false,
3309
+ annotations: {
3310
+ readOnlyHint: true,
3311
+ destructiveHint: false,
3312
+ idempotentHint: true,
3313
+ openWorldHint: true
3314
+ },
2819
3315
  inputSchema: {
2820
3316
  type: "object",
2821
3317
  properties: {
@@ -2823,6 +3319,17 @@ var generatedTools = [
2823
3319
  type: "boolean",
2824
3320
  default: false,
2825
3321
  description: "Include cluster member pods in the result. Defaults to false."
3322
+ },
3323
+ cursor: {
3324
+ type: "string",
3325
+ minLength: 1,
3326
+ 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"
3327
+ },
3328
+ limit: {
3329
+ type: "integer",
3330
+ minimum: 1,
3331
+ maximum: 1e3,
3332
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
2826
3333
  }
2827
3334
  }
2828
3335
  }
@@ -2830,7 +3337,7 @@ var generatedTools = [
2830
3337
  {
2831
3338
  name: "list-public-templates",
2832
3339
  operationId: "listPublicTemplates",
2833
- 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.",
3340
+ 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`).",
2834
3341
  method: "GET",
2835
3342
  path: "/v2/catalog/templates",
2836
3343
  params: [
@@ -2840,6 +3347,12 @@ var generatedTools = [
2840
3347
  }
2841
3348
  ],
2842
3349
  hasBody: false,
3350
+ annotations: {
3351
+ readOnlyHint: true,
3352
+ destructiveHint: false,
3353
+ idempotentHint: true,
3354
+ openWorldHint: true
3355
+ },
2843
3356
  inputSchema: {
2844
3357
  type: "object",
2845
3358
  properties: {
@@ -2860,11 +3373,46 @@ var generatedTools = [
2860
3373
  path: "/v2/registries",
2861
3374
  params: [],
2862
3375
  hasBody: false,
3376
+ annotations: {
3377
+ readOnlyHint: true,
3378
+ destructiveHint: false,
3379
+ idempotentHint: true,
3380
+ openWorldHint: true
3381
+ },
2863
3382
  inputSchema: {
2864
3383
  type: "object",
2865
3384
  properties: {}
2866
3385
  }
2867
3386
  },
3387
+ {
3388
+ name: "list-secrets",
3389
+ operationId: "listSecrets",
3390
+ 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.",
3391
+ method: "GET",
3392
+ path: "/v2/account/secrets",
3393
+ params: [
3394
+ {
3395
+ name: "name",
3396
+ location: "query"
3397
+ }
3398
+ ],
3399
+ hasBody: false,
3400
+ annotations: {
3401
+ readOnlyHint: true,
3402
+ destructiveHint: false,
3403
+ idempotentHint: true,
3404
+ openWorldHint: true
3405
+ },
3406
+ inputSchema: {
3407
+ type: "object",
3408
+ properties: {
3409
+ name: {
3410
+ type: "string",
3411
+ description: "When provided, returns only the secret with this name (case-insensitive)."
3412
+ }
3413
+ }
3414
+ }
3415
+ },
2868
3416
  {
2869
3417
  name: "list-serverless-billing",
2870
3418
  operationId: "listServerlessBilling",
@@ -2894,6 +3442,12 @@ var generatedTools = [
2894
3442
  }
2895
3443
  ],
2896
3444
  hasBody: false,
3445
+ annotations: {
3446
+ readOnlyHint: true,
3447
+ destructiveHint: false,
3448
+ idempotentHint: true,
3449
+ openWorldHint: true
3450
+ },
2897
3451
  inputSchema: {
2898
3452
  type: "object",
2899
3453
  properties: {
@@ -2952,6 +3506,12 @@ var generatedTools = [
2952
3506
  }
2953
3507
  ],
2954
3508
  hasBody: true,
3509
+ annotations: {
3510
+ readOnlyHint: false,
3511
+ destructiveHint: true,
3512
+ idempotentHint: false,
3513
+ openWorldHint: true
3514
+ },
2955
3515
  inputSchema: {
2956
3516
  type: "object",
2957
3517
  properties: {
@@ -2995,6 +3555,12 @@ var generatedTools = [
2995
3555
  }
2996
3556
  ],
2997
3557
  hasBody: false,
3558
+ annotations: {
3559
+ readOnlyHint: false,
3560
+ destructiveHint: true,
3561
+ idempotentHint: true,
3562
+ openWorldHint: true
3563
+ },
2998
3564
  inputSchema: {
2999
3565
  type: "object",
3000
3566
  properties: {
@@ -3018,6 +3584,12 @@ var generatedTools = [
3018
3584
  }
3019
3585
  ],
3020
3586
  hasBody: true,
3587
+ annotations: {
3588
+ readOnlyHint: false,
3589
+ destructiveHint: false,
3590
+ idempotentHint: false,
3591
+ openWorldHint: true
3592
+ },
3021
3593
  inputSchema: {
3022
3594
  type: "object",
3023
3595
  properties: {
@@ -3060,6 +3632,12 @@ var generatedTools = [
3060
3632
  }
3061
3633
  ],
3062
3634
  hasBody: true,
3635
+ annotations: {
3636
+ readOnlyHint: false,
3637
+ destructiveHint: false,
3638
+ idempotentHint: false,
3639
+ openWorldHint: true
3640
+ },
3063
3641
  inputSchema: {
3064
3642
  type: "object",
3065
3643
  properties: {
@@ -3075,12 +3653,34 @@ var generatedTools = [
3075
3653
  $defs: {
3076
3654
  BaseContainerConfig: {
3077
3655
  type: "object",
3078
- 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",
3656
+ 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",
3079
3657
  properties: {
3080
3658
  args: {
3081
3659
  type: "string",
3082
- description: "Arguments passed to the container entrypoint",
3083
- examples: [""]
3660
+ 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',
3661
+ examples: [
3662
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
3663
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
3664
+ ""
3665
+ ]
3666
+ },
3667
+ cmd: {
3668
+ type: "array",
3669
+ items: {
3670
+ type: "string"
3671
+ },
3672
+ 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",
3673
+ examples: [
3674
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
3675
+ ]
3676
+ },
3677
+ entrypoint: {
3678
+ type: "array",
3679
+ items: {
3680
+ type: "string"
3681
+ },
3682
+ 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",
3683
+ examples: [["/bin/bash", "-c"]]
3084
3684
  },
3085
3685
  disk: {
3086
3686
  type: "integer",
@@ -3139,7 +3739,7 @@ var generatedTools = [
3139
3739
  pools: {
3140
3740
  type: "array",
3141
3741
  minItems: 1,
3142
- 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",
3742
+ 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',
3143
3743
  items: {
3144
3744
  type: "string"
3145
3745
  },
@@ -3384,6 +3984,12 @@ var generatedTools = [
3384
3984
  }
3385
3985
  ],
3386
3986
  hasBody: true,
3987
+ annotations: {
3988
+ readOnlyHint: false,
3989
+ destructiveHint: false,
3990
+ idempotentHint: false,
3991
+ openWorldHint: true
3992
+ },
3387
3993
  inputSchema: {
3388
3994
  type: "object",
3389
3995
  properties: {
@@ -3434,6 +4040,12 @@ var generatedTools = [
3434
4040
  }
3435
4041
  ],
3436
4042
  hasBody: true,
4043
+ annotations: {
4044
+ readOnlyHint: false,
4045
+ destructiveHint: false,
4046
+ idempotentHint: false,
4047
+ openWorldHint: true
4048
+ },
3437
4049
  inputSchema: {
3438
4050
  type: "object",
3439
4051
  properties: {
@@ -3449,12 +4061,34 @@ var generatedTools = [
3449
4061
  $defs: {
3450
4062
  BaseContainerConfig: {
3451
4063
  type: "object",
3452
- 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",
4064
+ 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",
3453
4065
  properties: {
3454
4066
  args: {
3455
4067
  type: "string",
3456
- description: "Arguments passed to the container entrypoint",
3457
- examples: [""]
4068
+ 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',
4069
+ examples: [
4070
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
4071
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
4072
+ ""
4073
+ ]
4074
+ },
4075
+ cmd: {
4076
+ type: "array",
4077
+ items: {
4078
+ type: "string"
4079
+ },
4080
+ 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",
4081
+ examples: [
4082
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
4083
+ ]
4084
+ },
4085
+ entrypoint: {
4086
+ type: "array",
4087
+ items: {
4088
+ type: "string"
4089
+ },
4090
+ 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",
4091
+ examples: [["/bin/bash", "-c"]]
3458
4092
  },
3459
4093
  disk: {
3460
4094
  type: "integer",
@@ -3597,6 +4231,60 @@ var generatedTools = [
3597
4231
  }
3598
4232
  }
3599
4233
  },
4234
+ {
4235
+ name: "update-secret",
4236
+ operationId: "updateSecret",
4237
+ 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.",
4238
+ method: "PATCH",
4239
+ path: "/v2/account/secrets/{id}",
4240
+ params: [
4241
+ {
4242
+ name: "id",
4243
+ location: "path"
4244
+ }
4245
+ ],
4246
+ hasBody: true,
4247
+ annotations: {
4248
+ readOnlyHint: false,
4249
+ destructiveHint: false,
4250
+ idempotentHint: false,
4251
+ openWorldHint: true
4252
+ },
4253
+ inputSchema: {
4254
+ type: "object",
4255
+ properties: {
4256
+ id: {
4257
+ type: "string",
4258
+ description: "Secret identifier"
4259
+ },
4260
+ body: {
4261
+ $ref: "#/$defs/UpdateSecretRequest"
4262
+ }
4263
+ },
4264
+ required: ["id", "body"],
4265
+ $defs: {
4266
+ UpdateSecretRequest: {
4267
+ type: "object",
4268
+ additionalProperties: false,
4269
+ minProperties: 1,
4270
+ description: "Only the provided fields are updated; at least one field is required.\nThe secret's `name` is immutable.\n",
4271
+ properties: {
4272
+ value: {
4273
+ type: "string",
4274
+ minLength: 1,
4275
+ maxLength: 16777216,
4276
+ 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)."
4277
+ },
4278
+ description: {
4279
+ type: "string",
4280
+ maxLength: 65535,
4281
+ description: 'New human-readable description, at most 65,535 bytes of UTF-8 text. Send `""` to clear.'
4282
+ }
4283
+ }
4284
+ }
4285
+ }
4286
+ }
4287
+ },
3600
4288
  {
3601
4289
  name: "update-ssh-keys",
3602
4290
  operationId: "updateSshKeys",
@@ -3605,6 +4293,12 @@ var generatedTools = [
3605
4293
  path: "/v2/account/ssh-keys",
3606
4294
  params: [],
3607
4295
  hasBody: true,
4296
+ annotations: {
4297
+ readOnlyHint: false,
4298
+ destructiveHint: true,
4299
+ idempotentHint: true,
4300
+ openWorldHint: true
4301
+ },
3608
4302
  inputSchema: {
3609
4303
  type: "object",
3610
4304
  properties: {
@@ -3650,6 +4344,12 @@ var generatedTools = [
3650
4344
  }
3651
4345
  ],
3652
4346
  hasBody: true,
4347
+ annotations: {
4348
+ readOnlyHint: false,
4349
+ destructiveHint: false,
4350
+ idempotentHint: false,
4351
+ openWorldHint: true
4352
+ },
3653
4353
  inputSchema: {
3654
4354
  type: "object",
3655
4355
  properties: {
@@ -3664,12 +4364,34 @@ var generatedTools = [
3664
4364
  $defs: {
3665
4365
  BaseContainerConfig: {
3666
4366
  type: "object",
3667
- 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",
4367
+ 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",
3668
4368
  properties: {
3669
4369
  args: {
3670
4370
  type: "string",
3671
- description: "Arguments passed to the container entrypoint",
3672
- examples: [""]
4371
+ 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',
4372
+ examples: [
4373
+ "--model meta-llama/Llama-3-8B --max-model-len 8192",
4374
+ '{"entrypoint":["/bin/bash","-c"],"cmd":["python -u main.py"]}',
4375
+ ""
4376
+ ]
4377
+ },
4378
+ cmd: {
4379
+ type: "array",
4380
+ items: {
4381
+ type: "string"
4382
+ },
4383
+ 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",
4384
+ examples: [
4385
+ ["--model", "meta-llama/Llama-3-8B", "--max-model-len", "8192"]
4386
+ ]
4387
+ },
4388
+ entrypoint: {
4389
+ type: "array",
4390
+ items: {
4391
+ type: "string"
4392
+ },
4393
+ 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",
4394
+ examples: [["/bin/bash", "-c"]]
3673
4395
  },
3674
4396
  disk: {
3675
4397
  type: "integer",
@@ -3986,6 +4708,26 @@ var listPaginationProperties = {
3986
4708
  description: "Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning."
3987
4709
  }
3988
4710
  };
4711
+ function clampListLimit(limit) {
4712
+ const requested = Number(limit);
4713
+ return Math.min(
4714
+ Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
4715
+ MAX_LIST_LIMIT
4716
+ );
4717
+ }
4718
+ function serverPageQuery(args) {
4719
+ const cursor = typeof args.cursor === "string" && args.cursor !== "" ? args.cursor : void 0;
4720
+ return { limit: clampListLimit(args.limit), ...cursor ? { cursor } : {} };
4721
+ }
4722
+ function serverPagination(pagination, returned) {
4723
+ const hasNextPage = pagination?.hasNextPage === true;
4724
+ return {
4725
+ returned,
4726
+ hasNextPage,
4727
+ nextCursor: pagination?.nextCursor ?? null,
4728
+ ...hasNextPage ? { note: "More results exist. Pass cursor=nextCursor to fetch them." } : {}
4729
+ };
4730
+ }
3989
4731
  function decodeCursorOffset(cursor) {
3990
4732
  if (!cursor) return 0;
3991
4733
  try {
@@ -4001,11 +4743,7 @@ function encodeCursorOffset(offset) {
4001
4743
  return Buffer.from(String(offset), "utf8").toString("base64");
4002
4744
  }
4003
4745
  function capList(items, options, extra) {
4004
- const requested = Number(options.limit);
4005
- const limit = Math.min(
4006
- Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_LIST_LIMIT,
4007
- MAX_LIST_LIMIT
4008
- );
4746
+ const limit = clampListLimit(options.limit);
4009
4747
  const offset = decodeCursorOffset(options.cursor);
4010
4748
  const total = items.length;
4011
4749
  const page = items.slice(offset, offset + limit);
@@ -4084,6 +4822,38 @@ async function runTool(body) {
4084
4822
  }
4085
4823
  }
4086
4824
 
4825
+ // src/specgen/tools/annotations.ts
4826
+ var readOnly = {
4827
+ readOnlyHint: true,
4828
+ destructiveHint: false,
4829
+ idempotentHint: true,
4830
+ openWorldHint: true
4831
+ };
4832
+ var bundledRead = {
4833
+ readOnlyHint: true,
4834
+ destructiveHint: false,
4835
+ idempotentHint: true,
4836
+ openWorldHint: false
4837
+ };
4838
+ var write = {
4839
+ readOnlyHint: false,
4840
+ destructiveHint: false,
4841
+ idempotentHint: false,
4842
+ openWorldHint: true
4843
+ };
4844
+ var idempotentWrite = {
4845
+ readOnlyHint: false,
4846
+ destructiveHint: false,
4847
+ idempotentHint: true,
4848
+ openWorldHint: true
4849
+ };
4850
+ var destructive = {
4851
+ readOnlyHint: false,
4852
+ destructiveHint: true,
4853
+ idempotentHint: true,
4854
+ openWorldHint: true
4855
+ };
4856
+
4087
4857
  // src/specgen/tools/capacity.ts
4088
4858
  var CUDA_VERSION_REGEX = /^\d{1,2}\.\d{1,2}$/;
4089
4859
  var MAX_PROBE_VERSIONS = 12;
@@ -4118,6 +4888,7 @@ function rankByStock(rows, stats, includeUnavailable) {
4118
4888
  }
4119
4889
  var getCapacity = {
4120
4890
  name: "get-capacity",
4891
+ annotations: readOnly,
4121
4892
  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.",
4122
4893
  inputSchema: {
4123
4894
  type: "object",
@@ -4318,6 +5089,7 @@ function formatGpuIds(gpu) {
4318
5089
  }
4319
5090
  var setEndpointGpus = {
4320
5091
  name: "set-endpoint-gpus",
5092
+ annotations: idempotentWrite,
4321
5093
  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.",
4322
5094
  inputSchema: {
4323
5095
  type: "object",
@@ -4511,6 +5283,7 @@ function randomSuffix() {
4511
5283
  }
4512
5284
  var listHubRepos = {
4513
5285
  name: "list-hub-repos",
5286
+ annotations: readOnly,
4514
5287
  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.",
4515
5288
  inputSchema: {
4516
5289
  type: "object",
@@ -4612,6 +5385,7 @@ var listHubRepos = {
4612
5385
  };
4613
5386
  var deployHubRepo = {
4614
5387
  name: "deploy-hub-repo",
5388
+ annotations: write,
4615
5389
  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).",
4616
5390
  inputSchema: {
4617
5391
  type: "object",
@@ -5069,6 +5843,7 @@ function validateWait(wait) {
5069
5843
  }
5070
5844
  var runEndpoint = {
5071
5845
  name: "run-endpoint",
5846
+ annotations: write,
5072
5847
  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.",
5073
5848
  inputSchema: {
5074
5849
  type: "object",
@@ -5098,6 +5873,7 @@ var runEndpoint = {
5098
5873
  };
5099
5874
  var runsyncEndpoint = {
5100
5875
  name: "runsync-endpoint",
5876
+ annotations: write,
5101
5877
  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)."),
5102
5878
  inputSchema: {
5103
5879
  type: "object",
@@ -5141,6 +5917,7 @@ var runsyncEndpoint = {
5141
5917
  };
5142
5918
  var getJobStatus = {
5143
5919
  name: "get-job-status",
5920
+ annotations: readOnly,
5144
5921
  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.",
5145
5922
  inputSchema: {
5146
5923
  type: "object",
@@ -5188,6 +5965,7 @@ var getJobStatus = {
5188
5965
  };
5189
5966
  var streamJob = {
5190
5967
  name: "stream-job",
5968
+ annotations: readOnly,
5191
5969
  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.`,
5192
5970
  inputSchema: {
5193
5971
  type: "object",
@@ -5218,6 +5996,7 @@ var streamJob = {
5218
5996
  };
5219
5997
  var cancelJob = {
5220
5998
  name: "cancel-job",
5999
+ annotations: destructive,
5221
6000
  description: "Cancel a Serverless job that is queued or in progress.",
5222
6001
  inputSchema: {
5223
6002
  type: "object",
@@ -5242,6 +6021,7 @@ var cancelJob = {
5242
6021
  };
5243
6022
  var retryJob = {
5244
6023
  name: "retry-job",
6024
+ annotations: write,
5245
6025
  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.",
5246
6026
  inputSchema: {
5247
6027
  type: "object",
@@ -5266,6 +6046,7 @@ var retryJob = {
5266
6046
  };
5267
6047
  var endpointHealth = {
5268
6048
  name: "endpoint-health",
6049
+ annotations: readOnly,
5269
6050
  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.",
5270
6051
  inputSchema: {
5271
6052
  type: "object",
@@ -5285,6 +6066,7 @@ var endpointHealth = {
5285
6066
  };
5286
6067
  var purgeEndpointQueue = {
5287
6068
  name: "purge-endpoint-queue",
6069
+ annotations: destructive,
5288
6070
  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.",
5289
6071
  inputSchema: {
5290
6072
  type: "object",
@@ -5320,13 +6102,16 @@ var jobTools = [
5320
6102
  // src/specgen/tools/list-endpoints.ts
5321
6103
  var listEndpoints = {
5322
6104
  name: "list-endpoints",
6105
+ annotations: readOnly,
5323
6106
  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.",
5324
6107
  inputSchema: {
5325
6108
  type: "object",
5326
6109
  properties: { ...listPaginationProperties }
5327
6110
  },
5328
6111
  async handler(ctx, args) {
5329
- const { data, error, response } = await ctx.sdk.GET("/v2/serverless");
6112
+ const { data, error, response } = await ctx.sdk.GET("/v2/serverless", {
6113
+ params: { query: serverPageQuery(args) }
6114
+ });
5330
6115
  if (!response.ok) return restError(response, error);
5331
6116
  if (!data || !Array.isArray(data.endpoints)) {
5332
6117
  return {
@@ -5351,10 +6136,10 @@ var listEndpoints = {
5351
6136
  return {
5352
6137
  ok: true,
5353
6138
  status: response.status,
5354
- payload: capList(trimmed, {
5355
- limit: args.limit,
5356
- cursor: args.cursor
5357
- })
6139
+ payload: {
6140
+ items: trimmed,
6141
+ pagination: serverPagination(data.pagination, trimmed.length)
6142
+ }
5358
6143
  };
5359
6144
  }
5360
6145
  };
@@ -5362,10 +6147,16 @@ var listEndpoints = {
5362
6147
  // src/specgen/tools/list-templates.ts
5363
6148
  var listTemplates = {
5364
6149
  name: "list-templates",
5365
- description: "List templates visible to the account. Returns id, name, image, and serverless flag per template; use get-template for full detail.",
5366
- inputSchema: { type: "object", properties: {} },
5367
- async handler(ctx) {
5368
- const { data, error, response } = await ctx.sdk.GET("/v2/templates");
6150
+ annotations: readOnly,
6151
+ 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.",
6152
+ inputSchema: {
6153
+ type: "object",
6154
+ properties: { ...listPaginationProperties }
6155
+ },
6156
+ async handler(ctx, args) {
6157
+ const { data, error, response } = await ctx.sdk.GET("/v2/templates", {
6158
+ params: { query: serverPageQuery(args) }
6159
+ });
5369
6160
  if (!response.ok) return restError(response, error);
5370
6161
  if (!data || !Array.isArray(data.templates)) {
5371
6162
  return {
@@ -5383,7 +6174,8 @@ var listTemplates = {
5383
6174
  name: template.name,
5384
6175
  image: template.image,
5385
6176
  serverless: template.serverless
5386
- }))
6177
+ })),
6178
+ pagination: serverPagination(data.pagination, data.templates.length)
5387
6179
  }
5388
6180
  };
5389
6181
  }
@@ -5406,7 +6198,7 @@ function authedGraphqlBase(env) {
5406
6198
  return pick(env.RUNPOD_AUTHED_GRAPHQL_URL, "https://api.runpod.io/graphql");
5407
6199
  }
5408
6200
 
5409
- // node_modules/.pnpm/@runpod+typescript-api-sdk@0.1.1/node_modules/@runpod/typescript-api-sdk/dist/index.js
6201
+ // node_modules/.pnpm/@runpod+typescript-api-sdk@0.2.0/node_modules/@runpod/typescript-api-sdk/dist/index.js
5410
6202
  var PATH_PARAM_RE = /\{[^{}]+\}/g;
5411
6203
  var supportsRequestInitExt = () => {
5412
6204
  return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
@@ -6810,6 +7602,7 @@ function logParams(args) {
6810
7602
  }
6811
7603
  var streamPodLogs = {
6812
7604
  name: "stream-pod-logs",
7605
+ annotations: readOnly,
6813
7606
  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.",
6814
7607
  inputSchema: {
6815
7608
  type: "object",
@@ -6831,6 +7624,7 @@ var streamPodLogs = {
6831
7624
  };
6832
7625
  var streamWorkerLogs = {
6833
7626
  name: "stream-worker-logs",
7627
+ annotations: readOnly,
6834
7628
  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.",
6835
7629
  inputSchema: {
6836
7630
  type: "object",
@@ -6871,6 +7665,7 @@ function parseMetadata(metadata) {
6871
7665
  }
6872
7666
  var listPublicEndpoints = {
6873
7667
  name: "list-public-endpoints",
7668
+ annotations: readOnly,
6874
7669
  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.",
6875
7670
  inputSchema: {
6876
7671
  type: "object",
@@ -6969,9 +7764,319 @@ var listPublicEndpoints = {
6969
7764
  })
6970
7765
  };
6971
7766
 
7767
+ // src/specgen/tools/knowledge.ts
7768
+ var import_plugin_knowledge = require("@runpod/plugin-knowledge");
7769
+ var knowledge = (0, import_plugin_knowledge.loadKnowledge)();
7770
+ var GUIDE_KINDS = ["skill", "reference", "golden-path"];
7771
+ var STOPWORDS = new Set(
7772
+ "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(
7773
+ " "
7774
+ )
7775
+ );
7776
+ var singular = (word) => {
7777
+ if (word.length > 4 && word.endsWith("ies")) return `${word.slice(0, -3)}y`;
7778
+ if (word.length > 3 && word.endsWith("s") && !word.endsWith("ss"))
7779
+ return word.slice(0, -1);
7780
+ return word;
7781
+ };
7782
+ var words = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 1 && !STOPWORDS.has(word)).map(singular);
7783
+ function editDistance(a, b, max) {
7784
+ if (Math.abs(a.length - b.length) > max) return max + 1;
7785
+ let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
7786
+ for (let i = 1; i <= a.length; i++) {
7787
+ const current = [i];
7788
+ for (let j = 1; j <= b.length; j++) {
7789
+ current[j] = Math.min(
7790
+ previous[j] + 1,
7791
+ current[j - 1] + 1,
7792
+ previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
7793
+ );
7794
+ }
7795
+ if (Math.min(...current) > max) return max + 1;
7796
+ previous = current;
7797
+ }
7798
+ return previous[b.length];
7799
+ }
7800
+ var typoBudget = (text) => text.length >= 8 ? 2 : text.length >= 4 ? 1 : 0;
7801
+ var oneTypo = (word, term) => term.length >= 5 && editDistance(word, term, 1) <= 1;
7802
+ var termMatches = (word, term) => word.startsWith(term) || oneTypo(word, term);
7803
+ var nameMatches = (name, term) => name === term || oneTypo(name, term);
7804
+ var guideSummary = ({
7805
+ id,
7806
+ kind,
7807
+ title,
7808
+ description,
7809
+ lanes,
7810
+ mcp,
7811
+ needs_shell,
7812
+ concepts
7813
+ }) => ({
7814
+ id,
7815
+ kind,
7816
+ title,
7817
+ description,
7818
+ lanes,
7819
+ mcp,
7820
+ needs_shell,
7821
+ concepts
7822
+ });
7823
+ function linkedGuides(conceptId) {
7824
+ const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));
7825
+ const seen = /* @__PURE__ */ new Set();
7826
+ const examples = [];
7827
+ const docs = [];
7828
+ for (const link of knowledge.links) {
7829
+ if (link.to !== conceptId || seen.has(link.from)) continue;
7830
+ seen.add(link.from);
7831
+ const guide = byId.get(link.from);
7832
+ if (!guide) continue;
7833
+ if (guide.kind === "golden-path")
7834
+ examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });
7835
+ else
7836
+ docs.push({
7837
+ id: guide.id,
7838
+ title: guide.title,
7839
+ ...link.rules ? { rules: link.rules } : {}
7840
+ });
7841
+ }
7842
+ return { examples, docs };
7843
+ }
7844
+ var conceptIndex = /* @__PURE__ */ new Map();
7845
+ for (const concept of knowledge.concepts) {
7846
+ for (const key of [concept.id, concept.name, ...concept.aliases]) {
7847
+ if (!conceptIndex.has(key.toLowerCase()))
7848
+ conceptIndex.set(key.toLowerCase(), concept);
7849
+ }
7850
+ }
7851
+ var conceptKey = (text) => text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).map(singular).join(" ");
7852
+ var conceptKeyIndex = /* @__PURE__ */ new Map();
7853
+ for (const [key, concept] of conceptIndex) {
7854
+ if (!conceptKeyIndex.has(conceptKey(key)))
7855
+ conceptKeyIndex.set(conceptKey(key), concept);
7856
+ }
7857
+ function resolveConcept(input) {
7858
+ const exact = conceptIndex.get(input.trim().toLowerCase());
7859
+ if (exact) return { concept: exact };
7860
+ const key = conceptKey(input);
7861
+ const plural = conceptKeyIndex.get(key);
7862
+ if (plural) return { concept: plural, matchedAs: key };
7863
+ const budget = typoBudget(key);
7864
+ let best;
7865
+ let tied = false;
7866
+ for (const [candidate, concept] of conceptKeyIndex) {
7867
+ const distance = editDistance(key, candidate, budget);
7868
+ if (distance > budget) continue;
7869
+ if (!best || distance < best.distance) {
7870
+ best = { concept, key: candidate, distance };
7871
+ tied = false;
7872
+ } else if (distance === best.distance && concept.id !== best.concept.id) {
7873
+ tied = true;
7874
+ }
7875
+ }
7876
+ return best && !tied ? { concept: best.concept, matchedAs: best.key } : void 0;
7877
+ }
7878
+ var ruleIndex = /* @__PURE__ */ new Map();
7879
+ for (const concept of knowledge.concepts) {
7880
+ for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });
7881
+ }
7882
+ var source = {
7883
+ plugin_version: knowledge.version,
7884
+ plugin_commit: knowledge.commit
7885
+ };
7886
+ var listGuides = {
7887
+ name: "list-guides",
7888
+ annotations: bundledRead,
7889
+ 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.",
7890
+ inputSchema: {
7891
+ type: "object",
7892
+ properties: {
7893
+ kind: {
7894
+ type: "string",
7895
+ enum: [...GUIDE_KINDS],
7896
+ description: "Only this kind of guide."
7897
+ },
7898
+ query: {
7899
+ type: "string",
7900
+ description: "Words to match against the id, title and description."
7901
+ },
7902
+ concept: {
7903
+ type: "string",
7904
+ description: 'Only guides linked to this concept id, for example "network-volume".'
7905
+ }
7906
+ },
7907
+ additionalProperties: false
7908
+ },
7909
+ handler: async (_ctx, args) => {
7910
+ const kind = args.kind;
7911
+ const terms = words(String(args.query ?? ""));
7912
+ const concept = args.concept ? String(args.concept).trim() : void 0;
7913
+ const guides = knowledge.guides.filter((guide) => !kind || guide.kind === kind).filter((guide) => !concept || guide.concepts.includes(concept)).filter((guide) => {
7914
+ if (!terms.length) return true;
7915
+ const haystack = `${guide.id} ${guide.title} ${guide.description}`.toLowerCase();
7916
+ return terms.some((term) => haystack.includes(term));
7917
+ }).map(guideSummary);
7918
+ return ok({ ...source, count: guides.length, guides });
7919
+ }
7920
+ };
7921
+ var readGuide = {
7922
+ name: "read-guide",
7923
+ annotations: bundledRead,
7924
+ 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").',
7925
+ inputSchema: {
7926
+ type: "object",
7927
+ properties: {
7928
+ id: { type: "string", description: "The guide id from list-guides." }
7929
+ },
7930
+ required: ["id"],
7931
+ additionalProperties: false
7932
+ },
7933
+ handler: async (_ctx, args) => {
7934
+ const id = String(args.id).trim();
7935
+ const guide = knowledge.guides.find((candidate) => candidate.id === id);
7936
+ if (!guide) {
7937
+ const close = knowledge.guides.filter(
7938
+ (candidate) => candidate.id.includes(id) || id.includes(candidate.id)
7939
+ ).map((candidate) => candidate.id);
7940
+ return {
7941
+ ok: false,
7942
+ status: 404,
7943
+ payload: {
7944
+ error: `No guide with id "${id}".`,
7945
+ hint: close.length ? `Did you mean: ${close.join(", ")}?` : "Call list-guides for the ids."
7946
+ }
7947
+ };
7948
+ }
7949
+ return ok({
7950
+ ...source,
7951
+ ...guideSummary(guide),
7952
+ parent: guide.parent,
7953
+ path: guide.path,
7954
+ body: guide.body
7955
+ });
7956
+ }
7957
+ };
7958
+ var lookupConcept = {
7959
+ name: "lookup-concept",
7960
+ annotations: bundledRead,
7961
+ 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".',
7962
+ inputSchema: {
7963
+ type: "object",
7964
+ properties: {
7965
+ concept: {
7966
+ type: "string",
7967
+ description: 'An id, name or alias, such as "pod", "Network volume" or "volume disk".'
7968
+ }
7969
+ },
7970
+ required: ["concept"],
7971
+ additionalProperties: false
7972
+ },
7973
+ handler: async (_ctx, args) => {
7974
+ const resolved = resolveConcept(String(args.concept));
7975
+ if (!resolved) {
7976
+ const ref = conceptKey(String(args.concept));
7977
+ const close = [...conceptKeyIndex.keys()].filter(
7978
+ (key) => key.includes(ref) || editDistance(key, ref, typoBudget(ref) + 1) <= typoBudget(ref) + 1
7979
+ ).slice(0, 10);
7980
+ return {
7981
+ ok: false,
7982
+ status: 404,
7983
+ payload: {
7984
+ error: `No concept matches "${args.concept}".`,
7985
+ hint: close.length ? `Close matches: ${close.join(", ")}.` : "Try search-concepts with a few words instead."
7986
+ }
7987
+ };
7988
+ }
7989
+ const { concept, matchedAs } = resolved;
7990
+ const pointedAtBy = knowledge.concepts.flatMap((other) => [
7991
+ ...other.is_a === concept.id ? [{ concept: other.id, type: "is_a" }] : [],
7992
+ ...other.part_of === concept.id ? [{ concept: other.id, type: "part_of" }] : [],
7993
+ ...other.relations.filter((relation) => relation.target === concept.id).map((relation) => ({ concept: other.id, type: relation.type }))
7994
+ ]);
7995
+ const linkedRules = [...new Set(concept.rules.flatMap((rule) => rule.see))].map((id) => ruleIndex.get(id)).filter((entry) => entry !== void 0).map(({ rule, concept: owner }) => ({
7996
+ concept: owner.id,
7997
+ id: rule.id,
7998
+ statement: rule.statement.trim()
7999
+ }));
8000
+ return ok({
8001
+ ...source,
8002
+ ...matchedAs ? { matched_as: matchedAs } : {},
8003
+ ...concept,
8004
+ pointed_at_by: pointedAtBy,
8005
+ linked_rules: linkedRules,
8006
+ ...linkedGuides(concept.id)
8007
+ });
8008
+ }
8009
+ };
8010
+ var searchConcepts = {
8011
+ name: "search-concepts",
8012
+ annotations: bundledRead,
8013
+ 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.',
8014
+ inputSchema: {
8015
+ type: "object",
8016
+ properties: {
8017
+ query: {
8018
+ type: "string",
8019
+ description: "A few words describing the question."
8020
+ },
8021
+ limit: {
8022
+ type: "integer",
8023
+ minimum: 1,
8024
+ maximum: 25,
8025
+ description: "Most rules to return. Default 8."
8026
+ }
8027
+ },
8028
+ required: ["query"],
8029
+ additionalProperties: false
8030
+ },
8031
+ handler: async (_ctx, args) => {
8032
+ const terms = words(String(args.query));
8033
+ if (!terms.length) return badRequest("query needs at least one word.");
8034
+ const limit = Math.min(Math.max(Number(args.limit) || 8, 1), 25);
8035
+ const hits = [...ruleIndex.values()].map(({ rule, concept }) => {
8036
+ const statement = words(rule.statement);
8037
+ const names = words(
8038
+ [concept.id, concept.name, ...concept.aliases].join(" ")
8039
+ );
8040
+ const ruleId = words(rule.id);
8041
+ const score = terms.reduce(
8042
+ (total, term) => total + statement.filter((word) => termMatches(word, term)).length + (names.some((name) => nameMatches(name, term)) ? 3 : 0) + (ruleId.includes(term) ? 1 : 0),
8043
+ 0
8044
+ );
8045
+ const matched = terms.filter(
8046
+ (term) => statement.some((word) => termMatches(word, term)) || names.some((name) => nameMatches(name, term))
8047
+ ).length;
8048
+ return { rule, concept, score: score * matched };
8049
+ }).filter((hit) => hit.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map(({ rule, concept }) => ({
8050
+ concept: concept.id,
8051
+ concept_name: concept.name,
8052
+ id: rule.id,
8053
+ statement: rule.statement.trim(),
8054
+ status: rule.status,
8055
+ conflict: rule.conflict,
8056
+ evidence: rule.evidence
8057
+ }));
8058
+ return ok({ ...source, count: hits.length, rules: hits });
8059
+ }
8060
+ };
8061
+ var knowledgeTools = [
8062
+ listGuides,
8063
+ readGuide,
8064
+ lookupConcept,
8065
+ searchConcepts
8066
+ ];
8067
+ var GUIDE_URI_PREFIX = "runpod://guides/";
8068
+ var guideResources = knowledge.guides.map((guide) => ({
8069
+ uri: `${GUIDE_URI_PREFIX}${guide.id}`,
8070
+ name: guide.id,
8071
+ title: guide.title,
8072
+ description: guide.description,
8073
+ mimeType: "text/markdown",
8074
+ text: guide.body
8075
+ }));
8076
+
6972
8077
  // src/server.ts
6973
8078
  var SERVER_NAME = "Runpod API Server";
6974
- var SERVER_VERSION = true ? "4.0.0" : "dev";
8079
+ var SERVER_VERSION = true ? "4.1.0" : "dev";
6975
8080
 
6976
8081
  // src/specgen/analytics.ts
6977
8082
  var import_node_crypto = require("crypto");
@@ -7113,6 +8218,7 @@ function createAlpTools(opts) {
7113
8218
  // is ignored, never a 400 that derails the task the agent is actually on.
7114
8219
  lenientArguments: true,
7115
8220
  name: "report_feedback",
8221
+ annotations: write,
7116
8222
  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.",
7117
8223
  inputSchema: alpInputSchema(
7118
8224
  "The observation: what happened, what you expected, and the exact error or response text if you have it.",
@@ -7148,6 +8254,7 @@ function createAlpTools(opts) {
7148
8254
  // is ignored, never a 400 that derails the task the agent is actually on.
7149
8255
  lenientArguments: true,
7150
8256
  name: "save_to_journal",
8257
+ annotations: write,
7151
8258
  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.",
7152
8259
  inputSchema: alpInputSchema(
7153
8260
  "The learning, stated so a future agent can act on it: the situation, what turned out to be true, and how you verified it.",
@@ -7178,6 +8285,7 @@ function createAlpTools(opts) {
7178
8285
  // is ignored, never a 400 that derails the task the agent is actually on.
7179
8286
  lenientArguments: true,
7180
8287
  name: "ask_question",
8288
+ annotations: write,
7181
8289
  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.",
7182
8290
  inputSchema: alpInputSchema(
7183
8291
  "The question, with enough context that someone reading it later understands what you were blocked on.",
@@ -7202,6 +8310,7 @@ function createAlpTools(opts) {
7202
8310
  const readJournalTool = {
7203
8311
  lenientArguments: true,
7204
8312
  name: "read_journal",
8313
+ annotations: readOnly,
7205
8314
  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.",
7206
8315
  inputSchema: {
7207
8316
  type: "object",
@@ -7252,7 +8361,8 @@ var curatedTools = [
7252
8361
  getCapacity,
7253
8362
  ...hubTools,
7254
8363
  setEndpointGpus,
7255
- listPublicEndpoints
8364
+ listPublicEndpoints,
8365
+ ...knowledgeTools
7256
8366
  ];
7257
8367
  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.
7258
8368
 
@@ -7264,6 +8374,8 @@ Mutations cost money and bind to what this conversation created. State the hourl
7264
8374
 
7265
8375
  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.
7266
8376
 
8377
+ 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.
8378
+
7267
8379
  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.
7268
8380
 
7269
8381
  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.
@@ -7295,32 +8407,56 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
7295
8407
  };
7296
8408
  server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({
7297
8409
  tools: [
7298
- ...servedCuratedTools.map(({ name, description, inputSchema }) => ({
7299
- name,
7300
- description,
7301
- inputSchema
7302
- })),
7303
- ...generatedTools.map(({ name, description, inputSchema }) => ({
7304
- name,
7305
- description,
7306
- inputSchema
7307
- }))
8410
+ ...servedCuratedTools.map(
8411
+ ({ name, description, inputSchema, annotations }) => ({
8412
+ name,
8413
+ description,
8414
+ inputSchema,
8415
+ annotations
8416
+ })
8417
+ ),
8418
+ ...generatedTools.map(
8419
+ ({ name, description, inputSchema, annotations }) => ({
8420
+ name,
8421
+ description,
8422
+ inputSchema,
8423
+ annotations
8424
+ })
8425
+ )
7308
8426
  ]
7309
8427
  }));
7310
8428
  const SKILL_URI_PREFIX = "runpod://skills/";
7311
8429
  server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => ({
7312
- resources: skillDocs.map((skill) => ({
7313
- uri: `${SKILL_URI_PREFIX}${skill.name}`,
7314
- name: skill.name,
7315
- title: `Runpod skill: ${skill.name}`,
7316
- description: skill.description,
7317
- mimeType: "text/markdown"
7318
- }))
8430
+ resources: [
8431
+ ...skillDocs.map((skill) => ({
8432
+ uri: `${SKILL_URI_PREFIX}${skill.name}`,
8433
+ name: skill.name,
8434
+ title: `Runpod skill: ${skill.name}`,
8435
+ description: skill.description,
8436
+ mimeType: "text/markdown"
8437
+ })),
8438
+ ...guideResources.map(({ text: _text, ...resource }) => resource)
8439
+ ]
7319
8440
  }));
7320
8441
  server.setRequestHandler(import_types.ListResourceTemplatesRequestSchema, async () => ({
7321
8442
  resourceTemplates: []
7322
8443
  }));
7323
8444
  server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
8445
+ if (request.params.uri.startsWith(GUIDE_URI_PREFIX)) {
8446
+ const guide = guideResources.find(
8447
+ (candidate) => candidate.uri === request.params.uri
8448
+ );
8449
+ if (!guide) {
8450
+ throw new Error(
8451
+ `Unknown resource ${request.params.uri}. Call list-guides for the guide ids.`
8452
+ );
8453
+ }
8454
+ return {
8455
+ contents: [
8456
+ { uri: guide.uri, mimeType: "text/markdown", text: guide.text }
8457
+ ]
8458
+ };
8459
+ }
7324
8460
  const name = request.params.uri.startsWith(SKILL_URI_PREFIX) ? request.params.uri.slice(SKILL_URI_PREFIX.length) : void 0;
7325
8461
  const skill = skillDocs.find((candidate) => candidate.name === name);
7326
8462
  if (!skill) {