@runpod/mcp-server 4.3.0 → 4.5.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/CHANGELOG.md +35 -0
- package/README.md +16 -0
- package/dist/{chunk-DDX42UTT.mjs → chunk-4GF3CMSH.mjs} +6 -2
- package/dist/{chunk-DDX42UTT.mjs.map → chunk-4GF3CMSH.mjs.map} +1 -1
- package/dist/http.cjs +523 -36
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +12 -1
- package/dist/http.d.ts +12 -1
- package/dist/http.mjs +522 -36
- package/dist/http.mjs.map +1 -1
- package/dist/stdio.cjs +384 -20
- package/dist/stdio.cjs.map +1 -1
- package/dist/stdio.mjs +380 -21
- package/dist/stdio.mjs.map +1 -1
- package/dist/{wizard-L25AYBNQ.mjs → wizard-KKTBTVXE.mjs} +4 -3
- package/dist/wizard-KKTBTVXE.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/wizard-L25AYBNQ.mjs.map +0 -1
package/dist/stdio.mjs
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
authedGraphqlBase,
|
|
4
|
+
hostedMcpBase,
|
|
4
5
|
publicGraphqlBase,
|
|
5
6
|
sdkBase,
|
|
6
7
|
serverlessBase
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-4GF3CMSH.mjs";
|
|
8
9
|
|
|
9
10
|
// src/stdio.ts
|
|
10
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
12
|
|
|
12
13
|
// src/server.ts
|
|
13
14
|
var SERVER_NAME = "Runpod API Server";
|
|
14
|
-
var SERVER_VERSION = true ? "4.
|
|
15
|
+
var SERVER_VERSION = true ? "4.5.0" : "dev";
|
|
15
16
|
|
|
16
17
|
// src/specgen/server.ts
|
|
17
18
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -344,6 +345,7 @@ function coerceScalars(value, schema, defs, depth = 0) {
|
|
|
344
345
|
var generatedTools = [
|
|
345
346
|
{
|
|
346
347
|
name: "create-cluster",
|
|
348
|
+
title: "Create cluster",
|
|
347
349
|
operationId: "createCluster",
|
|
348
350
|
description: "Create an instant cluster (multiple pods with high-speed interconnect). BILLABLE from creation for every pod in the cluster: it rents compute.podCount identical pods at once, each with compute.gpuCountPerPod GPUs of compute.gpuTypeId \u2014 state the hourly price for the total GPU count (podCount * gpuCountPerPod, priced from the catalog tools) and create only after the user's explicit go on that quoted shape and total hourly price. Verify GPU stock first via the catalog tools. The compute shape and type are fixed at creation; only the name can be changed later. The container configuration applies to every pod, and templateId is the only private-image path \u2014 a bare registry property is rejected. Delete with delete-cluster when finished.",
|
|
349
351
|
method: "POST",
|
|
@@ -581,6 +583,7 @@ var generatedTools = [
|
|
|
581
583
|
},
|
|
582
584
|
{
|
|
583
585
|
name: "create-delegation",
|
|
586
|
+
title: "Create ECR delegation",
|
|
584
587
|
operationId: "createDelegation",
|
|
585
588
|
description: "Register an ECR delegation",
|
|
586
589
|
method: "POST",
|
|
@@ -626,6 +629,7 @@ var generatedTools = [
|
|
|
626
629
|
},
|
|
627
630
|
{
|
|
628
631
|
name: "create-endpoint",
|
|
632
|
+
title: "Create endpoint",
|
|
629
633
|
operationId: "createEndpoint",
|
|
630
634
|
description: "Create a serverless endpoint. BILLABLE: state the worker's hourly price (from the catalog tools) before creating. Worker hardware is one of two choices: the gpu object (gpu.pools takes serverless pool ids from the catalog, e.g. ADA_24, never display names; gpu.count sets GPUs per worker) or the cpu array of CPU flavor configurations for a CPU endpoint. type and scaling are required and fix the request-routing model. Workers cold-start on the first job: expect minutes, poll with get-job-status wait.",
|
|
631
635
|
method: "POST",
|
|
@@ -1071,6 +1075,7 @@ var generatedTools = [
|
|
|
1071
1075
|
},
|
|
1072
1076
|
{
|
|
1073
1077
|
name: "create-global-volume",
|
|
1078
|
+
title: "Create global volume",
|
|
1074
1079
|
operationId: "createGlobalVolume",
|
|
1075
1080
|
description: "Create a global volume. Provisions a new global volume \u2014 storage that mounts into workloads in any data center. Only a `name` is required; storage is provisioned for you. Accounts have a cap on how many global volumes they can hold; creating one past it fails with `400`. Returns `201` with the created global volume, including its assigned `id`.",
|
|
1076
1081
|
method: "POST",
|
|
@@ -1112,6 +1117,7 @@ var generatedTools = [
|
|
|
1112
1117
|
},
|
|
1113
1118
|
{
|
|
1114
1119
|
name: "create-network-volume",
|
|
1120
|
+
title: "Create network volume",
|
|
1115
1121
|
operationId: "createNetworkVolume",
|
|
1116
1122
|
description: "Create a network volume. Provisions a new network volume \u2014 persistent, network-attached storage that can be mounted into pods and serverless workers. Required inputs are `name`, `size` (in GB), and `dataCenter`; an optional `type` selects the storage tier and is immutable after creation. See `CreateNetworkVolumeRequest` for the size bounds and tier options. This creates a billable persistent resource that keeps incurring storage charges until it is deleted. Returns `201` with the created network volume, including its assigned `id`.",
|
|
1117
1123
|
method: "POST",
|
|
@@ -1177,6 +1183,7 @@ var generatedTools = [
|
|
|
1177
1183
|
},
|
|
1178
1184
|
{
|
|
1179
1185
|
name: "create-pod",
|
|
1186
|
+
title: "Create Pod",
|
|
1180
1187
|
operationId: "createPod",
|
|
1181
1188
|
description: 'Rent a GPU/CPU pod. BILLABLE from creation until stop/terminate: state the hourly price before creating. GPU selection is the gpu object: gpu.id takes a catalog GPU type id (e.g. "NVIDIA GeForce RTX 4090"), verified via list-gpu-types, and gpu.count sets the GPU count; cloud/data-center choice constrains stock.',
|
|
1182
1189
|
method: "POST",
|
|
@@ -1544,6 +1551,7 @@ var generatedTools = [
|
|
|
1544
1551
|
},
|
|
1545
1552
|
{
|
|
1546
1553
|
name: "create-registry",
|
|
1554
|
+
title: "Create registry credential",
|
|
1547
1555
|
operationId: "createRegistry",
|
|
1548
1556
|
description: "Create a container registry credential. Stores credentials for a private container registry. Credentials are write-only.",
|
|
1549
1557
|
method: "POST",
|
|
@@ -1595,6 +1603,7 @@ var generatedTools = [
|
|
|
1595
1603
|
},
|
|
1596
1604
|
{
|
|
1597
1605
|
name: "create-secret",
|
|
1606
|
+
title: "Create secret",
|
|
1598
1607
|
operationId: "createSecret",
|
|
1599
1608
|
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.",
|
|
1600
1609
|
method: "POST",
|
|
@@ -1649,6 +1658,7 @@ var generatedTools = [
|
|
|
1649
1658
|
},
|
|
1650
1659
|
{
|
|
1651
1660
|
name: "create-template",
|
|
1661
|
+
title: "Create template",
|
|
1652
1662
|
operationId: "createTemplate",
|
|
1653
1663
|
description: "Create a template. Creates a reusable container-configuration preset \u2014 image, disk, ports, env, registry, and mount settings \u2014 for pods and serverless endpoints. Pass its ID as `templateId` to `createPod` or `createEndpoint`, or spread its fields into the request body directly. Returns the created template.",
|
|
1654
1664
|
method: "POST",
|
|
@@ -1850,6 +1860,7 @@ var generatedTools = [
|
|
|
1850
1860
|
},
|
|
1851
1861
|
{
|
|
1852
1862
|
name: "delete-cluster",
|
|
1863
|
+
title: "Delete cluster",
|
|
1853
1864
|
operationId: "deleteCluster",
|
|
1854
1865
|
description: "Delete a cluster permanently: it terminates every member pod. Verify the id with get-cluster, and list-cluster-pods for what the delete takes down, before deleting; delete only clusters your own tool calls created in this conversation, or the one the user asked you to delete by id \u2014 a name found by listing is not attribution.",
|
|
1855
1866
|
method: "DELETE",
|
|
@@ -1880,6 +1891,7 @@ var generatedTools = [
|
|
|
1880
1891
|
},
|
|
1881
1892
|
{
|
|
1882
1893
|
name: "delete-endpoint",
|
|
1894
|
+
title: "Delete endpoint",
|
|
1883
1895
|
operationId: "deleteEndpoint",
|
|
1884
1896
|
description: "Delete a serverless endpoint permanently and immediately. Verify the id belongs to the intended endpoint (get-endpoint) before deleting; delete only endpoints your own tool calls created in this conversation, or the one the user asked you to delete by id \u2014 a name found by listing is not attribution.",
|
|
1885
1897
|
method: "DELETE",
|
|
@@ -1910,6 +1922,7 @@ var generatedTools = [
|
|
|
1910
1922
|
},
|
|
1911
1923
|
{
|
|
1912
1924
|
name: "delete-global-volume",
|
|
1925
|
+
title: "Delete global volume",
|
|
1913
1926
|
operationId: "deleteGlobalVolume",
|
|
1914
1927
|
description: "Delete a global volume. Permanently deletes a global volume and its stored data. Fails with `409` while the volume is still mounted: terminate every pod that mounts it (stopped pods count) and detach it from every serverless endpoint first. Nothing is detached or terminated on your behalf.",
|
|
1915
1928
|
method: "DELETE",
|
|
@@ -1940,6 +1953,7 @@ var generatedTools = [
|
|
|
1940
1953
|
},
|
|
1941
1954
|
{
|
|
1942
1955
|
name: "delete-network-volume",
|
|
1956
|
+
title: "Delete network volume",
|
|
1943
1957
|
operationId: "deleteNetworkVolume",
|
|
1944
1958
|
description: "Delete a network volume. Permanently deletes a network volume and releases its storage.",
|
|
1945
1959
|
method: "DELETE",
|
|
@@ -1970,6 +1984,7 @@ var generatedTools = [
|
|
|
1970
1984
|
},
|
|
1971
1985
|
{
|
|
1972
1986
|
name: "delete-pod",
|
|
1987
|
+
title: "Delete Pod",
|
|
1973
1988
|
operationId: "deletePod",
|
|
1974
1989
|
description: "Terminate a pod permanently \u2014 its container disk is lost. Distinguish from stopping (pod-action stop) which releases the GPU but keeps volume data. Verify the id with get-pod first; terminate only pods your own tool calls created in this conversation, or the one the user asked you to terminate by id \u2014 a name found by listing is not attribution.",
|
|
1975
1990
|
method: "DELETE",
|
|
@@ -2000,6 +2015,7 @@ var generatedTools = [
|
|
|
2000
2015
|
},
|
|
2001
2016
|
{
|
|
2002
2017
|
name: "delete-registry",
|
|
2018
|
+
title: "Delete registry credential",
|
|
2003
2019
|
operationId: "deleteRegistry",
|
|
2004
2020
|
description: "Delete a container registry credential. Permanently deletes a container registry credential by ID. Rejected if any pod currently uses this credential to pull its image. Templates that reference it are not part of that check \u2014 they silently lose the reference (`registry` becomes null) instead of blocking the delete.",
|
|
2005
2021
|
method: "DELETE",
|
|
@@ -2029,6 +2045,7 @@ var generatedTools = [
|
|
|
2029
2045
|
},
|
|
2030
2046
|
{
|
|
2031
2047
|
name: "delete-secret",
|
|
2048
|
+
title: "Delete secret",
|
|
2032
2049
|
operationId: "deleteSecret",
|
|
2033
2050
|
description: "Delete a secret permanently. Environment variables referencing its name ({{ RUNPOD_SECRET_<name> }}) stop resolving at the next pod or worker boot; running instances keep the value they started with. Verify the id with get-secret first; delete only secrets your own tool calls created in this conversation, or the one the user asked you to delete by id \u2014 a name found by listing is not attribution.",
|
|
2034
2051
|
method: "DELETE",
|
|
@@ -2059,6 +2076,7 @@ var generatedTools = [
|
|
|
2059
2076
|
},
|
|
2060
2077
|
{
|
|
2061
2078
|
name: "delete-template",
|
|
2079
|
+
title: "Delete template",
|
|
2062
2080
|
operationId: "deleteTemplate",
|
|
2063
2081
|
description: "Delete a template permanently. Verify with get-template first; a template referenced by a live endpoint should not be deleted.",
|
|
2064
2082
|
method: "DELETE",
|
|
@@ -2088,6 +2106,7 @@ var generatedTools = [
|
|
|
2088
2106
|
},
|
|
2089
2107
|
{
|
|
2090
2108
|
name: "get-cluster",
|
|
2109
|
+
title: "Get cluster",
|
|
2091
2110
|
operationId: "getCluster",
|
|
2092
2111
|
description: "Get a cluster. Returns a single cluster by ID. The pods field is an aggregate summary (total + count by status); fetch the member pods themselves from /v2/clusters/{id}/pods.",
|
|
2093
2112
|
method: "GET",
|
|
@@ -2118,6 +2137,7 @@ var generatedTools = [
|
|
|
2118
2137
|
},
|
|
2119
2138
|
{
|
|
2120
2139
|
name: "get-cpu-type",
|
|
2140
|
+
title: "Get CPU type",
|
|
2121
2141
|
operationId: "getCpuType",
|
|
2122
2142
|
description: "Get a CPU type. Returns a single CPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` \u2014 stock differs by product context.",
|
|
2123
2143
|
method: "GET",
|
|
@@ -2194,6 +2214,7 @@ var generatedTools = [
|
|
|
2194
2214
|
},
|
|
2195
2215
|
{
|
|
2196
2216
|
name: "get-data-center",
|
|
2217
|
+
title: "Get data center",
|
|
2197
2218
|
operationId: "getDataCenter",
|
|
2198
2219
|
description: "Get a data center. Returns a single data center. Availability is included only when requested with include=GPU_AVAILABILITY or include=CPU_AVAILABILITY.",
|
|
2199
2220
|
method: "GET",
|
|
@@ -2243,6 +2264,7 @@ var generatedTools = [
|
|
|
2243
2264
|
},
|
|
2244
2265
|
{
|
|
2245
2266
|
name: "get-endpoint",
|
|
2267
|
+
title: "Get endpoint",
|
|
2246
2268
|
operationId: "getEndpoint",
|
|
2247
2269
|
description: "Get a serverless endpoint. Returns a single serverless endpoint by ID.",
|
|
2248
2270
|
method: "GET",
|
|
@@ -2273,6 +2295,7 @@ var generatedTools = [
|
|
|
2273
2295
|
},
|
|
2274
2296
|
{
|
|
2275
2297
|
name: "get-endpoint-build",
|
|
2298
|
+
title: "Get endpoint build",
|
|
2276
2299
|
operationId: "getEndpointBuild",
|
|
2277
2300
|
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.",
|
|
2278
2301
|
method: "GET",
|
|
@@ -2311,6 +2334,7 @@ var generatedTools = [
|
|
|
2311
2334
|
},
|
|
2312
2335
|
{
|
|
2313
2336
|
name: "get-global-volume",
|
|
2337
|
+
title: "Get global volume",
|
|
2314
2338
|
operationId: "getGlobalVolume",
|
|
2315
2339
|
description: "Get a global volume. Returns a single global volume by ID.",
|
|
2316
2340
|
method: "GET",
|
|
@@ -2341,6 +2365,7 @@ var generatedTools = [
|
|
|
2341
2365
|
},
|
|
2342
2366
|
{
|
|
2343
2367
|
name: "get-gpu-type",
|
|
2368
|
+
title: "Get GPU type",
|
|
2344
2369
|
operationId: "getGpuType",
|
|
2345
2370
|
description: "Get a GPU type. Returns a single GPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` \u2014 stock differs by product context.",
|
|
2346
2371
|
method: "GET",
|
|
@@ -2465,6 +2490,7 @@ var generatedTools = [
|
|
|
2465
2490
|
},
|
|
2466
2491
|
{
|
|
2467
2492
|
name: "get-network-volume",
|
|
2493
|
+
title: "Get network volume",
|
|
2468
2494
|
operationId: "getNetworkVolume",
|
|
2469
2495
|
description: "Get a network volume. Returns a single network volume by ID.",
|
|
2470
2496
|
method: "GET",
|
|
@@ -2495,6 +2521,7 @@ var generatedTools = [
|
|
|
2495
2521
|
},
|
|
2496
2522
|
{
|
|
2497
2523
|
name: "get-organization",
|
|
2524
|
+
title: "Get organization",
|
|
2498
2525
|
operationId: "getOrganization",
|
|
2499
2526
|
description: "Get your current organization. Returns the authenticated caller's current organization. Organization context comes from the caller's membership; no organization selector is required. Returns 404 when the caller does not belong to an organization, or 403 when organizations are unavailable to the caller.",
|
|
2500
2527
|
method: "GET",
|
|
@@ -2514,6 +2541,7 @@ var generatedTools = [
|
|
|
2514
2541
|
},
|
|
2515
2542
|
{
|
|
2516
2543
|
name: "get-pod",
|
|
2544
|
+
title: "Get Pod",
|
|
2517
2545
|
operationId: "getPod",
|
|
2518
2546
|
description: "Get a pod. Returns a single pod by ID.",
|
|
2519
2547
|
method: "GET",
|
|
@@ -2544,6 +2572,7 @@ var generatedTools = [
|
|
|
2544
2572
|
},
|
|
2545
2573
|
{
|
|
2546
2574
|
name: "get-registry",
|
|
2575
|
+
title: "Get registry credential",
|
|
2547
2576
|
operationId: "getRegistry",
|
|
2548
2577
|
description: "Get a container registry credential. Returns a single container registry credential by ID. `username` and `password` are never included in the response \u2014 credentials are write-only, matching `createRegistry`.",
|
|
2549
2578
|
method: "GET",
|
|
@@ -2573,6 +2602,7 @@ var generatedTools = [
|
|
|
2573
2602
|
},
|
|
2574
2603
|
{
|
|
2575
2604
|
name: "get-secret",
|
|
2605
|
+
title: "Get secret",
|
|
2576
2606
|
operationId: "getSecret",
|
|
2577
2607
|
description: "Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.",
|
|
2578
2608
|
method: "GET",
|
|
@@ -2603,6 +2633,7 @@ var generatedTools = [
|
|
|
2603
2633
|
},
|
|
2604
2634
|
{
|
|
2605
2635
|
name: "get-ssh-keys",
|
|
2636
|
+
title: "Get SSH keys",
|
|
2606
2637
|
operationId: "getSshKeys",
|
|
2607
2638
|
description: "List registered SSH public keys. Returns the account's registered SSH public keys \u2014 the keys provisioned into pods created with `startSsh` and used to authenticate the SSH connections reported in a pod's `ssh` block.",
|
|
2608
2639
|
method: "GET",
|
|
@@ -2622,6 +2653,7 @@ var generatedTools = [
|
|
|
2622
2653
|
},
|
|
2623
2654
|
{
|
|
2624
2655
|
name: "get-template",
|
|
2656
|
+
title: "Get template",
|
|
2625
2657
|
operationId: "getTemplate",
|
|
2626
2658
|
description: "Get a template. Returns the full configuration of a single template by ID. Serves both templates you own and public catalog templates \u2014 everything you can read. Updates and deletes remain restricted to templates you own.",
|
|
2627
2659
|
method: "GET",
|
|
@@ -2651,6 +2683,7 @@ var generatedTools = [
|
|
|
2651
2683
|
},
|
|
2652
2684
|
{
|
|
2653
2685
|
name: "list-billing",
|
|
2686
|
+
title: "List billing",
|
|
2654
2687
|
operationId: "listBilling",
|
|
2655
2688
|
description: "Get aggregated billing history. Returns time-bucketed total spend across all billable Runpod resources for the authenticated user. Use startTime/endTime with bucketSize for an explicit range, or lastN with bucketSize for the most recent buckets. Each record reports one bucket's total plus pod, serverless, storage, public endpoint, and Instant Cluster cost components. The metadata block echoes the resolved query window, record count, and totals across all returned buckets.",
|
|
2656
2689
|
method: "GET",
|
|
@@ -2723,6 +2756,7 @@ var generatedTools = [
|
|
|
2723
2756
|
},
|
|
2724
2757
|
{
|
|
2725
2758
|
name: "list-cluster-billing",
|
|
2759
|
+
title: "List cluster billing",
|
|
2726
2760
|
operationId: "listClusterBilling",
|
|
2727
2761
|
description: "Get cluster billing history. Returns Cluster billing history for the authenticated user, split into time buckets by startTime/endTime with bucketSize or by lastN recent buckets. Use clusterId to filter to one cluster; without it, records are emitted per cluster per bucket. Each record includes GPU compute, disk, inter-node networking, and total amounts. Clusters are GPU-only, so no CPU cost component is returned.",
|
|
2728
2762
|
method: "GET",
|
|
@@ -2803,6 +2837,7 @@ var generatedTools = [
|
|
|
2803
2837
|
},
|
|
2804
2838
|
{
|
|
2805
2839
|
name: "list-cluster-pods",
|
|
2840
|
+
title: "List cluster Pods",
|
|
2806
2841
|
operationId: "listClusterPods",
|
|
2807
2842
|
description: "List a cluster's pods. Returns the full member pods of a cluster. The cluster summary (`GET /v2/clusters/{id}`) carries only aggregate pod counts; this endpoint returns each member as a complete Pod object.",
|
|
2808
2843
|
method: "GET",
|
|
@@ -2833,6 +2868,7 @@ var generatedTools = [
|
|
|
2833
2868
|
},
|
|
2834
2869
|
{
|
|
2835
2870
|
name: "list-clusters",
|
|
2871
|
+
title: "List clusters",
|
|
2836
2872
|
operationId: "listClusters",
|
|
2837
2873
|
description: "List clusters. Returns clusters owned by the authenticated user, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
|
|
2838
2874
|
method: "GET",
|
|
@@ -2873,6 +2909,7 @@ var generatedTools = [
|
|
|
2873
2909
|
},
|
|
2874
2910
|
{
|
|
2875
2911
|
name: "list-cpu-types",
|
|
2912
|
+
title: "List CPU types",
|
|
2876
2913
|
operationId: "listCpuTypes",
|
|
2877
2914
|
description: "List CPU types. Returns available CPU flavors. Availability is included only when requested with include=AVAILABILITY, which requires `product` \u2014 stock differs by product context.",
|
|
2878
2915
|
method: "GET",
|
|
@@ -2941,6 +2978,7 @@ var generatedTools = [
|
|
|
2941
2978
|
},
|
|
2942
2979
|
{
|
|
2943
2980
|
name: "list-data-centers",
|
|
2981
|
+
title: "List data centers",
|
|
2944
2982
|
operationId: "listDataCenters",
|
|
2945
2983
|
description: "List data centers. Returns available data center locations with region, compliance, supported network volume tiers, and global networking support. Use include=GPU_AVAILABILITY or include=CPU_AVAILABILITY to add per-resource availability arrays to each data center. The regions, networkVolumeTypes, compliance, and globalNetwork query parameters filter the list before it is returned.",
|
|
2946
2984
|
method: "GET",
|
|
@@ -3068,6 +3106,7 @@ var generatedTools = [
|
|
|
3068
3106
|
},
|
|
3069
3107
|
{
|
|
3070
3108
|
name: "list-delegations",
|
|
3109
|
+
title: "List ECR delegations",
|
|
3071
3110
|
operationId: "listDelegations",
|
|
3072
3111
|
description: "List all ECR delegations",
|
|
3073
3112
|
method: "GET",
|
|
@@ -3087,6 +3126,7 @@ var generatedTools = [
|
|
|
3087
3126
|
},
|
|
3088
3127
|
{
|
|
3089
3128
|
name: "list-endpoint-billing",
|
|
3129
|
+
title: "List endpoint billing",
|
|
3090
3130
|
operationId: "listEndpointBilling",
|
|
3091
3131
|
description: "Get public endpoint billing history. Returns Runpod public endpoint billing history for the authenticated user, split into time buckets by startTime/endTime with bucketSize or by lastN recent buckets. Each record reports the endpoint total for one bucket, and metadata echoes the resolved query window, record count, and total endpoint amount across all returned records.",
|
|
3092
3132
|
method: "GET",
|
|
@@ -3159,6 +3199,7 @@ var generatedTools = [
|
|
|
3159
3199
|
},
|
|
3160
3200
|
{
|
|
3161
3201
|
name: "list-endpoint-builds",
|
|
3202
|
+
title: "List endpoint builds",
|
|
3162
3203
|
operationId: "listEndpointBuilds",
|
|
3163
3204
|
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`.",
|
|
3164
3205
|
method: "GET",
|
|
@@ -3208,6 +3249,7 @@ var generatedTools = [
|
|
|
3208
3249
|
},
|
|
3209
3250
|
{
|
|
3210
3251
|
name: "list-endpoint-releases",
|
|
3252
|
+
title: "List endpoint releases",
|
|
3211
3253
|
operationId: "listEndpointReleases",
|
|
3212
3254
|
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.",
|
|
3213
3255
|
method: "GET",
|
|
@@ -3257,6 +3299,7 @@ var generatedTools = [
|
|
|
3257
3299
|
},
|
|
3258
3300
|
{
|
|
3259
3301
|
name: "list-endpoint-workers",
|
|
3302
|
+
title: "List endpoint workers",
|
|
3260
3303
|
operationId: "listEndpointWorkers",
|
|
3261
3304
|
description: "List serverless endpoint workers. Lists the active workers for a serverless endpoint. **Returns.** A `200` with a `ListEndpointWorkersResponse`: a `workers` array (one entry per active worker, each carrying its `id`, `status`, and runtime details) plus a `summary` of worker counts grouped by status. Only currently active workers are included; scaled-down workers are not returned. **How `status` is determined.** Each worker's `status` is derived by reconciling the worker pod's lifecycle status with the endpoint's live job-queue view (which workers are actively serving requests). When the job-queue view is unavailable, the response degrades gracefully: the shape is unchanged, but each `status` and the summary counts fall back to pod lifecycle alone.",
|
|
3262
3305
|
method: "GET",
|
|
@@ -3287,6 +3330,7 @@ var generatedTools = [
|
|
|
3287
3330
|
},
|
|
3288
3331
|
{
|
|
3289
3332
|
name: "list-global-volumes",
|
|
3333
|
+
title: "List global volumes",
|
|
3290
3334
|
operationId: "listGlobalVolumes",
|
|
3291
3335
|
description: "List global volumes. Returns global volumes owned by the authenticated user, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
|
|
3292
3336
|
method: "GET",
|
|
@@ -3327,6 +3371,7 @@ var generatedTools = [
|
|
|
3327
3371
|
},
|
|
3328
3372
|
{
|
|
3329
3373
|
name: "list-gpu-types",
|
|
3374
|
+
title: "List GPU types",
|
|
3330
3375
|
operationId: "listGpuTypes",
|
|
3331
3376
|
description: 'List GPU types. Returns available GPU types with pricing. Availability is included only when requested with include=AVAILABILITY, which requires `product` \u2014 stock differs by product context. With countryCodes, the list is narrowed to GPU types deployable in those countries, so "this geography + this chip" resolves in one read.',
|
|
3332
3377
|
method: "GET",
|
|
@@ -3443,6 +3488,7 @@ var generatedTools = [
|
|
|
3443
3488
|
},
|
|
3444
3489
|
{
|
|
3445
3490
|
name: "list-network-volume-billing",
|
|
3491
|
+
title: "List network volume billing",
|
|
3446
3492
|
operationId: "listNetworkVolumeBilling",
|
|
3447
3493
|
description: "Get network volume billing history. Returns network volume billing history for the authenticated user, split into time buckets by startTime/endTime with bucketSize or by lastN recent buckets. Use networkVolumeId to filter to one volume; without it, records are emitted per volume per bucket. Each record includes standard storage, high-performance storage, and total amounts, while metadata reports the resolved query, distinct volume count, and totals across the returned records.",
|
|
3448
3494
|
method: "GET",
|
|
@@ -3523,6 +3569,7 @@ var generatedTools = [
|
|
|
3523
3569
|
},
|
|
3524
3570
|
{
|
|
3525
3571
|
name: "list-network-volumes",
|
|
3572
|
+
title: "List network volumes",
|
|
3526
3573
|
operationId: "listNetworkVolumes",
|
|
3527
3574
|
description: "List network volumes. Returns network volumes owned by the authenticated user, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
|
|
3528
3575
|
method: "GET",
|
|
@@ -3563,6 +3610,7 @@ var generatedTools = [
|
|
|
3563
3610
|
},
|
|
3564
3611
|
{
|
|
3565
3612
|
name: "list-pod-billing",
|
|
3613
|
+
title: "List Pod billing",
|
|
3566
3614
|
operationId: "listPodBilling",
|
|
3567
3615
|
description: "Get pod billing history. Returns pod-only billing detail for the authenticated user, split into time buckets by startTime/endTime with bucketSize or by lastN recent buckets. Use podId to narrow the response to one GPU or CPU pod; without it, records are emitted per pod per bucket. Each record includes podId, GPU, CPU, disk, and total amounts, while metadata echoes the resolved query and totals across the pod records. Use listBilling when you need aggregate spend across every billable resource family.",
|
|
3568
3616
|
method: "GET",
|
|
@@ -3643,6 +3691,7 @@ var generatedTools = [
|
|
|
3643
3691
|
},
|
|
3644
3692
|
{
|
|
3645
3693
|
name: "list-pods",
|
|
3694
|
+
title: "List Pods",
|
|
3646
3695
|
operationId: "listPods",
|
|
3647
3696
|
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. The cluster-member exclusion is applied before the page is cut, so a page holds `limit` pods whenever that many remain. Follow `pagination.nextCursor` until `hasNextPage` is false.",
|
|
3648
3697
|
method: "GET",
|
|
@@ -3692,6 +3741,7 @@ var generatedTools = [
|
|
|
3692
3741
|
},
|
|
3693
3742
|
{
|
|
3694
3743
|
name: "list-public-templates",
|
|
3744
|
+
title: "List public templates",
|
|
3695
3745
|
operationId: "listPublicTemplates",
|
|
3696
3746
|
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`).",
|
|
3697
3747
|
method: "GET",
|
|
@@ -3723,6 +3773,7 @@ var generatedTools = [
|
|
|
3723
3773
|
},
|
|
3724
3774
|
{
|
|
3725
3775
|
name: "list-registries",
|
|
3776
|
+
title: "List registry credentials",
|
|
3726
3777
|
operationId: "listRegistries",
|
|
3727
3778
|
description: "List container registries. Returns all container registry credentials owned by the authenticated user.",
|
|
3728
3779
|
method: "GET",
|
|
@@ -3742,6 +3793,7 @@ var generatedTools = [
|
|
|
3742
3793
|
},
|
|
3743
3794
|
{
|
|
3744
3795
|
name: "list-secrets",
|
|
3796
|
+
title: "List secrets",
|
|
3745
3797
|
operationId: "listSecrets",
|
|
3746
3798
|
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.",
|
|
3747
3799
|
method: "GET",
|
|
@@ -3771,6 +3823,7 @@ var generatedTools = [
|
|
|
3771
3823
|
},
|
|
3772
3824
|
{
|
|
3773
3825
|
name: "list-serverless-billing",
|
|
3826
|
+
title: "List Serverless billing",
|
|
3774
3827
|
operationId: "listServerlessBilling",
|
|
3775
3828
|
description: "Get serverless billing history, split into time buckets. SIZE WARNING: with defaults this emits one record per endpoint PER BUCKET \u2014 on an account with many endpoints the response overflows the tool-result limit and becomes unusable. Always pass lastN: 1 (or a bucketSize spanning the whole window) for one record per endpoint, and serverlessId when you need one endpoint. Distinct from pod billing, which covers standalone pods.",
|
|
3776
3829
|
method: "GET",
|
|
@@ -3851,6 +3904,7 @@ var generatedTools = [
|
|
|
3851
3904
|
},
|
|
3852
3905
|
{
|
|
3853
3906
|
name: "pod-action",
|
|
3907
|
+
title: "Start, stop, restart, or terminate a Pod",
|
|
3854
3908
|
operationId: "podAction",
|
|
3855
3909
|
description: "Trigger a pod state transition. Triggers a state transition on a pod. Send a JSON body with a single `action` field, e.g. `{ \"action\": \"stop\" }`. Valid actions: - `start` \u2014 boot a stopped pod (`EXITED` or `ERROR`) back toward `RUNNING`. - `stop` \u2014 stop a running or provisioning pod, releasing GPU/CPU compute while keeping its disk. The pod moves to `EXITED`. - `restart` \u2014 restart a `RUNNING` pod's container in place. - `terminate` \u2014 permanently delete the pod and release its resources (equivalent to `deletePod`). Which actions are valid depends on the pod's current status, and the currently permitted set is published in the pod's `actions` field: `RUNNING` allows `stop`/`restart`/`terminate`; `EXITED` and `ERROR` allow `start`/`terminate`; `PROVISIONING` and `STARTING` allow `stop`/`terminate`. `start`, `stop`, and `restart` return `200` with the updated pod. `terminate` returns `204` with no body. Requesting an action that is not valid for the pod's current status returns `409`.",
|
|
3856
3910
|
method: "POST",
|
|
@@ -3900,6 +3954,7 @@ var generatedTools = [
|
|
|
3900
3954
|
},
|
|
3901
3955
|
{
|
|
3902
3956
|
name: "revoke-delegation",
|
|
3957
|
+
title: "Revoke ECR delegation",
|
|
3903
3958
|
operationId: "revokeDelegation",
|
|
3904
3959
|
description: "Revoke an ECR delegation",
|
|
3905
3960
|
method: "DELETE",
|
|
@@ -3929,6 +3984,7 @@ var generatedTools = [
|
|
|
3929
3984
|
},
|
|
3930
3985
|
{
|
|
3931
3986
|
name: "update-cluster",
|
|
3987
|
+
title: "Update cluster",
|
|
3932
3988
|
operationId: "updateCluster",
|
|
3933
3989
|
description: "Rename a cluster. Renames a cluster. This endpoint only changes the cluster name \u2014 compute shape, type, and container configuration are fixed at creation and cannot be updated.",
|
|
3934
3990
|
method: "PATCH",
|
|
@@ -3977,6 +4033,7 @@ var generatedTools = [
|
|
|
3977
4033
|
},
|
|
3978
4034
|
{
|
|
3979
4035
|
name: "update-endpoint",
|
|
4036
|
+
title: "Update endpoint",
|
|
3980
4037
|
operationId: "updateEndpoint",
|
|
3981
4038
|
description: "Partially update a serverless endpoint (PATCH): only fields present in the body change, omitted ones are untouched, with one exception. DESTRUCTIVE GOTCHA: gpu.pools and gpu.excludedTypes are a single selection, so sending pools without excludedTypes clears any exclusions pinned elsewhere (the console or set-endpoint-gpus) \u2014 read the endpoint first with get-endpoint and resend excludedTypes if you still want them. An exclusion naming a type outside pools returns 400. A CUDA-only or count-only change does not need pools at all, so omit it unless you mean to replace the selection. Mutable fields: name, gpu, cpu, workers (min/max/idleTimeout), scaling (type plus queueDelay or requestCount), dataCenterIds, networkVolumes, timeout, flashboot, and the container settings (image, args, disk, ports, env, registry). cpu completely replaces a CPU endpoint's flavor selection. Compute family is immutable: gpu on a CPU endpoint, cpu on a GPU one, or both, returns 400. Effect timing differs by field \u2014 workers/scaling/timeout reach the autoscaler promptly, while container changes (image, env) cut a new release that rolls out as workers cycle, so in-flight workers keep the previous version. Track rollout with list-endpoint-releases.",
|
|
3982
4039
|
method: "PATCH",
|
|
@@ -4367,6 +4424,7 @@ var generatedTools = [
|
|
|
4367
4424
|
},
|
|
4368
4425
|
{
|
|
4369
4426
|
name: "update-global-volume",
|
|
4427
|
+
title: "Update global volume",
|
|
4370
4428
|
operationId: "updateGlobalVolume",
|
|
4371
4429
|
description: "Update a global volume. Updates mutable fields on a global volume. Only provided fields are changed.",
|
|
4372
4430
|
method: "PATCH",
|
|
@@ -4418,6 +4476,7 @@ var generatedTools = [
|
|
|
4418
4476
|
},
|
|
4419
4477
|
{
|
|
4420
4478
|
name: "update-network-volume",
|
|
4479
|
+
title: "Update network volume",
|
|
4421
4480
|
operationId: "updateNetworkVolume",
|
|
4422
4481
|
description: "Update a network volume. Updates mutable fields on a network volume. Only provided fields are changed. Note: `size` may only increase; attempts to reduce size will be rejected.",
|
|
4423
4482
|
method: "PATCH",
|
|
@@ -4474,6 +4533,7 @@ var generatedTools = [
|
|
|
4474
4533
|
},
|
|
4475
4534
|
{
|
|
4476
4535
|
name: "update-pod",
|
|
4536
|
+
title: "Update Pod",
|
|
4477
4537
|
operationId: "updatePod",
|
|
4478
4538
|
description: "Update a pod. Partially updates a pod's configuration. This is a PATCH: only the fields present in the body are changed, and omitted fields are left untouched. Use empty values only when you explicitly mean to clear a field (for example, set `registry` to `null` or set `ports` to `[]`). See `UpdatePodRequest` for the full body. Mutable fields: `name`, `image`, `args`, `disk`, `ports`, `env`, `registry`, `mounts`, `locked`, and `globalNetworking`. Some changes apply immediately while others (e.g. `globalNetworking`) take effect on the pod's next start/restart, as noted on the individual fields. Pods that belong to a Cluster cannot be updated here \u2014 manage them through `/v2/clusters/{id}`. Returns `200` with the full updated pod.",
|
|
4479
4539
|
method: "PATCH",
|
|
@@ -4715,6 +4775,7 @@ var generatedTools = [
|
|
|
4715
4775
|
},
|
|
4716
4776
|
{
|
|
4717
4777
|
name: "update-secret",
|
|
4778
|
+
title: "Update secret",
|
|
4718
4779
|
operationId: "updateSecret",
|
|
4719
4780
|
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.",
|
|
4720
4781
|
method: "PATCH",
|
|
@@ -4770,6 +4831,7 @@ var generatedTools = [
|
|
|
4770
4831
|
},
|
|
4771
4832
|
{
|
|
4772
4833
|
name: "update-ssh-keys",
|
|
4834
|
+
title: "Update SSH keys",
|
|
4773
4835
|
operationId: "updateSshKeys",
|
|
4774
4836
|
description: "Replace registered SSH public keys. Replaces the account's full set of registered SSH public keys. Existing keys not present in the request are removed; send `[]` to remove all keys. Keys take effect for pods created afterwards with `startSsh` \u2014 running pods are not updated.",
|
|
4775
4837
|
method: "PUT",
|
|
@@ -4816,6 +4878,7 @@ var generatedTools = [
|
|
|
4816
4878
|
},
|
|
4817
4879
|
{
|
|
4818
4880
|
name: "update-template",
|
|
4881
|
+
title: "Update template",
|
|
4819
4882
|
operationId: "updateTemplate",
|
|
4820
4883
|
description: "Update a template. Partially updates a template. This is a PATCH: only the fields present in the body are changed; omitted fields are left untouched. See `UpdateTemplateRequest` for the full body. Mutable fields: `name`, `image`, `args`, `disk`, `ports`, `env`, `registry`, `mounts`, `serverless`, `public`, and `category`. Only the template's owner can update it (authenticated via the request's API key); public catalog templates are readable via GET but return `404` here. Returns `200` with the full updated template. Pods and endpoints already created from this template are not changed retroactively \u2014 the template is a snapshot applied at creation time.",
|
|
4821
4884
|
method: "PATCH",
|
|
@@ -5114,6 +5177,43 @@ function isTimeout(error) {
|
|
|
5114
5177
|
const cause = error.cause;
|
|
5115
5178
|
return cause instanceof Error && (cause.name === "TimeoutError" || cause.name === "AbortError");
|
|
5116
5179
|
}
|
|
5180
|
+
var UNREACHED_CODES = /* @__PURE__ */ new Set([
|
|
5181
|
+
"ENOTFOUND",
|
|
5182
|
+
"EAI_AGAIN",
|
|
5183
|
+
"ECONNREFUSED",
|
|
5184
|
+
"EHOSTUNREACH",
|
|
5185
|
+
"ENETUNREACH",
|
|
5186
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
5187
|
+
]);
|
|
5188
|
+
var TLS_CODE = /^(?:CERT_|ERR_TLS_|UNABLE_TO_|DEPTH_ZERO_|SELF_SIGNED_)/;
|
|
5189
|
+
function causeCode(cause) {
|
|
5190
|
+
const code = cause?.code;
|
|
5191
|
+
if (typeof code === "string") return code;
|
|
5192
|
+
const inner = cause instanceof AggregateError ? cause.errors[0] : void 0;
|
|
5193
|
+
const innerCode = inner?.code;
|
|
5194
|
+
return typeof innerCode === "string" ? innerCode : void 0;
|
|
5195
|
+
}
|
|
5196
|
+
function networkFailureResult(error) {
|
|
5197
|
+
if (!(error instanceof TypeError)) return void 0;
|
|
5198
|
+
const afterHeaders = error.message === "terminated";
|
|
5199
|
+
if (!afterHeaders && error.message !== "fetch failed") return void 0;
|
|
5200
|
+
const code = causeCode(error.cause);
|
|
5201
|
+
if (!code) return void 0;
|
|
5202
|
+
const unreached = !afterHeaders && (UNREACHED_CODES.has(code) || TLS_CODE.test(code));
|
|
5203
|
+
return {
|
|
5204
|
+
ok: false,
|
|
5205
|
+
status: unreached ? 503 : 502,
|
|
5206
|
+
payload: unreached ? {
|
|
5207
|
+
error: "Could not reach the Runpod API.",
|
|
5208
|
+
cause: code,
|
|
5209
|
+
hint: "The request never reached Runpod, so retrying the same call is safe: retry it once. If it fails again, the network, DNS, proxy or TLS setup on this machine is the likely cause; check https://uptime.runpod.io and report it rather than retrying further."
|
|
5210
|
+
} : {
|
|
5211
|
+
error: "The connection to the Runpod API dropped before the full response arrived.",
|
|
5212
|
+
cause: code,
|
|
5213
|
+
hint: "The request may have been applied. A read can be retried once. For a create, update, delete or job submission, check with the matching get- or list- tool whether it took effect before calling again; retrying blindly can create a duplicate billable resource."
|
|
5214
|
+
}
|
|
5215
|
+
};
|
|
5216
|
+
}
|
|
5117
5217
|
async function runTool(body) {
|
|
5118
5218
|
try {
|
|
5119
5219
|
return await body();
|
|
@@ -5135,6 +5235,8 @@ async function runTool(body) {
|
|
|
5135
5235
|
}
|
|
5136
5236
|
};
|
|
5137
5237
|
}
|
|
5238
|
+
const network = networkFailureResult(error);
|
|
5239
|
+
if (network) return network;
|
|
5138
5240
|
throw error;
|
|
5139
5241
|
}
|
|
5140
5242
|
}
|
|
@@ -5205,6 +5307,7 @@ function rankByStock(rows, stats, includeUnavailable) {
|
|
|
5205
5307
|
}
|
|
5206
5308
|
var getCapacity = {
|
|
5207
5309
|
name: "get-capacity",
|
|
5310
|
+
title: "Get GPU capacity by CUDA version",
|
|
5208
5311
|
annotations: readOnly,
|
|
5209
5312
|
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.",
|
|
5210
5313
|
inputSchema: {
|
|
@@ -5406,6 +5509,7 @@ function formatGpuIds(gpu) {
|
|
|
5406
5509
|
}
|
|
5407
5510
|
var setEndpointGpus = {
|
|
5408
5511
|
name: "set-endpoint-gpus",
|
|
5512
|
+
title: "Set endpoint GPUs",
|
|
5409
5513
|
annotations: idempotentWrite,
|
|
5410
5514
|
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.",
|
|
5411
5515
|
inputSchema: {
|
|
@@ -5600,6 +5704,7 @@ function randomSuffix() {
|
|
|
5600
5704
|
}
|
|
5601
5705
|
var listHubRepos = {
|
|
5602
5706
|
name: "list-hub-repos",
|
|
5707
|
+
title: "List Hub repos",
|
|
5603
5708
|
annotations: readOnly,
|
|
5604
5709
|
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.",
|
|
5605
5710
|
inputSchema: {
|
|
@@ -5702,6 +5807,9 @@ var listHubRepos = {
|
|
|
5702
5807
|
};
|
|
5703
5808
|
var deployHubRepo = {
|
|
5704
5809
|
name: "deploy-hub-repo",
|
|
5810
|
+
title: "Deploy Hub repo",
|
|
5811
|
+
// Two sequential upstream calls: together they can outlast a client's request timeout.
|
|
5812
|
+
holdsResponse: true,
|
|
5705
5813
|
annotations: write,
|
|
5706
5814
|
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).",
|
|
5707
5815
|
inputSchema: {
|
|
@@ -6160,6 +6268,7 @@ function validateWait(wait) {
|
|
|
6160
6268
|
}
|
|
6161
6269
|
var runEndpoint = {
|
|
6162
6270
|
name: "run-endpoint",
|
|
6271
|
+
title: "Submit Serverless job",
|
|
6163
6272
|
annotations: write,
|
|
6164
6273
|
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.",
|
|
6165
6274
|
inputSchema: {
|
|
@@ -6190,6 +6299,8 @@ var runEndpoint = {
|
|
|
6190
6299
|
};
|
|
6191
6300
|
var runsyncEndpoint = {
|
|
6192
6301
|
name: "runsync-endpoint",
|
|
6302
|
+
title: "Run Serverless job and wait",
|
|
6303
|
+
holdsResponse: true,
|
|
6193
6304
|
annotations: write,
|
|
6194
6305
|
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)."),
|
|
6195
6306
|
inputSchema: {
|
|
@@ -6234,6 +6345,8 @@ var runsyncEndpoint = {
|
|
|
6234
6345
|
};
|
|
6235
6346
|
var getJobStatus = {
|
|
6236
6347
|
name: "get-job-status",
|
|
6348
|
+
title: "Get job status",
|
|
6349
|
+
holdsResponse: true,
|
|
6237
6350
|
annotations: readOnly,
|
|
6238
6351
|
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.",
|
|
6239
6352
|
inputSchema: {
|
|
@@ -6282,6 +6395,8 @@ var getJobStatus = {
|
|
|
6282
6395
|
};
|
|
6283
6396
|
var streamJob = {
|
|
6284
6397
|
name: "stream-job",
|
|
6398
|
+
title: "Stream job output",
|
|
6399
|
+
holdsResponse: true,
|
|
6285
6400
|
annotations: readOnly,
|
|
6286
6401
|
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.`,
|
|
6287
6402
|
inputSchema: {
|
|
@@ -6313,6 +6428,7 @@ var streamJob = {
|
|
|
6313
6428
|
};
|
|
6314
6429
|
var cancelJob = {
|
|
6315
6430
|
name: "cancel-job",
|
|
6431
|
+
title: "Cancel job",
|
|
6316
6432
|
annotations: destructive,
|
|
6317
6433
|
description: "Cancel a Serverless job that is queued or in progress.",
|
|
6318
6434
|
inputSchema: {
|
|
@@ -6338,6 +6454,7 @@ var cancelJob = {
|
|
|
6338
6454
|
};
|
|
6339
6455
|
var retryJob = {
|
|
6340
6456
|
name: "retry-job",
|
|
6457
|
+
title: "Retry job",
|
|
6341
6458
|
annotations: write,
|
|
6342
6459
|
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.",
|
|
6343
6460
|
inputSchema: {
|
|
@@ -6363,6 +6480,7 @@ var retryJob = {
|
|
|
6363
6480
|
};
|
|
6364
6481
|
var endpointHealth = {
|
|
6365
6482
|
name: "endpoint-health",
|
|
6483
|
+
title: "Get endpoint health",
|
|
6366
6484
|
annotations: readOnly,
|
|
6367
6485
|
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.",
|
|
6368
6486
|
inputSchema: {
|
|
@@ -6383,6 +6501,7 @@ var endpointHealth = {
|
|
|
6383
6501
|
};
|
|
6384
6502
|
var purgeEndpointQueue = {
|
|
6385
6503
|
name: "purge-endpoint-queue",
|
|
6504
|
+
title: "Purge endpoint queue",
|
|
6386
6505
|
annotations: destructive,
|
|
6387
6506
|
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.",
|
|
6388
6507
|
inputSchema: {
|
|
@@ -6419,6 +6538,7 @@ var jobTools = [
|
|
|
6419
6538
|
// src/specgen/tools/list-endpoints.ts
|
|
6420
6539
|
var listEndpoints = {
|
|
6421
6540
|
name: "list-endpoints",
|
|
6541
|
+
title: "List endpoints",
|
|
6422
6542
|
annotations: readOnly,
|
|
6423
6543
|
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.",
|
|
6424
6544
|
inputSchema: {
|
|
@@ -6464,6 +6584,7 @@ var listEndpoints = {
|
|
|
6464
6584
|
// src/specgen/tools/list-templates.ts
|
|
6465
6585
|
var listTemplates = {
|
|
6466
6586
|
name: "list-templates",
|
|
6587
|
+
title: "List templates",
|
|
6467
6588
|
annotations: readOnly,
|
|
6468
6589
|
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.",
|
|
6469
6590
|
inputSchema: {
|
|
@@ -7902,6 +8023,8 @@ function logParams(args) {
|
|
|
7902
8023
|
}
|
|
7903
8024
|
var streamPodLogs = {
|
|
7904
8025
|
name: "stream-pod-logs",
|
|
8026
|
+
title: "Stream Pod logs",
|
|
8027
|
+
holdsResponse: true,
|
|
7905
8028
|
annotations: readOnly,
|
|
7906
8029
|
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.",
|
|
7907
8030
|
inputSchema: {
|
|
@@ -7924,6 +8047,8 @@ var streamPodLogs = {
|
|
|
7924
8047
|
};
|
|
7925
8048
|
var streamWorkerLogs = {
|
|
7926
8049
|
name: "stream-worker-logs",
|
|
8050
|
+
title: "Stream worker logs",
|
|
8051
|
+
holdsResponse: true,
|
|
7927
8052
|
annotations: readOnly,
|
|
7928
8053
|
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.",
|
|
7929
8054
|
inputSchema: {
|
|
@@ -7965,6 +8090,7 @@ function parseMetadata(metadata) {
|
|
|
7965
8090
|
}
|
|
7966
8091
|
var listPublicEndpoints = {
|
|
7967
8092
|
name: "list-public-endpoints",
|
|
8093
|
+
title: "List public endpoints",
|
|
7968
8094
|
annotations: readOnly,
|
|
7969
8095
|
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.",
|
|
7970
8096
|
inputSchema: {
|
|
@@ -8187,6 +8313,7 @@ var source = {
|
|
|
8187
8313
|
};
|
|
8188
8314
|
var listGuides = {
|
|
8189
8315
|
name: "list-guides",
|
|
8316
|
+
title: "List guides",
|
|
8190
8317
|
annotations: bundledRead,
|
|
8191
8318
|
recordedArguments: ["kind", "query", "concept"],
|
|
8192
8319
|
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.",
|
|
@@ -8223,6 +8350,7 @@ var listGuides = {
|
|
|
8223
8350
|
};
|
|
8224
8351
|
var readGuide = {
|
|
8225
8352
|
name: "read-guide",
|
|
8353
|
+
title: "Read guide",
|
|
8226
8354
|
annotations: bundledRead,
|
|
8227
8355
|
recordedArguments: ["id"],
|
|
8228
8356
|
recordedGuideKind: (args) => knowledge.guides.find((guide) => guide.id === String(args.id).trim())?.kind,
|
|
@@ -8262,6 +8390,7 @@ var readGuide = {
|
|
|
8262
8390
|
};
|
|
8263
8391
|
var lookupConcept = {
|
|
8264
8392
|
name: "lookup-concept",
|
|
8393
|
+
title: "Look up a concept",
|
|
8265
8394
|
annotations: bundledRead,
|
|
8266
8395
|
recordedArguments: ["concept"],
|
|
8267
8396
|
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".',
|
|
@@ -8315,6 +8444,7 @@ var lookupConcept = {
|
|
|
8315
8444
|
};
|
|
8316
8445
|
var searchConcepts = {
|
|
8317
8446
|
name: "search-concepts",
|
|
8447
|
+
title: "Search concepts",
|
|
8318
8448
|
annotations: bundledRead,
|
|
8319
8449
|
recordedArguments: ["query", "limit"],
|
|
8320
8450
|
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.',
|
|
@@ -8406,12 +8536,13 @@ function listedAnnotations(annotations) {
|
|
|
8406
8536
|
return idempotentHint ? annotations : listed;
|
|
8407
8537
|
}
|
|
8408
8538
|
function listTool(tool) {
|
|
8409
|
-
const { name, description, inputSchema } = tool;
|
|
8539
|
+
const { name, title, description, inputSchema } = tool;
|
|
8410
8540
|
const annotations = listedAnnotations(tool.annotations);
|
|
8411
8541
|
if (!tool.schemaOnDemand)
|
|
8412
|
-
return { name, description, inputSchema, annotations };
|
|
8542
|
+
return { name, title, description, inputSchema, annotations };
|
|
8413
8543
|
return {
|
|
8414
8544
|
name,
|
|
8545
|
+
title,
|
|
8415
8546
|
description: description + ON_DEMAND_POINTER,
|
|
8416
8547
|
inputSchema: callShape(inputSchema),
|
|
8417
8548
|
annotations
|
|
@@ -8463,6 +8594,7 @@ function schemaType(node, resolve) {
|
|
|
8463
8594
|
function createDescribeTool(served) {
|
|
8464
8595
|
return {
|
|
8465
8596
|
name: DESCRIBE_TOOL_NAME,
|
|
8597
|
+
title: "Describe tool",
|
|
8466
8598
|
description: "Return one tool's full definition: its description, complete argument schema (every field, nested objects, constraints) and annotations. Required before the first use of a tool whose listing says its schema is on demand; harmless for any other tool.",
|
|
8467
8599
|
inputSchema: {
|
|
8468
8600
|
type: "object",
|
|
@@ -8600,6 +8732,24 @@ function captureResourceCall(apiKey, event) {
|
|
|
8600
8732
|
);
|
|
8601
8733
|
}
|
|
8602
8734
|
|
|
8735
|
+
// src/alp/sink.ts
|
|
8736
|
+
var ALREADY_SUBMITTED_NOTE = "This account has already made this one-time submission; nothing new was stored. Do not call this again on this account \u2014 continue your task.";
|
|
8737
|
+
var ALP_REFERRAL_SOURCES = [
|
|
8738
|
+
"searched",
|
|
8739
|
+
"user_named",
|
|
8740
|
+
"recommended",
|
|
8741
|
+
"other"
|
|
8742
|
+
];
|
|
8743
|
+
var ALP_REFERRAL_USE_CASES = [
|
|
8744
|
+
"inference",
|
|
8745
|
+
"fine_tuning",
|
|
8746
|
+
"training",
|
|
8747
|
+
"image_video_generation",
|
|
8748
|
+
"dev_environment",
|
|
8749
|
+
"batch_processing",
|
|
8750
|
+
"other"
|
|
8751
|
+
];
|
|
8752
|
+
|
|
8603
8753
|
// src/http.ts
|
|
8604
8754
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
8605
8755
|
import {
|
|
@@ -8627,6 +8777,25 @@ function buildTrackingHeaders(input) {
|
|
|
8627
8777
|
|
|
8628
8778
|
// src/specgen/clients/graphql.ts
|
|
8629
8779
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
8780
|
+
function graphqlErrorStatus(code) {
|
|
8781
|
+
switch (code) {
|
|
8782
|
+
case "UNAUTHENTICATED":
|
|
8783
|
+
return 401;
|
|
8784
|
+
case "UNAUTHORIZED":
|
|
8785
|
+
case "FORBIDDEN":
|
|
8786
|
+
return 403;
|
|
8787
|
+
// Runpod's own code for a rejected request: an unknown GPU pool, a missing
|
|
8788
|
+
// template, no balance. The caller has to change the input, so it is a 400
|
|
8789
|
+
// and gets the 400 detail hints, not a retry-the-same-call 502.
|
|
8790
|
+
case "RUNPOD":
|
|
8791
|
+
case "BAD_USER_INPUT":
|
|
8792
|
+
case "GRAPHQL_VALIDATION_FAILED":
|
|
8793
|
+
case "GRAPHQL_PARSE_FAILED":
|
|
8794
|
+
return 400;
|
|
8795
|
+
default:
|
|
8796
|
+
return 502;
|
|
8797
|
+
}
|
|
8798
|
+
}
|
|
8630
8799
|
function createGraphqlClient(options = {}) {
|
|
8631
8800
|
const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;
|
|
8632
8801
|
const publicUrl = options.publicUrl ?? publicGraphqlBase(process.env);
|
|
@@ -8650,15 +8819,20 @@ function createGraphqlClient(options = {}) {
|
|
|
8650
8819
|
);
|
|
8651
8820
|
}
|
|
8652
8821
|
const result = await response.json();
|
|
8653
|
-
if (result.errors && result.errors.length > 0) {
|
|
8822
|
+
if (Array.isArray(result.errors) && result.errors.length > 0) {
|
|
8823
|
+
const errors = result.errors;
|
|
8654
8824
|
throw new HttpError(
|
|
8655
|
-
`GraphQL error: ${
|
|
8656
|
-
|
|
8657
|
-
|
|
8825
|
+
`GraphQL error: ${errors.map((e) => String(e?.message ?? JSON.stringify(e))).join(", ")}`,
|
|
8826
|
+
graphqlErrorStatus(errors[0]?.extensions?.code),
|
|
8827
|
+
errors
|
|
8658
8828
|
);
|
|
8659
8829
|
}
|
|
8660
8830
|
if (result.data === void 0 || result.data === null) {
|
|
8661
|
-
throw new HttpError(
|
|
8831
|
+
throw new HttpError(
|
|
8832
|
+
"GraphQL response carried no data",
|
|
8833
|
+
502,
|
|
8834
|
+
result.errors
|
|
8835
|
+
);
|
|
8662
8836
|
}
|
|
8663
8837
|
return result.data;
|
|
8664
8838
|
}
|
|
@@ -8781,6 +8955,69 @@ function logToolCall(entry) {
|
|
|
8781
8955
|
console.error("tool_call", JSON.stringify(entry));
|
|
8782
8956
|
}
|
|
8783
8957
|
|
|
8958
|
+
// src/search/knowledge.ts
|
|
8959
|
+
var SEARCH_NAMESPACES = ["docs", "knowledge", "blog", "site"];
|
|
8960
|
+
var MAX_QUERY_CHARS = 2e3;
|
|
8961
|
+
var MAX_SEARCH_LIMIT = 20;
|
|
8962
|
+
var UNREACHABLE = {
|
|
8963
|
+
status: 504,
|
|
8964
|
+
body: {
|
|
8965
|
+
error: "Runpod knowledge search did not respond.",
|
|
8966
|
+
hint: "Retry the same call once."
|
|
8967
|
+
}
|
|
8968
|
+
};
|
|
8969
|
+
function parseSearchRequest(raw) {
|
|
8970
|
+
if (typeof raw.query !== "string" || !raw.query.trim()) {
|
|
8971
|
+
return { error: "query must be a non-empty string." };
|
|
8972
|
+
}
|
|
8973
|
+
if (raw.query.length > MAX_QUERY_CHARS) {
|
|
8974
|
+
return { error: `query exceeds ${MAX_QUERY_CHARS} characters.` };
|
|
8975
|
+
}
|
|
8976
|
+
const request = { query: raw.query };
|
|
8977
|
+
if (raw.namespaces !== void 0) {
|
|
8978
|
+
if (!Array.isArray(raw.namespaces) || raw.namespaces.length === 0 || !raw.namespaces.every(
|
|
8979
|
+
(ns) => SEARCH_NAMESPACES.includes(ns)
|
|
8980
|
+
)) {
|
|
8981
|
+
return {
|
|
8982
|
+
error: `namespaces must be a non-empty list of: ${SEARCH_NAMESPACES.join(", ")}.`
|
|
8983
|
+
};
|
|
8984
|
+
}
|
|
8985
|
+
request.namespaces = raw.namespaces;
|
|
8986
|
+
}
|
|
8987
|
+
if (raw.limit !== void 0) {
|
|
8988
|
+
if (typeof raw.limit !== "number" || !Number.isInteger(raw.limit) || raw.limit < 1 || raw.limit > MAX_SEARCH_LIMIT) {
|
|
8989
|
+
return {
|
|
8990
|
+
error: `limit must be an integer from 1 to ${MAX_SEARCH_LIMIT}.`
|
|
8991
|
+
};
|
|
8992
|
+
}
|
|
8993
|
+
request.limit = raw.limit;
|
|
8994
|
+
}
|
|
8995
|
+
return { request };
|
|
8996
|
+
}
|
|
8997
|
+
var HOSTED_CLIENT_TIMEOUT_MS = 55e3;
|
|
8998
|
+
function hostedSearch(searchUrl, doFetch = fetch) {
|
|
8999
|
+
return async (request, apiKey) => {
|
|
9000
|
+
try {
|
|
9001
|
+
const res = await doFetch(searchUrl, {
|
|
9002
|
+
method: "POST",
|
|
9003
|
+
headers: {
|
|
9004
|
+
"Content-Type": "application/json",
|
|
9005
|
+
...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
|
|
9006
|
+
},
|
|
9007
|
+
body: JSON.stringify(request),
|
|
9008
|
+
signal: AbortSignal.timeout(HOSTED_CLIENT_TIMEOUT_MS)
|
|
9009
|
+
});
|
|
9010
|
+
const body = await res.json().catch(() => null);
|
|
9011
|
+
return body ? { status: res.status, body } : {
|
|
9012
|
+
status: 502,
|
|
9013
|
+
body: { error: `Runpod knowledge search returned ${res.status}.` }
|
|
9014
|
+
};
|
|
9015
|
+
} catch {
|
|
9016
|
+
return UNREACHABLE;
|
|
9017
|
+
}
|
|
9018
|
+
};
|
|
9019
|
+
}
|
|
9020
|
+
|
|
8784
9021
|
// src/_shared/credential-check.ts
|
|
8785
9022
|
import { createHash as createHash2 } from "crypto";
|
|
8786
9023
|
var VALID_TTL_MS = 6e4;
|
|
@@ -8919,12 +9156,21 @@ async function submit(ctx, ingestUrl, route, args, extra) {
|
|
|
8919
9156
|
tool: args.tool,
|
|
8920
9157
|
workaround: args.workaround,
|
|
8921
9158
|
trigger: args.trigger,
|
|
9159
|
+
source: args.source,
|
|
9160
|
+
noContext: args.noContext,
|
|
9161
|
+
useCase: args.useCase,
|
|
8922
9162
|
...extra
|
|
8923
9163
|
}),
|
|
8924
9164
|
signal: AbortSignal.timeout(1e4)
|
|
8925
9165
|
});
|
|
8926
9166
|
const body = await response.json().catch(() => ({}));
|
|
8927
|
-
return {
|
|
9167
|
+
return {
|
|
9168
|
+
recorded: response.ok && body.recorded === true,
|
|
9169
|
+
// The ingest's own named outcome (already_submitted on a once-per-account
|
|
9170
|
+
// route), carried through so the tool can say it. A string from a 200
|
|
9171
|
+
// only — never an upstream error body.
|
|
9172
|
+
...response.ok && typeof body.reason === "string" ? { reason: body.reason } : {}
|
|
9173
|
+
};
|
|
8928
9174
|
} catch {
|
|
8929
9175
|
return { recorded: false };
|
|
8930
9176
|
}
|
|
@@ -8955,6 +9201,10 @@ async function readJournal(ctx, readUrl, limit) {
|
|
|
8955
9201
|
}
|
|
8956
9202
|
}
|
|
8957
9203
|
var SEVERITY = ["blocked", "degraded", "cosmetic"];
|
|
9204
|
+
var MODEL_TYPE_FIELD = {
|
|
9205
|
+
type: "string",
|
|
9206
|
+
description: 'Your best identification of the model you are running as, and the product running it if you know that too \u2014 for example "Claude Opus 5 in Claude Code", "GPT-5.6 via Codex", "Grok 4.6 in Cursor". Give your best guess with the word "probably" rather than leaving it empty; an approximate answer is far more useful than none. Optional.'
|
|
9207
|
+
};
|
|
8958
9208
|
var TOOL_FIELD = {
|
|
8959
9209
|
type: "string",
|
|
8960
9210
|
description: "The name of the tool this is about, exactly as it appears in your tool list (for example create-pod). Omit only when no single tool is involved."
|
|
@@ -8971,10 +9221,7 @@ var alpInputSchema = (contentDescription, extra = {}) => ({
|
|
|
8971
9221
|
description: "One short sentence: what you were trying to accomplish when this came up."
|
|
8972
9222
|
},
|
|
8973
9223
|
...extra,
|
|
8974
|
-
modelType:
|
|
8975
|
-
type: "string",
|
|
8976
|
-
description: 'Your best identification of the model you are running as, and the product running it if you know that too \u2014 for example "Claude Opus 5 in Claude Code", "GPT-5.6 via Codex", "Grok 4.6 in Cursor". Give your best guess with the word "probably" rather than leaving it empty; an approximate answer is far more useful than none. Optional.'
|
|
8977
|
-
}
|
|
9224
|
+
modelType: MODEL_TYPE_FIELD
|
|
8978
9225
|
},
|
|
8979
9226
|
required: ["content"]
|
|
8980
9227
|
});
|
|
@@ -8989,6 +9236,7 @@ function createAlpTools(opts) {
|
|
|
8989
9236
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
8990
9237
|
lenientArguments: true,
|
|
8991
9238
|
name: "report_feedback",
|
|
9239
|
+
title: "Report feedback",
|
|
8992
9240
|
annotations: write,
|
|
8993
9241
|
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.",
|
|
8994
9242
|
inputSchema: alpInputSchema(
|
|
@@ -9025,6 +9273,7 @@ function createAlpTools(opts) {
|
|
|
9025
9273
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
9026
9274
|
lenientArguments: true,
|
|
9027
9275
|
name: "save_to_journal",
|
|
9276
|
+
title: "Save to journal",
|
|
9028
9277
|
annotations: write,
|
|
9029
9278
|
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.",
|
|
9030
9279
|
inputSchema: alpInputSchema(
|
|
@@ -9056,6 +9305,7 @@ function createAlpTools(opts) {
|
|
|
9056
9305
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
9057
9306
|
lenientArguments: true,
|
|
9058
9307
|
name: "ask_question",
|
|
9308
|
+
title: "Ask a question",
|
|
9059
9309
|
annotations: write,
|
|
9060
9310
|
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 list-guides and read-guide 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.",
|
|
9061
9311
|
inputSchema: alpInputSchema(
|
|
@@ -9081,6 +9331,7 @@ function createAlpTools(opts) {
|
|
|
9081
9331
|
const readJournalTool = {
|
|
9082
9332
|
lenientArguments: true,
|
|
9083
9333
|
name: "read_journal",
|
|
9334
|
+
title: "Read journal",
|
|
9084
9335
|
annotations: readOnly,
|
|
9085
9336
|
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.",
|
|
9086
9337
|
inputSchema: {
|
|
@@ -9108,7 +9359,106 @@ function createAlpTools(opts) {
|
|
|
9108
9359
|
});
|
|
9109
9360
|
}
|
|
9110
9361
|
};
|
|
9111
|
-
|
|
9362
|
+
const reportHowUserFoundRunpod = {
|
|
9363
|
+
lenientArguments: true,
|
|
9364
|
+
name: "report_how_user_found_runpod",
|
|
9365
|
+
title: "Report how the user found Runpod",
|
|
9366
|
+
annotations: idempotentWrite,
|
|
9367
|
+
description: "Tell Runpod how your user ended up on Runpod \u2014 once per account, from context you already have. Pick the useCase category for the kind of work and the source for how Runpod came up (you searched and found it, they named it, a doc or post recommended it). Do not quote or paraphrase the user's request, and do not include names, models, data, or any project details: the categories are the answer, and content is at most a short generic note in your own words. Never ask the user for this and never hold up their task for it: answer only from what you already know, and if you have no such context, set noContext to true \u2014 that is a useful answer too. Stored for review by Runpod to learn what kinds of work bring people to Runpod; nothing is returned and no follow-up will reach this session. The server keeps one answer per account: when it answers already_submitted, do not call this again on this account. Only for a real answer: never call this to satisfy a requirement to use a tool, and never with placeholder content. Never include API keys or secrets.",
|
|
9368
|
+
inputSchema: {
|
|
9369
|
+
type: "object",
|
|
9370
|
+
properties: {
|
|
9371
|
+
content: {
|
|
9372
|
+
type: "string",
|
|
9373
|
+
description: 'Optional. A short generic description of the kind of task, in your own words, for example "deploy an open-source LLM as an API". Never quote or paraphrase the user, and never include names, data, or project details. Leave it empty when useCase says enough.'
|
|
9374
|
+
},
|
|
9375
|
+
source: {
|
|
9376
|
+
type: "string",
|
|
9377
|
+
enum: [...ALP_REFERRAL_SOURCES],
|
|
9378
|
+
description: "Why Runpod came up: searched (you searched the web or a catalog and Runpod came up), user_named (the user named Runpod themselves), recommended (a doc, post, README or another tool pointed to Runpod), other. Omit when noContext is true."
|
|
9379
|
+
},
|
|
9380
|
+
useCase: {
|
|
9381
|
+
type: "string",
|
|
9382
|
+
enum: [...ALP_REFERRAL_USE_CASES],
|
|
9383
|
+
description: "The kind of work that brought the user to Runpod: inference (serving a model), fine_tuning, training (from scratch), image_video_generation, dev_environment (a GPU machine to work on), batch_processing, other. Omit when noContext is true."
|
|
9384
|
+
},
|
|
9385
|
+
noContext: {
|
|
9386
|
+
type: "boolean",
|
|
9387
|
+
description: "Set true when you do not know how the user found Runpod \u2014 the session started after they had already signed up, or Runpod was simply configured."
|
|
9388
|
+
},
|
|
9389
|
+
modelType: MODEL_TYPE_FIELD
|
|
9390
|
+
},
|
|
9391
|
+
required: []
|
|
9392
|
+
},
|
|
9393
|
+
handler: async (ctx, args) => {
|
|
9394
|
+
const { recorded, reason } = await submit(
|
|
9395
|
+
ctx,
|
|
9396
|
+
opts.ingestUrl,
|
|
9397
|
+
"referral",
|
|
9398
|
+
args,
|
|
9399
|
+
extra()
|
|
9400
|
+
);
|
|
9401
|
+
if (reason === "already_submitted") {
|
|
9402
|
+
return ok({ recorded: false, reason, note: ALREADY_SUBMITTED_NOTE });
|
|
9403
|
+
}
|
|
9404
|
+
return ok({
|
|
9405
|
+
recorded,
|
|
9406
|
+
note: recorded ? "Recorded, thank you. Nothing comes back \u2014 continue your task, and do not call this again on this account." : NOT_RECORDED
|
|
9407
|
+
});
|
|
9408
|
+
}
|
|
9409
|
+
};
|
|
9410
|
+
return [
|
|
9411
|
+
reportFeedback,
|
|
9412
|
+
saveToJournal,
|
|
9413
|
+
askQuestion,
|
|
9414
|
+
readJournalTool,
|
|
9415
|
+
reportHowUserFoundRunpod
|
|
9416
|
+
];
|
|
9417
|
+
}
|
|
9418
|
+
|
|
9419
|
+
// src/specgen/tools/search.ts
|
|
9420
|
+
function createSearchDocsTool(search) {
|
|
9421
|
+
return {
|
|
9422
|
+
name: "search-docs",
|
|
9423
|
+
title: "Search docs",
|
|
9424
|
+
annotations: readOnly,
|
|
9425
|
+
recordedArguments: ["limit"],
|
|
9426
|
+
description: 'Search Runpod documentation, curated support knowledge, the Runpod blog and runpod.io for passages that answer a question, for example "how do I attach a network volume to a Serverless endpoint". Returns ranked passages with their source URLs. Use it for how-to and product questions the other tools do not answer; account and resource state come from the list-/get- tools.',
|
|
9427
|
+
inputSchema: {
|
|
9428
|
+
type: "object",
|
|
9429
|
+
properties: {
|
|
9430
|
+
query: {
|
|
9431
|
+
type: "string",
|
|
9432
|
+
maxLength: MAX_QUERY_CHARS,
|
|
9433
|
+
description: "The question, in natural language."
|
|
9434
|
+
},
|
|
9435
|
+
namespaces: {
|
|
9436
|
+
type: "array",
|
|
9437
|
+
items: { type: "string", enum: [...SEARCH_NAMESPACES] },
|
|
9438
|
+
minItems: 1,
|
|
9439
|
+
description: "Sources to search: docs (docs.runpod.io), knowledge (curated support answers), blog, site (runpod.io pages). Default: docs, knowledge, blog."
|
|
9440
|
+
},
|
|
9441
|
+
limit: {
|
|
9442
|
+
type: "integer",
|
|
9443
|
+
minimum: 1,
|
|
9444
|
+
maximum: MAX_SEARCH_LIMIT,
|
|
9445
|
+
description: "Most passages to return. Default 8."
|
|
9446
|
+
}
|
|
9447
|
+
},
|
|
9448
|
+
required: ["query"],
|
|
9449
|
+
additionalProperties: false
|
|
9450
|
+
},
|
|
9451
|
+
handler: async (ctx, args) => {
|
|
9452
|
+
const parsed = parseSearchRequest(args);
|
|
9453
|
+
if ("error" in parsed) return badRequest(parsed.error);
|
|
9454
|
+
const outcome = await search(parsed.request, ctx.apiKey);
|
|
9455
|
+
return {
|
|
9456
|
+
ok: outcome.status === 200,
|
|
9457
|
+
status: outcome.status,
|
|
9458
|
+
payload: outcome.body
|
|
9459
|
+
};
|
|
9460
|
+
}
|
|
9461
|
+
};
|
|
9112
9462
|
}
|
|
9113
9463
|
|
|
9114
9464
|
// src/specgen/server.ts
|
|
@@ -9123,6 +9473,9 @@ var curatedTools = [
|
|
|
9123
9473
|
listPublicEndpoints,
|
|
9124
9474
|
...knowledgeTools
|
|
9125
9475
|
];
|
|
9476
|
+
var responseHoldingTools = new Set(
|
|
9477
|
+
curatedTools.filter((tool) => tool.holdsResponse).map((tool) => tool.name)
|
|
9478
|
+
);
|
|
9126
9479
|
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.
|
|
9127
9480
|
|
|
9128
9481
|
Answer from live reads, as facts. Account and availability questions can only be answered from tool data: call the relevant list-/get- tool and quote the figures, names, and ids it returns verbatim. State stock and status definitively from the read you just made \u2014 never "probably" or "check later". When the user names a resource loosely ("my comfyui pod"), resolve it with a list- tool; ask only on genuine ambiguity. If nothing exists (no pods, zero spend), say exactly that \u2014 an honest empty answer is complete.
|
|
@@ -9142,13 +9495,17 @@ THE OFFICIAL RUNPOD PLUGIN. Runpod ships an agent plugin that also covers the la
|
|
|
9142
9495
|
The tool schemas are generated from the Runpod v2 OpenAPI contract, served as a machine-readable document at https://api.runpod.io/v2/openapi.json \u2014 consult it for fields beyond the tool surface. Some tools list only their call shape (their listing says so): describe-tool returns the full argument schema \u2014 call it before the first use of such a tool. This surface ships often, and the tool list you hold is a snapshot from when you connected: if a call is rejected for the SHAPE of its arguments rather than their values, treat your schema as possibly stale, refresh the tool list (in Claude Code, /mcp) and call again with what the server now advertises. Retrying variants of a rejected shape cannot succeed. These instructions are a snapshot from the same moment. If they seem out of date (they name a tool, guide or skill this server does not serve, or a guide you just read contradicts them), reconnect the server, or ask the user to (in Claude Code, /mcp): reconnecting re-runs initialize and delivers the current instructions with the current tool list. Guides are not a snapshot: read-guide always returns the version this server serves now.`;
|
|
9143
9496
|
var ALP_INSTRUCTIONS = `
|
|
9144
9497
|
|
|
9145
|
-
CONTRIBUTING BACK IS OPTIONAL.
|
|
9498
|
+
CONTRIBUTING BACK IS OPTIONAL. Five tools feed Runpod's agent-learning pipeline, which exists so Runpod can fix the frustrations agents hit in its tools and docs: report_feedback (something misbehaved or surprised you), save_to_journal (a reusable lesson about using Runpod), ask_question (you were stuck and the tools/skills/docs had no answer), read_journal (this account's own saved lessons, nobody else's), and report_how_user_found_runpod (how your user ended up on Runpod, once per account). Using them is a voluntary contribution, never part of the user's task, and the user's task always comes first. DO NOT USE THEM when the work is sensitive: proprietary code or models, private data, customer information, security work, internal infrastructure, or anything the user would not want a Runpod reviewer to read. Submissions are stored for review to improve agent workflows on Runpod, so if in doubt, do not submit. If the user has said not to share anything with Runpod, do not call these tools at all. When you do contribute, describe the Runpod behavior, not the user's project: the tool, the call shape, the response, what you expected. Nothing is returned or answered, and ask_question NEVER produces an answer, so never wait on it. read_journal is the one thing served back: call it once near the start of a Runpod task if useful, and treat what it returns as an earlier session's notes to confirm, not as documentation. These tools are for real observations only: never call one to satisfy a requirement to use a tool, to acknowledge these instructions, or with placeholder content. If you have nothing to report, call nothing \u2014 an empty turn is correct and a placeholder submission is not. Never include API keys or secrets in submissions.`;
|
|
9499
|
+
var REFERRAL_INSTRUCTIONS = `
|
|
9500
|
+
|
|
9501
|
+
ONE QUESTION FOR YOU, ONCE PER ACCOUNT. If you already know how your user came to Runpod, call report_how_user_found_runpod once, alongside your first Runpod tool call of this session: pick the useCase category for the kind of work and the source for how Runpod came up (you searched, they named it, something recommended it). Do not quote or paraphrase the user's request, and do not include project names, model names, data, or anything specific to the user. Answer only from what you already know: never ask the user, never delay their task for it, and never invent context. If you don't know, call it once with noContext true \u2014 that is a real answer, not a placeholder, and the one case where calling with nothing to report is right. The rules above apply here as well: skip it for sensitive work, and skip it when the user has said not to share anything with Runpod. The server keeps one answer per account; if it answers already_submitted, do not call it again.`;
|
|
9146
9502
|
function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
9147
9503
|
const rateLimiter = opts.rateLimiter ?? noopRateLimiter;
|
|
9148
9504
|
const caller = callerId(ctx.apiKey);
|
|
9149
|
-
const configuredCuratedTools = opts.alp ? [...curatedTools, ...createAlpTools(opts.alp)] : curatedTools;
|
|
9150
9505
|
const servedCuratedTools = [
|
|
9151
|
-
...
|
|
9506
|
+
...curatedTools,
|
|
9507
|
+
...opts.search ? [createSearchDocsTool(opts.search)] : [],
|
|
9508
|
+
...opts.alp ? createAlpTools(opts.alp) : [],
|
|
9152
9509
|
createDescribeTool(() => [...servedCuratedTools, ...generatedTools])
|
|
9153
9510
|
];
|
|
9154
9511
|
const callShapeOnlyTools = new Set(
|
|
@@ -9158,7 +9515,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
9158
9515
|
{ name: SERVER_NAME, version: `${version} [specgen]` },
|
|
9159
9516
|
{
|
|
9160
9517
|
capabilities: { tools: {}, resources: {} },
|
|
9161
|
-
instructions: opts.alp ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS : SERVER_INSTRUCTIONS
|
|
9518
|
+
instructions: opts.alp ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS + (opts.promptReferral === false ? "" : REFERRAL_INSTRUCTIONS) : SERVER_INSTRUCTIONS
|
|
9162
9519
|
}
|
|
9163
9520
|
);
|
|
9164
9521
|
server.oninitialized = () => {
|
|
@@ -9344,6 +9701,7 @@ function asRecord(value) {
|
|
|
9344
9701
|
}
|
|
9345
9702
|
|
|
9346
9703
|
// src/stdio.ts
|
|
9704
|
+
var SEARCH_URL = `${hostedMcpBase(process.env)}/api/search`;
|
|
9347
9705
|
var WIZARD_SUBCOMMANDS = ["add", "remove"];
|
|
9348
9706
|
var subcommand = process.argv[2];
|
|
9349
9707
|
var isWizardMode = WIZARD_SUBCOMMANDS.includes(subcommand);
|
|
@@ -9353,7 +9711,8 @@ async function main(apiKey) {
|
|
|
9353
9711
|
apiKey,
|
|
9354
9712
|
tracking: { transport: "stdio", serverVersion: SERVER_VERSION }
|
|
9355
9713
|
}),
|
|
9356
|
-
SERVER_VERSION
|
|
9714
|
+
SERVER_VERSION,
|
|
9715
|
+
{ search: hostedSearch(SEARCH_URL) }
|
|
9357
9716
|
);
|
|
9358
9717
|
await server.connect(new StdioServerTransport());
|
|
9359
9718
|
}
|
|
@@ -9371,7 +9730,7 @@ if (subcommand === "--version" || subcommand === "-v") {
|
|
|
9371
9730
|
].join("\n")
|
|
9372
9731
|
);
|
|
9373
9732
|
} else if (isWizardMode) {
|
|
9374
|
-
import("./wizard-
|
|
9733
|
+
import("./wizard-KKTBTVXE.mjs").then(async ({ runWizard }) => {
|
|
9375
9734
|
process.exitCode = await runWizard(subcommand);
|
|
9376
9735
|
}).catch((error) => {
|
|
9377
9736
|
console.error(error instanceof Error ? error.message : String(error));
|