@runpod/mcp-server 4.4.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 +25 -0
- package/dist/http.cjs +326 -32
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +6 -0
- package/dist/http.d.ts +6 -0
- package/dist/http.mjs +326 -32
- package/dist/http.mjs.map +1 -1
- package/dist/stdio.cjs +254 -16
- package/dist/stdio.cjs.map +1 -1
- package/dist/stdio.mjs +254 -16
- package/dist/stdio.mjs.map +1 -1
- package/package.json +2 -2
package/dist/http.cjs
CHANGED
|
@@ -34,6 +34,80 @@ module.exports = __toCommonJS(http_exports);
|
|
|
34
34
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
35
35
|
var import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
36
36
|
|
|
37
|
+
// src/alp/sink.ts
|
|
38
|
+
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.";
|
|
39
|
+
var ALP_REFERRAL_SOURCES = [
|
|
40
|
+
"searched",
|
|
41
|
+
"user_named",
|
|
42
|
+
"recommended",
|
|
43
|
+
"other"
|
|
44
|
+
];
|
|
45
|
+
var ALP_REFERRAL_USE_CASES = [
|
|
46
|
+
"inference",
|
|
47
|
+
"fine_tuning",
|
|
48
|
+
"training",
|
|
49
|
+
"image_video_generation",
|
|
50
|
+
"dev_environment",
|
|
51
|
+
"batch_processing",
|
|
52
|
+
"other"
|
|
53
|
+
];
|
|
54
|
+
function isSinkUrl(value) {
|
|
55
|
+
try {
|
|
56
|
+
const url = new URL(value);
|
|
57
|
+
return url.protocol === "https:" && url.hostname.endsWith(".convex.site") && url.pathname === "/alp/submit";
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function sinkRouteUrl(submitUrl, path) {
|
|
63
|
+
if (!isSinkUrl(submitUrl)) return null;
|
|
64
|
+
const url = new URL(submitUrl);
|
|
65
|
+
url.pathname = path;
|
|
66
|
+
return url.toString();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/alp/answered.ts
|
|
70
|
+
var ANSWERED_TIMEOUT_MS = 2500;
|
|
71
|
+
async function hasAnswered(identity, route, opts = {}) {
|
|
72
|
+
const env = opts.env ?? process.env;
|
|
73
|
+
const submitUrl = env.ALP_SINK_URL;
|
|
74
|
+
const sinkSecret = env.ALP_SINK_SECRET;
|
|
75
|
+
if (!identity || !submitUrl || !sinkSecret) return null;
|
|
76
|
+
const url = sinkRouteUrl(submitUrl, "/alp/answered");
|
|
77
|
+
if (!url) {
|
|
78
|
+
console.warn("alp_sink_misconfigured");
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const sinkFetch = opts.sinkFetch ?? fetch;
|
|
83
|
+
const response = await sinkFetch(url, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: {
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
"X-ALP-Secret": sinkSecret
|
|
88
|
+
},
|
|
89
|
+
// The resolved account id and the route, nothing from any request body.
|
|
90
|
+
body: JSON.stringify({ identity, route }),
|
|
91
|
+
signal: AbortSignal.timeout(ANSWERED_TIMEOUT_MS)
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
console.warn("alp_answered_sink_error", { status: response.status });
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const body = await response.json().catch(() => null);
|
|
98
|
+
if (body?.ok !== true || typeof body.answered !== "boolean") {
|
|
99
|
+
console.warn("alp_answered_sink_unrecognized", {
|
|
100
|
+
status: response.status
|
|
101
|
+
});
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return body.answered;
|
|
105
|
+
} catch {
|
|
106
|
+
console.warn("alp_answered_sink_unreachable");
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
37
111
|
// src/specgen/server.ts
|
|
38
112
|
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
39
113
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
@@ -359,6 +433,7 @@ function coerceScalars(value, schema, defs, depth = 0) {
|
|
|
359
433
|
var generatedTools = [
|
|
360
434
|
{
|
|
361
435
|
name: "create-cluster",
|
|
436
|
+
title: "Create cluster",
|
|
362
437
|
operationId: "createCluster",
|
|
363
438
|
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.",
|
|
364
439
|
method: "POST",
|
|
@@ -596,6 +671,7 @@ var generatedTools = [
|
|
|
596
671
|
},
|
|
597
672
|
{
|
|
598
673
|
name: "create-delegation",
|
|
674
|
+
title: "Create ECR delegation",
|
|
599
675
|
operationId: "createDelegation",
|
|
600
676
|
description: "Register an ECR delegation",
|
|
601
677
|
method: "POST",
|
|
@@ -641,6 +717,7 @@ var generatedTools = [
|
|
|
641
717
|
},
|
|
642
718
|
{
|
|
643
719
|
name: "create-endpoint",
|
|
720
|
+
title: "Create endpoint",
|
|
644
721
|
operationId: "createEndpoint",
|
|
645
722
|
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.",
|
|
646
723
|
method: "POST",
|
|
@@ -1086,6 +1163,7 @@ var generatedTools = [
|
|
|
1086
1163
|
},
|
|
1087
1164
|
{
|
|
1088
1165
|
name: "create-global-volume",
|
|
1166
|
+
title: "Create global volume",
|
|
1089
1167
|
operationId: "createGlobalVolume",
|
|
1090
1168
|
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`.",
|
|
1091
1169
|
method: "POST",
|
|
@@ -1127,6 +1205,7 @@ var generatedTools = [
|
|
|
1127
1205
|
},
|
|
1128
1206
|
{
|
|
1129
1207
|
name: "create-network-volume",
|
|
1208
|
+
title: "Create network volume",
|
|
1130
1209
|
operationId: "createNetworkVolume",
|
|
1131
1210
|
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`.",
|
|
1132
1211
|
method: "POST",
|
|
@@ -1192,6 +1271,7 @@ var generatedTools = [
|
|
|
1192
1271
|
},
|
|
1193
1272
|
{
|
|
1194
1273
|
name: "create-pod",
|
|
1274
|
+
title: "Create Pod",
|
|
1195
1275
|
operationId: "createPod",
|
|
1196
1276
|
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.',
|
|
1197
1277
|
method: "POST",
|
|
@@ -1559,6 +1639,7 @@ var generatedTools = [
|
|
|
1559
1639
|
},
|
|
1560
1640
|
{
|
|
1561
1641
|
name: "create-registry",
|
|
1642
|
+
title: "Create registry credential",
|
|
1562
1643
|
operationId: "createRegistry",
|
|
1563
1644
|
description: "Create a container registry credential. Stores credentials for a private container registry. Credentials are write-only.",
|
|
1564
1645
|
method: "POST",
|
|
@@ -1610,6 +1691,7 @@ var generatedTools = [
|
|
|
1610
1691
|
},
|
|
1611
1692
|
{
|
|
1612
1693
|
name: "create-secret",
|
|
1694
|
+
title: "Create secret",
|
|
1613
1695
|
operationId: "createSecret",
|
|
1614
1696
|
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.",
|
|
1615
1697
|
method: "POST",
|
|
@@ -1664,6 +1746,7 @@ var generatedTools = [
|
|
|
1664
1746
|
},
|
|
1665
1747
|
{
|
|
1666
1748
|
name: "create-template",
|
|
1749
|
+
title: "Create template",
|
|
1667
1750
|
operationId: "createTemplate",
|
|
1668
1751
|
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.",
|
|
1669
1752
|
method: "POST",
|
|
@@ -1865,6 +1948,7 @@ var generatedTools = [
|
|
|
1865
1948
|
},
|
|
1866
1949
|
{
|
|
1867
1950
|
name: "delete-cluster",
|
|
1951
|
+
title: "Delete cluster",
|
|
1868
1952
|
operationId: "deleteCluster",
|
|
1869
1953
|
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.",
|
|
1870
1954
|
method: "DELETE",
|
|
@@ -1895,6 +1979,7 @@ var generatedTools = [
|
|
|
1895
1979
|
},
|
|
1896
1980
|
{
|
|
1897
1981
|
name: "delete-endpoint",
|
|
1982
|
+
title: "Delete endpoint",
|
|
1898
1983
|
operationId: "deleteEndpoint",
|
|
1899
1984
|
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.",
|
|
1900
1985
|
method: "DELETE",
|
|
@@ -1925,6 +2010,7 @@ var generatedTools = [
|
|
|
1925
2010
|
},
|
|
1926
2011
|
{
|
|
1927
2012
|
name: "delete-global-volume",
|
|
2013
|
+
title: "Delete global volume",
|
|
1928
2014
|
operationId: "deleteGlobalVolume",
|
|
1929
2015
|
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.",
|
|
1930
2016
|
method: "DELETE",
|
|
@@ -1955,6 +2041,7 @@ var generatedTools = [
|
|
|
1955
2041
|
},
|
|
1956
2042
|
{
|
|
1957
2043
|
name: "delete-network-volume",
|
|
2044
|
+
title: "Delete network volume",
|
|
1958
2045
|
operationId: "deleteNetworkVolume",
|
|
1959
2046
|
description: "Delete a network volume. Permanently deletes a network volume and releases its storage.",
|
|
1960
2047
|
method: "DELETE",
|
|
@@ -1985,6 +2072,7 @@ var generatedTools = [
|
|
|
1985
2072
|
},
|
|
1986
2073
|
{
|
|
1987
2074
|
name: "delete-pod",
|
|
2075
|
+
title: "Delete Pod",
|
|
1988
2076
|
operationId: "deletePod",
|
|
1989
2077
|
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.",
|
|
1990
2078
|
method: "DELETE",
|
|
@@ -2015,6 +2103,7 @@ var generatedTools = [
|
|
|
2015
2103
|
},
|
|
2016
2104
|
{
|
|
2017
2105
|
name: "delete-registry",
|
|
2106
|
+
title: "Delete registry credential",
|
|
2018
2107
|
operationId: "deleteRegistry",
|
|
2019
2108
|
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.",
|
|
2020
2109
|
method: "DELETE",
|
|
@@ -2044,6 +2133,7 @@ var generatedTools = [
|
|
|
2044
2133
|
},
|
|
2045
2134
|
{
|
|
2046
2135
|
name: "delete-secret",
|
|
2136
|
+
title: "Delete secret",
|
|
2047
2137
|
operationId: "deleteSecret",
|
|
2048
2138
|
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.",
|
|
2049
2139
|
method: "DELETE",
|
|
@@ -2074,6 +2164,7 @@ var generatedTools = [
|
|
|
2074
2164
|
},
|
|
2075
2165
|
{
|
|
2076
2166
|
name: "delete-template",
|
|
2167
|
+
title: "Delete template",
|
|
2077
2168
|
operationId: "deleteTemplate",
|
|
2078
2169
|
description: "Delete a template permanently. Verify with get-template first; a template referenced by a live endpoint should not be deleted.",
|
|
2079
2170
|
method: "DELETE",
|
|
@@ -2103,6 +2194,7 @@ var generatedTools = [
|
|
|
2103
2194
|
},
|
|
2104
2195
|
{
|
|
2105
2196
|
name: "get-cluster",
|
|
2197
|
+
title: "Get cluster",
|
|
2106
2198
|
operationId: "getCluster",
|
|
2107
2199
|
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.",
|
|
2108
2200
|
method: "GET",
|
|
@@ -2133,6 +2225,7 @@ var generatedTools = [
|
|
|
2133
2225
|
},
|
|
2134
2226
|
{
|
|
2135
2227
|
name: "get-cpu-type",
|
|
2228
|
+
title: "Get CPU type",
|
|
2136
2229
|
operationId: "getCpuType",
|
|
2137
2230
|
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.",
|
|
2138
2231
|
method: "GET",
|
|
@@ -2209,6 +2302,7 @@ var generatedTools = [
|
|
|
2209
2302
|
},
|
|
2210
2303
|
{
|
|
2211
2304
|
name: "get-data-center",
|
|
2305
|
+
title: "Get data center",
|
|
2212
2306
|
operationId: "getDataCenter",
|
|
2213
2307
|
description: "Get a data center. Returns a single data center. Availability is included only when requested with include=GPU_AVAILABILITY or include=CPU_AVAILABILITY.",
|
|
2214
2308
|
method: "GET",
|
|
@@ -2258,6 +2352,7 @@ var generatedTools = [
|
|
|
2258
2352
|
},
|
|
2259
2353
|
{
|
|
2260
2354
|
name: "get-endpoint",
|
|
2355
|
+
title: "Get endpoint",
|
|
2261
2356
|
operationId: "getEndpoint",
|
|
2262
2357
|
description: "Get a serverless endpoint. Returns a single serverless endpoint by ID.",
|
|
2263
2358
|
method: "GET",
|
|
@@ -2288,6 +2383,7 @@ var generatedTools = [
|
|
|
2288
2383
|
},
|
|
2289
2384
|
{
|
|
2290
2385
|
name: "get-endpoint-build",
|
|
2386
|
+
title: "Get endpoint build",
|
|
2291
2387
|
operationId: "getEndpointBuild",
|
|
2292
2388
|
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.",
|
|
2293
2389
|
method: "GET",
|
|
@@ -2326,6 +2422,7 @@ var generatedTools = [
|
|
|
2326
2422
|
},
|
|
2327
2423
|
{
|
|
2328
2424
|
name: "get-global-volume",
|
|
2425
|
+
title: "Get global volume",
|
|
2329
2426
|
operationId: "getGlobalVolume",
|
|
2330
2427
|
description: "Get a global volume. Returns a single global volume by ID.",
|
|
2331
2428
|
method: "GET",
|
|
@@ -2356,6 +2453,7 @@ var generatedTools = [
|
|
|
2356
2453
|
},
|
|
2357
2454
|
{
|
|
2358
2455
|
name: "get-gpu-type",
|
|
2456
|
+
title: "Get GPU type",
|
|
2359
2457
|
operationId: "getGpuType",
|
|
2360
2458
|
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.",
|
|
2361
2459
|
method: "GET",
|
|
@@ -2480,6 +2578,7 @@ var generatedTools = [
|
|
|
2480
2578
|
},
|
|
2481
2579
|
{
|
|
2482
2580
|
name: "get-network-volume",
|
|
2581
|
+
title: "Get network volume",
|
|
2483
2582
|
operationId: "getNetworkVolume",
|
|
2484
2583
|
description: "Get a network volume. Returns a single network volume by ID.",
|
|
2485
2584
|
method: "GET",
|
|
@@ -2510,6 +2609,7 @@ var generatedTools = [
|
|
|
2510
2609
|
},
|
|
2511
2610
|
{
|
|
2512
2611
|
name: "get-organization",
|
|
2612
|
+
title: "Get organization",
|
|
2513
2613
|
operationId: "getOrganization",
|
|
2514
2614
|
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.",
|
|
2515
2615
|
method: "GET",
|
|
@@ -2529,6 +2629,7 @@ var generatedTools = [
|
|
|
2529
2629
|
},
|
|
2530
2630
|
{
|
|
2531
2631
|
name: "get-pod",
|
|
2632
|
+
title: "Get Pod",
|
|
2532
2633
|
operationId: "getPod",
|
|
2533
2634
|
description: "Get a pod. Returns a single pod by ID.",
|
|
2534
2635
|
method: "GET",
|
|
@@ -2559,6 +2660,7 @@ var generatedTools = [
|
|
|
2559
2660
|
},
|
|
2560
2661
|
{
|
|
2561
2662
|
name: "get-registry",
|
|
2663
|
+
title: "Get registry credential",
|
|
2562
2664
|
operationId: "getRegistry",
|
|
2563
2665
|
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`.",
|
|
2564
2666
|
method: "GET",
|
|
@@ -2588,6 +2690,7 @@ var generatedTools = [
|
|
|
2588
2690
|
},
|
|
2589
2691
|
{
|
|
2590
2692
|
name: "get-secret",
|
|
2693
|
+
title: "Get secret",
|
|
2591
2694
|
operationId: "getSecret",
|
|
2592
2695
|
description: "Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.",
|
|
2593
2696
|
method: "GET",
|
|
@@ -2618,6 +2721,7 @@ var generatedTools = [
|
|
|
2618
2721
|
},
|
|
2619
2722
|
{
|
|
2620
2723
|
name: "get-ssh-keys",
|
|
2724
|
+
title: "Get SSH keys",
|
|
2621
2725
|
operationId: "getSshKeys",
|
|
2622
2726
|
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.",
|
|
2623
2727
|
method: "GET",
|
|
@@ -2637,6 +2741,7 @@ var generatedTools = [
|
|
|
2637
2741
|
},
|
|
2638
2742
|
{
|
|
2639
2743
|
name: "get-template",
|
|
2744
|
+
title: "Get template",
|
|
2640
2745
|
operationId: "getTemplate",
|
|
2641
2746
|
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.",
|
|
2642
2747
|
method: "GET",
|
|
@@ -2666,6 +2771,7 @@ var generatedTools = [
|
|
|
2666
2771
|
},
|
|
2667
2772
|
{
|
|
2668
2773
|
name: "list-billing",
|
|
2774
|
+
title: "List billing",
|
|
2669
2775
|
operationId: "listBilling",
|
|
2670
2776
|
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.",
|
|
2671
2777
|
method: "GET",
|
|
@@ -2738,6 +2844,7 @@ var generatedTools = [
|
|
|
2738
2844
|
},
|
|
2739
2845
|
{
|
|
2740
2846
|
name: "list-cluster-billing",
|
|
2847
|
+
title: "List cluster billing",
|
|
2741
2848
|
operationId: "listClusterBilling",
|
|
2742
2849
|
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.",
|
|
2743
2850
|
method: "GET",
|
|
@@ -2818,6 +2925,7 @@ var generatedTools = [
|
|
|
2818
2925
|
},
|
|
2819
2926
|
{
|
|
2820
2927
|
name: "list-cluster-pods",
|
|
2928
|
+
title: "List cluster Pods",
|
|
2821
2929
|
operationId: "listClusterPods",
|
|
2822
2930
|
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.",
|
|
2823
2931
|
method: "GET",
|
|
@@ -2848,6 +2956,7 @@ var generatedTools = [
|
|
|
2848
2956
|
},
|
|
2849
2957
|
{
|
|
2850
2958
|
name: "list-clusters",
|
|
2959
|
+
title: "List clusters",
|
|
2851
2960
|
operationId: "listClusters",
|
|
2852
2961
|
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.",
|
|
2853
2962
|
method: "GET",
|
|
@@ -2888,6 +2997,7 @@ var generatedTools = [
|
|
|
2888
2997
|
},
|
|
2889
2998
|
{
|
|
2890
2999
|
name: "list-cpu-types",
|
|
3000
|
+
title: "List CPU types",
|
|
2891
3001
|
operationId: "listCpuTypes",
|
|
2892
3002
|
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.",
|
|
2893
3003
|
method: "GET",
|
|
@@ -2956,6 +3066,7 @@ var generatedTools = [
|
|
|
2956
3066
|
},
|
|
2957
3067
|
{
|
|
2958
3068
|
name: "list-data-centers",
|
|
3069
|
+
title: "List data centers",
|
|
2959
3070
|
operationId: "listDataCenters",
|
|
2960
3071
|
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.",
|
|
2961
3072
|
method: "GET",
|
|
@@ -3083,6 +3194,7 @@ var generatedTools = [
|
|
|
3083
3194
|
},
|
|
3084
3195
|
{
|
|
3085
3196
|
name: "list-delegations",
|
|
3197
|
+
title: "List ECR delegations",
|
|
3086
3198
|
operationId: "listDelegations",
|
|
3087
3199
|
description: "List all ECR delegations",
|
|
3088
3200
|
method: "GET",
|
|
@@ -3102,6 +3214,7 @@ var generatedTools = [
|
|
|
3102
3214
|
},
|
|
3103
3215
|
{
|
|
3104
3216
|
name: "list-endpoint-billing",
|
|
3217
|
+
title: "List endpoint billing",
|
|
3105
3218
|
operationId: "listEndpointBilling",
|
|
3106
3219
|
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.",
|
|
3107
3220
|
method: "GET",
|
|
@@ -3174,6 +3287,7 @@ var generatedTools = [
|
|
|
3174
3287
|
},
|
|
3175
3288
|
{
|
|
3176
3289
|
name: "list-endpoint-builds",
|
|
3290
|
+
title: "List endpoint builds",
|
|
3177
3291
|
operationId: "listEndpointBuilds",
|
|
3178
3292
|
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`.",
|
|
3179
3293
|
method: "GET",
|
|
@@ -3223,6 +3337,7 @@ var generatedTools = [
|
|
|
3223
3337
|
},
|
|
3224
3338
|
{
|
|
3225
3339
|
name: "list-endpoint-releases",
|
|
3340
|
+
title: "List endpoint releases",
|
|
3226
3341
|
operationId: "listEndpointReleases",
|
|
3227
3342
|
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.",
|
|
3228
3343
|
method: "GET",
|
|
@@ -3272,6 +3387,7 @@ var generatedTools = [
|
|
|
3272
3387
|
},
|
|
3273
3388
|
{
|
|
3274
3389
|
name: "list-endpoint-workers",
|
|
3390
|
+
title: "List endpoint workers",
|
|
3275
3391
|
operationId: "listEndpointWorkers",
|
|
3276
3392
|
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.",
|
|
3277
3393
|
method: "GET",
|
|
@@ -3302,6 +3418,7 @@ var generatedTools = [
|
|
|
3302
3418
|
},
|
|
3303
3419
|
{
|
|
3304
3420
|
name: "list-global-volumes",
|
|
3421
|
+
title: "List global volumes",
|
|
3305
3422
|
operationId: "listGlobalVolumes",
|
|
3306
3423
|
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.",
|
|
3307
3424
|
method: "GET",
|
|
@@ -3342,6 +3459,7 @@ var generatedTools = [
|
|
|
3342
3459
|
},
|
|
3343
3460
|
{
|
|
3344
3461
|
name: "list-gpu-types",
|
|
3462
|
+
title: "List GPU types",
|
|
3345
3463
|
operationId: "listGpuTypes",
|
|
3346
3464
|
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.',
|
|
3347
3465
|
method: "GET",
|
|
@@ -3458,6 +3576,7 @@ var generatedTools = [
|
|
|
3458
3576
|
},
|
|
3459
3577
|
{
|
|
3460
3578
|
name: "list-network-volume-billing",
|
|
3579
|
+
title: "List network volume billing",
|
|
3461
3580
|
operationId: "listNetworkVolumeBilling",
|
|
3462
3581
|
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.",
|
|
3463
3582
|
method: "GET",
|
|
@@ -3538,6 +3657,7 @@ var generatedTools = [
|
|
|
3538
3657
|
},
|
|
3539
3658
|
{
|
|
3540
3659
|
name: "list-network-volumes",
|
|
3660
|
+
title: "List network volumes",
|
|
3541
3661
|
operationId: "listNetworkVolumes",
|
|
3542
3662
|
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.",
|
|
3543
3663
|
method: "GET",
|
|
@@ -3578,6 +3698,7 @@ var generatedTools = [
|
|
|
3578
3698
|
},
|
|
3579
3699
|
{
|
|
3580
3700
|
name: "list-pod-billing",
|
|
3701
|
+
title: "List Pod billing",
|
|
3581
3702
|
operationId: "listPodBilling",
|
|
3582
3703
|
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.",
|
|
3583
3704
|
method: "GET",
|
|
@@ -3658,6 +3779,7 @@ var generatedTools = [
|
|
|
3658
3779
|
},
|
|
3659
3780
|
{
|
|
3660
3781
|
name: "list-pods",
|
|
3782
|
+
title: "List Pods",
|
|
3661
3783
|
operationId: "listPods",
|
|
3662
3784
|
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.",
|
|
3663
3785
|
method: "GET",
|
|
@@ -3707,6 +3829,7 @@ var generatedTools = [
|
|
|
3707
3829
|
},
|
|
3708
3830
|
{
|
|
3709
3831
|
name: "list-public-templates",
|
|
3832
|
+
title: "List public templates",
|
|
3710
3833
|
operationId: "listPublicTemplates",
|
|
3711
3834
|
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`).",
|
|
3712
3835
|
method: "GET",
|
|
@@ -3738,6 +3861,7 @@ var generatedTools = [
|
|
|
3738
3861
|
},
|
|
3739
3862
|
{
|
|
3740
3863
|
name: "list-registries",
|
|
3864
|
+
title: "List registry credentials",
|
|
3741
3865
|
operationId: "listRegistries",
|
|
3742
3866
|
description: "List container registries. Returns all container registry credentials owned by the authenticated user.",
|
|
3743
3867
|
method: "GET",
|
|
@@ -3757,6 +3881,7 @@ var generatedTools = [
|
|
|
3757
3881
|
},
|
|
3758
3882
|
{
|
|
3759
3883
|
name: "list-secrets",
|
|
3884
|
+
title: "List secrets",
|
|
3760
3885
|
operationId: "listSecrets",
|
|
3761
3886
|
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.",
|
|
3762
3887
|
method: "GET",
|
|
@@ -3786,6 +3911,7 @@ var generatedTools = [
|
|
|
3786
3911
|
},
|
|
3787
3912
|
{
|
|
3788
3913
|
name: "list-serverless-billing",
|
|
3914
|
+
title: "List Serverless billing",
|
|
3789
3915
|
operationId: "listServerlessBilling",
|
|
3790
3916
|
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.",
|
|
3791
3917
|
method: "GET",
|
|
@@ -3866,6 +3992,7 @@ var generatedTools = [
|
|
|
3866
3992
|
},
|
|
3867
3993
|
{
|
|
3868
3994
|
name: "pod-action",
|
|
3995
|
+
title: "Start, stop, restart, or terminate a Pod",
|
|
3869
3996
|
operationId: "podAction",
|
|
3870
3997
|
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`.",
|
|
3871
3998
|
method: "POST",
|
|
@@ -3915,6 +4042,7 @@ var generatedTools = [
|
|
|
3915
4042
|
},
|
|
3916
4043
|
{
|
|
3917
4044
|
name: "revoke-delegation",
|
|
4045
|
+
title: "Revoke ECR delegation",
|
|
3918
4046
|
operationId: "revokeDelegation",
|
|
3919
4047
|
description: "Revoke an ECR delegation",
|
|
3920
4048
|
method: "DELETE",
|
|
@@ -3944,6 +4072,7 @@ var generatedTools = [
|
|
|
3944
4072
|
},
|
|
3945
4073
|
{
|
|
3946
4074
|
name: "update-cluster",
|
|
4075
|
+
title: "Update cluster",
|
|
3947
4076
|
operationId: "updateCluster",
|
|
3948
4077
|
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.",
|
|
3949
4078
|
method: "PATCH",
|
|
@@ -3992,6 +4121,7 @@ var generatedTools = [
|
|
|
3992
4121
|
},
|
|
3993
4122
|
{
|
|
3994
4123
|
name: "update-endpoint",
|
|
4124
|
+
title: "Update endpoint",
|
|
3995
4125
|
operationId: "updateEndpoint",
|
|
3996
4126
|
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.",
|
|
3997
4127
|
method: "PATCH",
|
|
@@ -4382,6 +4512,7 @@ var generatedTools = [
|
|
|
4382
4512
|
},
|
|
4383
4513
|
{
|
|
4384
4514
|
name: "update-global-volume",
|
|
4515
|
+
title: "Update global volume",
|
|
4385
4516
|
operationId: "updateGlobalVolume",
|
|
4386
4517
|
description: "Update a global volume. Updates mutable fields on a global volume. Only provided fields are changed.",
|
|
4387
4518
|
method: "PATCH",
|
|
@@ -4433,6 +4564,7 @@ var generatedTools = [
|
|
|
4433
4564
|
},
|
|
4434
4565
|
{
|
|
4435
4566
|
name: "update-network-volume",
|
|
4567
|
+
title: "Update network volume",
|
|
4436
4568
|
operationId: "updateNetworkVolume",
|
|
4437
4569
|
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.",
|
|
4438
4570
|
method: "PATCH",
|
|
@@ -4489,6 +4621,7 @@ var generatedTools = [
|
|
|
4489
4621
|
},
|
|
4490
4622
|
{
|
|
4491
4623
|
name: "update-pod",
|
|
4624
|
+
title: "Update Pod",
|
|
4492
4625
|
operationId: "updatePod",
|
|
4493
4626
|
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.",
|
|
4494
4627
|
method: "PATCH",
|
|
@@ -4730,6 +4863,7 @@ var generatedTools = [
|
|
|
4730
4863
|
},
|
|
4731
4864
|
{
|
|
4732
4865
|
name: "update-secret",
|
|
4866
|
+
title: "Update secret",
|
|
4733
4867
|
operationId: "updateSecret",
|
|
4734
4868
|
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.",
|
|
4735
4869
|
method: "PATCH",
|
|
@@ -4785,6 +4919,7 @@ var generatedTools = [
|
|
|
4785
4919
|
},
|
|
4786
4920
|
{
|
|
4787
4921
|
name: "update-ssh-keys",
|
|
4922
|
+
title: "Update SSH keys",
|
|
4788
4923
|
operationId: "updateSshKeys",
|
|
4789
4924
|
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.",
|
|
4790
4925
|
method: "PUT",
|
|
@@ -4831,6 +4966,7 @@ var generatedTools = [
|
|
|
4831
4966
|
},
|
|
4832
4967
|
{
|
|
4833
4968
|
name: "update-template",
|
|
4969
|
+
title: "Update template",
|
|
4834
4970
|
operationId: "updateTemplate",
|
|
4835
4971
|
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.",
|
|
4836
4972
|
method: "PATCH",
|
|
@@ -5129,6 +5265,43 @@ function isTimeout(error) {
|
|
|
5129
5265
|
const cause = error.cause;
|
|
5130
5266
|
return cause instanceof Error && (cause.name === "TimeoutError" || cause.name === "AbortError");
|
|
5131
5267
|
}
|
|
5268
|
+
var UNREACHED_CODES = /* @__PURE__ */ new Set([
|
|
5269
|
+
"ENOTFOUND",
|
|
5270
|
+
"EAI_AGAIN",
|
|
5271
|
+
"ECONNREFUSED",
|
|
5272
|
+
"EHOSTUNREACH",
|
|
5273
|
+
"ENETUNREACH",
|
|
5274
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
5275
|
+
]);
|
|
5276
|
+
var TLS_CODE = /^(?:CERT_|ERR_TLS_|UNABLE_TO_|DEPTH_ZERO_|SELF_SIGNED_)/;
|
|
5277
|
+
function causeCode(cause) {
|
|
5278
|
+
const code = cause?.code;
|
|
5279
|
+
if (typeof code === "string") return code;
|
|
5280
|
+
const inner = cause instanceof AggregateError ? cause.errors[0] : void 0;
|
|
5281
|
+
const innerCode = inner?.code;
|
|
5282
|
+
return typeof innerCode === "string" ? innerCode : void 0;
|
|
5283
|
+
}
|
|
5284
|
+
function networkFailureResult(error) {
|
|
5285
|
+
if (!(error instanceof TypeError)) return void 0;
|
|
5286
|
+
const afterHeaders = error.message === "terminated";
|
|
5287
|
+
if (!afterHeaders && error.message !== "fetch failed") return void 0;
|
|
5288
|
+
const code = causeCode(error.cause);
|
|
5289
|
+
if (!code) return void 0;
|
|
5290
|
+
const unreached = !afterHeaders && (UNREACHED_CODES.has(code) || TLS_CODE.test(code));
|
|
5291
|
+
return {
|
|
5292
|
+
ok: false,
|
|
5293
|
+
status: unreached ? 503 : 502,
|
|
5294
|
+
payload: unreached ? {
|
|
5295
|
+
error: "Could not reach the Runpod API.",
|
|
5296
|
+
cause: code,
|
|
5297
|
+
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."
|
|
5298
|
+
} : {
|
|
5299
|
+
error: "The connection to the Runpod API dropped before the full response arrived.",
|
|
5300
|
+
cause: code,
|
|
5301
|
+
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."
|
|
5302
|
+
}
|
|
5303
|
+
};
|
|
5304
|
+
}
|
|
5132
5305
|
async function runTool(body) {
|
|
5133
5306
|
try {
|
|
5134
5307
|
return await body();
|
|
@@ -5150,6 +5323,8 @@ async function runTool(body) {
|
|
|
5150
5323
|
}
|
|
5151
5324
|
};
|
|
5152
5325
|
}
|
|
5326
|
+
const network = networkFailureResult(error);
|
|
5327
|
+
if (network) return network;
|
|
5153
5328
|
throw error;
|
|
5154
5329
|
}
|
|
5155
5330
|
}
|
|
@@ -5220,6 +5395,7 @@ function rankByStock(rows, stats, includeUnavailable) {
|
|
|
5220
5395
|
}
|
|
5221
5396
|
var getCapacity = {
|
|
5222
5397
|
name: "get-capacity",
|
|
5398
|
+
title: "Get GPU capacity by CUDA version",
|
|
5223
5399
|
annotations: readOnly,
|
|
5224
5400
|
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.",
|
|
5225
5401
|
inputSchema: {
|
|
@@ -5421,6 +5597,7 @@ function formatGpuIds(gpu) {
|
|
|
5421
5597
|
}
|
|
5422
5598
|
var setEndpointGpus = {
|
|
5423
5599
|
name: "set-endpoint-gpus",
|
|
5600
|
+
title: "Set endpoint GPUs",
|
|
5424
5601
|
annotations: idempotentWrite,
|
|
5425
5602
|
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.",
|
|
5426
5603
|
inputSchema: {
|
|
@@ -5615,6 +5792,7 @@ function randomSuffix() {
|
|
|
5615
5792
|
}
|
|
5616
5793
|
var listHubRepos = {
|
|
5617
5794
|
name: "list-hub-repos",
|
|
5795
|
+
title: "List Hub repos",
|
|
5618
5796
|
annotations: readOnly,
|
|
5619
5797
|
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.",
|
|
5620
5798
|
inputSchema: {
|
|
@@ -5717,6 +5895,7 @@ var listHubRepos = {
|
|
|
5717
5895
|
};
|
|
5718
5896
|
var deployHubRepo = {
|
|
5719
5897
|
name: "deploy-hub-repo",
|
|
5898
|
+
title: "Deploy Hub repo",
|
|
5720
5899
|
// Two sequential upstream calls: together they can outlast a client's request timeout.
|
|
5721
5900
|
holdsResponse: true,
|
|
5722
5901
|
annotations: write,
|
|
@@ -6177,6 +6356,7 @@ function validateWait(wait) {
|
|
|
6177
6356
|
}
|
|
6178
6357
|
var runEndpoint = {
|
|
6179
6358
|
name: "run-endpoint",
|
|
6359
|
+
title: "Submit Serverless job",
|
|
6180
6360
|
annotations: write,
|
|
6181
6361
|
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.",
|
|
6182
6362
|
inputSchema: {
|
|
@@ -6207,6 +6387,7 @@ var runEndpoint = {
|
|
|
6207
6387
|
};
|
|
6208
6388
|
var runsyncEndpoint = {
|
|
6209
6389
|
name: "runsync-endpoint",
|
|
6390
|
+
title: "Run Serverless job and wait",
|
|
6210
6391
|
holdsResponse: true,
|
|
6211
6392
|
annotations: write,
|
|
6212
6393
|
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)."),
|
|
@@ -6252,6 +6433,7 @@ var runsyncEndpoint = {
|
|
|
6252
6433
|
};
|
|
6253
6434
|
var getJobStatus = {
|
|
6254
6435
|
name: "get-job-status",
|
|
6436
|
+
title: "Get job status",
|
|
6255
6437
|
holdsResponse: true,
|
|
6256
6438
|
annotations: readOnly,
|
|
6257
6439
|
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.",
|
|
@@ -6301,6 +6483,7 @@ var getJobStatus = {
|
|
|
6301
6483
|
};
|
|
6302
6484
|
var streamJob = {
|
|
6303
6485
|
name: "stream-job",
|
|
6486
|
+
title: "Stream job output",
|
|
6304
6487
|
holdsResponse: true,
|
|
6305
6488
|
annotations: readOnly,
|
|
6306
6489
|
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.`,
|
|
@@ -6333,6 +6516,7 @@ var streamJob = {
|
|
|
6333
6516
|
};
|
|
6334
6517
|
var cancelJob = {
|
|
6335
6518
|
name: "cancel-job",
|
|
6519
|
+
title: "Cancel job",
|
|
6336
6520
|
annotations: destructive,
|
|
6337
6521
|
description: "Cancel a Serverless job that is queued or in progress.",
|
|
6338
6522
|
inputSchema: {
|
|
@@ -6358,6 +6542,7 @@ var cancelJob = {
|
|
|
6358
6542
|
};
|
|
6359
6543
|
var retryJob = {
|
|
6360
6544
|
name: "retry-job",
|
|
6545
|
+
title: "Retry job",
|
|
6361
6546
|
annotations: write,
|
|
6362
6547
|
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.",
|
|
6363
6548
|
inputSchema: {
|
|
@@ -6383,6 +6568,7 @@ var retryJob = {
|
|
|
6383
6568
|
};
|
|
6384
6569
|
var endpointHealth = {
|
|
6385
6570
|
name: "endpoint-health",
|
|
6571
|
+
title: "Get endpoint health",
|
|
6386
6572
|
annotations: readOnly,
|
|
6387
6573
|
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.",
|
|
6388
6574
|
inputSchema: {
|
|
@@ -6403,6 +6589,7 @@ var endpointHealth = {
|
|
|
6403
6589
|
};
|
|
6404
6590
|
var purgeEndpointQueue = {
|
|
6405
6591
|
name: "purge-endpoint-queue",
|
|
6592
|
+
title: "Purge endpoint queue",
|
|
6406
6593
|
annotations: destructive,
|
|
6407
6594
|
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.",
|
|
6408
6595
|
inputSchema: {
|
|
@@ -6439,6 +6626,7 @@ var jobTools = [
|
|
|
6439
6626
|
// src/specgen/tools/list-endpoints.ts
|
|
6440
6627
|
var listEndpoints = {
|
|
6441
6628
|
name: "list-endpoints",
|
|
6629
|
+
title: "List endpoints",
|
|
6442
6630
|
annotations: readOnly,
|
|
6443
6631
|
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.",
|
|
6444
6632
|
inputSchema: {
|
|
@@ -6484,6 +6672,7 @@ var listEndpoints = {
|
|
|
6484
6672
|
// src/specgen/tools/list-templates.ts
|
|
6485
6673
|
var listTemplates = {
|
|
6486
6674
|
name: "list-templates",
|
|
6675
|
+
title: "List templates",
|
|
6487
6676
|
annotations: readOnly,
|
|
6488
6677
|
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.",
|
|
6489
6678
|
inputSchema: {
|
|
@@ -7942,6 +8131,7 @@ function logParams(args) {
|
|
|
7942
8131
|
}
|
|
7943
8132
|
var streamPodLogs = {
|
|
7944
8133
|
name: "stream-pod-logs",
|
|
8134
|
+
title: "Stream Pod logs",
|
|
7945
8135
|
holdsResponse: true,
|
|
7946
8136
|
annotations: readOnly,
|
|
7947
8137
|
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.",
|
|
@@ -7965,6 +8155,7 @@ var streamPodLogs = {
|
|
|
7965
8155
|
};
|
|
7966
8156
|
var streamWorkerLogs = {
|
|
7967
8157
|
name: "stream-worker-logs",
|
|
8158
|
+
title: "Stream worker logs",
|
|
7968
8159
|
holdsResponse: true,
|
|
7969
8160
|
annotations: readOnly,
|
|
7970
8161
|
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.",
|
|
@@ -8007,6 +8198,7 @@ function parseMetadata(metadata) {
|
|
|
8007
8198
|
}
|
|
8008
8199
|
var listPublicEndpoints = {
|
|
8009
8200
|
name: "list-public-endpoints",
|
|
8201
|
+
title: "List public endpoints",
|
|
8010
8202
|
annotations: readOnly,
|
|
8011
8203
|
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.",
|
|
8012
8204
|
inputSchema: {
|
|
@@ -8227,6 +8419,7 @@ var source = {
|
|
|
8227
8419
|
};
|
|
8228
8420
|
var listGuides = {
|
|
8229
8421
|
name: "list-guides",
|
|
8422
|
+
title: "List guides",
|
|
8230
8423
|
annotations: bundledRead,
|
|
8231
8424
|
recordedArguments: ["kind", "query", "concept"],
|
|
8232
8425
|
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.",
|
|
@@ -8263,6 +8456,7 @@ var listGuides = {
|
|
|
8263
8456
|
};
|
|
8264
8457
|
var readGuide = {
|
|
8265
8458
|
name: "read-guide",
|
|
8459
|
+
title: "Read guide",
|
|
8266
8460
|
annotations: bundledRead,
|
|
8267
8461
|
recordedArguments: ["id"],
|
|
8268
8462
|
recordedGuideKind: (args) => knowledge.guides.find((guide) => guide.id === String(args.id).trim())?.kind,
|
|
@@ -8302,6 +8496,7 @@ var readGuide = {
|
|
|
8302
8496
|
};
|
|
8303
8497
|
var lookupConcept = {
|
|
8304
8498
|
name: "lookup-concept",
|
|
8499
|
+
title: "Look up a concept",
|
|
8305
8500
|
annotations: bundledRead,
|
|
8306
8501
|
recordedArguments: ["concept"],
|
|
8307
8502
|
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".',
|
|
@@ -8355,6 +8550,7 @@ var lookupConcept = {
|
|
|
8355
8550
|
};
|
|
8356
8551
|
var searchConcepts = {
|
|
8357
8552
|
name: "search-concepts",
|
|
8553
|
+
title: "Search concepts",
|
|
8358
8554
|
annotations: bundledRead,
|
|
8359
8555
|
recordedArguments: ["query", "limit"],
|
|
8360
8556
|
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.',
|
|
@@ -8446,12 +8642,13 @@ function listedAnnotations(annotations) {
|
|
|
8446
8642
|
return idempotentHint ? annotations : listed;
|
|
8447
8643
|
}
|
|
8448
8644
|
function listTool(tool) {
|
|
8449
|
-
const { name, description, inputSchema } = tool;
|
|
8645
|
+
const { name, title, description, inputSchema } = tool;
|
|
8450
8646
|
const annotations = listedAnnotations(tool.annotations);
|
|
8451
8647
|
if (!tool.schemaOnDemand)
|
|
8452
|
-
return { name, description, inputSchema, annotations };
|
|
8648
|
+
return { name, title, description, inputSchema, annotations };
|
|
8453
8649
|
return {
|
|
8454
8650
|
name,
|
|
8651
|
+
title,
|
|
8455
8652
|
description: description + ON_DEMAND_POINTER,
|
|
8456
8653
|
inputSchema: callShape(inputSchema),
|
|
8457
8654
|
annotations
|
|
@@ -8503,6 +8700,7 @@ function schemaType(node, resolve) {
|
|
|
8503
8700
|
function createDescribeTool(served) {
|
|
8504
8701
|
return {
|
|
8505
8702
|
name: DESCRIBE_TOOL_NAME,
|
|
8703
|
+
title: "Describe tool",
|
|
8506
8704
|
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.",
|
|
8507
8705
|
inputSchema: {
|
|
8508
8706
|
type: "object",
|
|
@@ -8557,7 +8755,7 @@ function words2(name) {
|
|
|
8557
8755
|
|
|
8558
8756
|
// src/server.ts
|
|
8559
8757
|
var SERVER_NAME = "Runpod API Server";
|
|
8560
|
-
var SERVER_VERSION = true ? "4.
|
|
8758
|
+
var SERVER_VERSION = true ? "4.5.0" : "dev";
|
|
8561
8759
|
|
|
8562
8760
|
// src/specgen/analytics.ts
|
|
8563
8761
|
var import_node_crypto = require("crypto");
|
|
@@ -8657,16 +8855,6 @@ function captureResourceCall(apiKey, event) {
|
|
|
8657
8855
|
);
|
|
8658
8856
|
}
|
|
8659
8857
|
|
|
8660
|
-
// src/alp/ingest.ts
|
|
8661
|
-
function isSinkUrl(value) {
|
|
8662
|
-
try {
|
|
8663
|
-
const url = new URL(value);
|
|
8664
|
-
return url.protocol === "https:" && url.hostname.endsWith(".convex.site") && url.pathname === "/alp/submit";
|
|
8665
|
-
} catch {
|
|
8666
|
-
return false;
|
|
8667
|
-
}
|
|
8668
|
-
}
|
|
8669
|
-
|
|
8670
8858
|
// src/alp/read.ts
|
|
8671
8859
|
var DEFAULT_JOURNAL_LIMIT = 20;
|
|
8672
8860
|
var MAX_JOURNAL_LIMIT = 50;
|
|
@@ -8695,12 +8883,21 @@ async function submit(ctx, ingestUrl, route, args, extra) {
|
|
|
8695
8883
|
tool: args.tool,
|
|
8696
8884
|
workaround: args.workaround,
|
|
8697
8885
|
trigger: args.trigger,
|
|
8886
|
+
source: args.source,
|
|
8887
|
+
noContext: args.noContext,
|
|
8888
|
+
useCase: args.useCase,
|
|
8698
8889
|
...extra
|
|
8699
8890
|
}),
|
|
8700
8891
|
signal: AbortSignal.timeout(1e4)
|
|
8701
8892
|
});
|
|
8702
8893
|
const body = await response.json().catch(() => ({}));
|
|
8703
|
-
return {
|
|
8894
|
+
return {
|
|
8895
|
+
recorded: response.ok && body.recorded === true,
|
|
8896
|
+
// The ingest's own named outcome (already_submitted on a once-per-account
|
|
8897
|
+
// route), carried through so the tool can say it. A string from a 200
|
|
8898
|
+
// only — never an upstream error body.
|
|
8899
|
+
...response.ok && typeof body.reason === "string" ? { reason: body.reason } : {}
|
|
8900
|
+
};
|
|
8704
8901
|
} catch {
|
|
8705
8902
|
return { recorded: false };
|
|
8706
8903
|
}
|
|
@@ -8731,6 +8928,10 @@ async function readJournal(ctx, readUrl, limit) {
|
|
|
8731
8928
|
}
|
|
8732
8929
|
}
|
|
8733
8930
|
var SEVERITY = ["blocked", "degraded", "cosmetic"];
|
|
8931
|
+
var MODEL_TYPE_FIELD = {
|
|
8932
|
+
type: "string",
|
|
8933
|
+
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.'
|
|
8934
|
+
};
|
|
8734
8935
|
var TOOL_FIELD = {
|
|
8735
8936
|
type: "string",
|
|
8736
8937
|
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."
|
|
@@ -8747,10 +8948,7 @@ var alpInputSchema = (contentDescription, extra = {}) => ({
|
|
|
8747
8948
|
description: "One short sentence: what you were trying to accomplish when this came up."
|
|
8748
8949
|
},
|
|
8749
8950
|
...extra,
|
|
8750
|
-
modelType:
|
|
8751
|
-
type: "string",
|
|
8752
|
-
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.'
|
|
8753
|
-
}
|
|
8951
|
+
modelType: MODEL_TYPE_FIELD
|
|
8754
8952
|
},
|
|
8755
8953
|
required: ["content"]
|
|
8756
8954
|
});
|
|
@@ -8765,6 +8963,7 @@ function createAlpTools(opts) {
|
|
|
8765
8963
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
8766
8964
|
lenientArguments: true,
|
|
8767
8965
|
name: "report_feedback",
|
|
8966
|
+
title: "Report feedback",
|
|
8768
8967
|
annotations: write,
|
|
8769
8968
|
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.",
|
|
8770
8969
|
inputSchema: alpInputSchema(
|
|
@@ -8801,6 +9000,7 @@ function createAlpTools(opts) {
|
|
|
8801
9000
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
8802
9001
|
lenientArguments: true,
|
|
8803
9002
|
name: "save_to_journal",
|
|
9003
|
+
title: "Save to journal",
|
|
8804
9004
|
annotations: write,
|
|
8805
9005
|
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.",
|
|
8806
9006
|
inputSchema: alpInputSchema(
|
|
@@ -8832,6 +9032,7 @@ function createAlpTools(opts) {
|
|
|
8832
9032
|
// is ignored, never a 400 that derails the task the agent is actually on.
|
|
8833
9033
|
lenientArguments: true,
|
|
8834
9034
|
name: "ask_question",
|
|
9035
|
+
title: "Ask a question",
|
|
8835
9036
|
annotations: write,
|
|
8836
9037
|
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.",
|
|
8837
9038
|
inputSchema: alpInputSchema(
|
|
@@ -8857,6 +9058,7 @@ function createAlpTools(opts) {
|
|
|
8857
9058
|
const readJournalTool = {
|
|
8858
9059
|
lenientArguments: true,
|
|
8859
9060
|
name: "read_journal",
|
|
9061
|
+
title: "Read journal",
|
|
8860
9062
|
annotations: readOnly,
|
|
8861
9063
|
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.",
|
|
8862
9064
|
inputSchema: {
|
|
@@ -8884,7 +9086,61 @@ function createAlpTools(opts) {
|
|
|
8884
9086
|
});
|
|
8885
9087
|
}
|
|
8886
9088
|
};
|
|
8887
|
-
|
|
9089
|
+
const reportHowUserFoundRunpod = {
|
|
9090
|
+
lenientArguments: true,
|
|
9091
|
+
name: "report_how_user_found_runpod",
|
|
9092
|
+
title: "Report how the user found Runpod",
|
|
9093
|
+
annotations: idempotentWrite,
|
|
9094
|
+
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.",
|
|
9095
|
+
inputSchema: {
|
|
9096
|
+
type: "object",
|
|
9097
|
+
properties: {
|
|
9098
|
+
content: {
|
|
9099
|
+
type: "string",
|
|
9100
|
+
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.'
|
|
9101
|
+
},
|
|
9102
|
+
source: {
|
|
9103
|
+
type: "string",
|
|
9104
|
+
enum: [...ALP_REFERRAL_SOURCES],
|
|
9105
|
+
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."
|
|
9106
|
+
},
|
|
9107
|
+
useCase: {
|
|
9108
|
+
type: "string",
|
|
9109
|
+
enum: [...ALP_REFERRAL_USE_CASES],
|
|
9110
|
+
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."
|
|
9111
|
+
},
|
|
9112
|
+
noContext: {
|
|
9113
|
+
type: "boolean",
|
|
9114
|
+
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."
|
|
9115
|
+
},
|
|
9116
|
+
modelType: MODEL_TYPE_FIELD
|
|
9117
|
+
},
|
|
9118
|
+
required: []
|
|
9119
|
+
},
|
|
9120
|
+
handler: async (ctx, args) => {
|
|
9121
|
+
const { recorded, reason } = await submit(
|
|
9122
|
+
ctx,
|
|
9123
|
+
opts.ingestUrl,
|
|
9124
|
+
"referral",
|
|
9125
|
+
args,
|
|
9126
|
+
extra()
|
|
9127
|
+
);
|
|
9128
|
+
if (reason === "already_submitted") {
|
|
9129
|
+
return ok({ recorded: false, reason, note: ALREADY_SUBMITTED_NOTE });
|
|
9130
|
+
}
|
|
9131
|
+
return ok({
|
|
9132
|
+
recorded,
|
|
9133
|
+
note: recorded ? "Recorded, thank you. Nothing comes back \u2014 continue your task, and do not call this again on this account." : NOT_RECORDED
|
|
9134
|
+
});
|
|
9135
|
+
}
|
|
9136
|
+
};
|
|
9137
|
+
return [
|
|
9138
|
+
reportFeedback,
|
|
9139
|
+
saveToJournal,
|
|
9140
|
+
askQuestion,
|
|
9141
|
+
readJournalTool,
|
|
9142
|
+
reportHowUserFoundRunpod
|
|
9143
|
+
];
|
|
8888
9144
|
}
|
|
8889
9145
|
|
|
8890
9146
|
// src/search/knowledge.ts
|
|
@@ -9018,6 +9274,7 @@ function errorField(text) {
|
|
|
9018
9274
|
function createSearchDocsTool(search) {
|
|
9019
9275
|
return {
|
|
9020
9276
|
name: "search-docs",
|
|
9277
|
+
title: "Search docs",
|
|
9021
9278
|
annotations: readOnly,
|
|
9022
9279
|
recordedArguments: ["limit"],
|
|
9023
9280
|
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.',
|
|
@@ -9104,7 +9361,10 @@ THE OFFICIAL RUNPOD PLUGIN. Runpod ships an agent plugin that also covers the la
|
|
|
9104
9361
|
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.`;
|
|
9105
9362
|
var ALP_INSTRUCTIONS = `
|
|
9106
9363
|
|
|
9107
|
-
CONTRIBUTING BACK IS OPTIONAL.
|
|
9364
|
+
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.`;
|
|
9365
|
+
var REFERRAL_INSTRUCTIONS = `
|
|
9366
|
+
|
|
9367
|
+
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.`;
|
|
9108
9368
|
function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
9109
9369
|
const rateLimiter = opts.rateLimiter ?? noopRateLimiter;
|
|
9110
9370
|
const caller = callerId(ctx.apiKey);
|
|
@@ -9121,7 +9381,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
9121
9381
|
{ name: SERVER_NAME, version: `${version} [specgen]` },
|
|
9122
9382
|
{
|
|
9123
9383
|
capabilities: { tools: {}, resources: {} },
|
|
9124
|
-
instructions: opts.alp ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS : SERVER_INSTRUCTIONS
|
|
9384
|
+
instructions: opts.alp ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS + (opts.promptReferral === false ? "" : REFERRAL_INSTRUCTIONS) : SERVER_INSTRUCTIONS
|
|
9125
9385
|
}
|
|
9126
9386
|
);
|
|
9127
9387
|
server.oninitialized = () => {
|
|
@@ -9325,6 +9585,25 @@ function buildTrackingHeaders(input) {
|
|
|
9325
9585
|
|
|
9326
9586
|
// src/specgen/clients/graphql.ts
|
|
9327
9587
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
9588
|
+
function graphqlErrorStatus(code) {
|
|
9589
|
+
switch (code) {
|
|
9590
|
+
case "UNAUTHENTICATED":
|
|
9591
|
+
return 401;
|
|
9592
|
+
case "UNAUTHORIZED":
|
|
9593
|
+
case "FORBIDDEN":
|
|
9594
|
+
return 403;
|
|
9595
|
+
// Runpod's own code for a rejected request: an unknown GPU pool, a missing
|
|
9596
|
+
// template, no balance. The caller has to change the input, so it is a 400
|
|
9597
|
+
// and gets the 400 detail hints, not a retry-the-same-call 502.
|
|
9598
|
+
case "RUNPOD":
|
|
9599
|
+
case "BAD_USER_INPUT":
|
|
9600
|
+
case "GRAPHQL_VALIDATION_FAILED":
|
|
9601
|
+
case "GRAPHQL_PARSE_FAILED":
|
|
9602
|
+
return 400;
|
|
9603
|
+
default:
|
|
9604
|
+
return 502;
|
|
9605
|
+
}
|
|
9606
|
+
}
|
|
9328
9607
|
function createGraphqlClient(options = {}) {
|
|
9329
9608
|
const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;
|
|
9330
9609
|
const publicUrl = options.publicUrl ?? publicGraphqlBase(process.env);
|
|
@@ -9348,15 +9627,20 @@ function createGraphqlClient(options = {}) {
|
|
|
9348
9627
|
);
|
|
9349
9628
|
}
|
|
9350
9629
|
const result = await response.json();
|
|
9351
|
-
if (result.errors && result.errors.length > 0) {
|
|
9630
|
+
if (Array.isArray(result.errors) && result.errors.length > 0) {
|
|
9631
|
+
const errors = result.errors;
|
|
9352
9632
|
throw new HttpError(
|
|
9353
|
-
`GraphQL error: ${
|
|
9354
|
-
|
|
9355
|
-
|
|
9633
|
+
`GraphQL error: ${errors.map((e) => String(e?.message ?? JSON.stringify(e))).join(", ")}`,
|
|
9634
|
+
graphqlErrorStatus(errors[0]?.extensions?.code),
|
|
9635
|
+
errors
|
|
9356
9636
|
);
|
|
9357
9637
|
}
|
|
9358
9638
|
if (result.data === void 0 || result.data === null) {
|
|
9359
|
-
throw new HttpError(
|
|
9639
|
+
throw new HttpError(
|
|
9640
|
+
"GraphQL response carried no data",
|
|
9641
|
+
502,
|
|
9642
|
+
result.errors
|
|
9643
|
+
);
|
|
9360
9644
|
}
|
|
9361
9645
|
return result.data;
|
|
9362
9646
|
}
|
|
@@ -9472,10 +9756,7 @@ var SINK_TIMEOUT_MS = 3e3;
|
|
|
9472
9756
|
var NOT_FOUND_LOOP = "not_found_loop";
|
|
9473
9757
|
var blocked = /* @__PURE__ */ new Map();
|
|
9474
9758
|
function notFoundSinkUrl(submitUrl) {
|
|
9475
|
-
|
|
9476
|
-
const url = new URL(submitUrl);
|
|
9477
|
-
url.pathname = "/ratelimit/not-found";
|
|
9478
|
-
return url.toString();
|
|
9759
|
+
return sinkRouteUrl(submitUrl, "/ratelimit/not-found");
|
|
9479
9760
|
}
|
|
9480
9761
|
function createNotFoundLimiter(opts) {
|
|
9481
9762
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -9740,6 +10021,7 @@ var callsResponseHoldingTool = (message) => {
|
|
|
9740
10021
|
const call = import_types2.CallToolRequestSchema.safeParse(message);
|
|
9741
10022
|
return call.success && responseHoldingTools.has(call.data.params.name);
|
|
9742
10023
|
};
|
|
10024
|
+
var isInitialize = (message) => import_types2.InitializeRequestSchema.safeParse(message).success;
|
|
9743
10025
|
function prefersJsonResponse(messages) {
|
|
9744
10026
|
return messages.length > 0 && !messages.some(callsResponseHoldingTool);
|
|
9745
10027
|
}
|
|
@@ -9886,6 +10168,17 @@ async function handleMcpRequest(req, res, opts = {}) {
|
|
|
9886
10168
|
accountId
|
|
9887
10169
|
})
|
|
9888
10170
|
}) : null;
|
|
10171
|
+
const alpConfigured = Boolean(
|
|
10172
|
+
process.env.ALP_SINK_URL && process.env.ALP_SINK_SECRET
|
|
10173
|
+
);
|
|
10174
|
+
let promptReferral = true;
|
|
10175
|
+
if (alpConfigured && accountId && messages.some(isInitialize)) {
|
|
10176
|
+
const answered = await (opts.hasAnswered ?? hasAnswered)(
|
|
10177
|
+
accountId,
|
|
10178
|
+
"referral"
|
|
10179
|
+
).catch(() => null);
|
|
10180
|
+
promptReferral = answered !== true;
|
|
10181
|
+
}
|
|
9889
10182
|
const server = createSpecgenServer(
|
|
9890
10183
|
createToolContext({
|
|
9891
10184
|
apiKey: bearerToken,
|
|
@@ -9916,7 +10209,7 @@ async function handleMcpRequest(req, res, opts = {}) {
|
|
|
9916
10209
|
// store submissions (the sink is configured). The ingest endpoint is
|
|
9917
10210
|
// this deployment's own /api/alp/submit — one write path, both
|
|
9918
10211
|
// transports (docs/agent-learning-protocol.md).
|
|
9919
|
-
...
|
|
10212
|
+
...alpConfigured ? {
|
|
9920
10213
|
alp: {
|
|
9921
10214
|
ingestUrl: `${getBaseUrl(req)}/api/alp/submit`,
|
|
9922
10215
|
transport: "http",
|
|
@@ -9924,7 +10217,8 @@ async function handleMcpRequest(req, res, opts = {}) {
|
|
|
9924
10217
|
String(req.headers["user-agent"] ?? "unknown")
|
|
9925
10218
|
),
|
|
9926
10219
|
harnessSource: "user_agent"
|
|
9927
|
-
}
|
|
10220
|
+
},
|
|
10221
|
+
promptReferral
|
|
9928
10222
|
} : {},
|
|
9929
10223
|
// search-docs: listed only where the deployment holds the assistant's
|
|
9930
10224
|
// service key; the search runs in-process with it.
|