@runpod/mcp-server 4.2.0 → 4.4.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 +60 -0
- package/README.md +29 -2
- 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 +1330 -255
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +22 -6
- package/dist/http.d.ts +22 -6
- package/dist/http.mjs +1328 -254
- package/dist/http.mjs.map +1 -1
- package/dist/stdio.cjs +1296 -236
- package/dist/stdio.cjs.map +1 -1
- package/dist/stdio.mjs +1084 -229
- package/dist/stdio.mjs.map +1 -1
- package/dist/{wizard-YYU3OXFW.mjs → wizard-KKTBTVXE.mjs} +204 -5
- package/dist/wizard-KKTBTVXE.mjs.map +1 -0
- package/package.json +6 -3
- package/dist/wizard-YYU3OXFW.mjs.map +0 -1
package/dist/stdio.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/_shared/hosts.ts","../src/install/clients.ts","../src/install/verify-key.ts","../src/install/wizard.ts","../src/stdio.ts","../src/server.ts","../src/specgen/server.ts","../src/_shared/rate-limit.ts","../src/specgen/clients/rest-result.ts","../src/specgen/dispatch.ts","../src/specgen/generated/tools.gen.ts","../src/specgen/pagination.ts","../src/specgen/clients/http-error.ts","../src/specgen/tools/util.ts","../src/specgen/tools/annotations.ts","../src/specgen/tools/capacity.ts","../src/specgen/tools/endpoint-gpus.ts","../src/specgen/tools/hub.ts","../src/specgen/tools/jobs.ts","../src/specgen/tools/list-endpoints.ts","../src/specgen/tools/list-templates.ts","../src/specgen/tools/logs.ts","../node_modules/.pnpm/@runpod+typescript-api-sdk@0.2.0/node_modules/@runpod/typescript-api-sdk/dist/index.js","../src/specgen/clients/sse.ts","../src/specgen/tools/public-endpoints.ts","../src/specgen/tools/knowledge.ts","../src/specgen/analytics.ts","../src/http.ts","../src/specgen/context.ts","../src/_shared/tracking.ts","../src/specgen/clients/graphql.ts","../src/specgen/clients/runtime.ts","../src/_shared/credential-check.ts","../src/alp/read.ts","../src/specgen/tools/alp.ts","../src/specgen/ops.ts"],"sourcesContent":["// Env-resolved API base URLs, extracted from the retired dual-version backend\n// resolver (backend.ts) when the spec-generated surface became the only one.\n// The credential preflight compares only active SDK and runtime destinations.\n\nexport type Env = Record<string, string | undefined>;\n\n// '' reads as unset everywhere: the wrong-environment guard already strips\n// empty vars before comparing, and every consumer (the credential checker's\n// probe URL, the GraphQL/log clients) must resolve identically or the\n// guard's \"checker and guard cannot disagree\" invariant breaks.\nfunction pick(value: string | undefined, fallback: string): string {\n return value?.trim().replace(/\\/+$/, '') || fallback;\n}\n\n// Generated paths include /v2, so the SDK base is the API origin.\nexport function sdkBase(env: Env): string {\n return pick(env.RUNPOD_API_BASE_URL, 'https://api.runpod.io');\n}\nexport function serverlessBase(env: Env): string {\n return pick(env.RUNPOD_SERVERLESS_API_URL, 'https://api.runpod.ai/v2');\n}\nexport function publicGraphqlBase(env: Env): string {\n return pick(env.RUNPOD_PUBLIC_GRAPHQL_URL, 'https://api.runpod.io/graphql');\n}\n// A separate var from publicGraphqlBase despite the identical default:\n// RUNPOD_PUBLIC_GRAPHQL_URL is the documented credential-free discovery\n// override and gets pointed at stubs freely, so routing authed calls through it\n// would turn \"point this anywhere\" into \"send the caller's API key there\".\nexport function authedGraphqlBase(env: Env): string {\n return pick(env.RUNPOD_AUTHED_GRAPHQL_URL, 'https://api.runpod.io/graphql');\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { execSync, spawnSync } from 'child_process';\nimport * as jsonc from 'jsonc-parser';\n\n// The npm package and the name the server is registered under in client config.\nexport const SERVER_NAME = 'runpod';\nexport const NPM_PACKAGE = '@runpod/mcp-server@latest';\n\n// The hosted Streamable HTTP endpoint. Clients point here and authenticate with\n// the OAuth \"Sign in with Runpod\" flow — no API key is stored in their config.\n// Overridable so a non-production deployment can be targeted during testing.\nexport const HOSTED_URL =\n process.env.RUNPOD_MCP_URL ?? 'https://mcp.getrunpod.io/';\n\n// How the user wants the server wired up:\n// - local: run via npx on this machine, authenticated by an API key in the env.\n// - hosted: connect to the hosted HTTP server and sign in with Runpod (OAuth).\nexport type AddMode =\n | { kind: 'local'; apiKey: string }\n | { kind: 'hosted'; url: string };\n\nexport interface AddResult {\n success: boolean;\n message?: string;\n}\n\nexport interface McpClient {\n // Stable id used as the multiselect value.\n id: string;\n // Human-readable label shown in the picker.\n name: string;\n // True when the client appears to be installed on this machine.\n detect(): Promise<boolean>;\n // Write (or update) the Runpod server entry in the client's config.\n add(mode: AddMode): Promise<AddResult>;\n // Remove the Runpod server entry from the client's config.\n remove(): Promise<AddResult>;\n // Where the config lives, for display and manual fallback.\n describeTarget(): string;\n // How this client parses its config, for clients that own a JSON file. Exposed so the\n // per-client wiring is assertable: reverting it to a single shared default left every\n // test green while Cursor was misclassified, because upsertJsonServer was only ever\n // exercised with an explicit dialect. Absent for Claude Code, which is driven by CLI.\n dialect?: ConfigDialect;\n}\n\n// The local stdio config: Runpod's MCP server runs via npx and reads the API\n// key from the environment. VS Code's `servers` map requires an explicit\n// transport type for stdio servers (mcpServers-style clients infer it).\nfunction localServerConfig(apiKey: string, serverProperty: string) {\n const config = {\n command: 'npx',\n args: ['-y', NPM_PACKAGE],\n env: { RUNPOD_API_KEY: apiKey },\n };\n return serverProperty === 'servers' ? { type: 'stdio', ...config } : config;\n}\n\n// The hosted config. Clients with native remote-MCP support take the URL\n// directly (VS Code additionally needs `type: 'http'`); the rest reach the\n// hosted server through the `mcp-remote` stdio bridge, which also drives OAuth.\nfunction hostedServerConfig(\n strategy: 'http' | 'mcp-remote',\n serverProperty: string,\n url: string\n) {\n if (strategy === 'mcp-remote') {\n return { command: 'npx', args: ['-y', 'mcp-remote', url] };\n }\n return serverProperty === 'servers' ? { type: 'http', url } : { url };\n}\n\n/**\n * How the client that owns a config parses it. This decides what \"valid\" means, so\n * every value here is a claim about a specific shipped parser and must be read out of\n * that client's own code — not inferred from \"it's an Electron app\".\n *\n * 'jsonc' comments and trailing commas are accepted.\n * 'json' strict `JSON.parse`; both are fatal.\n * 'unverified' tolerance not established. Validated leniently (so a config the\n * client may well load is never refused) and any reliance on that\n * leniency is disclosed to the user instead of being asserted away.\n *\n * Getting a value wrong breaks a user either way round: too strict refuses a healthy\n * config and leaves the client unconfigured, too lenient reports \"configured\" for a\n * file the client silently never loads. Verified against the shipped code:\n *\n * Cursor 'jsonc'. Not strict, despite being an Electron app — a VS Code fork,\n * and its reader keeps VS Code's tolerance. `parseMcpServersFromFile`\n * → `t$t(content)`, which is\n * `stripComments` → `JSON.parse`, and on failure\n * `.replace(/,\\s*([}\\]])/g,'$1')` → `JSON.parse` again.\n * So comments and trailing commas both survive.\n * (workbench.desktop.main.js; a BOM is still fatal, hence the strip\n * on write below.)\n * Claude Desktop 'json'. `wxr()` is `JSON.parse(Et.readFileSync(t,'utf8'))` with no\n * preprocessing and no retry (app.asar).\n * VS Code 'jsonc'. Reads mcp.json as JSONC by design.\n * Windsurf 'unverified' — not installed here, so its parser was never read.\n * It is a VS Code fork like Cursor, so it is probably lenient, but\n * \"probably\" is not a fact to put in a success message.\n */\nexport type ConfigDialect = 'json' | 'jsonc' | 'unverified';\n\nfunction describeDialect(dialect: ConfigDialect): string {\n return dialect === 'json' ? 'JSON' : 'JSONC';\n}\n\nfunction parseFailure(\n content: string,\n dialect: ConfigDialect\n): string | undefined {\n if (dialect === 'json') {\n try {\n JSON.parse(content);\n return undefined;\n } catch (error) {\n return errMessage(error);\n }\n }\n const errors: jsonc.ParseError[] = [];\n jsonc.parse(content, errors, { allowTrailingComma: true });\n return errors.length > 0\n ? `JSONC parse error at offset ${errors[0].offset}`\n : undefined;\n}\n\n// Parse the way the owning client parses, to answer \"what will the client actually\n// see?\" rather than \"is this file well-formed?\". The two differ: duplicate keys are\n// legal JSON, and every parser here keeps the LAST occurrence while `jsonc.modify`\n// edits the FIRST.\nfunction parseAsClient(content: string, dialect: ConfigDialect): unknown {\n // Lenient for 'unverified' as well as 'jsonc'. Using the strict parser here made a\n // commented config look as though the entry were absent, so the duplicate-key guard\n // below refused a perfectly good write — the same false-refusal defect as the Cursor\n // misclassification, introduced by the fix for it. This question is only \"which\n // duplicate block wins\", which is independent of comment tolerance.\n if (dialect !== 'json') {\n return jsonc.parse(content, [], { allowTrailingComma: true });\n }\n try {\n return JSON.parse(content);\n } catch {\n return undefined;\n }\n}\n\n// What the client will read at `[serverProperty][SERVER_NAME]` — undefined when absent.\nfunction readBackEntry(\n content: string,\n serverProperty: string,\n dialect: ConfigDialect\n): unknown {\n const parsed = parseAsClient(content, dialect);\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const servers = (parsed as Record<string, unknown>)[serverProperty];\n if (typeof servers !== 'object' || servers === null) return undefined;\n return (servers as Record<string, unknown>)[SERVER_NAME];\n}\n\n// A file that only parses because the reader is lenient. Used to disclose the risk for\n// 'unverified' clients rather than silently betting on it.\nfunction reliesOnLeniency(content: string): boolean {\n if (content.trim() === '') return false;\n try {\n JSON.parse(content);\n return false;\n } catch {\n return parseFailure(content, 'jsonc') === undefined;\n }\n}\n\n// Read, edit, and write a JSON config while preserving the user's existing\n// formatting and comments (jsonc). Creates the file and parent dirs if missing.\n// Exported for tests: the client wrappers hardcode real config paths under $HOME, and\n// a test must never write there.\nexport function upsertJsonServer(\n configPath: string,\n serverProperty: string,\n value: unknown,\n // Required, with no default: the default used to be the lenient value, so a caller\n // that forgot it silently got the very behaviour this parameter exists to prevent.\n dialect: ConfigDialect\n): AddResult {\n // Refuse a relative target outright rather than trusting every caller to have\n // resolved one. This function creates directories and writes a plaintext API key, so\n // a relative path means creating a folder and leaking a credential into whatever\n // directory the wizard happened to be launched from. Guarding here closes the class\n // for every client at once, however the path was computed.\n if (!path.isAbsolute(configPath)) {\n return {\n success: false,\n message: `refusing to write \"${configPath}\": not an absolute path, so it would resolve against the current directory. This usually means an environment variable (APPDATA, XDG_CONFIG_HOME) is set to an empty or relative value.`,\n };\n }\n try {\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n const content = fs.existsSync(configPath)\n ? fs.readFileSync(configPath, 'utf8')\n : '';\n const edits = jsonc.modify(content, [serverProperty, SERVER_NAME], value, {\n formattingOptions: { tabSize: 2, insertSpaces: true },\n });\n // Strip a leading BOM from what gets WRITTEN, not just from the validity check.\n // `JSON.parse` throws `Unexpected token '\\uFEFF'` on one, and Cursor / Windsurf /\n // Claude Desktop are Node/Electron apps doing exactly that — so keeping the BOM\n // would report success for a config the client silently never loads, which is the\n // one thing this guard exists to prevent. Only VS Code (jsonc) tolerates it.\n const updated = jsonc.applyEdits(content, edits).replace(/^\\uFEFF/, '');\n // jsonc edits a malformed file on a best-effort basis: it will happily insert the\n // entry into a config with an unbalanced brace and hand back something still\n // unparseable, which the client then silently never loads. Refuse instead of\n // reporting success over a file we just confirmed is broken.\n // Checked with the parser the OWNING CLIENT uses, not a lenient one. PowerShell's\n // Set-Content and Notepad write BOMs by default on the platform this targets, so the\n // BOM is stripped above rather than refused; double or trailing BOMs still fail here.\n const failure = parseFailure(updated, dialect);\n if (failure) {\n // Distinguish \"we would break it\" from \"it was already broken\", because the second\n // is the user's pre-existing problem and the advice differs.\n const wasAlreadyBroken =\n content.trim() !== '' && parseFailure(content, dialect) !== undefined;\n return {\n success: false,\n message: wasAlreadyBroken\n ? `${configPath} could not be parsed as ${describeDialect(dialect)} before this change either (${failure}), so it was left untouched — this client would not load the entry. Fix the file (or move it aside) and re-run.`\n : `writing to ${configPath} would leave it unparseable (${failure}), so it was left untouched.`,\n };\n }\n // Valid is not the same as effective. `jsonc.modify` edits the FIRST occurrence of a\n // duplicated key; every parser here keeps the LAST. Duplicate keys are legal JSON, so\n // the validity check above passes and the entry lands in a block nothing reads —\n // reporting success while writing a plaintext API key that never takes effect. Ask\n // the client's own parser what it will see instead of trusting that an edit applied.\n const landed = readBackEntry(updated, serverProperty, dialect);\n if (JSON.stringify(landed) !== JSON.stringify(value)) {\n return {\n success: false,\n message: `${configPath} was left untouched: the entry would have been written where this client does not read it, so it would have had no effect. This usually means \"${serverProperty}\" appears more than once in the file — the last one wins, so merge them into a single block and re-run.`,\n };\n }\n // mode is honoured only when the file is created; an existing config keeps its\n // own. 0600 because this file holds a plaintext API key, and a freshly created\n // Claude Code config is 0600 — a config this wizard creates should not be looser.\n // No effect on Windows, which has no POSIX mode bits (only the read-only flag is\n // real); there the ACL on the user profile directory is what governs access.\n fs.writeFileSync(configPath, updated, { encoding: 'utf8', mode: 0o600 });\n // The entry is written and this client's parser accepts the file. When that\n // acceptance rests on leniency we have not actually verified, say so rather than\n // print an unqualified tick: refusing would leave a probably-fine client\n // unconfigured, and claiming success would be asserting the thing we do not know.\n if (dialect === 'unverified' && reliesOnLeniency(updated)) {\n return {\n success: true,\n message:\n 'written, but this config uses comments or trailing commas and whether this client accepts them is unverified — if the Runpod server does not appear, remove them',\n };\n }\n return { success: true };\n } catch (error) {\n return { success: false, message: errMessage(error) };\n }\n}\n\n// Exported for the same reason as upsertJsonServer: the client wrappers hardcode real\n// config paths under $HOME. Untested while unexported, which is how the relative-path\n// guard here — and the trailing-comma corruption below — went unnoticed.\nexport function removeJsonServer(\n configPath: string,\n serverProperty: string,\n dialect: ConfigDialect\n): AddResult {\n if (!path.isAbsolute(configPath)) {\n return {\n success: false,\n message: `refusing to touch \"${configPath}\": not an absolute path. Check APPDATA / XDG_CONFIG_HOME.`,\n };\n }\n try {\n if (!fs.existsSync(configPath)) {\n return { success: true, message: 'nothing to remove' };\n }\n const content = fs.readFileSync(configPath, 'utf8');\n if (content.trim() === '') {\n return { success: true, message: 'nothing to remove' };\n }\n const existingFailure = parseFailure(content, dialect);\n if (existingFailure !== undefined) {\n return {\n success: false,\n message: `could not safely remove the Runpod entry from ${configPath}: the existing config is not valid ${describeDialect(dialect)} (${existingFailure}). The original file was left unchanged; repair it or delete the entry by hand.`,\n };\n }\n let edits;\n try {\n edits = jsonc.modify(content, [serverProperty, SERVER_NAME], undefined, {\n formattingOptions: { tabSize: 2, insertSpaces: true },\n });\n } catch (error) {\n // jsonc throws `Can not delete in empty document` whenever the FIRST path segment\n // is absent — `{}`, an empty file, whitespace, an array root, and also a\n // populated object with no `mcpServers` key. Its message is a misnomer; in every\n // such case there is genuinely no runpod entry to remove. Reporting those as failures is the same class of bug as\n // reporting a failure as a success, just pointed the other way: the user is told\n // cleanup broke when the desired end state already held.\n if (/empty document/i.test(errMessage(error))) {\n return { success: true, message: 'nothing to remove' };\n }\n throw error;\n }\n // Zero edits normally means the entry is absent. It can also mean `jsonc.modify`\n // targeted a duplicate `serverProperty` block that does not contain it while the\n // block the client actually reads does — reporting \"nothing to remove\" over a\n // plaintext key still on disk. Confirm absence with the client's parser.\n if (edits.length === 0) {\n return readBackEntry(content, serverProperty, dialect) === undefined\n ? { success: true, message: 'nothing to remove' }\n : {\n success: false,\n message: `the Runpod entry is still present in ${configPath} and could not be removed automatically — \"${serverProperty}\" appears more than once, so the edit targeted a block this client does not read. Delete the entry by hand.`,\n };\n }\n const updated = jsonc.applyEdits(content, edits);\n // A surgical delete can leave a hole the parser rejects: removing the sole member of\n // `servers` that is followed by a trailing comma yields `{ , }`. Verified turning a\n // clean VS Code mcp.json into one with a parse error while reporting success. Both\n // VS Code and Cursor happen to recover from that shape, but a strict client would\n // stop loading every other server in the file, so it cannot be left behind.\n //\n // Do not fall back to a structural rewrite. JSON.stringify would make the file\n // parseable, but it would also erase comments and formatting from unrelated user\n // configuration without asking. The edit has not been written yet, so failing\n // closed leaves the original recoverable and gives the user a manual path.\n const brokeIt = parseFailure(updated, dialect) !== undefined;\n const stillThere =\n readBackEntry(updated, serverProperty, dialect) !== undefined;\n if (brokeIt || stillThere) {\n return {\n success: false,\n message: `could not remove the Runpod entry from ${configPath} without ${brokeIt ? 'making the config unparseable' : 'leaving the entry present'}. The original file was left unchanged so its comments and formatting are preserved; delete the Runpod entry by hand.`,\n };\n }\n fs.writeFileSync(configPath, updated, 'utf8');\n return { success: true };\n } catch (error) {\n return { success: false, message: errMessage(error) };\n }\n}\n\nfunction errMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction exists(p: string): boolean {\n try {\n return fs.existsSync(p);\n } catch {\n return false;\n }\n}\n\n// A JSON-config client that differs only in config path, server property, and\n// how it reaches the hosted server.\nfunction jsonClient(opts: {\n id: string;\n name: string;\n serverProperty?: string;\n // How the owning client parses its config — see ConfigDialect for the evidence\n // behind each value. Deliberately required and un-defaulted: Cursor was misread as\n // strict purely by inheriting a default here, which refused configs Cursor loads fine\n // and left it unconfigured. A wrong value breaks users in one direction or the other,\n // so every client has to state its own.\n dialect: ConfigDialect;\n // Native HTTP support, or the `mcp-remote` bridge for stdio-only clients.\n hostedStrategy?: 'http' | 'mcp-remote';\n configPath: () => string;\n detectPaths?: () => string[];\n}): McpClient {\n const serverProperty = opts.serverProperty ?? 'mcpServers';\n const hostedStrategy = opts.hostedStrategy ?? 'http';\n return {\n id: opts.id,\n name: opts.name,\n detect: () =>\n Promise.resolve(\n (opts.detectPaths?.() ?? [path.dirname(opts.configPath())]).some(exists)\n ),\n add: (mode) => {\n const value =\n mode.kind === 'local'\n ? localServerConfig(mode.apiKey, serverProperty)\n : hostedServerConfig(hostedStrategy, serverProperty, mode.url);\n return Promise.resolve(\n upsertJsonServer(opts.configPath(), serverProperty, value, opts.dialect)\n );\n },\n dialect: opts.dialect,\n remove: () =>\n Promise.resolve(\n removeJsonServer(opts.configPath(), serverProperty, opts.dialect)\n ),\n describeTarget: () => opts.configPath(),\n };\n}\n\n// A direct install location to probe, paired with the root its canonical target must\n// stay inside. Pairing them here — rather than re-deriving the root from the\n// candidate's position in a list, as an earlier revision did — means inserting or\n// reordering a candidate cannot silently confine it to the wrong root.\nexport interface ClaudeCandidate {\n path: string;\n trustedRoot: string;\n}\n\n/**\n * Install locations to probe before the POSIX-only PATH lookup. Windows uses win32\n * path semantics regardless of the host so the branch is testable anywhere.\n *\n * `.local\\bin\\claude.exe` is the documented native-installer location and comes\n * first deliberately: it is a real executable and launches with no shell at all.\n * It also covers installs where the native installer failed to add\n * itself to PATH, which the lookup below could never find.\n */\nexport function claudeCandidates(\n platform: string,\n homedir: string,\n appdata?: string\n): ClaudeCandidate[] {\n if (platform === 'win32') {\n const win = path.win32;\n // Automatic credential-bearing execution is limited to the standard per-user\n // roaming root, whatever APPDATA says: an arbitrary redirected APPDATA has no\n // trustworthy provenance merely because it is absolute.\n const defaultAppdata = win.join(homedir, 'AppData', 'Roaming');\n return [\n {\n path: win.join(homedir, '.local', 'bin', 'claude.exe'),\n trustedRoot: homedir,\n },\n // npm -g installs a .cmd shim. runClaude bypasses it and resolves the real\n // native or JavaScript target from the installed package manifest.\n //\n // absoluteEnvDir, not `?? `: an empty or relative APPDATA yielded the relative\n // `npm\\claude.cmd`. Candidates are probed before any lookup, so a relative\n // candidate would resolve against the current directory and receive the live\n // API key.\n {\n path: win.join(\n absoluteEnvDir(appdata, () => defaultAppdata),\n 'npm',\n 'claude.cmd'\n ),\n trustedRoot: defaultAppdata,\n },\n ];\n }\n return [\n // Where the current native installer puts it (verified on a real install:\n // ~/.local/bin/claude -> versions/2.1.220). Same reasoning as the Windows\n // .local\\bin\\claude.exe entry — it also covers an install whose PATH entry is\n // missing, which the lookup can never find. Without it, POSIX detection depended\n // entirely on PATH.\n {\n path: path.posix.join(homedir, '.local', 'bin', 'claude'),\n trustedRoot: homedir,\n },\n {\n path: path.posix.join(homedir, '.claude', 'local', 'claude'),\n trustedRoot: homedir,\n },\n { path: '/usr/local/bin/claude', trustedRoot: '/usr/local' },\n { path: '/opt/homebrew/bin/claude', trustedRoot: '/opt/homebrew' },\n ];\n}\n\n// The probe locations alone. Kept as the stable test surface for \"which paths does\n// each platform look at\".\nexport function claudeCandidatePaths(\n platform: string,\n homedir: string,\n appdata?: string\n): string[] {\n return claudeCandidates(platform, homedir, appdata).map((c) => c.path);\n}\n\nfunction pathIsInside(\n candidate: string,\n directory: string,\n pathApi: typeof path.posix | typeof path.win32\n): boolean {\n const relative = pathApi.relative(\n pathApi.resolve(directory),\n pathApi.resolve(candidate)\n );\n return (\n relative === '' ||\n (!relative.startsWith(`..${pathApi.sep}`) &&\n relative !== '..' &&\n !pathApi.isAbsolute(relative))\n );\n}\n\nfunction isNodeModulesBin(candidate: string): boolean {\n return /(^|[\\\\/])node_modules[\\\\/]\\.bin([\\\\/]|$)/i.test(candidate);\n}\n\n/**\n * Picks a trustworthy absolute result from POSIX `command -v` output.\n *\n * Windows never calls this helper: its two standard install locations are probed\n * directly, avoiding both a shadowable lookup executable and project-local PATH\n * entries. POSIX still needs a fallback for package-manager/custom installs, but\n * relative paths, cwd descendants, and node_modules/.bin shims are rejected before\n * the canonical project-boundary check in findClaudeBinary.\n */\nexport function pickClaudeBinary(\n stdout: string,\n platform: string,\n cwd?: string\n): string | null {\n if (platform === 'win32') return null;\n\n const hits = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n return (\n hits.find(\n (hit) =>\n path.posix.isAbsolute(hit) &&\n !isNodeModulesBin(hit) &&\n (cwd === undefined || !pathIsInside(hit, cwd, path.posix))\n ) ?? null\n );\n}\n\nconst PROJECT_BOUNDARY_MARKERS = [\n '.git',\n 'package.json',\n 'pnpm-workspace.yaml',\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'bun.lock',\n 'bun.lockb',\n] as const;\n\n/**\n * The outermost source/workspace boundary containing cwd, never $HOME itself.\n *\n * `.git` alone is insufficient: release archives and copied workspaces routinely\n * omit VCS metadata. A nested package can have its own package.json, so keep\n * walking and retain the outermost ancestor carrying a project marker.\n *\n * The walk stops at `home` (canonical) without counting it. $HOME routinely carries\n * project markers that make it no repository at all — a stray `package.json` from an\n * accidental `npm install`, a dotfiles `.git` — and treating it as a boundary rejects\n * every candidate underneath it, including `~/.local/bin/claude` itself: the wizard\n * then reports Claude Code not found on exactly the standard installs it probes for.\n * A repository can only plant files inside its own tree, so a boundary above the\n * outermost marked directory *below* home defends nothing. Deliberately still the\n * OUTERMOST marked ancestor below home, not the nearest: in a monorepo whose package\n * dirs carry their own package.json, \"nearest\" would trust a tool planted at the repo\n * root.\n */\nfunction projectBoundary(cwd: string, home?: string): string | null {\n let current = cwd;\n let boundary: string | null = null;\n while (true) {\n if (current === home) return boundary;\n if (\n PROJECT_BOUNDARY_MARKERS.some((marker) =>\n exists(path.join(current, marker))\n )\n ) {\n boundary = current;\n }\n const parent = path.dirname(current);\n if (parent === current) return boundary;\n current = parent;\n }\n}\n\n/**\n * Canonical trust check for every Claude executable candidate.\n *\n * Direct user-level candidates are not automatically trusted: the path can be a\n * symlink/junction into the repository, and APPDATA/HOME can be redirected. PATH\n * results are rejected when they resolve inside an identifiable source/workspace\n * boundary. An unmarked cwd cannot be treated as a project root: doing so rejects\n * ordinary nvm/asdf/Volta installs when the wizard is launched from $HOME. Nor can a\n * MARKED $HOME — see projectBoundary, which never counts home itself.\n */\nfunction trustedClaudeBinary(\n binary: string,\n cwd: string,\n home?: string,\n requiredRoot?: string\n): string | null {\n try {\n const canonicalBinary = fs.realpathSync.native(binary);\n const canonicalCwd = fs.realpathSync.native(cwd);\n // Canonical, because the walk compares it against ancestors of a canonical cwd. A\n // home that cannot be canonicalized falls back to no cap — the stricter direction.\n let canonicalHome: string | undefined;\n if (home !== undefined) {\n try {\n canonicalHome = fs.realpathSync.native(home);\n } catch {\n canonicalHome = undefined;\n }\n }\n const projectRoot = projectBoundary(canonicalCwd, canonicalHome);\n const canonicalRequiredRoot =\n requiredRoot === undefined\n ? undefined\n : fs.realpathSync.native(requiredRoot);\n if (\n isNodeModulesBin(canonicalBinary) ||\n (canonicalRequiredRoot !== undefined &&\n !pathIsInside(canonicalBinary, canonicalRequiredRoot, path)) ||\n (projectRoot !== null && pathIsInside(canonicalBinary, projectRoot, path))\n ) {\n return null;\n }\n return canonicalBinary;\n } catch {\n // A lookup result that cannot be canonicalized is not safe to execute with a\n // credential, even if command -v reported it successfully.\n return null;\n }\n}\n\n// cmd.exe metacharacters used only when rendering a manual command for display.\nconst CMD_META = /[()\\][%!^\"`<>&|;, *?\\t\\n\\v\\r]/;\n\nexport interface FindClaudeBinaryOptions {\n platform?: string;\n // `null` means \"known unavailable\" — what a failed os.userInfo() lookup produces.\n // Distinct from `undefined` (= resolve it here), so a test can drive the\n // no-home-directory path without mocking os.userInfo across module boundaries.\n homedir?: string | null;\n appdata?: string;\n cwd?: string;\n}\n\n// Locate the Claude Code CLI binary across common install locations and PATH.\n// Claude Code is the only client here detected by locating its executable rather\n// than by an existing config file. `command -v` remains the POSIX fallback.\n// Windows intentionally has no executable-lookup fallback: both the implicit\n// current-directory search and npm/npx's project-local PATH entries can resolve a\n// repository-supplied executable, and even a bare `where.exe` can itself be\n// shadowed. The documented native and global-npm locations cover the standard\n// Windows installs without executing anything discovered from the project.\n// Exported for tests: the platform decisions are pure, so both branches can be\n// exercised on any host without spawning anything or faking process.platform.\nexport function findClaudeBinary(\n options: FindClaudeBinaryOptions = {}\n): string | null {\n const platform = options.platform ?? process.platform;\n let homedir = options.homedir;\n if (homedir === undefined) {\n try {\n // os.homedir() honors HOME/USERPROFILE environment overrides. userInfo()\n // asks the OS for the account profile instead, so a launching project cannot\n // redirect an automatic credential-bearing candidate through those variables.\n homedir = os.userInfo().homedir;\n } catch {\n // No passwd entry for the process UID (arbitrary-UID containers, some CI\n // sandboxes). NOT os.homedir(): its answer is exactly the env-redirectable one\n // userInfo() exists to avoid. Home-anchored candidates are skipped, but the\n // POSIX PATH lookup below needs no homedir — returning here regressed those\n // environments from working (on main, via `command -v`) to undetectable.\n homedir = null;\n }\n }\n const appdata = options.appdata ?? process.env.APPDATA;\n const cwd = options.cwd ?? process.cwd();\n\n const candidates =\n homedir == null ? [] : claudeCandidates(platform, homedir, appdata);\n for (const candidate of candidates) {\n // Absolute only. `exists()` resolves a relative candidate against the CURRENT\n // DIRECTORY, and candidates are probed before the POSIX PATH lookup — so a\n // relative one would win outright and receive the live API key.\n if (\n !path.isAbsolute(candidate.path) &&\n !path.win32.isAbsolute(candidate.path)\n )\n continue;\n if (exists(candidate.path)) {\n // `?? undefined` only for the type: candidates is empty when homedir is null.\n const trusted = trustedClaudeBinary(\n candidate.path,\n cwd,\n homedir ?? undefined,\n candidate.trustedRoot\n );\n if (trusted !== null) return trusted;\n }\n }\n\n try {\n // Do not fall back to PATH on Windows. A repository can influence PATH and the\n // current-directory executable search, including shadowing the lookup program\n // itself. The standard native and global-npm locations above cover issue #56.\n if (platform === 'win32') return null;\n\n const out = execSync('command -v claude', {\n stdio: ['ignore', 'pipe', 'ignore'],\n encoding: 'utf8',\n });\n // `pickClaudeBinary` still rejects relative and node_modules/.bin results. Do\n // not pass cwd here: an unmarked cwd might be $HOME, with a legitimate\n // nvm/asdf/Volta executable beneath it. The canonical check below rejects a\n // result inside cwd whenever cwd is actually part of a marked project.\n const binary = pickClaudeBinary(out, platform);\n return binary === null\n ? null\n : trustedClaudeBinary(binary, cwd, homedir ?? undefined);\n } catch {\n return null;\n }\n}\n\n/**\n * Renders a command for a human to copy, quoting only what needs it. Display only:\n * this string is never executed. Plain double-quote wrapping, NOT JSON.stringify —\n * the latter escapes the backslashes in a Windows path, which is exactly wrong for\n * something the user will paste.\n */\nexport function describeCommand(binary: string, args: string[]): string {\n // Quote on cmd.exe metacharacters, not just whitespace. This function renders the\n // command printed when the wizard REFUSES to spawn something because an argument\n // holds a metacharacter — so quoting on whitespace alone handed the user a command\n // broken by the very character that triggered the refusal: with a URL override, a\n // bare `?a=1&b=2` makes cmd.exe split `&b=2` into a second command.\n const quote = (s: string) =>\n /\\s/.test(s) || CMD_META.test(s) ? `\"${s}\"` : s;\n return [binary, ...args].map(quote).join(' ');\n}\n\n// Placeholder substituted for the key when a command is printed for the user.\n// No cmd.exe metacharacters: this string is printed for a user to paste into\n// cmd.exe, and `<`/`>` would be parsed as redirection — turning the wizard's own\n// remediation command into an error.\nexport const KEY_PLACEHOLDER = 'YOUR_RUNPOD_API_KEY';\n\n/**\n * Same as describeCommand, with the API key replaced by a placeholder. Anything\n * printed to the terminal ends up in scrollback, and in a support thread or CI log\n * the moment someone pastes wizard output — so a command shown to a user names the\n * variable but not its value. The user knows their own key.\n */\nexport function describeCommandRedacted(\n binary: string,\n args: string[]\n): string {\n return describeCommand(\n binary,\n args.map((arg) =>\n arg.startsWith('RUNPOD_API_KEY=')\n ? `RUNPOD_API_KEY=${KEY_PLACEHOLDER}`\n : arg\n )\n );\n}\n\n/**\n * Runs the Claude Code CLI.\n *\n * A Windows npm-global `claude.cmd` is never executed. Its package manifest names\n * the real entrypoint. Current releases point at a native `bin/claude.exe`; older\n * releases may point at a JavaScript entrypoint. The target is canonicalized inside\n * the installed package, then spawned directly (native) or through this\n * already-running Node process (JavaScript). This avoids cmd.exe, COMSPEC, PATH\n * lookup, `%*` re-parsing, and command-line escaping entirely.\n */\n// `refused` marks \"we declined to run this\", as opposed to \"we ran it and it\n// failed\" — `remove` treats those differently.\nexport interface RunResult extends AddResult {\n refused?: boolean;\n // Raw combined stdout+stderr, for callers that must inspect what the CLI said.\n // INTERNAL ONLY — never surface this to a user: `claude mcp get` prints\n // `Environment: RUNPOD_API_KEY=<plaintext>`.\n output?: string;\n}\n\n/**\n * Strips a secret from text that is about to be shown to a user.\n *\n * The redaction above works on argv shape (`RUNPOD_API_KEY=<value>`); this works on\n * the value, which is what actually matters. Needed because `runClaude` surfaces the\n * CLI's own stdout/stderr, and that CLI does echo `-e` tokens back on some errors\n * (observed: `Invalid environment variable format: RUNPOD_API_KEY_rpa_…`). A\n * shape-based guard cannot cover output produced by another program.\n */\nexport function redactSecret(text: string, secret?: string): string {\n if (!secret) return text;\n return text.split(secret).join(KEY_PLACEHOLDER);\n}\n\nfunction sanitizedClaudeEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env };\n for (const key of Object.keys(env)) {\n if (\n ['path', 'comspec', 'pathext', 'node_options', 'node_path'].includes(\n key.toLowerCase()\n )\n ) {\n delete env[key];\n }\n }\n if (process.platform === 'win32') {\n env.Path = path.dirname(process.execPath);\n } else {\n env.PATH = [\n path.dirname(process.execPath),\n '/usr/local/bin',\n '/opt/homebrew/bin',\n '/usr/bin',\n '/bin',\n ].join(path.delimiter);\n }\n return env;\n}\n\ninterface WindowsNpmClaudeTarget {\n command: string;\n argsPrefix: string[];\n}\n\nfunction windowsNpmClaudeTarget(binary: string): WindowsNpmClaudeTarget | null {\n if (process.platform !== 'win32' || !binary.toLowerCase().endsWith('.cmd')) {\n return null;\n }\n try {\n const npmRoot = fs.realpathSync.native(path.dirname(binary));\n const packageRoot = fs.realpathSync.native(\n path.join(npmRoot, 'node_modules', '@anthropic-ai', 'claude-code')\n );\n if (!pathIsInside(packageRoot, npmRoot, path)) return null;\n\n const manifestPath = fs.realpathSync.native(\n path.join(packageRoot, 'package.json')\n );\n if (!pathIsInside(manifestPath, packageRoot, path)) return null;\n const manifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf8')\n ) as unknown;\n if (manifest === null || typeof manifest !== 'object') return null;\n const bin = (manifest as { bin?: unknown }).bin;\n const target =\n typeof bin === 'string'\n ? bin\n : bin !== null && typeof bin === 'object'\n ? (bin as Record<string, unknown>).claude\n : undefined;\n if (typeof target !== 'string' || target.trim() === '') return null;\n\n const entrypoint = fs.realpathSync.native(\n path.resolve(packageRoot, target)\n );\n if (!pathIsInside(entrypoint, packageRoot, path)) return null;\n if (/\\.(?:exe|com)$/i.test(entrypoint)) {\n return { command: entrypoint, argsPrefix: [] };\n }\n if (/\\.(?:c?js|mjs)$/i.test(entrypoint)) {\n return { command: process.execPath, argsPrefix: [entrypoint] };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function runClaude(\n binary: string,\n args: string[],\n secret?: string\n): RunResult {\n const isWindowsCmd =\n process.platform === 'win32' && binary.toLowerCase().endsWith('.cmd');\n const npmTarget = windowsNpmClaudeTarget(binary);\n if (isWindowsCmd && npmTarget === null) {\n return {\n success: false,\n refused: true,\n message: `could not locate a trusted Claude Code npm entrypoint beside ${binary}. Run the shim yourself, substituting your key:\\n ${describeCommandRedacted(binary, args)}`,\n };\n }\n const command = npmTarget?.command ?? binary;\n const commandArgs = [...(npmTarget?.argsPrefix ?? []), ...args];\n const result = spawnSync(command, commandArgs, {\n stdio: 'pipe',\n encoding: 'utf8',\n env: sanitizedClaudeEnv(),\n });\n if (result.error)\n return {\n success: false,\n message: redactSecret(errMessage(result.error), secret),\n };\n const stdio = `${result.stdout ?? ''}${result.stderr ?? ''}`;\n if (result.status === 0) return { success: true, output: stdio };\n if (result.status === null) {\n return { success: false, message: `killed by ${result.signal}` };\n }\n // The CLI reports \"already exists\" on stderr with a non-zero exit. Re-running the\n // wizard should be idempotent, not an error — but it is NOT an update: the CLI\n // leaves the existing entry alone, so a user re-running the wizard after rotating\n // their API key still has the old key. Say so rather than reporting a bare\n // success. Observed with claude 2.1.220 at the scope this wizard actually writes:\n // `MCP server runpod already exists in user config`, exit 1, stored key unchanged.\n // The remediation command carries the full binary path, because the first candidate\n // path exists precisely to cover installs that are not on PATH.\n if (stdio.includes('already exists')) {\n return {\n success: true,\n // Deliberately not \"to replace the API key\": this branch is also reached in\n // hosted mode, where there is no key — and the pre-existing entry may be of the\n // other kind entirely, which is exactly what the user needs to know.\n message: `already configured, existing entry left unchanged — it was NOT updated to what you just chose (to replace it, run \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'user'])}\\` first, then re-run this wizard)`,\n };\n }\n return {\n success: false,\n message: redactSecret(\n stdio.trim() ||\n `${path.basename(binary)} exited with code ${result.status}`,\n secret\n ),\n };\n}\n\n// What Claude Code's own config says about the runpod entry. Read from the file\n// rather than inferred from `claude mcp get`, because that command answers \"what\n// would Claude Code use from here\" — it reports only the WINNING scope, and local\n// shadows user. Verified with claude 2.1.220: with a user-scope AND a local-scope\n// entry both on disk, `mcp get` prints only `Scope: Local config`. So one scope\n// string cannot distinguish \"user entry present, shadowed by a local one\" from \"user\n// entry absent, local one present\" — and those need opposite verdicts. Two revisions\n// of this file got that wrong in both directions.\n//\n// `--scope user` writes exactly one place: the top-level `mcpServers` of\n// `.claude.json`. Reading it is exact, needs no spawn, and cannot be shadowed.\n//\n// VERSION COUPLING: that storage location is a claim about claude 2.1.x. If a future\n// Claude Code moves user-scope entries elsewhere, this reader will report \"absent\"\n// after every successful add — turning each one into a false \"Nothing was configured\"\n// failure in interpretAddResult. If that starts happening on a new CLI version, check\n// where `--scope user` writes before suspecting the wizard.\nexport interface ClaudeConfigState {\n // The file this state was read from. Carried so a message names the file actually\n // consulted — the reader is injectable, so `claudeUserConfigPath()` is not\n // necessarily it.\n configPath: string;\n // Is there a runpod entry in USER scope — the only scope this wizard writes?\n // undefined when the file cannot be read or parsed, i.e. \"unknown\", never a guess.\n userScope: boolean | undefined;\n // Directories whose local-scope config (projects[dir].mcpServers) also carries one.\n // This wizard never touches those, so a removal names them rather than implying the\n // key is gone. NOTE: project scope (`<dir>/.mcp.json`) is a separate file per\n // directory and is NOT covered here — a checked-in team entry can still shadow the\n // one this writes. Every message therefore scopes its claim to the user config.\n localScopeDirs: string[];\n}\n\n/**\n * An environment-provided directory, or the fallback when it is unusable.\n *\n * Unusable means unset, empty, or relative. The XDG spec says exactly this for its own\n * variables (\"must be treated as unset\", \"relative paths should be considered invalid\n * and ignored\"), and the same reasoning applies to APPDATA: a relative directory resolves\n * against the process's cwd, and every path built from these either stores a plaintext\n * API key or gets executed.\n *\n * NOT for CLAUDE_CONFIG_DIR — see claudeUserConfigPath. That names a file the Claude Code\n * CLI owns and resolves relatively itself, so ignoring a relative value there would point\n * this code at a file the CLI never touched.\n */\nexport function absoluteEnvDir(\n value: string | undefined,\n fallback: () => string\n): string {\n if (!value || !value.trim()) return fallback();\n // Check with both flavours: a Windows path is not absolute under path.posix and vice\n // versa, and this module deliberately computes win32 paths on any host for testing.\n if (!path.isAbsolute(value) && !path.win32.isAbsolute(value))\n return fallback();\n return value;\n}\n\nexport function claudeUserConfigPath(): string {\n const configured = process.env.CLAUDE_CONFIG_DIR;\n // Deliberately NOT absoluteEnvDir, unlike XDG_CONFIG_HOME and APPDATA. Those name\n // paths this wizard invents, where a relative value can only mean writing a credential\n // into the current directory — so refusing it is right. This one names a file another\n // program owns, and that program resolves a relative value against its own cwd:\n // verified with claude 2.1.220, `CLAUDE_CONFIG_DIR=relcfg claude mcp add … --scope\n // user` prints `File modified: relcfg/.claude.json` and creates ./relcfg. Treating it\n // as unset would point this at $HOME/.claude.json — a file the CLI never touched — and\n // then report a DEFINITE verdict about it, which is precisely how a false success gets\n // built. So resolve it the way the CLI does. Only a truly empty value is unset, which\n // the CLI also falls back to $HOME for (verified).\n return path.join(\n configured ? path.resolve(configured) : os.homedir(),\n '.claude.json'\n );\n}\n\nexport function readClaudeConfigState(configPath: string): ClaudeConfigState {\n const unknown: ClaudeConfigState = {\n configPath,\n userScope: undefined,\n localScopeDirs: [],\n };\n // Belt and braces on top of claudeUserConfigPath's own resolution: a relative path\n // is never the file the CLI would use, so answering \"absent\" from it would be a\n // guess. Say unknown.\n if (!path.isAbsolute(configPath)) return unknown;\n\n let raw: string;\n try {\n if (!fs.existsSync(configPath)) {\n // No config at all is a definite \"no user-scope entry\", not an unknown.\n return { configPath, userScope: false, localScopeDirs: [] };\n }\n raw = fs.readFileSync(configPath, 'utf8');\n } catch {\n // Unreadable (permissions) — say unknown rather than \"absent\", which would let a\n // caller announce that a key is gone when it cannot see the file at all.\n return unknown;\n }\n const errors: jsonc.ParseError[] = [];\n const parsed = jsonc.parse(raw.replace(/^\\uFEFF/, ''), errors, {\n allowTrailingComma: true,\n }) as\n | {\n mcpServers?: Record<string, unknown>;\n projects?: Record<string, { mcpServers?: Record<string, unknown> }>;\n }\n | undefined;\n // An array or a scalar at the root is not a config this code understands; saying\n // \"no user entry\" about it would be a guess dressed as a fact.\n if (\n errors.length > 0 ||\n typeof parsed !== 'object' ||\n parsed === null ||\n Array.isArray(parsed)\n ) {\n return unknown;\n }\n\n const has = (servers: unknown): boolean =>\n typeof servers === 'object' &&\n servers !== null &&\n Object.prototype.hasOwnProperty.call(servers, SERVER_NAME);\n\n // Own-property, so a config with a `__proto__` key cannot conjure an mcpServers map.\n const own = (key: string): unknown =>\n Object.prototype.hasOwnProperty.call(parsed, key)\n ? (parsed as Record<string, unknown>)[key]\n : undefined;\n\n const projects = own('projects');\n // A plain object only: an array would yield index keys (\"0\", \"1\") that then get\n // printed to the user as directories to cd into.\n const localScopeDirs =\n typeof projects === 'object' &&\n projects !== null &&\n !Array.isArray(projects)\n ? Object.entries(projects as Record<string, { mcpServers?: unknown }>)\n .filter(([, project]) => has(project?.mcpServers))\n .map(([dir]) => dir)\n : [];\n\n return { configPath, userScope: has(own('mcpServers')), localScopeDirs };\n}\n// Lists directories without dumping twenty paths into one line.\nfunction describeDirs(dirs: string[]): string {\n if (dirs.length === 1) return dirs[0];\n return `${dirs.length} project directories (${dirs.slice(0, 3).join(', ')}${dirs.length > 3 ? ', …' : ''})`;\n}\n\n/**\n * Turns a `claude mcp remove` run plus the config's own state into an outcome.\n *\n * Neither the exit code nor a `claude mcp get` probe can decide this. Four facts, all\n * observed with claude 2.1.220, each of which produced a false result in an earlier\n * revision of this file:\n *\n * 1. With an unwritable config, `mcp remove` prints `Removed MCP server runpod from\n * user config / File modified: …` and exits **0** having written nothing.\n * 2. `claude mcp add` defaults to LOCAL scope while this removes from USER scope, so\n * a hand-added entry reports `No MCP server named \"runpod\" in user scope`, exit 1.\n * 3. `mcp get` is cwd-pinned: an entry added in another directory is invisible.\n * 4. `mcp get` reports only the WINNING scope, and local shadows user — so a local\n * entry hides a user entry that is still on disk.\n *\n * Reading `.claude.json` sidesteps all four: `--scope user` writes exactly one place,\n * and local-scope entries are enumerable across every directory rather than only the\n * current one.\n */\nexport function interpretRemoveResult(\n result: RunResult,\n state: ClaudeConfigState,\n binary = 'claude'\n): AddResult {\n // A refusal ran nothing, so there is nothing to verify.\n if (result.refused) return result;\n\n const alsoElsewhere =\n state.localScopeDirs.length > 0\n ? ` A separate local-scope ${SERVER_NAME} entry (which may carry its own API key) also exists in ${describeDirs(state.localScopeDirs)} — this wizard does not touch those. Remove with \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'local'])}\\` from each.`\n : '';\n\n if (state.userScope === true) {\n // Cause (1): the CLI reported whatever it reported, and the entry is still there.\n return {\n success: false,\n message: `the ${SERVER_NAME} entry is STILL in Claude Code's user config (${state.configPath}), so your API key is still on disk. ${\n result.success\n ? 'Most likely that file is not writable — the CLI reports success anyway.'\n : `The removal command itself failed: ${result.message ?? 'no output'}`\n }${alsoElsewhere}`,\n };\n }\n\n if (state.userScope === false) {\n // Exact, not inferred: the file was read and has no user-scope entry.\n return {\n success: true,\n message:\n (result.success\n ? 'removed from your user config'\n : 'nothing to remove in your user config') + alsoElsewhere,\n };\n }\n\n // Config unreadable/unparseable — do not claim either way.\n if (result.success) {\n return {\n success: true,\n message: `removal reported success, but ${state.configPath} could not be read to confirm it`,\n };\n }\n return { success: false, message: result.message };\n}\n\n/**\n * Turns a `claude mcp add` run plus the config's own state into an outcome.\n *\n * Same reason as above, and the mirror failure is why the scope-string approach was\n * abandoned: with a pre-existing LOCAL entry in the current directory, `mcp get`\n * reports `local` even after a perfectly successful user-scope write — so keying off\n * it reported \"nothing was configured\" for a key that had just been written.\n */\nexport function interpretAddResult(\n result: RunResult,\n state: ClaudeConfigState,\n // Threaded through for the same reason interpretRemoveResult takes it: the\n // remediation command has to name the binary that was actually found. A bare\n // `claude` fails for exactly the not-on-PATH installs the candidate paths exist\n // to serve.\n binary: string\n): AddResult {\n if (result.refused || !result.success) return result;\n\n if (state.userScope === false) {\n return {\n success: false,\n message: `Claude Code reported success but no ${SERVER_NAME} entry is in its user config afterwards (${state.configPath}) — that file is most likely not writable. Nothing was configured.`,\n };\n }\n\n if (state.userScope === true && state.localScopeDirs.length > 0) {\n // Local scope SHADOWS user scope, so in these directories the entry just written is\n // inert and Claude Code keeps using the local one, with its own possibly stale key.\n // That shadowing is the entire reason this reader exists, and the add path was\n // dropping the fact while the remove path reported it. The \"already exists\" caveat\n // cannot cover it: `mcp add --scope user` exits 0 when a local entry is present,\n // because the collision is per-scope.\n return {\n success: true,\n message: `${result.message ? `${result.message}; ` : ''}note a local-scope ${SERVER_NAME} entry also exists in ${describeDirs(state.localScopeDirs)} and takes precedence over the user config there, so Claude Code will keep using it in those projects — remove it with \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'local'])}\\` run from each`,\n };\n }\n\n if (state.userScope === undefined) {\n // Accepted — failing closed would break every user whose config this cannot parse,\n // for a problem that may not exist — but not reported as a clean success, or the\n // user has no way to know the write went unconfirmed.\n return {\n success: true,\n message: `${result.message ? `${result.message}; ` : ''}could not read ${state.configPath} to confirm the entry landed`,\n };\n }\n\n return { success: true, message: result.message };\n}\n\n/**\n * Built around an injectable binary resolver.\n *\n * The injection is not decoration: tests that drive this client must NOT be able to\n * reach a real `claude`. `findClaudeBinary` probes `~/.claude/local/claude`,\n * `/usr/local/bin/claude` and `/opt/homebrew/bin/claude` BEFORE consulting PATH, so a\n * harness that merely prepends a fake to PATH still runs the contributor's real CLI on\n * any machine with a native-installer or Homebrew install — executing\n * `claude mcp remove --scope user runpod` against their live config. CI cannot catch\n * that, because clean runner images have none of those paths.\n */\nexport function createClaudeCodeClient(\n resolveBinary: () => string | null,\n // Injected for the same reason as the binary: a test must not read — or draw\n // conclusions from — the developer's real ~/.claude.json.\n readState: () => ClaudeConfigState = () =>\n readClaudeConfigState(claudeUserConfigPath())\n): McpClient {\n return {\n id: 'claude-code',\n name: 'Claude Code',\n detect: () => Promise.resolve(resolveBinary() !== null),\n add: (mode) => {\n const args =\n mode.kind === 'local'\n ? [\n 'mcp',\n 'add',\n SERVER_NAME,\n '--scope',\n 'user',\n '-e',\n `RUNPOD_API_KEY=${mode.apiKey}`,\n '--',\n 'npx',\n '-y',\n NPM_PACKAGE,\n ]\n : [\n 'mcp',\n 'add',\n '--transport',\n 'http',\n '--scope',\n 'user',\n SERVER_NAME,\n mode.url,\n ];\n const binary = resolveBinary();\n if (!binary) {\n // Automatic detection deliberately covers only the standard install\n // locations (see findClaudeBinary) — a custom npm prefix or redirected\n // profile still works, the user just registers it themselves from their own\n // shell, where their own PATH applies and this wizard's trust rules do not.\n return Promise.resolve({\n success: false,\n message: `claude CLI not found in the standard install locations. If Claude Code is installed somewhere custom, register it yourself${mode.kind === 'local' ? ', substituting your key' : ''}:\\n ${describeCommandRedacted('claude', args)}`,\n });\n }\n // The key is passed in only so any message built from the CLI's output can have\n // it stripped — see redactSecret.\n const result = runClaude(\n binary,\n args,\n mode.kind === 'local' ? mode.apiKey : undefined\n );\n // interpretAddResult passes failures and refusals through verbatim, so only a\n // success needs the config read to confirm it.\n if (!result.success) return Promise.resolve(result);\n // Verified against the config, not the exit code — see interpretAddResult.\n return Promise.resolve(interpretAddResult(result, readState(), binary));\n },\n remove: () => {\n const binary = resolveBinary();\n if (!binary) {\n return Promise.resolve({\n success: false,\n message: `claude CLI not found in the standard install locations. If Claude Code is installed somewhere custom, remove the entry yourself:\\n ${describeCommand('claude', ['mcp', 'remove', SERVER_NAME, '--scope', 'user'])}`,\n });\n }\n // Through runClaude so this shares the spawn handling: previously it called\n // execFileSync directly, which cannot spawn a .cmd — and its catch reported\n // success regardless, so a failed removal printed a tick while the entry\n // stayed in the user's config.\n const result = runClaude(binary, [\n 'mcp',\n 'remove',\n '--scope',\n 'user',\n SERVER_NAME,\n ]);\n // A refusal ran nothing, so there is nothing to verify — and reading the config\n // anyway would let interpretRemoveResult convert an unexecuted removal into\n // \"nothing to remove\".\n if (result.refused) return Promise.resolve(result);\n return Promise.resolve(\n interpretRemoveResult(result, readState(), binary)\n );\n },\n describeTarget: () => 'Claude Code user config (via `claude mcp` CLI)',\n };\n}\n\nconst claudeCodeClient = createClaudeCodeClient(findClaudeBinary);\n\nconst home = os.homedir();\n// `absoluteEnvDir` rather than `??`: an empty OR relative value must be treated as\n// unset. `path.join('', 'Claude', …)` yields a RELATIVE path, and every consumer here\n// either writes a plaintext API key to it or spawns it — so a relative value means\n// writing the key into whatever directory the wizard was launched from, or executing a\n// file out of it. This is the same defect three env vars have now produced\n// (CLAUDE_CONFIG_DIR, XDG_CONFIG_HOME, APPDATA), so it is resolved in one place.\n// A function, not a module-level const: read at call time so a test can exercise the\n// guard at all. As an import-time const, a test mutating process.env.APPDATA proved\n// nothing — reverting the guard to `??` left the entire suite green.\nfunction appDataDir(): string {\n return absoluteEnvDir(process.env.APPDATA, () =>\n path.join(home, 'AppData', 'Roaming')\n );\n}\n\n// Claude Desktop stores its config in an OS-specific location.\nexport function claudeDesktopConfigPath(): string {\n if (process.platform === 'win32') {\n return path.join(appDataDir(), 'Claude', 'claude_desktop_config.json');\n }\n if (process.platform === 'darwin') {\n return path.join(\n home,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json'\n );\n }\n // Linux followed the XDG location. Previously this returned the macOS path on\n // Linux, so a Linux user was told `✓ Claude Desktop configured` for a file under\n // ~/Library that nothing reads.\n return path.join(\n absoluteEnvDir(process.env.XDG_CONFIG_HOME, () =>\n path.join(home, '.config')\n ),\n 'Claude',\n 'claude_desktop_config.json'\n );\n}\n\n// VS Code uses a `servers` property (not `mcpServers`) in a per-user mcp.json.\nexport function vsCodeConfigPath(): string {\n if (process.platform === 'win32') {\n return path.join(appDataDir(), 'Code', 'User', 'mcp.json');\n }\n if (process.platform === 'darwin') {\n return path.join(\n home,\n 'Library',\n 'Application Support',\n 'Code',\n 'User',\n 'mcp.json'\n );\n }\n // Honours XDG_CONFIG_HOME like the Claude Desktop path does. Hardcoding ~/.config\n // meant an XDG user got `✓ Visual Studio Code configured` for a file VS Code does not\n // read — the same defect this PR fixed for Claude Desktop on Linux.\n return path.join(\n absoluteEnvDir(process.env.XDG_CONFIG_HOME, () =>\n path.join(home, '.config')\n ),\n 'Code',\n 'User',\n 'mcp.json'\n );\n}\n\nexport const CLIENTS: McpClient[] = [\n claudeCodeClient,\n jsonClient({\n id: 'cursor',\n name: 'Cursor',\n // A VS Code fork, and its MCP reader keeps VS Code's tolerance — comments and\n // trailing commas both parse. Read out of the shipped bundle, not assumed from\n // \"Electron app\"; see ConfigDialect.\n dialect: 'jsonc',\n configPath: () => path.join(home, '.cursor', 'mcp.json'),\n }),\n jsonClient({\n id: 'windsurf',\n name: 'Windsurf',\n // Not installed on any machine this was checked on, so its parser was never read.\n // Lenient-and-disclosed rather than a guess in either direction.\n dialect: 'unverified',\n // Windsurf is stdio-only, so it reaches the hosted server via mcp-remote.\n hostedStrategy: 'mcp-remote',\n configPath: () =>\n path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),\n }),\n jsonClient({\n id: 'claude-desktop',\n name: 'Claude Desktop',\n // Genuinely strict: its reader is a bare `JSON.parse(readFileSync(...))` with no\n // preprocessing and no retry, so a comment or trailing comma is fatal.\n dialect: 'json',\n // Claude Desktop config files are stdio-only; use the mcp-remote bridge.\n hostedStrategy: 'mcp-remote',\n configPath: claudeDesktopConfigPath,\n // Detect by the application/support directory, which exists once the app runs.\n detectPaths: () => [path.dirname(claudeDesktopConfigPath())],\n }),\n jsonClient({\n id: 'vscode',\n name: 'Visual Studio Code',\n serverProperty: 'servers',\n // The one client that genuinely reads JSONC — comments and trailing commas in\n // mcp.json are supported and common.\n dialect: 'jsonc',\n configPath: vsCodeConfigPath,\n detectPaths: () => [path.dirname(vsCodeConfigPath())],\n }),\n];\n","// Keep key verification independent of the interactive wizard.\nimport { sdkBase } from '../_shared/hosts.js';\n\n// Interactive: the user is watching a spinner, so fail fast enough to retype a\n// key rather than wait out a network stall.\nexport const VERIFY_API_KEY_TIMEOUT_MS = 10_000;\n\n// Verify the API key works by calling a read-only REST endpoint. Returns true\n// on success, false on auth failure, and null when the check itself failed\n// (offline, timed out, etc.) so we can warn without blocking. The deadline is a\n// parameter so a test can drive the stall in milliseconds; the wizard always\n// takes the default.\nexport async function verifyApiKey(\n apiKey: string,\n timeoutMs: number = VERIFY_API_KEY_TIMEOUT_MS\n): Promise<boolean | null> {\n try {\n const response = await fetch(`${sdkBase(process.env)}/v2/pods`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n // Without this the wizard sits at \"Verifying…\" forever against a host\n // that accepts the connection and goes quiet, with no way out but ^C.\n // An abort lands in the catch below and is reported as \"check failed\",\n // which is exactly what it is.\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (response.ok) return true;\n if (response.status === 401 || response.status === 403) return false;\n return null;\n } catch {\n return null;\n }\n}\n","import { execFileSync } from 'child_process';\nimport * as p from '@clack/prompts';\nimport {\n CLIENTS,\n HOSTED_URL,\n type AddMode,\n type McpClient,\n} from './clients.js';\nimport { verifyApiKey } from './verify-key.js';\n\nconst API_KEYS_URL = 'https://www.runpod.io/console/user/settings';\n\n// Open a URL in the user's default browser. Best-effort and non-fatal.\nfunction openBrowser(url: string): void {\n try {\n // The URL is a literal arg, not an interpolated string. The Windows branch is\n // the exception: `start` is a cmd built-in, so that one does go through a shell\n // (the first quoted arg is the window title, hence the empty ''). Safe only\n // because every URL reaching here is a compile-time constant — do not extend\n // this to a URL from user input without escaping it.\n if (process.platform === 'darwin') {\n execFileSync('open', [url], { stdio: 'ignore' });\n } else if (process.platform === 'win32') {\n execFileSync('cmd', ['/c', 'start', '', url], { stdio: 'ignore' });\n } else {\n execFileSync('xdg-open', [url], { stdio: 'ignore' });\n }\n } catch {\n // Ignore — the user can open the URL manually.\n }\n}\n\nfunction bail(message = 'Cancelled.'): never {\n p.cancel(message);\n process.exit(0);\n}\n\nasync function promptForApiKey(): Promise<string> {\n // Trimmed like the pasted path below. An env var picked up from a shell profile\n // or a .env file can carry a trailing newline, which would otherwise be written\n // verbatim into every client config and, on Windows, reach a shim's `%*`.\n const fromEnv = process.env.RUNPOD_API_KEY?.trim();\n if (fromEnv) {\n const useEnv = await p.confirm({\n message: 'Use the RUNPOD_API_KEY from your environment?',\n });\n if (p.isCancel(useEnv)) bail();\n if (useEnv) return fromEnv;\n }\n\n const create = await p.confirm({\n message: 'Open the Runpod console to create or copy an API key?',\n });\n if (p.isCancel(create)) bail();\n if (create) {\n openBrowser(API_KEYS_URL);\n p.log.info(`Opening ${API_KEYS_URL}`);\n }\n\n const apiKey = await p.password({\n message: 'Paste your Runpod API key',\n validate: (value) =>\n !value || value.trim().length === 0\n ? 'API key cannot be empty'\n : undefined,\n });\n if (p.isCancel(apiKey)) bail();\n return apiKey.trim();\n}\n\nasync function selectClients(\n detected: Map<string, boolean>,\n verb: string\n): Promise<McpClient[]> {\n const options = CLIENTS.map((client) => ({\n value: client.id,\n label: client.name,\n hint: detected.get(client.id) ? 'detected' : undefined,\n }));\n\n const selected = await p.multiselect<string>({\n message: `Which agents should we ${verb}?`,\n options,\n // Pre-select detected clients so the common case is a single Enter press.\n initialValues: CLIENTS.filter((c) => detected.get(c.id)).map((c) => c.id),\n required: true,\n });\n if (p.isCancel(selected)) bail();\n\n return CLIENTS.filter((c) => selected.includes(c.id));\n}\n\nasync function detectAll(): Promise<Map<string, boolean>> {\n const entries = await Promise.all(\n CLIENTS.map(async (c) => [c.id, await c.detect()] as const)\n );\n return new Map(entries);\n}\n\n// Ask how the server should be wired up, then collect what that mode needs.\n// Hosted is the default: the client signs in with Runpod over OAuth and no key\n// is ever written to disk. Local runs the server via npx with an API key.\nasync function selectMode(): Promise<AddMode> {\n const kind = await p.select({\n message: 'How do you want to connect to Runpod?',\n options: [\n {\n value: 'hosted',\n label: 'Sign in with Runpod (recommended)',\n hint: 'hosted, OAuth, no API key stored',\n },\n {\n value: 'local',\n label: 'Run locally with an API key',\n hint: 'runs on this machine via npx',\n },\n ],\n initialValue: 'hosted',\n });\n if (p.isCancel(kind)) bail();\n\n if (kind === 'hosted') {\n return { kind: 'hosted', url: HOSTED_URL };\n }\n\n const apiKey = await promptForApiKey();\n\n const verifySpinner = p.spinner();\n verifySpinner.start('Verifying API key');\n const valid = await verifyApiKey(apiKey);\n if (valid === true) {\n verifySpinner.stop('API key verified.');\n } else if (valid === false) {\n verifySpinner.stop('API key rejected by Runpod.');\n const proceed = await p.confirm({\n message: 'The key did not authenticate. Continue anyway?',\n initialValue: false,\n });\n if (p.isCancel(proceed) || !proceed) bail();\n } else {\n verifySpinner.stop('Could not verify the key (offline?). Continuing.');\n }\n\n return { kind: 'local', apiKey };\n}\n\nasync function runAdd(): Promise<void> {\n const detected = await detectAll();\n const clients = await selectClients(detected, 'set up');\n const mode = await selectMode();\n\n const results: string[] = [];\n for (const client of clients) {\n const spinner = p.spinner();\n spinner.start(`Configuring ${client.name}`);\n const result = await client.add(mode);\n if (result.success) {\n spinner.stop(`${client.name} configured.`);\n // A success can still carry a caveat — notably \"the entry already existed, so\n // your key was NOT updated\". Dropping the message turned that into an\n // unqualified tick, which is how a user rotating their key would end up with\n // the old one still in place.\n results.push(\n `✓ ${client.name} — ${result.message ? `${result.message}; ` : ''}${client.describeTarget()}`\n );\n } else {\n spinner.stop(`${client.name} failed.`);\n results.push(`✗ ${client.name} — ${result.message ?? 'unknown error'}`);\n }\n }\n\n p.note(results.join('\\n'), 'Results');\n p.outro(\n mode.kind === 'hosted'\n ? 'Restart your agent, then complete \"Sign in with Runpod\" when it connects.'\n : 'Restart your agent (or reconnect MCP) to load the Runpod tools.'\n );\n}\n\nasync function runRemove(): Promise<void> {\n const detected = await detectAll();\n const clients = await selectClients(detected, 'remove Runpod from');\n\n const results: string[] = [];\n for (const client of clients) {\n const spinner = p.spinner();\n spinner.start(`Removing from ${client.name}`);\n const result = await client.remove();\n spinner.stop(\n result.success ? `${client.name} cleaned up.` : `${client.name} failed.`\n );\n results.push(\n `${result.success ? '✓' : '✗'} ${client.name}${\n result.message ? ` — ${result.message}` : ''\n }`\n );\n }\n\n p.note(results.join('\\n'), 'Results');\n p.outro('Done.');\n}\n\n// Entry point for `npx @runpod/mcp-server <add|remove>`.\nexport async function runWizard(subcommand: string): Promise<void> {\n p.intro('Runpod MCP server installer');\n\n if (subcommand === 'remove') {\n await runRemove();\n } else {\n await runAdd();\n }\n}\n","import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { SERVER_VERSION } from './server.js';\nimport { createSpecgenServer } from './specgen/server.js';\nimport { createToolContext } from './specgen/context.js';\n\n// Detect the install wizard subcommand (`add` / `remove`). In this mode we run\n// the interactive installer instead of starting the stdio server, and the API\n// key is collected by the wizard rather than required up front.\nconst WIZARD_SUBCOMMANDS = ['add', 'remove'];\nconst subcommand = process.argv[2];\nconst isWizardMode = WIZARD_SUBCOMMANDS.includes(subcommand);\n\nasync function main(apiKey: string): Promise<void> {\n // One surface everywhere: stdio serves the same spec-generated tool set\n // and skill resources the hosted path serves (see specgen/DESIGN.md).\n // stdio keeps the 5-minute wait budgets — no gateway reaper applies here.\n // ALP write tools are hosted-only by decision (docs/agent-learning-protocol.md):\n // the stdio path never registers them, so local users cannot enable them.\n const server = createSpecgenServer(\n createToolContext({\n apiKey,\n tracking: { transport: 'stdio', serverVersion: SERVER_VERSION },\n }),\n SERVER_VERSION\n );\n await server.connect(new StdioServerTransport());\n}\n\nif (isWizardMode) {\n import('./install/wizard.js')\n .then(({ runWizard }) => runWizard(subcommand))\n .catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n} else {\n // Get API key from environment variable\n const API_KEY = process.env.RUNPOD_API_KEY;\n if (!API_KEY) {\n console.error('RUNPOD_API_KEY environment variable is required');\n process.exit(1);\n }\n\n main(API_KEY).catch((error) => {\n console.error('Failed to start Runpod MCP server:', error);\n process.exit(1);\n });\n}\n","// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` with the\n// current `version` from package.json. Falls back to `'dev'` when the\n// substitution doesn't happen (e.g. running via tsx).\ndeclare const __PACKAGE_VERSION__: string;\n\nexport const SERVER_NAME = 'Runpod API Server';\nexport const SERVER_VERSION =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : 'dev';\n","// MCP server wiring: the generated tool set plus the curated overlay, served\n// over the low-level protocol Server so generated JSON Schemas pass through\n// without a Zod round-trip.\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolContext } from './context.js';\nimport {\n dispatchGeneratedTool,\n validateArguments,\n type ToolResult,\n} from './dispatch.js';\nimport { generatedTools } from './generated/tools.gen.js';\nimport { getCapacity } from './tools/capacity.js';\nimport { setEndpointGpus } from './tools/endpoint-gpus.js';\nimport { hubTools } from './tools/hub.js';\nimport { jobTools } from './tools/jobs.js';\nimport { listEndpoints } from './tools/list-endpoints.js';\nimport { listTemplates } from './tools/list-templates.js';\nimport { logTools } from './tools/logs.js';\nimport { listPublicEndpoints } from './tools/public-endpoints.js';\nimport {\n GUIDE_URI_PREFIX,\n guideResources,\n knowledgeTools,\n} from './tools/knowledge.js';\nimport { runTool } from './tools/util.js';\nimport { STATUS_WAIT_MAX_MS } from './tools/jobs.js';\nimport { SERVER_NAME } from '../server.js';\nimport { captureToolCall } from './analytics.js';\nimport { createAlpTools, type AlpToolsOptions } from './tools/alp.js';\nimport {\n callerId,\n logToolCall,\n noopRateLimiter,\n type RateLimiter,\n} from './ops.js';\n\nimport type { CuratedTool } from './types.js';\nexport type { CuratedTool } from './types.js';\n\n// The curated overlay: tools whose backing plane the v2 spec does not cover\n// (Serverless runtime, GraphQL), plus targeted replacements for generated\n// tools that need shaping (list-templates) or a non-JSON transport (the SSE\n// log tools).\nexport const curatedTools: CuratedTool[] = [\n listEndpoints,\n listTemplates,\n ...jobTools,\n ...logTools,\n getCapacity,\n ...hubTools,\n setEndpointGpus,\n listPublicEndpoints,\n ...knowledgeTools,\n];\n\n// Usage briefing delivered to connecting agents at initialize (the MCP\n// `instructions` field). The official server ships one; agents without it\n// tend to answer account questions from memory instead of calling tools.\n// This block is the maintained EXCERPT of the answer contract; the canonical\n// full text lives in the plugin's runpod-mcp skill, served here as the\n// runpod-mcp guide from @runpod/plugin-knowledge.\nexport const 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.\n\nAnswer 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 — 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 — an honest empty answer is complete.\n\nCommit; don't hedge, don't defer. Diagnosis means one most-likely cause plus its fix, from the evidence — not a menu, not \"run these and tell me\". For jobs, submit with run-endpoint and block server-side with get-job-status wait (up to ${STATUS_WAIT_MAX_MS} ms); use runsync-endpoint only for a warm endpoint and a fast job. Expect first-job cold starts of minutes, and check worker states between holds; when a wait outlasts what the tools can hold, report the evidenced state — what was created, what was submitted, what the worker states show — and the recommended next step. Offering to keep watching is fine; stopping mid-wait without that report is not. Never claim success without the artifact that proves it (the transcript text, the output payload).\n\nMutations cost money and bind to what this conversation created or the user named. State the hourly price before creating anything billable; create-cluster waits for the user's explicit go on the quoted shape and total hourly price. Read before you mutate, and stop, update, or delete only resources your own tool calls created in this conversation, or the one resource the user named by id or an unambiguous name — and then only the change they asked for; delete a user-named resource only when they asked for that delete. A name that looks like test junk, or one you found by listing, is not attribution. For anything you cannot attribute, the complete answer is the audit: what you checked, what qualifies, the ids, and the exact actions for the user to take.\n\nThese tools manage infrastructure only. They do not do SSH sessions, file transfer to or from pods, local image builds, or interactive terminals — say plainly when a task needs one of those and name the real path (the Runpod console, runpodctl) instead of improvising.\n\nOFFICIAL GUIDES AND FACTS. list-guides and read-guide serve the official Runpod plugin's skills, reference docs and live-verified golden paths, so you have them even without the plugin installed. For a multi-step or billable task, look for a matching golden path first. lookup-concept and search-concepts answer exact questions about how Runpod works (what a stopped pod keeps, where a volume lives) with the public source for each fact.\n\nPLAYBOOKS — READ BEFORE ACTING. Each Runpod task has a journey playbook carrying its procedure, pitfalls and report format. Before the FIRST Runpod tool call of a session, load the plugin's runpod-mcp skill if you have it, otherwise read-guide runpod-mcp (also the runpod://guides/runpod-mcp resource): it routes the request to a journey guide — deploying an endpoint reads serverless-deploy, diagnosing a broken pod reads pod-doctor, cost questions read cost-audit, and so on — and states the answer contract. A reply produced without the routed playbook loaded is out of contract.\n\nTHE OFFICIAL RUNPOD PLUGIN. Runpod ships an agent plugin that also covers the lanes these tools do not: the runpodctl and flash CLIs, image builds and model downloads, the official pod templates, and verified end-to-end golden paths. Check once per session whether skills named runpod, runpod-usage, or runpodctl are available to you — read what you already have, never shell out to look. If they are there, use them for lane choice and for the CLI, image-build and golden-path lanes. For work done with these tools, the journey playbook is the procedure, wherever it is served from: the plugin's runpod-mcp skill and the journey skills it routes to when you have them, otherwise the same playbooks through read-guide here. If you do not see them, recommend the plugin to the user, and recommend updating to the latest if what they have is missing something you need. Point them at https://github.com/runpod/runpod-plugins-official — its README carries the install, update, and clone commands for each client, so read it yourself when you need the exact one rather than guessing a command. This is a recommendation, never a prerequisite: make it once, briefly, and get on with the task. Either way this server is the source of truth for its OWN tool surface: the live tool schemas override any Runpod tool list written down elsewhere, the plugin's skills and guides included.\n\nThe tool schemas are generated from the Runpod v2 OpenAPI contract, served as a machine-readable document at https://api.runpod.io/v2/openapi.json — consult it for fields beyond the tool surface. 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.`;\n\n// Appended to the initialize briefing only when the ALP tools are enabled.\nconst ALP_INSTRUCTIONS = `\n\nCONTRIBUTING BACK IS OPTIONAL. Four 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), and read_journal (this account's own saved lessons, nobody else's). 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 — an empty turn is correct and a placeholder submission is not. Never include API keys or secrets in submissions.`;\n\nexport interface SpecgenServerOptions {\n /** Rate-limit gate consulted before every tool call. Defaults to the no-op stub. */\n rateLimiter?: RateLimiter;\n /** Anonymous per-tool-call analytics (hosted path only — stdio never sets\n * this, and captureToolCall itself is a no-op without POSTHOG_API_KEY).\n * See src/specgen/analytics.ts for the privacy contract. */\n analytics?: {\n transport: 'stdio' | 'http';\n serverVersion: string;\n /** Sanitized client token (never a raw header). */\n clientName?: string;\n /** Stable account id from the credential pre-flight (myself.id) — the\n * preferred identity source; hashed before it leaves the process. */\n accountId?: string;\n };\n /** Called when a tool result is a 401: the hosted path uses it to drop the\n * cached credential verdict so the NEXT request re-checks and can emit the\n * HTTP 401 that makes OAuth clients re-authenticate. */\n onUnauthorized?: () => void;\n /** ALP write tools (report_feedback / save_to_journal / ask_question).\n * Enablement follows configuration: when absent, the tools do not appear\n * in tools/list at all. See docs/agent-learning-protocol.md. */\n alp?: AlpToolsOptions;\n}\n\nexport function createSpecgenServer(\n ctx: ToolContext,\n version = '0.1.0',\n opts: SpecgenServerOptions = {}\n): Server {\n const rateLimiter = opts.rateLimiter ?? noopRateLimiter;\n const caller = callerId(ctx.apiKey);\n // The served curated set: the static surface plus the config-gated ALP\n // write tools. Everything downstream (list, routing) reads this, so a\n // disabled ALP is truly absent, not present-and-failing.\n const servedCuratedTools = opts.alp\n ? [...curatedTools, ...createAlpTools(opts.alp)]\n : curatedTools;\n const server = new Server(\n { name: SERVER_NAME, version: `${version} [specgen]` },\n {\n capabilities: { tools: {}, resources: {} },\n instructions: opts.alp\n ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS\n : SERVER_INSTRUCTIONS,\n }\n );\n\n // The stdio transport only learns which client is driving from the MCP\n // initialize handshake — feed it into the outbound tracking User-Agent\n // (the hosted path already resolves identity from the inbound UA).\n server.oninitialized = () => {\n const clientInfo = server.getClientVersion();\n if (clientInfo?.name) {\n ctx.setClientInfo?.(clientInfo.name, clientInfo.version);\n // ALP submissions attribute the harness the same way the tracking UA\n // does; the ALP tools read opts.alp at call time, so this late bind\n // reaches them.\n if (opts.alp) {\n opts.alp.harness = clientInfo.version\n ? `${clientInfo.name}/${clientInfo.version}`\n : clientInfo.name;\n opts.alp.harnessSource = 'client_info';\n }\n }\n };\n\n // annotations travel with every tool: hosts use readOnlyHint and\n // destructiveHint to decide what a human has to approve, so dropping them\n // here would make delete-pod indistinguishable from list-pods. Generated\n // tools derive theirs from the HTTP method; curated ones declare theirs.\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...servedCuratedTools.map(\n ({ name, description, inputSchema, annotations }) => ({\n name,\n description,\n inputSchema,\n annotations,\n })\n ),\n ...generatedTools.map(\n ({ name, description, inputSchema, annotations }) => ({\n name,\n description,\n inputSchema,\n annotations,\n })\n ),\n ],\n }));\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: guideResources.map(({ text: _text, ...resource }) => resource),\n }));\n\n // Some clients probe templates unconditionally; answer empty instead of -32601.\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({\n resourceTemplates: [],\n }));\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const guide = guideResources.find(\n (candidate) => candidate.uri === request.params.uri\n );\n if (!guide) {\n throw new Error(\n `Unknown resource ${request.params.uri}. Resources are the plugin guides under ${GUIDE_URI_PREFIX}; call list-guides for the guide ids.`\n );\n }\n return {\n contents: [\n { uri: guide.uri, mimeType: 'text/markdown', text: guide.text },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n // Rate-limit seat: consulted before any tool work. The stub always admits;\n // a denial comes back as a retryable tool error, not a protocol failure.\n const verdict = await rateLimiter(caller, request.params.name);\n if (!verdict.allowed) {\n logToolCall({\n tool: request.params.name,\n caller,\n ok: false,\n status: 429,\n durationMs: 0,\n });\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: 'Rate limited by this MCP server.',\n hint: `Pause${verdict.retryAfterS ? ` ~${verdict.retryAfterS}s` : ' briefly'}, then retry the same call.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const startedAt = Date.now();\n const curated = servedCuratedTools.find(\n (tool) => tool.name === request.params.name\n );\n // runTool here as well as inside the curated handlers: it maps an HttpError\n // raised outside a handler body — a missing API key when the SDK client is\n // first built (src/specgen/context.ts) — onto a 401 tool result instead of a\n // protocol-level crash.\n // Curated tools get the same argument-shape gate as generated ones, from\n // their own inputSchema. Before this they read only the keys they knew,\n // so a misnamed argument produced a confident wrong answer (see\n // validateArguments). Generated tools run the gate inside dispatch.\n const rejected =\n curated && !curated.lenientArguments\n ? validateArguments(\n curated.inputSchema as { required?: unknown; properties?: unknown },\n args\n )\n : null;\n const result =\n rejected ??\n (await runTool(() =>\n curated\n ? curated.handler(ctx, args)\n : dispatchTool(request.params.name, args)\n ));\n logToolCall({\n tool: request.params.name,\n caller,\n ok: result.ok,\n status: result.status,\n durationMs: Date.now() - startedAt,\n });\n if (opts.analytics) {\n captureToolCall(ctx.apiKey, {\n tool: request.params.name,\n ok: result.ok,\n status: result.status,\n durationMs: Date.now() - startedAt,\n ...opts.analytics,\n });\n }\n // A 401 from the API proves a cached \"valid\" credential verdict wrong\n // before its TTL — let the shell drop it.\n if (!result.ok && result.status === 401) opts.onUnauthorized?.();\n\n // On errors, attach a recovery hint by status class — the bare-client\n // (no-skills) path self-corrects from these instead of dead-ending. A hint\n // already on the payload wins: dispatch/runtime derive precise 429 wait\n // instructions from the response headers, and the generic \"pause briefly\"\n // text must not clobber them.\n const payload = result.ok ? result.payload : withRecoveryHint(result);\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n isError: !result.ok,\n };\n });\n\n async function dispatchTool(\n name: string,\n args: Record<string, unknown>\n ): Promise<ToolResult> {\n const tool = generatedTools.find((candidate) => candidate.name === name);\n if (!tool)\n return {\n ok: false,\n status: 404,\n payload: { error: `unknown tool ${name}` },\n };\n return dispatchGeneratedTool(ctx.sdk, tool, args);\n }\n\n return server;\n}\n\nfunction errorHint(status: number): string | undefined {\n if (status === 400 || status === 422)\n return \"Input shape mismatch: check this tool's schema for required fields. For job payloads, the worker's release config defines the expected input object — fix the payload and retry; don't abandon the task.\";\n if (status === 401) return 'The Runpod API key is missing or invalid.';\n if (status === 402)\n return 'Check your account balance in the Runpod console before retrying billable operations; list-billing shows the recent spend behind it.';\n if (status === 403)\n return 'Check that this API key has permission for the requested resource and operation. Review its permissions in the Runpod console before retrying. A permission error on a resource you did not create is final: report it rather than retrying.';\n if (status === 404)\n return 'No such resource on this account: verify the id with the matching list- tool before retrying.';\n if (status === 429)\n return 'Rate limited: pause briefly, then retry the same call.';\n if (status >= 500)\n return 'Upstream Runpod error: retry once; if it persists, report it as an API-side failure.';\n return undefined;\n}\n\nfunction withRecoveryHint(result: ToolResult): Record<string, unknown> {\n const payload = asRecord(result.payload) ?? { error: result.payload };\n return {\n ...payload,\n hint:\n payload.hint ??\n asRecord(payload.detail)?.hint ??\n errorHint(result.status),\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","// ============== 429 RATE-LIMIT HINT ==============\n// A 429's bare \"rate limit exceeded\" invites the worst possible agent\n// response: retrying immediately. This turns one into a wait instruction,\n// reading the IETF `RateLimit` field and `Retry-After`. Kept out of the HTTP\n// client because it shares nothing with it — two strings in, one string out —\n// and because both the client and the SSE log reader need it.\n\n// No window names or numbers here: this same client serves the serverless host\n// (api.runpod.ai), whose quota shape this repo doesn't document, so naming\n// minute/hour/day windows would assert a REST fact somewhere it may not hold.\nconst GENERIC_RATE_LIMIT_HINT =\n 'rate limited — back off before retrying, and pace bulk operations';\n\n// The longest window this API documents is a day; the slack covers an\n// undocumented serverless policy without printing \"~1157407408 days\" for a\n// broken or hostile header, which the digit count alone would not bound.\n// Rejecting is cheap either way: a discarded reset never shortens the wait —\n// it hedges it when another source still answers, and otherwise leaves the\n// \"no usable reset time\" clause to say so outright.\nconst MAX_PLAUSIBLE_WAIT_S = 7 * 86400;\n\n// One window reporting zero requests left. `window` is null when the name was\n// unreadable — the reset is independently trustworthy, and dropping the item\n// would throw away a correct number to avoid printing a doubtful name.\n// `resetS` is null when the window sent no readable `t`: the parameter is\n// optional, and a value that is unparseable (`t=1.5`), implausible (past the\n// cap) or valueless (`t` alone) all read the same way — absent. The member\n// still counts, because its `r` is what said the window is out.\ninterface ExhaustedWindow {\n window: string | null;\n resetS: number | null;\n}\n\n// A count of remaining requests. Only ever compared against zero, so its\n// magnitude doesn't matter — but blank must not pass: `Number('')` is 0, which\n// would read `\"hour\";r=;t=` as a real exhausted window.\nfunction remainingRequests(raw: string | undefined): number | null {\n const value = raw?.trim();\n return value && /^\\d+$/.test(value) ? Number(value) : null;\n}\n\n// A number of seconds to wait, from `t` or from `Retry-After`. Both are plain\n// digit strings — `1.5`, `-30`, `0x10` and `1e3` are not, and `Number()` would\n// happily coerce every one of them.\nfunction waitSeconds(raw: string | null | undefined): number | null {\n const value = raw?.trim();\n if (!value || !/^\\d+$/.test(value)) return null;\n const seconds = Number(value);\n return seconds <= MAX_PLAUSIBLE_WAIT_S ? seconds : null;\n}\n\n// A window name, or null if it isn't one. The name lands verbatim in an error\n// message an agent reads, so validate rather than sanitize — including its\n// length. Truncating would print a name that isn't in the header, which is the\n// same defect as stripping the parts that don't belong: `\"a,b\"` reported as\n// \"the b quota\". A quoted name takes any UNESCAPED string character, so\n// `\"gpu hour\"` is named rather than dropped; a `\\`-escape or a display string\n// is legal but unsupported, and dropping the name beats printing one we\n// haven't unescaped. Bare names follow the token grammar.\nconst WINDOW_NAME_RE =\n /^(?:\"([\\x20-\\x21\\x23-\\x5b\\x5d-\\x7e]{1,32})\"|([A-Za-z*][A-Za-z0-9!#$%&'*+.^_`|~:/-]{0,31}))$/;\nfunction windowName(raw: string): string | null {\n const match = WINDOW_NAME_RE.exec(raw.trim());\n return match ? (match[1] ?? match[2]) : null;\n}\n\n// A parameter value that is a complete quoted string and nothing else. Testing\n// only the first and last character would pass `pk=\"x\" \"minute\"`, where a\n// second item was glued on after a legal value — the same merge as below, one\n// quote further along.\nconst QUOTED_VALUE_RE = /^\"(?:[\\x20-\\x21\\x23-\\x5b\\x5d-\\x7e]|\\\\[\"\\\\])*\"$/;\n// A display string is a legal parameter value too (`%\"caf%c3%a9\"`). Reading it\n// as malformed would silently collapse every hint on the day the API adds one,\n// which is the failure this file exists to avoid — so match it, still whole.\nconst DISPLAY_VALUE_RE =\n /^%\"(?:[\\x20-\\x21\\x23-\\x24\\x26-\\x5b\\x5d-\\x7e]|\\\\|%[0-9a-f]{2})*\"$/;\n\n// Whether a `;`-separated chunk is a well-formed parameter. A dropped comma\n// glues the next item onto the previous parameter's VALUE — `t=3600 \"minute\"`,\n// or `t=3600 minute` in the token form — and last-wins then merges the two\n// items under the FIRST one's name and the SECOND one's reset, which is how a\n// 3600s lockout gets answered with \"wait ~10s\". A bare value can hold no\n// whitespace (every unquoted item type excludes it) and no quote, so either\n// means two items ran together. The draft says a malformed field MUST be\n// ignored wholesale; dropping just the item keeps more signal and still never\n// over-reports, because `dropped` forces the \"at least\".\nfunction isWellFormedParam(param: string): boolean {\n const eq = param.indexOf('=');\n const key = (eq === -1 ? param : param.slice(0, eq)).trim();\n if (key.includes('\"')) return false;\n if (eq === -1) return true;\n const value = param.slice(eq + 1).trim();\n if (value.startsWith('\"')) return QUOTED_VALUE_RE.test(value);\n if (value.startsWith('%\"')) return DISPLAY_VALUE_RE.test(value);\n return !/[\\s\"]/.test(value);\n}\n\n// Split on `sep` only where it isn't inside a quoted string. A plain\n// `String.split` cuts `\"a,b\";r=0;t=1812` — a legal window name — in half,\n// losing that window's r/t entirely, and if a shorter window survives alongside\n// it the hint confidently reports the shorter wait. Same for a vendor parameter\n// the draft leaves untyped (`acme-scope=\"a,b\"`). Strings are the only construct\n// that can hide a delimiter: `pk` is a byte sequence (`pk=:QXBwLTk5OQ==:`),\n// whose base64 alphabet holds neither. An unterminated quote yields one chunk,\n// which then fails validation — as a name if the quote opened in the name\n// position, as a parameter otherwise. Malformed in, generic out.\nfunction splitOutsideStrings(input: string, sep: ',' | ';'): string[] {\n const parts: string[] = [];\n let current = '';\n let inString = false;\n // A display string opens with `%\"`, and inside one a backslash is a literal\n // character rather than an escape — treating it as an escape would eat the\n // closing quote and swallow the rest of the field.\n let inDisplay = false;\n let escaped = false;\n let prev = '';\n for (const ch of input) {\n if (escaped) escaped = false;\n else if (inString && !inDisplay && ch === '\\\\') escaped = true;\n else if (ch === '\"') {\n if (!inString) inDisplay = prev === '%';\n inString = !inString;\n } else if (ch === sep && !inString) {\n parts.push(current);\n current = '';\n prev = ch;\n continue;\n }\n current += ch;\n prev = ch;\n }\n parts.push(current);\n return parts;\n}\n\n// Split-based rather than one regex: the field is a structured-field list, so\n// params may be reordered (`\"hour\";t=1724;r=0`), spaced, or carry unknown\n// vendor keys, and `t` may be absent — a pattern pinned to `r=<n>;t=<n>` yields\n// nothing on variants that mean the same thing, and silence here costs the\n// specifics exactly when they matter. Never throws.\n//\n// `dropped` reports whether anything was thrown away unread — only a malformed\n// item, since an unreadable name keeps its numbers. It has to reach the caller:\n// otherwise a discarded `r=0;t=3600` lets a readable 10-second sibling answer\n// as if it were the whole truth.\ninterface ParsedWindows {\n windows: ExhaustedWindow[];\n dropped: boolean;\n}\n\n// A member's parameters, and whether reading them left `r` or `t` unreadable.\n// Three tells, the first two being shapes a lost comma produces:\n// - a valueless parameter FOLLOWED BY `r` or `t`. Valueless is the only legal\n// way to send a Boolean-true flag (RFC 9651 §3.1.2: a true value MUST be\n// omitted), but it is also exactly what a glued bare-token name looks like —\n// `\"minute\";t=10;hour;r=0` is one item with an `hour` flag, or two items and\n// a lost comma, and nothing in the field tells them apart. Only a number\n// AFTER the flag can have been misattributed, so a trailing flag\n// (`\"hour\";r=0;t=3600;acme-flag`) costs nothing and is kept.\n// - `r` or `t` twice. RFC 9651's note on parsing parameters — \"when duplicate\n// parameter keys are encountered, all but the last instance are ignored\" —\n// carries no RFC 2119 keyword, and `minute;r=0;t=2876;minute;r=0;t=1641` is\n// the same glue, where last-wins answers a 2876s lockout with 1641s.\n// - `r` or `t` sent valueless at all, glue or not. A bare flag is Boolean\n// true, so `\"hour\";r=0;t` states no reset and `\"hour\";r=0;r` never says\n// the window is out — the value simply isn't there to read.\n// In every case we can't say what the number is, or whether it is ours, so\n// don't pick one.\nfunction readParams(params: string[]): {\n values: Map<string, string>;\n unreadable: boolean;\n} {\n const values = new Map<string, string>();\n let unreadable = false;\n let valuelessAt = -1;\n for (const [index, param] of params.entries()) {\n const eq = param.indexOf('=');\n // Keys are lowercase in the grammar; fold case rather than miss an\n // exhausted window over a server sending `R=0`.\n const key = (eq === -1 ? param : param.slice(0, eq)).trim().toLowerCase();\n if (!key) continue;\n if (eq === -1) {\n // A bare `r`/`t` is Boolean true, and parameters are last-wins, so the\n // member's own count or reset is not there to read — `t=3599;t` must not\n // quote 3599 as fact, nor `r=0;t=3599;r` call a window exhausted unasked.\n // Checked before the `continue`, or neither would be caught at all.\n //\n // The two differ in what survives. `r` is REQUIRED, so losing it loses\n // the only thing that says the window is out: nothing to report. `t` is\n // optional, and a member that states `r=0` with no readable reset is an\n // ordinary \"exhausted, reset unknown\" — already modelled, and already\n // what an unparseable `t=1.5` produces. Dropping the whole member there\n // would throw away a readable `r=0` to avoid an unreadable `t`.\n if (key === 'r') unreadable = true;\n if (key === 't') values.delete('t');\n valuelessAt = index;\n continue;\n }\n // A repeated `r`/`t`, or one that follows a valueless flag: either way\n // we can't say which name the number belongs to.\n if (\n (key === 'r' || key === 't') &&\n (values.has(key) || (valuelessAt !== -1 && index > valuelessAt))\n ) {\n unreadable = true;\n }\n values.set(key, param.slice(eq + 1));\n }\n return { values, unreadable };\n}\n\nfunction parseExhaustedWindows(header: string | null): ParsedWindows {\n if (!header) return { windows: [], dropped: false };\n const windows: ExhaustedWindow[] = [];\n let dropped = false;\n for (const item of splitOutsideStrings(header, ',')) {\n if (item.trim() === '') continue;\n const [rawName, ...params] = splitOutsideStrings(item, ';');\n if (!params.every(isWellFormedParam)) {\n dropped = true;\n continue;\n }\n const { values, unreadable } = readParams(params);\n if (unreadable) {\n dropped = true;\n continue;\n }\n // draft-11 §4.1 makes `r` REQUIRED, so a member without a readable one is\n // malformed: we know a window exists but not whether it is exhausted, which\n // hides at least as much as an item rejected outright. A readable non-zero\n // `r` is different — that window simply has requests left.\n const remaining = remainingRequests(values.get('r'));\n if (remaining === null) {\n dropped = true;\n continue;\n }\n if (remaining !== 0) continue;\n // A name we can't read costs us the name, not the reset behind it.\n windows.push({\n window: windowName(rawName),\n resetS: waitSeconds(values.get('t')),\n });\n }\n return { windows, dropped };\n}\n\n// \"1724s\" is easy to skim past; \"~29 minutes\" is not, and an agent that grasps\n// the scale is the one that stops retrying. Exact seconds stay in the string,\n// so the unit is only ever a reading aid — but an agent that skims the unit and\n// not the parenthesis must not be sent back early, so each tier rounds UP: 140s\n// reads \"~3 minutes\", never \"~2 minutes\". The minute and hour tiers hand over\n// before their count reaches three digits, a reading as hard to skim as the raw\n// seconds it would replace.\nfunction humanWait(seconds: number): string {\n if (seconds < 120) return `~${seconds}s`;\n if (seconds < 3600)\n return `~${Math.ceil(seconds / 60)} minutes (${seconds}s)`;\n if (seconds < 2 * 86400) {\n const hours = Math.ceil(seconds / 3600);\n return `~${hours} hour${hours === 1 ? '' : 's'} (${seconds}s)`;\n }\n // The days tier opens at two days, so it is never singular.\n return `~${Math.ceil(seconds / 86400)} days (${seconds}s)`;\n}\n\n// Name the exhausted quota and say how long to wait, from the two headers v2\n// sends on a 429 — `Retry-After` (seconds) and `RateLimit` (live per-window\n// state, `\"minute\";r=0;t=12, \"hour\";r=2800;t=1812`, where r = calls left and\n// t = seconds to reset).\n//\n// Report the LONGEST wait either header justifies. draft-11 §7 says Retry-After\n// MUST take precedence, but §6 says a server SHOULD NOT send one earlier than\n// the end of the effective window, and this API's is documented \"per the\n// exceeded window\" (see the vendored spec) — i.e. it can be earlier.\n// RFC 9110 §10.2.3 defines Retry-After as how long a client \"ought to wait\" and\n// sets no upper bound (its \"minimum time\" wording is scoped to 3xx), so waiting\n// longer conforms. §7's \"MAY be ignored\" is permission, not obligation, and\n// max() never waits less than Retry-After asks — so this declines the\n// permission rather than violating the precedence. Windows can read r=0\n// together — a loop pacing itself at the 60/min quota sits at minute r=0, and\n// 3000/hr is an exact multiple of 60, so the call that zeroes the hour is also\n// the 60th of its minute — and Retry-After then describes only the window that\n// rejected THIS request. Obeying it alone sends the agent back in 12s to a\n// quota that is out for another half hour. Hence \"wait ~N\" rather than \"the\n// hour quota resets in ~N\": the number is an instruction, not a claim about the\n// named window, so the two can never contradict each other. Generic guidance\n// when neither header is usable — the v1 REST API sends neither, and this\n// client also serves the serverless host, which this repo doesn't document.\nexport function rateLimitHint(\n rateLimitHeader: string | null,\n retryAfterHeader?: string | null\n): string {\n const { windows, dropped } = parseExhaustedWindows(rateLimitHeader);\n // Longest reset first; a window that sent no `t` sorts last, since an\n // unknown reset can't outrank a known one. Ties keep header order.\n windows.sort((a, b) => (b.resetS ?? -1) - (a.resetS ?? -1));\n // Typed explicitly: `strict` is on but `noUncheckedIndexedAccess` is not, so\n // `windows[0]` types as non-optional and every `?.` below reads as dead. It\n // isn't — `windows` is empty on every generic-hint path.\n const longestWindow: ExhaustedWindow | undefined = windows[0];\n // A wait of zero — from `t` or from `Retry-After` — is the one instruction a\n // 429 can't mean, so it is not a wait on offer from either source. An\n // HTTP-date Retry-After (legal per RFC 9110, not what this API sends) or\n // junk is likewise rejected, leaving the RateLimit reset to answer.\n const waitCandidates = [\n waitSeconds(retryAfterHeader),\n longestWindow?.resetS,\n ].filter((n): n is number => typeof n === 'number' && n > 0);\n const waitS = waitCandidates.length ? Math.max(...waitCandidates) : null;\n // A Retry-After we couldn't read is a missed instruction, not an absent one:\n // the server named a delay, we don't know it, and it may be far longer than\n // anything RateLimit says. An HTTP-date, `3600.5`, `+1800` and a value past\n // the plausibility cap all land here, hedging the same way they would if the\n // unreadable value had arrived in `t`. A readable `0` is not unreadable.\n const retryAfterUnreadable =\n typeof retryAfterHeader === 'string' &&\n retryAfterHeader.trim() !== '' &&\n waitSeconds(retryAfterHeader) === null;\n // The generic hint is for a response that withheld nothing: no header, no\n // exhausted window, no delay stated. It must not absorb a response that DID\n // state something we failed to read — that would hand back the file's mildest\n // wording precisely when the most was hidden, and a header stating an\n // unreadable day-long lockout would read softer than one stating no reset at\n // all. Anything unread falls through to \"no usable reset time\" instead.\n if (!longestWindow && waitS === null) {\n if (!retryAfterUnreadable) return GENERIC_RATE_LIMIT_HINT;\n }\n // \"the hour quota is exhausted\" rather than \"rate limited on the hour quota\":\n // the response body names the window that rejected THIS request, which in the\n // co-exhaustion case is a different one. Both statements are true, and this\n // phrasing doesn't claim to be the other.\n const namedClause = longestWindow?.window\n ? `the ${longestWindow.window} quota is exhausted`\n : '';\n // Exhausted, but nothing usable said when it clears. A number here would be\n // invented, which is the defect this function exists to avoid.\n if (waitS === null) {\n const cause = namedClause\n ? `${namedClause}, but the response gave no usable reset time`\n : 'the response gave no usable reset time';\n return `rate limited — ${cause}; back off substantially before retrying, and pace bulk operations`;\n }\n // This number is a floor, not the answer, whenever the header held something\n // we couldn't read: another exhausted window that omitted its reset, or an\n // item dropped whole. A quantified 10s window must not speak for a silent\n // day-long one.\n const hedge =\n dropped || retryAfterUnreadable || windows.some((w) => w.resetS === null)\n ? 'at least '\n : '';\n const wait = `wait ${hedge}${humanWait(waitS)} before retrying, and pace bulk operations`;\n return `rate limited — ${namedClause ? `${namedClause}; ` : ''}${wait}`;\n}\n\n// The one 429-enrichment used by both the generated-tool dispatcher and the\n// runtime client: spread the upstream error payload and attach the concrete\n// wait instruction derived from the response headers. Kept here so a change\n// to hint precedence lands in every consumer at once.\nexport function withRateLimitHint(\n payload: unknown,\n headers: { get(name: string): string | null }\n): unknown {\n // Gateways can send plain text or JSON primitives. Preserve that detail\n // inside an object so every 429 can carry the same recovery hint.\n const detail =\n typeof payload === 'object' && payload !== null\n ? (payload as Record<string, unknown>)\n : { error: payload };\n return {\n ...detail,\n hint: rateLimitHint(headers.get('ratelimit'), headers.get('retry-after')),\n };\n}\n","import type { ToolResult } from '../dispatch.js';\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\n\n/** Preserve status even when the API error has no body; attach quota guidance. */\nexport function restError(response: Response, error: unknown): ToolResult {\n const payload = error ?? {\n error: response.statusText || `HTTP ${response.status}`,\n };\n return {\n ok: false,\n status: response.status,\n payload:\n response.status === 429\n ? withRateLimitHint(payload, response.headers)\n : payload,\n };\n}\n","// Executes a generated tool call by mapping its arguments onto the SDK client:\n// path params substitute into the URL template, query params pass through, and\n// the optional \"body\" argument becomes the request body.\n\nimport type { RunpodClient } from '@runpod/typescript-api-sdk';\nimport type { GeneratedTool } from './generated/tools.gen.js';\nimport { restError } from './clients/rest-result.js';\n\n// A client caches tools/list when it connects. If the served surface changes\n// under a live session — a release, or a deployment alias moving — the client\n// keeps validating calls against the OLD schema and silently strips arguments\n// the new schema requires. The agent cannot see this: from inside the session\n// its schema looks authoritative, so it retries variations of a shape the\n// server will never accept. A production report burned a session that way,\n// sending flat v1 arguments (gpuTypeIds, imageName) at a body-shaped\n// create-pod and then re-sending them nested under a `body` key its own client\n// dropped, leaving `received: []`. Reconnecting is the only fix, so name it on\n// exactly the two errors a stale schema produces.\nconst STALE_SCHEMA_HINT =\n 'If this disagrees with the schema you hold, your tool list may be cached from an earlier version of this server. Reconnect the Runpod MCP server (in Claude Code, /mcp) to refresh tools/list, then call again — do not retry variations of the same argument shape.';\n\nexport interface ToolResult {\n ok: boolean;\n status: number;\n payload: unknown;\n}\n\n// Argument-shape gate, shared by every tool on the server. Two checks, both\n// read from the tool's own JSON Schema so no tool needs per-tool code:\n//\n// Missing required argument. Without this an unresolved path placeholder\n// reaches the API and comes back as a resource 404 (\"gpu type not found\"),\n// sending the agent off to re-verify an id that was never sent.\n//\n// Unknown argument. Handlers only read declared keys, so an argument with a\n// plausible-but-wrong name used to vanish in silence and the call still went\n// out — `includeAvailability` (the v1 spelling) on list-gpu-types returned a\n// 200 with no availability fields at all, which reads as \"priced and in stock\"\n// if you trust the request you thought you made. The curated tools had the\n// same hole until the 2026-09-09 release smoke: stream-pod-logs called with\n// `id` instead of `podId` fetched /pods/undefined/logs and answered 404\n// \"pod not found\" with a hint to re-verify the id. A wrong answer is worse\n// than an error, so name the key and list what the tool accepts.\nexport function validateArguments(\n inputSchema: { required?: unknown; properties?: unknown },\n args: Record<string, unknown>\n): ToolResult | null {\n const required = (inputSchema.required ?? []) as string[];\n const missing = required.filter(\n (name) => args[name] === undefined || args[name] === null\n );\n if (missing.length) {\n return {\n ok: false,\n status: 400,\n payload: {\n error: `Missing required argument${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}`,\n expected: required,\n received: Object.keys(args),\n // A missing path/query param is an ordinary omission. A missing `body`\n // is the shape a stale schema produces, so only that one earns the hint.\n ...(missing.includes('body') ? { hint: STALE_SCHEMA_HINT } : {}),\n },\n };\n }\n const allowed = new Set(\n Object.keys((inputSchema.properties ?? {}) as Record<string, unknown>)\n );\n const unknown = Object.keys(args).filter((name) => !allowed.has(name));\n if (unknown.length) {\n return {\n ok: false,\n status: 400,\n payload: {\n error: `Unknown argument${unknown.length > 1 ? 's' : ''}: ${unknown.join(', ')}`,\n accepted: [...allowed],\n hint: STALE_SCHEMA_HINT,\n },\n };\n }\n return null;\n}\n\nexport async function dispatchGeneratedTool(\n client: RunpodClient,\n tool: GeneratedTool,\n args: Record<string, unknown>\n): Promise<ToolResult> {\n const rejected = validateArguments(tool.inputSchema, args);\n if (rejected) return rejected;\n\n const pathParams: Record<string, unknown> = {};\n const query: Record<string, unknown> = {};\n for (const param of tool.params) {\n if (args[param.name] === undefined) continue;\n if (param.location === 'path') {\n pathParams[param.name] = args[param.name];\n continue;\n }\n const value = args[param.name];\n // `explode: false` in the spec means form style with ONE comma-joined\n // value. openapi-fetch's default serializer repeats the key per array\n // item instead, and upstream rejects that with \"parameter 'x' is not\n // exploded, but is specified multiple times\" — so a multi-value filter\n // fails while a single value passes, which is exactly the shape of bug\n // that survives casual testing.\n query[param.name] =\n param.explode === false && Array.isArray(value) ? value.join(',') : value;\n }\n\n // Some MCP clients serialize a nested object argument as a JSON string\n // rather than an object. Forwarding that verbatim makes upstream reject the\n // whole request with \"$: got string, want object\" — which never mentions\n // that the body was stringified, so the agent re-reads the schema it already\n // followed and retries the same shape. Accept the string and parse it; a\n // body that is not valid JSON is the client's error, so name it plainly.\n let requestBody = args.body;\n if (tool.hasBody && typeof requestBody === 'string') {\n try {\n requestBody = JSON.parse(requestBody);\n } catch {\n return {\n ok: false,\n status: 400,\n payload: {\n error:\n 'The body argument arrived as a string that is not valid JSON. Send body as an object.',\n },\n };\n }\n }\n\n // openapi-fetch is typed per literal path; generated dispatch is generic by\n // construction, so the client is narrowed to the structural shape of a verb\n // call rather than asserted to any.\n type VerbCall = (\n path: string,\n init: Record<string, unknown>\n ) => Promise<{ data?: unknown; error?: unknown; response: Response }>;\n const verbs = client as unknown as Record<string, VerbCall>;\n const { data, error, response } = await verbs[tool.method](tool.path, {\n params: { path: pathParams, query },\n ...(tool.hasBody && requestBody !== undefined ? { body: requestBody } : {}),\n });\n\n // Branch on the RESPONSE, not on `error`: openapi-fetch returns\n // `{ error: undefined }` for a non-OK response with an empty body\n // (Content-Length: 0 — a WAF/edge answering a bare 429/403/502 does this),\n // and treating that as success would tell the agent a failed call worked\n // and bypass the 401 onUnauthorized gate.\n if (!response.ok) return restError(response, error);\n return {\n ok: true,\n status: response.status,\n payload: data ?? { status: response.status },\n };\n}\n","// Code generated from specgen/spec/openapi.yaml by specgen/generator/generate-tools.ts; DO NOT EDIT.\n\nexport interface GeneratedToolParam {\n name: string;\n location: 'path' | 'query';\n /** Spec-declared `explode: false`: serialize an array as one comma-joined value. */\n explode?: false;\n}\n\n/** MCP tool annotations (tools/list `annotations`): behavioral hints hosts use\n * to decide what needs human approval. */\nexport interface ToolAnnotations {\n readOnlyHint: boolean;\n destructiveHint: boolean;\n idempotentHint: boolean;\n openWorldHint: boolean;\n}\n\nexport interface GeneratedTool {\n name: string;\n operationId: string;\n description: string;\n method: string;\n path: string;\n params: GeneratedToolParam[];\n hasBody: boolean;\n annotations: ToolAnnotations;\n inputSchema: Record<string, unknown>;\n}\n\nexport const generatedTools: GeneratedTool[] = [\n {\n name: 'create-cluster',\n operationId: 'createCluster',\n description:\n \"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 — 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 — a bare registry property is rejected. Delete with delete-cluster when finished.\",\n method: 'POST',\n path: '/v2/clusters',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateClusterRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ClusterCompute: {\n type: 'object',\n additionalProperties: false,\n description:\n 'The homogeneous compute shape of a cluster. Every pod in the cluster is identical: `podCount` pods, each with `gpuCountPerPod` GPUs of type `gpuTypeId`. Total GPUs = `podCount` * `gpuCountPerPod`.',\n required: ['gpuTypeId', 'gpuCountPerPod', 'podCount'],\n properties: {\n gpuTypeId: {\n type: 'string',\n minLength: 1,\n description:\n 'GPU type for every pod in the cluster, as returned by GET /v2/catalog/gpus.',\n examples: ['NVIDIA H100 80GB HBM3'],\n },\n gpuCountPerPod: {\n type: 'integer',\n minimum: 1,\n description:\n \"Number of GPUs on each pod. Bounded above by the GPU type's per-cloud maximum (GpuType.maxCount); the upstream rejects values beyond it.\",\n examples: [8],\n },\n podCount: {\n type: 'integer',\n minimum: 2,\n maximum: 250,\n description: 'Number of pods (nodes) in the cluster.',\n examples: [4],\n },\n },\n },\n ClusterType: {\n type: 'string',\n description:\n 'Cluster type. TRAINING is the generic distributed-training cluster; SLURM provisions a managed Slurm controller/compute topology; RAY provisions a managed Ray head/worker topology; APPLICATION is a general multi-node application cluster.',\n enum: ['APPLICATION', 'TRAINING', 'SLURM', 'RAY'],\n examples: ['TRAINING'],\n },\n CreateClusterRequest: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n required: ['name', 'type', 'compute'],\n description:\n 'Request body for creating a cluster. `compute` defines the\\nhomogeneous pod shape; the container configuration (image, env, ports,\\n…) applies to every pod. Pass `templateId` to provision every member\\npod from a pod template instead of inline container fields — the\\ntemplate also supplies the container registry credential, the only\\nprivate-image path for clusters (a bare `registry` property on this\\nbody is rejected).\\n',\n properties: {\n compute: {\n $ref: '#/$defs/ClusterCompute',\n },\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-training-cluster'],\n },\n type: {\n $ref: '#/$defs/ClusterType',\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n 'ID of a pod template to provision every member pod from. The\\ntemplate supplies the container settings (image, args, disk,\\nenv, ports) and the container registry credential for private\\nimages — the only private-image path for clusters. Mutually\\nexclusive with `image`, `args`, `entrypoint`, `cmd`, `disk`,\\n`env`, `ports`, and `mounts` (rejected with 400). The cluster\\nretains the link: the `template` response field is set. Must be\\na non-serverless pod template accessible to the caller.\\n',\n examples: ['30zmvf89kd'],\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty\\narray to let the scheduler choose. A cluster is always placed\\nwithin a single data center.\\n',\n example: ['US-TX-3'],\n },\n mounts: {\n $ref: '#/$defs/Mounts',\n },\n startJupyter: {\n type: 'boolean',\n default: false,\n description:\n 'Start Jupyter on every member pod, as on pod create.',\n },\n startSsh: {\n type: 'boolean',\n default: false,\n description:\n \"Provision SSH access on every member pod: injects a PUBLIC_KEY environment variable carrying your account's registered SSH public key. Same semantics as the pod create flag.\",\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n Mounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts attached to a pod. At-most-one of `persistent` or\\n`network` may be set today (mutually exclusive, enforced at the\\nhandler with 400 if both are present). The `network` field is an\\narray for forward compatibility with eventual multi-network-volume\\nsupport, but `maxItems` is 1 today.\\n\\nPATCH semantics:\\n- Omitting `mounts` or sending `{}` leaves the existing mount\\n unchanged.\\n- An explicit `network: []` is rejected with 400 (clearing mounts\\n is not supported).\\n- Mount kind is fixed at create — a PATCH that introduces a kind\\n not present at create (persistent on a network pod, network on\\n a persistent pod, or any mount on a previously-mountless pod)\\n is rejected with 400.\\n- The `volumeId` of a network mount is immutable; a PATCH that\\n names a different `volumeId` is rejected with 400.\\n- Partial mounts are not supported — every mount entry must\\n include the full schema (`size` + `path` for persistent,\\n `volumeId` + `path` for network). Missing required fields → 422.\\n',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on\\nboth GPU and CPU pods. The underlying `volumeId` is immutable\\npost-create; the mount `path` may be changed via PATCH.\\n',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data\\ndoes not survive a host failure. Disallowed on CPU pods. Mutually\\nexclusive with NetworkMount. Deprecated: prefer NetworkMount for any\\ndata you cannot recreate.\\n\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-delegation',\n operationId: 'createDelegation',\n description: 'Register an ECR delegation',\n method: 'POST',\n path: '/v2/registries/delegations',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateDelegationRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateDelegationRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['resource'],\n properties: {\n resource: {\n type: 'string',\n description: 'ECR resource ARN',\n examples: [\n 'arn:aws:ecr:us-east-2:418399314813:repository/runpod/deployment',\n ],\n },\n name: {\n type: ['string', 'null'],\n description: 'Optional name for the delegation',\n examples: ['my-delegation'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-endpoint',\n operationId: 'createEndpoint',\n description:\n \"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.\",\n method: 'POST',\n path: '/v2/serverless',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateEndpointRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseEndpointGpuConfig: {\n type: 'object',\n properties: {\n pools: {\n type: 'array',\n minItems: 1,\n description:\n 'Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\\n`pool`). Workers are placed on whichever listed pool has capacity.\\nNarrow a pool down to specific cards with `excludedTypes`.\\n\\nOn `PATCH`, `pools` and `excludedTypes` are one selection and are\\nreplaced together, so sending `pools` by itself **clears the\\nexclusions**. Two cases:\\n\\n- **Changing pools, keeping exclusions** — send both fields in one\\n request: `{\"gpu\": {\"pools\": [\"ADA_24\"], \"excludedTypes\":\\n [\"NVIDIA L40\"]}}`. `GET` the endpoint first to read the current\\n `excludedTypes` and resend the ones that still apply to the new\\n pools; an exclusion naming a type outside `pools` is a 400.\\n- **Changing only `count` or a CUDA constraint** — omit `pools`:\\n `{\"gpu\": {\"minCudaVersion\": \"12.4\"}}`. The pool list and the\\n exclusions are both left exactly as they are.\\n\\n`excludedTypes` documents the full rule.\\n',\n items: {\n type: 'string',\n },\n examples: [['ADA_24']],\n },\n excludedTypes: {\n type: 'array',\n uniqueItems: true,\n description:\n 'GPU **type** IDs to subtract from the selected pools — the `id`\\nfield of `GET /v2/catalog/gpus`, the same identifiers pods take in\\n`gpu.id`. Workers run on every type in `pools` except these. Omit to\\nuse the whole pool.\\n\\nPools stay the unit of selection; types are the unit of\\nsubtraction. There is no inclusive allowlist: a card later added to\\none of your pools becomes eligible, which is the honest reading of\\n\"this pool, minus these\".\\n\\nTied to `pools`, because the two together are one selection:\\nsupplying `pools` replaces that selection wholesale, so a `PATCH`\\nsending `pools` **without `excludedTypes`** **clears** them —\\nrestate them to keep them. A `PATCH` that omits `pools` leaves both\\nthe pools and the exclusions untouched, so changing only a CUDA\\nconstraint cannot widen a pinned endpoint.\\n\\nRejected with 400 if a value is not a GPU type in one of `pools`;\\nupstream accepts unrecognized exclusions silently, so a typo would\\notherwise produce a filter that does nothing. Surrounding whitespace\\nis trimmed, so `\" NVIDIA L40\"` and `\"NVIDIA L40\"` mean the same card.\\n',\n items: {\n type: 'string',\n pattern: '^\\\\s*[^-\\\\s]',\n },\n examples: [['NVIDIA L40']],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'GPUs per worker',\n examples: [1],\n },\n },\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n CreateEndpointGpuConfig: {\n description:\n \"GPU request for an endpoint create. Carries the CUDA constraints, which\\nlive here rather than at the body's top level so they are\\nunrepresentable on a CPU endpoint.\\n\",\n allOf: [\n {\n $ref: '#/$defs/BaseEndpointGpuConfig',\n },\n {\n type: 'object',\n required: ['pools'],\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n \"Acceptable CUDA versions for worker placement, as\\n`major.minor`. Omit to accept any version (or inherit the\\ntemplate's constraint when creating from `templateId`).\\nMatching is exact — discover valid values per GPU type via\\n`GET /v2/catalog/gpus?include=AVAILABILITY&product=SERVERLESS`\\n(`cudaVersions`).\\n\\nA non-empty set is mutually exclusive with minCudaVersion (400\\nif both are sent). An explicit `[]` states no constraint, so it\\nmay accompany a floor.\\n\",\n examples: [['12.8', '12.6']],\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for worker placement, as\\n`major.minor`, compared numerically rather than as a decimal —\\nso 12.11 is above 12.2. Use this for an open-ended floor and\\nallowedCudaVersions for an exact set.\\n\\nMutually exclusive with a non-empty allowedCudaVersions (400 if\\nboth are sent); an explicit `[]` there states no constraint and\\nmay accompany this floor.\\n',\n examples: ['12.1'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n CreateEndpointRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n if: {\n not: {\n required: ['templateId'],\n },\n },\n then: {\n required: ['image'],\n },\n },\n {\n type: 'object',\n required: ['name', 'type', 'scaling'],\n properties: {\n gpu: {\n $ref: '#/$defs/CreateEndpointGpuConfig',\n },\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-inference'],\n },\n scaling: {\n $ref: '#/$defs/EndpointScaling',\n },\n type: {\n allOf: [\n {\n $ref: '#/$defs/EndpointType',\n },\n ],\n description:\n 'Request-routing model. Required — it determines the valid scaler\\nand request URLs, so it must be chosen explicitly on every create.\\n',\n },\n cpu: {\n type: 'array',\n minItems: 1,\n uniqueItems: true,\n description:\n \"Eligible CPU configurations for each worker. Memory is derived from the\\nselected flavor's catalog RAM multiplier. Exact duplicate configurations\\nare rejected; the same flavor may be listed at different vCPU counts.\\n\",\n items: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.',\n },\n flashboot: {\n allOf: [\n {\n $ref: '#/$defs/FlashBoot',\n },\n ],\n default: 'OFF',\n },\n networkVolumes: {\n type: 'array',\n items: {\n type: 'string',\n },\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n \"ID of a serverless template to base this endpoint on. The\\ntemplate is resolved at create time into the same container\\nsettings you could otherwise spread into this body (image,\\nargs, disk, ports, env, registry); explicit body fields\\noverride the template's, except `env`, which is merged per\\nkey with body values winning. The template's\\nallowedCudaVersions seeds `gpu.allowedCudaVersions` when the\\nbody omits it — but only for a GPU create, since a CPU endpoint\\nhas no gpu block to seed into, and not when the body sets\\n`gpu.minCudaVersion`, since seeding a set beside a floor would\\nmanufacture the mutual-exclusion 400 from a valid request. Its\\npod-specific startSsh/startJupyter flags are\\nignored. Later template edits do not affect the endpoint.\\nThe template may be one of your own or a public catalog\\ntemplate — see `GET /v2/catalog/templates` (unknown or\\ninaccessible ID → 404) — and must be a serverless template\\n(→ 422).\\n\",\n examples: ['30zmvf89kd'],\n },\n timeout: {\n type: 'integer',\n default: 300000,\n },\n workers: {\n allOf: [\n {\n $ref: '#/$defs/EndpointWorkers',\n },\n ],\n properties: {\n min: {\n type: 'integer',\n default: 0,\n },\n max: {\n type: 'integer',\n default: 3,\n },\n idleTimeout: {\n type: 'integer',\n default: 10,\n },\n },\n },\n },\n },\n ],\n unevaluatedProperties: false,\n if: {\n required: ['type'],\n properties: {\n type: {\n const: 'LOAD_BALANCER',\n },\n },\n },\n then: {\n properties: {\n scaling: {\n $ref: '#/$defs/RequestCountScaling',\n },\n },\n },\n },\n EndpointScaling: {\n description:\n \"Autoscaling signal — a discriminated union on `type`: `QUEUE_DELAY`\\n(queue-based endpoints only) or `REQUEST_COUNT`. The scaler is chosen\\nindependently of the endpoint's routing `type` and can be switched on\\nupdate.\\n\",\n oneOf: [\n {\n $ref: '#/$defs/QueueDelayScaling',\n },\n {\n $ref: '#/$defs/RequestCountScaling',\n },\n ],\n discriminator: {\n propertyName: 'type',\n mapping: {\n QUEUE_DELAY: '#/$defs/QueueDelayScaling',\n REQUEST_COUNT: '#/$defs/RequestCountScaling',\n },\n },\n },\n EndpointType: {\n type: 'string',\n description:\n 'Request-routing semantics for a modern serverless endpoint.\\n- `QUEUE` — submit asynchronous or synchronous jobs through the managed queue.\\n- `LOAD_BALANCER` — send requests directly to worker-defined HTTP paths.\\n Configure via `env`: `PORT` (server port, default 80), `PORT_HEALTH`\\n (health-check port, default 80), and `HEALTH_CHECK_PATH` (path the\\n load balancer polls for worker health, default `/ping`).\\n',\n 'x-enum-varnames': ['EndpointTypeQueue', 'EndpointTypeLoadBalancer'],\n enum: ['QUEUE', 'LOAD_BALANCER'],\n },\n EndpointWorkers: {\n type: 'object',\n additionalProperties: false,\n properties: {\n min: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum number of workers.',\n examples: [0],\n },\n max: {\n type: 'integer',\n minimum: 0,\n description: 'Maximum number of workers.',\n examples: [5],\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n maximum: 3600,\n description:\n 'Seconds before idle workers scale down. Not applicable to queue-based\\nendpoints scaling on `requestCount` — rejected on create/update and\\nomitted from responses for that combination.\\n',\n examples: [5],\n },\n },\n },\n FlashBoot: {\n type: 'string',\n description:\n 'FlashBoot cold-start acceleration mode.\\n- `OFF` — disabled\\n- `FLASHBOOT` — enabled\\n- `PRIORITY_FLASHBOOT` — enabled with priority capacity\\n',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n },\n QueueDelayScaling: {\n type: 'object',\n additionalProperties: false,\n description: 'Scale on queue wait time. Queue-based endpoints only.',\n required: ['type', 'queueDelay'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `QUEUE_DELAY` for this variant.',\n enum: ['QUEUE_DELAY'],\n },\n queueDelay: {\n type: 'number',\n format: 'float',\n minimum: 0.5,\n description:\n 'Adjusts the number of workers based on how long requests wait in the queue.',\n examples: [4],\n },\n },\n },\n RequestCountScaling: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Scale on concurrent in-flight requests per worker. Required for\\nload-balancing endpoints; also selectable for queue-based.\\n',\n required: ['type', 'requestCount'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `REQUEST_COUNT` for this variant.',\n enum: ['REQUEST_COUNT'],\n },\n requestCount: {\n type: 'integer',\n minimum: 1,\n description:\n 'Adjusts the number of workers based on active in-flight requests.',\n examples: [4],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-network-volume',\n operationId: 'createNetworkVolume',\n description:\n 'Create a network volume. Provisions a new network volume — 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`.',\n method: 'POST',\n path: '/v2/network-volumes',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateNetworkVolumeRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateNetworkVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'size', 'dataCenter'],\n properties: {\n dataCenter: {\n type: 'string',\n minLength: 1,\n description: 'Data center in which to create the volume',\n examples: ['EU-RO-1'],\n },\n name: {\n type: 'string',\n minLength: 1,\n description: 'Human-readable name',\n examples: ['my-dataset'],\n },\n size: {\n type: 'integer',\n minimum: 10,\n maximum: 4096,\n description: 'Storage to allocate in GB',\n examples: [50],\n },\n type: {\n allOf: [\n {\n $ref: '#/$defs/VolumeType',\n },\n ],\n description:\n \"Storage tier for the volume. Optional. When omitted, the volume is\\nprovisioned using the requested data center's default (primary)\\nstorage tier. HIGH_PERFORMANCE provisions a high-performance (HPS)\\nvolume; STANDARD provisions a standard volume. A volume's tier is\\nimmutable after creation.\\n\",\n },\n },\n },\n VolumeType: {\n type: 'string',\n description: 'Data center network volume storage type.',\n enum: ['STANDARD', 'HIGH_PERFORMANCE'],\n },\n },\n },\n },\n {\n name: 'create-pod',\n operationId: 'createPod',\n description:\n '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.',\n method: 'POST',\n path: '/v2/pods',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreatePodRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseGpuConfig: {\n type: 'object',\n required: ['id'],\n properties: {\n id: {\n type: 'string',\n description: 'GPU type identifier',\n examples: ['NVIDIA GeForce RTX 4090'],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'Number of GPUs',\n examples: [1],\n },\n },\n },\n Cloud: {\n type: 'string',\n description:\n 'Cloud tier.\\n- `SECURE` — Runpod-owned datacenter hardware\\n- `COMMUNITY` — community-hosted hardware\\n',\n enum: ['SECURE', 'COMMUNITY'],\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n CreateGpuConfig: {\n description:\n \"GPU request for a pod create. Carries the CUDA host constraints, which\\nlive here rather than at the body's top level so they are\\nunrepresentable on a CPU pod.\\n\",\n allOf: [\n {\n $ref: '#/$defs/BaseGpuConfig',\n },\n {\n type: 'object',\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for the host machine, as `major.minor`.\\nOmit to accept any version. Matching is exact, so a version no\\nmachine reports yields a capacity error rather than a fallback —\\ndiscover valid values per GPU type via\\n`GET /v2/catalog/gpus?include=AVAILABILITY&product=POD`\\n(`cudaVersions`).\\n\\nA non-empty set is mutually exclusive with minCudaVersion (400\\nif both are sent). An explicit `[]` states no constraint, so it\\nmay accompany a floor.\\n',\n examples: [['12.8', '12.6']],\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for the host machine, as\\n`major.minor`, compared numerically rather than as a decimal —\\nso 12.11 is above 12.2. Use this for an open-ended floor and\\nallowedCudaVersions for an exact set.\\n\\nMutually exclusive with a non-empty allowedCudaVersions (400 if\\nboth are sent); an explicit `[]` there states no constraint and\\nmay accompany this floor.\\n',\n examples: ['12.1'],\n },\n minRamPerGpu: {\n type: 'integer',\n minimum: 1,\n description:\n 'Minimum host system RAM in GB per requested GPU. This is a placement filter, not a resource request. The actual total allocated system RAM may be higher and is returned in gpu.memory.',\n examples: [8],\n },\n minVcpuCountPerGpu: {\n type: 'integer',\n minimum: 1,\n description:\n 'Minimum host vCPU count per requested GPU. This is a placement filter, not a resource request. The actual total allocated vCPU count may be higher and is returned in gpu.vcpuCount.',\n examples: [2],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n CreatePodRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n required: ['name'],\n description:\n \"Request body for creating a pod. Exactly one of `gpu` or `cpu`\\nmust be set — enforced at the handler layer. For CPU pods, memory\\nis derived by the API from the selected flavor's RAM multiplier;\\nclients provide only CPU flavor and vCPU count. CPU pods support\\ncontainer disk and network volumes only; `mounts.persistent` is\\ninvalid when `cpu` is set.\\n\\n`image` is required unless `templateId` is set.\\n\",\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-training-pod'],\n },\n cloud: {\n allOf: [\n {\n $ref: '#/$defs/Cloud',\n },\n ],\n default: 'SECURE',\n description: 'Cloud tier. Defaults to `SECURE` when omitted.',\n },\n cpu: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty\\narray to let the scheduler choose.\\n',\n examples: [['US-TX-3']],\n },\n globalNetworking: {\n type: 'boolean',\n default: false,\n description:\n 'Enable global networking, giving the pod a private IP reachable across data centers. Requires an NVIDIA GPU and a global-networking-enabled data center (both enforced upstream). See `GET /v2/catalog/datacenters` (`globalNetwork`) for eligible data centers.',\n examples: [false],\n },\n gpu: {\n $ref: '#/$defs/CreateGpuConfig',\n },\n mounts: {\n $ref: '#/$defs/Mounts',\n },\n startJupyter: {\n type: 'boolean',\n default: false,\n description:\n \"Create-time flag telling the provisioner to start JupyterLab:\\ninjects a generated `JUPYTER_PASSWORD` environment variable,\\nunless the request already sets one. Only images that honor\\nthe convention start Jupyter from it (Runpod official images\\ndo); expose `8888/http` in `ports` to reach it.\\n\\nNot part of the pod's readable config — never returned by\\nGET and not changeable by PATCH.\\n\",\n examples: [true],\n },\n startSsh: {\n type: 'boolean',\n default: false,\n description:\n \"Create-time flag telling the provisioner to set up SSH\\naccess: injects a `PUBLIC_KEY` environment variable carrying\\nyour account's registered SSH public keys, unless the request\\nalready sets one. **Requires registered keys** (`PUT\\n/v2/account/ssh-keys`) — with none registered the flag does\\nnothing and the pod has no SSH access. Only images that honor\\nthe convention start sshd from it (all Runpod official images\\ndo). Connect using the pod's `ssh` block; the `ssh.direct`\\nvariant additionally needs a `22/tcp` entry in `ports`.\\n\\nNot part of the pod's readable config — never returned by\\nGET and not changeable by PATCH.\\n\",\n examples: [true],\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n \"ID of a pod template to base this pod on. The template is\\nresolved at create time into the same container settings you\\ncould otherwise spread into this body (image, args, disk,\\nports, env, registry, persistent mount, startSsh,\\nstartJupyter, allowedCudaVersions); explicit body fields\\noverride the template's, except `env`, which is merged per\\nkey with body values winning. Sending either CUDA field\\n(`gpu.allowedCudaVersions` or `gpu.minCudaVersion`) replaces\\nthe template's CUDA constraint entirely, and CPU pods ignore\\nit (like the persistent mount). The template is a one-time\\nsource of settings: later template edits do not affect the\\npod, and the created pod does not retain a link to the\\ntemplate (`template` stays null). The template may be one\\nof your own or a public catalog template — see\\n`GET /v2/catalog/templates` (unknown or inaccessible ID →\\n404) — and must not be a serverless template (→ 422). CPU\\npods do not inherit a template's persistent mount.\\n\",\n examples: ['30zmvf89kd'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n if: {\n not: {\n required: ['templateId'],\n },\n },\n then: {\n required: ['image'],\n },\n },\n Mounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts attached to a pod. At-most-one of `persistent` or\\n`network` may be set today (mutually exclusive, enforced at the\\nhandler with 400 if both are present). The `network` field is an\\narray for forward compatibility with eventual multi-network-volume\\nsupport, but `maxItems` is 1 today.\\n\\nPATCH semantics:\\n- Omitting `mounts` or sending `{}` leaves the existing mount\\n unchanged.\\n- An explicit `network: []` is rejected with 400 (clearing mounts\\n is not supported).\\n- Mount kind is fixed at create — a PATCH that introduces a kind\\n not present at create (persistent on a network pod, network on\\n a persistent pod, or any mount on a previously-mountless pod)\\n is rejected with 400.\\n- The `volumeId` of a network mount is immutable; a PATCH that\\n names a different `volumeId` is rejected with 400.\\n- Partial mounts are not supported — every mount entry must\\n include the full schema (`size` + `path` for persistent,\\n `volumeId` + `path` for network). Missing required fields → 422.\\n',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on\\nboth GPU and CPU pods. The underlying `volumeId` is immutable\\npost-create; the mount `path` may be changed via PATCH.\\n',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data\\ndoes not survive a host failure. Disallowed on CPU pods. Mutually\\nexclusive with NetworkMount. Deprecated: prefer NetworkMount for any\\ndata you cannot recreate.\\n\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-registry',\n operationId: 'createRegistry',\n description:\n 'Create a container registry credential. Stores credentials for a private container registry. Credentials are write-only.',\n method: 'POST',\n path: '/v2/registries',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateRegistryRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateRegistryRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'username', 'password'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n examples: ['my-private-registry'],\n },\n password: {\n type: 'string',\n minLength: 1,\n maxLength: 16384,\n description:\n 'Registry password (write-only, not returned in responses)',\n },\n username: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n description:\n 'Registry username (write-only, not returned in responses)',\n },\n },\n },\n },\n },\n },\n {\n name: 'create-secret',\n operationId: 'createSecret',\n description:\n \"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> }}` — 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.\",\n method: 'POST',\n path: '/v2/account/secrets',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateSecretRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateSecretRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'value'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n pattern: '^[a-zA-Z_][a-zA-Z0-9_.\\\\-/]*$',\n description:\n 'Unique name for the secret — referenced from environment variables as `{{ RUNPOD_SECRET_<name> }}`; immutable after creation. Maximum 191 characters, must start with a letter or underscore, and may contain letters, digits, and `_.-/`. Names beginning with the reserved prefix `RUNPOD` are rejected (case-insensitive).',\n examples: ['hf-token'],\n },\n value: {\n type: 'string',\n minLength: 1,\n maxLength: 16777216,\n description:\n 'The secret value. Write-only — never returned by the API. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes).',\n },\n description: {\n type: 'string',\n maxLength: 65535,\n description:\n 'Optional human-readable description, at most 65,535 bytes of UTF-8 text.',\n examples: ['Hugging Face read token'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-template',\n operationId: 'createTemplate',\n description:\n 'Create a template. Creates a reusable container-configuration preset — image, disk, ports, env, registry, and mount settings — 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.',\n method: 'POST',\n path: '/v2/templates',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateTemplateRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateTemplateRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n required: ['name', 'image'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['My PyTorch Template'],\n },\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for containers created from this\\ntemplate, as `major.minor`. Omit to accept any version — see\\nthe same field on `createPod` for matching semantics.\\nExpanded into GPU pod and serverless endpoint creates; CPU\\npods ignore it.\\n',\n examples: [['12.8', '12.6']],\n },\n category: {\n description: 'Optional. Defaults to `NVIDIA` when omitted.',\n allOf: [\n {\n $ref: '#/$defs/TemplateCategory',\n },\n ],\n default: 'NVIDIA',\n },\n mounts: {\n $ref: '#/$defs/TemplateMounts',\n },\n public: {\n type: 'boolean',\n default: false,\n },\n serverless: {\n type: 'boolean',\n default: false,\n },\n startJupyter: {\n type: 'boolean',\n default: true,\n description:\n 'Start JupyterLab in containers created from this template:\\ninjects a generated `JUPYTER_PASSWORD` environment variable,\\nunless `env` already sets one. Only images that honor the\\nconvention start Jupyter from it (Runpod official images do);\\nexpose `8888/http` in `ports` to reach it. Defaults to `true`\\nwhen omitted, matching console-created templates.\\n',\n examples: [false],\n },\n startSsh: {\n type: 'boolean',\n default: true,\n description:\n \"Provision SSH access in containers created from this template:\\ninjects a `PUBLIC_KEY` environment variable carrying the\\ndeployer's registered SSH public keys (`PUT\\n/v2/account/ssh-keys` — with none registered the flag does\\nnothing), unless `env` already sets one. Only images that\\nhonor the convention start sshd from it (all Runpod official\\nimages do); direct SSH also needs a `22/tcp` entry in\\n`ports`. Defaults to `true` when omitted, matching\\nconsole-created templates.\\n\",\n examples: [true],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data\\ndoes not survive a host failure. Disallowed on CPU pods. Mutually\\nexclusive with NetworkMount. Deprecated: prefer NetworkMount for any\\ndata you cannot recreate.\\n\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n TemplateCategory: {\n type: 'string',\n description:\n 'Controls how the template is grouped and filtered in the Runpod console.\\nIt does not affect hardware selection, scheduling, or billing.\\n- `CPU` — CPU-only workloads\\n- `NVIDIA` — NVIDIA GPU workloads\\n- `AMD` — AMD GPU workloads\\n',\n enum: ['CPU', 'NVIDIA', 'AMD'],\n },\n TemplateMounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts attached to a template. Templates support only a\\nsingle persistent mount today; any `network` property is rejected\\nwith 422 by the schema validator.\\n\\nPATCH semantics: omitting `mounts` or sending `{}` leaves the\\nexisting mount unchanged.\\n',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n },\n },\n },\n },\n },\n {\n name: 'delete-cluster',\n operationId: 'deleteCluster',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-endpoint',\n operationId: 'deleteEndpoint',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-network-volume',\n operationId: 'deleteNetworkVolume',\n description:\n 'Delete a network volume. Permanently deletes a network volume and releases its storage.',\n method: 'DELETE',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-pod',\n operationId: 'deletePod',\n description:\n 'Terminate a pod permanently — 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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-registry',\n operationId: 'deleteRegistry',\n description:\n '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 — they silently lose the reference (`registry` becomes null) instead of blocking the delete.',\n method: 'DELETE',\n path: '/v2/registries/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-secret',\n operationId: 'deleteSecret',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-template',\n operationId: 'deleteTemplate',\n description:\n 'Delete a template permanently. Verify with get-template first; a template referenced by a live endpoint should not be deleted.',\n method: 'DELETE',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-cluster',\n operationId: 'getCluster',\n description:\n '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.',\n method: 'GET',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-cpu-type',\n operationId: 'getCpuType',\n description:\n 'Get a CPU type. Returns a single CPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/cpus/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'vcpuCount',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/CpuProduct',\n },\n example: ['POD', 'SERVERLESS'],\n description:\n 'Comma-separated availability product contexts. Supported values for CPUs: POD, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: availability differs by product.',\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Availability vCPU count. Valid only with include=AVAILABILITY. Must be a power of two.',\n },\n },\n required: ['id'],\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n CpuProduct: {\n type: 'string',\n description:\n 'CPU catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'get-data-center',\n operationId: 'getDataCenter',\n description:\n 'Get a data center. Returns a single data center. Availability is included only when requested with include=GPU_AVAILABILITY or include=CPU_AVAILABILITY.',\n method: 'GET',\n path: '/v2/catalog/datacenters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterInclude',\n },\n example: ['GPU_AVAILABILITY'],\n description:\n 'Comma-separated optional expansions. Supported value: GPU_AVAILABILITY, CPU_AVAILABILITY.',\n },\n },\n required: ['id'],\n $defs: {\n DataCenterInclude: {\n type: 'string',\n description: 'Data center catalog availability expansion.',\n enum: ['GPU_AVAILABILITY', 'CPU_AVAILABILITY'],\n },\n },\n },\n },\n {\n name: 'get-endpoint',\n operationId: 'getEndpoint',\n description:\n 'Get a serverless endpoint. Returns a single serverless endpoint by ID.',\n method: 'GET',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-endpoint-build',\n operationId: 'getEndpointBuild',\n description:\n \"Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age — no need to page through `GET /v2/serverless/{id}/builds` to reach it.\",\n method: 'GET',\n path: '/v2/serverless/{id}/builds/{buildId}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'buildId',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n buildId: {\n type: 'string',\n description:\n \"GitHub build identifier (from GET /v2/serverless/{id}/builds or a release's `buildId`)\",\n },\n },\n required: ['id', 'buildId'],\n },\n },\n {\n name: 'get-gpu-type',\n operationId: 'getGpuType',\n description:\n 'Get a GPU type. Returns a single GPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/gpus/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'count',\n location: 'query',\n },\n {\n name: 'cloud',\n location: 'query',\n },\n {\n name: 'countryCodes',\n location: 'query',\n explode: false,\n },\n {\n name: 'cudaVersions',\n location: 'query',\n explode: false,\n },\n {\n name: 'minCudaVersion',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/Product',\n },\n description:\n 'Comma-separated availability product contexts. Supported values: POD, CLUSTER, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: the same GPU type can be scarce for pods and plentiful for serverless, so the context has to be stated rather than assumed.',\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description:\n 'GPU count for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Defaults to 1.',\n },\n cloud: {\n $ref: '#/$defs/GpuCloudFilter',\n description:\n 'Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.',\n },\n countryCodes: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^[A-Z]{2}$',\n },\n description:\n 'Comma-separated ISO 3166-1 alpha-2 country codes, uppercase, to constrain availability to — e.g. FR or FR,DE. Values within this filter use OR semantics. Valid only with include=AVAILABILITY (400 otherwise); a malformed entry is a 422. Scopes availability, lowest-price calculations and the dataCenters array to those countries, so a listed data center outside them is omitted rather than returned with availability NONE. On the list endpoint a GPU type with no data center in those countries drops out entirely; the single-GPU endpoint still returns the requested type, with availability NONE and dataCenters omitted, so a 404 keeps meaning the GPU type does not exist. Read the NONE on availability rather than the absence of dataCenters, which is also absent when availability was not requested.',\n },\n cudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Comma-separated CUDA versions to scope availability and lowest-price calculations to, matched exactly. Format: major.minor, e.g. 12.8 — a bare major is rejected here because it identifies no version. Valid only with include=AVAILABILITY (400 otherwise) and mutually exclusive with minCudaVersion (400 if both are sent); a malformed entry is a 422. Also narrows the returned cudaVersions array; omit it to enumerate every version offered.',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+(\\\\.\\\\d+)?$',\n description:\n 'Lowest acceptable CUDA version to scope availability and lowest-price calculations to, compared numerically. Format: integer major or major.minor, e.g. 12 or 12.1 — unlike the `gpu.minCudaVersion` body field on pod and endpoint create, a bare major is accepted here and means any release of that major, because this filter only widens a read. Valid only with include=AVAILABILITY (400 otherwise) and mutually exclusive with cudaVersions (400 if both are sent); a malformed value is a 422. Use this for an open-ended floor and cudaVersions for an exact set.',\n },\n },\n required: ['id'],\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n GpuCloudFilter: {\n type: 'string',\n description: 'GPU availability cloud filter.',\n enum: ['SECURE', 'COMMUNITY'],\n },\n Product: {\n type: 'string',\n description:\n 'Catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'CLUSTER', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'get-network-volume',\n operationId: 'getNetworkVolume',\n description: 'Get a network volume. Returns a single network volume by ID.',\n method: 'GET',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-pod',\n operationId: 'getPod',\n description: 'Get a pod. Returns a single pod by ID.',\n method: 'GET',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-registry',\n operationId: 'getRegistry',\n description:\n 'Get a container registry credential. Returns a single container registry credential by ID. `username` and `password` are never included in the response — credentials are write-only, matching `createRegistry`.',\n method: 'GET',\n path: '/v2/registries/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-secret',\n operationId: 'getSecret',\n description:\n \"Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.\",\n method: 'GET',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-ssh-keys',\n operationId: 'getSshKeys',\n description:\n \"List registered SSH public keys. Returns the account's registered SSH public keys — the keys provisioned into pods created with `startSsh` and used to authenticate the SSH connections reported in a pod's `ssh` block.\",\n method: 'GET',\n path: '/v2/account/ssh-keys',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'get-template',\n operationId: 'getTemplate',\n description:\n 'Get a template. Returns the full configuration of a single template by ID. Serves both templates you own and public catalog templates — everything you can read. Updates and deletes remain restricted to templates you own.',\n method: 'GET',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-billing',\n operationId: 'listBilling',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/billing',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-cluster-billing',\n operationId: 'listClusterBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/clusters',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'clusterId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n clusterId: {\n type: 'string',\n description: 'Filter to a specific cluster.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-cluster-pods',\n operationId: 'listClusterPods',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/clusters/{id}/pods',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-clusters',\n operationId: 'listClusters',\n description:\n 'List clusters. Returns all clusters owned by the authenticated user.',\n method: 'GET',\n path: '/v2/clusters',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-cpu-types',\n operationId: 'listCpuTypes',\n description:\n 'List CPU types. Returns available CPU flavors. Availability is included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/cpus',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'vcpuCount',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/CpuProduct',\n },\n example: ['POD', 'SERVERLESS'],\n description:\n 'Comma-separated availability product contexts. Supported values for CPUs: POD, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: availability differs by product.',\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Availability vCPU count. Valid only with include=AVAILABILITY. Must be a power of two.',\n },\n },\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n CpuProduct: {\n type: 'string',\n description:\n 'CPU catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'list-data-centers',\n operationId: 'listDataCenters',\n description:\n '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.',\n method: 'GET',\n path: '/v2/catalog/datacenters',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'regions',\n location: 'query',\n explode: false,\n },\n {\n name: 'networkVolumeTypes',\n location: 'query',\n explode: false,\n },\n {\n name: 'compliance',\n location: 'query',\n explode: false,\n },\n {\n name: 'globalNetwork',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterInclude',\n },\n example: ['GPU_AVAILABILITY'],\n description:\n 'Comma-separated optional expansions. Supported value: GPU_AVAILABILITY, CPU_AVAILABILITY.',\n },\n regions: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterRegion',\n },\n example: ['EUROPE', 'ASIA'],\n description:\n 'Comma-separated DataCenterRegion enum values. Values within this filter use OR semantics. Different filter families combine with AND.',\n },\n networkVolumeTypes: {\n type: 'array',\n items: {\n $ref: '#/$defs/VolumeType',\n },\n example: ['STANDARD', 'HIGH_PERFORMANCE'],\n description:\n 'Comma-separated volume types. Supported values: STANDARD, HIGH_PERFORMANCE. Values within this filter use AND semantics; volumes=STANDARD,HIGH_PERFORMANCE requires both storage types. Different filter families combine with AND.',\n },\n compliance: {\n type: 'array',\n items: {\n $ref: '#/$defs/Compliance',\n },\n example: ['GDPR', 'SOC_2_TYPE_2'],\n description:\n 'Comma-separated Compliance enum values. Values within this filter use AND semantics; compliance=GDPR,SOC_2_TYPE_2 requires both certifications. Different filter families combine with AND.',\n },\n globalNetwork: {\n type: 'boolean',\n description:\n 'Filter by global networking support. true returns only data centers that support global networking; false only those that do not. Different filter families combine with AND.',\n },\n },\n $defs: {\n Compliance: {\n type: 'string',\n description: 'Compliance certifications.',\n enum: [\n 'GDPR',\n 'ISO_IEC_27001',\n 'ISO_14001',\n 'PCI_DSS',\n 'HITRUST',\n 'SOC_1_TYPE_2',\n 'SOC_2_TYPE_2',\n 'SOC_3_TYPE_2',\n 'ITAR',\n 'FISMA_HIGH',\n 'HIPAA',\n 'RENEWABLE',\n ],\n },\n DataCenterInclude: {\n type: 'string',\n description: 'Data center catalog availability expansion.',\n enum: ['GPU_AVAILABILITY', 'CPU_AVAILABILITY'],\n },\n DataCenterRegion: {\n type: 'string',\n description: 'Continental region containing the data center.',\n examples: ['EUROPE'],\n enum: [\n 'NORTH_AMERICA',\n 'SOUTH_AMERICA',\n 'EUROPE',\n 'ASIA',\n 'MIDDLE_EAST',\n 'AFRICA',\n 'OCEANIA',\n 'ANTARCTICA',\n 'UNKNOWN',\n ],\n },\n VolumeType: {\n type: 'string',\n description: 'Data center network volume storage type.',\n enum: ['STANDARD', 'HIGH_PERFORMANCE'],\n },\n },\n },\n },\n {\n name: 'list-delegations',\n operationId: 'listDelegations',\n description: 'List all ECR delegations',\n method: 'GET',\n path: '/v2/registries/delegations',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-endpoint-billing',\n operationId: 'listEndpointBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/endpoints',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-endpoint-builds',\n operationId: 'listEndpointBuilds',\n description:\n \"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`.\",\n method: 'GET',\n path: '/v2/serverless/{id}/builds',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\\n\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Page size, 1–100. Defaults to 100 when omitted.',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-endpoint-releases',\n operationId: 'listEndpointReleases',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/serverless/{id}/releases',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\\n\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-endpoint-workers',\n operationId: 'listEndpointWorkers',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/serverless/{id}/workers',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-gpu-types',\n operationId: 'listGpuTypes',\n description:\n 'List GPU types. Returns available GPU types with pricing. Availability is included only when requested with include=AVAILABILITY, which requires `product` — 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.',\n method: 'GET',\n path: '/v2/catalog/gpus',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'count',\n location: 'query',\n },\n {\n name: 'cloud',\n location: 'query',\n },\n {\n name: 'countryCodes',\n location: 'query',\n explode: false,\n },\n {\n name: 'cudaVersions',\n location: 'query',\n explode: false,\n },\n {\n name: 'minCudaVersion',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/Product',\n },\n description:\n 'Comma-separated availability product contexts. Supported values: POD, CLUSTER, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: the same GPU type can be scarce for pods and plentiful for serverless, so the context has to be stated rather than assumed.',\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description:\n 'GPU count for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Defaults to 1.',\n },\n cloud: {\n $ref: '#/$defs/GpuCloudFilter',\n description:\n 'Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.',\n },\n countryCodes: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^[A-Z]{2}$',\n },\n description:\n 'Comma-separated ISO 3166-1 alpha-2 country codes, uppercase, to constrain availability to — e.g. FR or FR,DE. Values within this filter use OR semantics. Valid only with include=AVAILABILITY (400 otherwise); a malformed entry is a 422. Scopes availability, lowest-price calculations and the dataCenters array to those countries, so a listed data center outside them is omitted rather than returned with availability NONE. On the list endpoint a GPU type with no data center in those countries drops out entirely; the single-GPU endpoint still returns the requested type, with availability NONE and dataCenters omitted, so a 404 keeps meaning the GPU type does not exist. Read the NONE on availability rather than the absence of dataCenters, which is also absent when availability was not requested.',\n },\n cudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Comma-separated CUDA versions to scope availability and lowest-price calculations to, matched exactly. Format: major.minor, e.g. 12.8 — a bare major is rejected here because it identifies no version. Valid only with include=AVAILABILITY (400 otherwise) and mutually exclusive with minCudaVersion (400 if both are sent); a malformed entry is a 422. Also narrows the returned cudaVersions array; omit it to enumerate every version offered.',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+(\\\\.\\\\d+)?$',\n description:\n 'Lowest acceptable CUDA version to scope availability and lowest-price calculations to, compared numerically. Format: integer major or major.minor, e.g. 12 or 12.1 — unlike the `gpu.minCudaVersion` body field on pod and endpoint create, a bare major is accepted here and means any release of that major, because this filter only widens a read. Valid only with include=AVAILABILITY (400 otherwise) and mutually exclusive with cudaVersions (400 if both are sent); a malformed value is a 422. Use this for an open-ended floor and cudaVersions for an exact set.',\n },\n },\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n GpuCloudFilter: {\n type: 'string',\n description: 'GPU availability cloud filter.',\n enum: ['SECURE', 'COMMUNITY'],\n },\n Product: {\n type: 'string',\n description:\n 'Catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'CLUSTER', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'list-network-volume-billing',\n operationId: 'listNetworkVolumeBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/network-volumes',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'networkVolumeId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n networkVolumeId: {\n type: 'string',\n description: 'Filter to a specific network volume.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-network-volumes',\n operationId: 'listNetworkVolumes',\n description:\n 'List network volumes. Returns all network volumes owned by the authenticated user.',\n method: 'GET',\n path: '/v2/network-volumes',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-pod-billing',\n operationId: 'listPodBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/pods',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'podId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n podId: {\n type: 'string',\n description: 'Filter to a specific pod (GPU or CPU).',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-pods',\n operationId: 'listPods',\n description:\n 'List pods. Returns pods owned by the authenticated user. Cluster member pods are excluded by default; set `includeClusterPods=true` to include them (each carries a non-null `cluster` membership block). Results are cursor-paginated newest-first; an omitted `limit` defaults to 1000. When cluster member pods are excluded, the exclusion applies to each page after it is cut, so a page may hold fewer than `limit` pods — follow `pagination.nextCursor` until `hasNextPage` is false rather than counting items.',\n method: 'GET',\n path: '/v2/pods',\n params: [\n {\n name: 'includeClusterPods',\n location: 'query',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n includeClusterPods: {\n type: 'boolean',\n default: false,\n description:\n 'Include cluster member pods in the result. Defaults to false.',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected with 422.\\n\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n },\n },\n {\n name: 'list-public-templates',\n operationId: 'listPublicTemplates',\n description:\n \"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 — 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 — catalog or owned — 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`).\",\n method: 'GET',\n path: '/v2/catalog/templates',\n params: [\n {\n name: 'source',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n source: {\n type: 'string',\n enum: ['official', 'verified', 'community'],\n default: 'official',\n description:\n 'Which slice of the catalog to return: `official` for\\nRunpod-curated templates (default), `verified` for\\nRunpod-verified community templates, or `community` for all other\\npublicly shared templates.\\n',\n },\n },\n },\n },\n {\n name: 'list-registries',\n operationId: 'listRegistries',\n description:\n 'List container registries. Returns all container registry credentials owned by the authenticated user.',\n method: 'GET',\n path: '/v2/registries',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-secrets',\n operationId: 'listSecrets',\n description:\n \"List secrets. Returns the account's secrets — 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.\",\n method: 'GET',\n path: '/v2/account/secrets',\n params: [\n {\n name: 'name',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description:\n 'When provided, returns only the secret with this name (case-insensitive).',\n },\n },\n },\n },\n {\n name: 'list-serverless-billing',\n operationId: 'listServerlessBilling',\n description:\n 'Get serverless billing history, split into time buckets. SIZE WARNING: with defaults this emits one record per endpoint PER BUCKET — 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.',\n method: 'GET',\n path: '/v2/billing/serverless',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'serverlessId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago. Snapped down to the start of its bucketSize bucket so the window aligns with the returned records; provide a boundary-aligned value (e.g. midnight for bucketSize=day) to avoid widening.\\n',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.\\n',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\". The resolved window is aligned to bucket boundaries: startTime is the start of the earliest bucket (e.g. midnight of the earliest day) and endTime is the end of the current bucket. Mutually exclusive with startTime/endTime; provide one or the other, not both.\\n',\n },\n serverlessId: {\n type: 'string',\n description: 'Filter to a specific serverless endpoint.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'pod-action',\n operationId: 'podAction',\n description:\n '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` — boot a stopped pod (`EXITED` or `ERROR`) back toward `RUNNING`. - `stop` — stop a running or provisioning pod, releasing GPU/CPU compute while keeping its disk. The pod moves to `EXITED`. - `restart` — restart a `RUNNING` pod\\'s container in place. - `terminate` — 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`.',\n method: 'POST',\n path: '/v2/pods/{id}/action',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n body: {\n $ref: '#/$defs/PodActionRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n PodAction: {\n type: 'string',\n description: 'State transition to trigger on a pod.',\n enum: ['start', 'stop', 'restart', 'terminate'],\n },\n PodActionRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['action'],\n properties: {\n action: {\n $ref: '#/$defs/PodAction',\n },\n },\n },\n },\n },\n },\n {\n name: 'revoke-delegation',\n operationId: 'revokeDelegation',\n description: 'Revoke an ECR delegation',\n method: 'DELETE',\n path: '/v2/registries/delegations/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'update-cluster',\n operationId: 'updateCluster',\n description:\n 'Rename a cluster. Renames a cluster. This endpoint only changes the cluster name — compute shape, type, and container configuration are fixed at creation and cannot be updated.',\n method: 'PATCH',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n body: {\n $ref: '#/$defs/UpdateClusterRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateClusterRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n 'Request body for updating a cluster. Only the cluster name can be\\nchanged — this endpoint is a rename. Compute shape, type, and container\\nconfiguration are fixed at creation.\\n',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['renamed-cluster'],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-endpoint',\n operationId: 'updateEndpoint',\n description:\n \"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) — 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 — 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.\",\n method: 'PATCH',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n body: {\n $ref: '#/$defs/UpdateEndpointRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseEndpointGpuConfig: {\n type: 'object',\n properties: {\n pools: {\n type: 'array',\n minItems: 1,\n description:\n 'Serverless GPU pool IDs (as returned by `GET /v2/catalog/gpus` in\\n`pool`). Workers are placed on whichever listed pool has capacity.\\nNarrow a pool down to specific cards with `excludedTypes`.\\n\\nOn `PATCH`, `pools` and `excludedTypes` are one selection and are\\nreplaced together, so sending `pools` by itself **clears the\\nexclusions**. Two cases:\\n\\n- **Changing pools, keeping exclusions** — send both fields in one\\n request: `{\"gpu\": {\"pools\": [\"ADA_24\"], \"excludedTypes\":\\n [\"NVIDIA L40\"]}}`. `GET` the endpoint first to read the current\\n `excludedTypes` and resend the ones that still apply to the new\\n pools; an exclusion naming a type outside `pools` is a 400.\\n- **Changing only `count` or a CUDA constraint** — omit `pools`:\\n `{\"gpu\": {\"minCudaVersion\": \"12.4\"}}`. The pool list and the\\n exclusions are both left exactly as they are.\\n\\n`excludedTypes` documents the full rule.\\n',\n items: {\n type: 'string',\n },\n examples: [['ADA_24']],\n },\n excludedTypes: {\n type: 'array',\n uniqueItems: true,\n description:\n 'GPU **type** IDs to subtract from the selected pools — the `id`\\nfield of `GET /v2/catalog/gpus`, the same identifiers pods take in\\n`gpu.id`. Workers run on every type in `pools` except these. Omit to\\nuse the whole pool.\\n\\nPools stay the unit of selection; types are the unit of\\nsubtraction. There is no inclusive allowlist: a card later added to\\none of your pools becomes eligible, which is the honest reading of\\n\"this pool, minus these\".\\n\\nTied to `pools`, because the two together are one selection:\\nsupplying `pools` replaces that selection wholesale, so a `PATCH`\\nsending `pools` **without `excludedTypes`** **clears** them —\\nrestate them to keep them. A `PATCH` that omits `pools` leaves both\\nthe pools and the exclusions untouched, so changing only a CUDA\\nconstraint cannot widen a pinned endpoint.\\n\\nRejected with 400 if a value is not a GPU type in one of `pools`;\\nupstream accepts unrecognized exclusions silently, so a typo would\\notherwise produce a filter that does nothing. Surrounding whitespace\\nis trimmed, so `\" NVIDIA L40\"` and `\"NVIDIA L40\"` mean the same card.\\n',\n items: {\n type: 'string',\n pattern: '^\\\\s*[^-\\\\s]',\n },\n examples: [['NVIDIA L40']],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'GPUs per worker',\n examples: [1],\n },\n },\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n EndpointScaling: {\n description:\n \"Autoscaling signal — a discriminated union on `type`: `QUEUE_DELAY`\\n(queue-based endpoints only) or `REQUEST_COUNT`. The scaler is chosen\\nindependently of the endpoint's routing `type` and can be switched on\\nupdate.\\n\",\n oneOf: [\n {\n $ref: '#/$defs/QueueDelayScaling',\n },\n {\n $ref: '#/$defs/RequestCountScaling',\n },\n ],\n discriminator: {\n propertyName: 'type',\n mapping: {\n QUEUE_DELAY: '#/$defs/QueueDelayScaling',\n REQUEST_COUNT: '#/$defs/RequestCountScaling',\n },\n },\n },\n EndpointWorkers: {\n type: 'object',\n additionalProperties: false,\n properties: {\n min: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum number of workers.',\n examples: [0],\n },\n max: {\n type: 'integer',\n minimum: 0,\n description: 'Maximum number of workers.',\n examples: [5],\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n maximum: 3600,\n description:\n 'Seconds before idle workers scale down. Not applicable to queue-based\\nendpoints scaling on `requestCount` — rejected on create/update and\\nomitted from responses for that combination.\\n',\n examples: [5],\n },\n },\n },\n FlashBoot: {\n type: 'string',\n description:\n 'FlashBoot cold-start acceleration mode.\\n- `OFF` — disabled\\n- `FLASHBOOT` — enabled\\n- `PRIORITY_FLASHBOOT` — enabled with priority capacity\\n',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n },\n QueueDelayScaling: {\n type: 'object',\n additionalProperties: false,\n description: 'Scale on queue wait time. Queue-based endpoints only.',\n required: ['type', 'queueDelay'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `QUEUE_DELAY` for this variant.',\n enum: ['QUEUE_DELAY'],\n },\n queueDelay: {\n type: 'number',\n format: 'float',\n minimum: 0.5,\n description:\n 'Adjusts the number of workers based on how long requests wait in the queue.',\n examples: [4],\n },\n },\n },\n RequestCountScaling: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Scale on concurrent in-flight requests per worker. Required for\\nload-balancing endpoints; also selectable for queue-based.\\n',\n required: ['type', 'requestCount'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `REQUEST_COUNT` for this variant.',\n enum: ['REQUEST_COUNT'],\n },\n requestCount: {\n type: 'integer',\n minimum: 1,\n description:\n 'Adjusts the number of workers based on active in-flight requests.',\n examples: [4],\n },\n },\n },\n UpdateEndpointGpuConfig: {\n description:\n 'Partial GPU update — every field is optional and an omitted one is left\\nunchanged. Unlike create, `pools` is optional, so changing only a CUDA\\nconstraint does not require resending the pool list.\\n\\n`excludedTypes` requires `pools`, because the two are one selection and\\nonly a supplied `pools` replaces it — an exclusion on its own would\\notherwise be silently dropped.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseEndpointGpuConfig',\n },\n {\n type: 'object',\n dependentRequired: {\n excludedTypes: ['pools'],\n },\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for worker placement, as\\n`major.minor`. An explicit `[]` clears the constraint;\\nomitting the field leaves it unchanged. Takes effect as\\nworkers are replaced.\\n\\nA non-empty set is mutually exclusive with minCudaVersion (400\\nif both are sent). An explicit `[]` states no constraint, so it\\nmay accompany a floor.\\nSetting one does not clear the other — clear it explicitly in\\nthe same patch if the endpoint already carries it.\\n',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^$|^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for worker placement, as\\n`major.minor`. An explicit `\"\"` clears the floor; omitting the\\nfield leaves it unchanged. Takes effect as workers are\\nreplaced.\\n\\nMutually exclusive with a non-empty allowedCudaVersions (400 if\\nboth are sent); an explicit `[]` there states no constraint and\\nmay accompany this floor.\\n',\n examples: ['12.1'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n UpdateEndpointRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n description: 'Only provided fields are changed.',\n properties: {\n cpu: {\n type: 'array',\n minItems: 1,\n uniqueItems: true,\n description:\n 'Complete replacement CPU selection. Valid only for an existing CPU\\nendpoint; endpoint compute family cannot be changed.\\n',\n items: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.',\n },\n flashboot: {\n $ref: '#/$defs/FlashBoot',\n },\n gpu: {\n $ref: '#/$defs/UpdateEndpointGpuConfig',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n networkVolumes: {\n type: 'array',\n items: {\n type: 'string',\n },\n },\n scaling: {\n $ref: '#/$defs/EndpointScaling',\n },\n templateId: {\n type: 'string',\n description:\n \"ID of a serverless template whose container settings are\\napplied as if they were provided in this PATCH body (image,\\nargs, disk, ports, env, registry). Explicit body fields\\noverride the template's; `env` merges template and body per\\nkey (body wins) and, per PATCH semantics, replaces the\\nendpoint's env. One-time application — no link to the\\ntemplate is retained. Must be one of your templates or a\\npublic template (unknown or inaccessible ID → 404); must be\\na serverless template (→ 422).\\n\",\n examples: ['30zmvf89kd'],\n },\n timeout: {\n type: 'integer',\n },\n workers: {\n $ref: '#/$defs/EndpointWorkers',\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n {\n name: 'update-network-volume',\n operationId: 'updateNetworkVolume',\n description:\n '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.',\n method: 'PATCH',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n body: {\n $ref: '#/$defs/UpdateNetworkVolumeRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateNetworkVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n 'Only the provided fields are updated. At least one field must be\\npresent; an empty body is rejected.\\n',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n description: 'New human-readable name',\n examples: ['renamed-volume'],\n },\n size: {\n type: 'integer',\n minimum: 10,\n maximum: 4096,\n description:\n 'New size in GB. Must be greater than or equal to the current size —\\nnetwork volume storage cannot be reduced.\\n',\n examples: [100],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-pod',\n operationId: 'updatePod',\n description:\n \"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 — manage them through `/v2/clusters/{id}`. Returns `200` with the full updated pod.\",\n method: 'PATCH',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n body: {\n $ref: '#/$defs/UpdatePodRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n Mounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts attached to a pod. At-most-one of `persistent` or\\n`network` may be set today (mutually exclusive, enforced at the\\nhandler with 400 if both are present). The `network` field is an\\narray for forward compatibility with eventual multi-network-volume\\nsupport, but `maxItems` is 1 today.\\n\\nPATCH semantics:\\n- Omitting `mounts` or sending `{}` leaves the existing mount\\n unchanged.\\n- An explicit `network: []` is rejected with 400 (clearing mounts\\n is not supported).\\n- Mount kind is fixed at create — a PATCH that introduces a kind\\n not present at create (persistent on a network pod, network on\\n a persistent pod, or any mount on a previously-mountless pod)\\n is rejected with 400.\\n- The `volumeId` of a network mount is immutable; a PATCH that\\n names a different `volumeId` is rejected with 400.\\n- Partial mounts are not supported — every mount entry must\\n include the full schema (`size` + `path` for persistent,\\n `volumeId` + `path` for network). Missing required fields → 422.\\n',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on\\nboth GPU and CPU pods. The underlying `volumeId` is immutable\\npost-create; the mount `path` may be changed via PATCH.\\n',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data\\ndoes not survive a host failure. Disallowed on CPU pods. Mutually\\nexclusive with NetworkMount. Deprecated: prefer NetworkMount for any\\ndata you cannot recreate.\\n\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n UpdatePodRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n properties: {\n globalNetworking: {\n type: 'boolean',\n description:\n 'Enable (true) or disable (false) global networking. Takes effect on the next pod start/restart, not live. Requires an NVIDIA GPU and a global-networking-enabled data center (both enforced upstream). See `GET /v2/catalog/datacenters` (`globalNetwork`) for eligible data centers.',\n },\n locked: {\n type: 'boolean',\n description:\n 'Lock the pod (true) or unlock it (false). Locked pods cannot be stopped or reset.',\n },\n mounts: {\n $ref: '#/$defs/Mounts',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n templateId: {\n type: 'string',\n description:\n \"ID of a pod template whose container settings are applied as\\nif they were provided in this PATCH body (image, args, disk,\\nports, env, registry — mounts are not applied on update).\\nExplicit body fields override the template's; `env` merges\\ntemplate and body per key (body wins) and, per PATCH\\nsemantics, replaces the pod's env. One-time application —\\nno link to the template is retained. Must be one of your\\ntemplates or a public template (unknown or inaccessible ID\\n→ 404); must not be a serverless template (→ 422).\\n\",\n examples: ['30zmvf89kd'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n {\n name: 'update-secret',\n operationId: 'updateSecret',\n description:\n \"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 — 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.\",\n method: 'PATCH',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n body: {\n $ref: '#/$defs/UpdateSecretRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateSecretRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n \"Only the provided fields are updated; at least one field is required.\\nThe secret's `name` is immutable.\\n\",\n properties: {\n value: {\n type: 'string',\n minLength: 1,\n maxLength: 16777216,\n description:\n 'New secret value, replacing the current one. Write-only. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes).',\n },\n description: {\n type: 'string',\n maxLength: 65535,\n description:\n 'New human-readable description, at most 65,535 bytes of UTF-8 text. Send `\"\"` to clear.',\n },\n },\n },\n },\n },\n },\n {\n name: 'update-ssh-keys',\n operationId: 'updateSshKeys',\n description:\n \"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` — running pods are not updated.\",\n method: 'PUT',\n path: '/v2/account/ssh-keys',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/UpdateSshKeysRequest',\n },\n },\n required: ['body'],\n $defs: {\n UpdateSshKeysRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['keys'],\n properties: {\n keys: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^(ssh|ecdsa|sk)-[^\\\\s]+ [^\\\\s]+([ \\\\t][^\\\\n\\\\r]*)?$',\n },\n description:\n \"The full set of SSH public keys to register — this is a complete\\nreplacement, not a merge. Each entry is an authorized_keys-style\\nline: `<type> <base64-key> [comment]`, e.g. from\\n`~/.ssh/id_ed25519.pub`. Send `[]` to remove all keys. These keys\\nare provisioned into pods created with `startSsh` and\\nauthenticate both SSH paths reported in the pod's `ssh` block.\\n\",\n examples: [\n [\n 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILXGDN/SclOozk1xsDztpmhGiKkkrfQB9SKoO8dSIQQZ me@example.com',\n ],\n ],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-template',\n operationId: 'updateTemplate',\n description:\n \"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 — the template is a snapshot applied at creation time.\",\n method: 'PATCH',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n body: {\n $ref: '#/$defs/UpdateTemplateRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n description:\n 'Container configuration universal to every containerized resource. Compose ContainerConfig instead unless the resource cannot support a direct registry credential (clusters — there the registry credential arrives via a pod template, see CreateClusterRequest.templateId).\\n',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command, as a single raw string. This is the field `entrypoint` and `cmd` encode into, exposed in its stored form.\\n\\nTwo shapes are accepted. A bare shell string is treated as CMD and split into arguments, which is what the console\\'s \"Container start command\" field writes. A JSON object of the form `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both explicitly.\\n\\nResponses always return both representations: `args` exactly as stored, plus the deconstructed `entrypoint` and `cmd`. Supplying `args` together with `entrypoint` or `cmd` is allowed only when they describe the same command, so a read-modify-write client can send back everything it received. Send `\"\"` to clear, omit to leave unchanged.\\n',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form. When the image defines an ENTRYPOINT, this is the argument list passed to it. Encoded into the `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\\n\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ContainerConfig: {\n description:\n 'Reusable container configuration shared across templates, pods, and serverless endpoints. Adding a field here automatically propagates to all three resources.\\n',\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data\\ndoes not survive a host failure. Disallowed on CPU pods. Mutually\\nexclusive with NetworkMount. Deprecated: prefer NetworkMount for any\\ndata you cannot recreate.\\n\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n TemplateCategory: {\n type: 'string',\n description:\n 'Controls how the template is grouped and filtered in the Runpod console.\\nIt does not affect hardware selection, scheduling, or billing.\\n- `CPU` — CPU-only workloads\\n- `NVIDIA` — NVIDIA GPU workloads\\n- `AMD` — AMD GPU workloads\\n',\n enum: ['CPU', 'NVIDIA', 'AMD'],\n },\n TemplateMounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts attached to a template. Templates support only a\\nsingle persistent mount today; any `network` property is rejected\\nwith 422 by the schema validator.\\n\\nPATCH semantics: omitting `mounts` or sending `{}` leaves the\\nexisting mount unchanged.\\n',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n },\n },\n UpdateTemplateRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for pods created from this template. An explicit `[]` clears the constraint; omitting the field leaves it unchanged.',\n },\n category: {\n $ref: '#/$defs/TemplateCategory',\n },\n mounts: {\n $ref: '#/$defs/TemplateMounts',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n public: {\n type: 'boolean',\n },\n serverless: {\n type: 'boolean',\n },\n startJupyter: {\n type: 'boolean',\n description:\n 'Start JupyterLab at container startup (`JUPYTER_PASSWORD` env injection). See the create-time field for details.',\n },\n startSsh: {\n type: 'boolean',\n description:\n 'Provision SSH access at container startup (`PUBLIC_KEY` env injection). See the create-time field for details.',\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n];\n","// List caps so a large account's response cannot exceed an LLM's context\n// window. Curated tools over a paginated v2 list endpoint (list-endpoints,\n// list-templates) pass the server's `limit`/`cursor` through with\n// serverPageQuery and return its `pagination` block via serverPagination.\n// Tools whose data has no server pagination (hub, public endpoints, capacity)\n// cap client-side with capList, whose cursors are offsets into one response.\n\nexport const DEFAULT_LIST_LIMIT = 20;\nexport const MAX_LIST_LIMIT = 100;\n\n// JSON Schema fragments for the shared list parameters (spread into a curated\n// tool's inputSchema properties).\nexport const listPaginationProperties = {\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: MAX_LIST_LIMIT,\n description: `Maximum number of items to return (default ${DEFAULT_LIST_LIMIT}, max ${MAX_LIST_LIMIT}). Use the returned nextCursor to fetch the next page.`,\n },\n cursor: {\n type: 'string',\n description:\n 'Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning.',\n },\n} as const;\n\n// Coerce, floor at 1, and cap: the low-level server never validates the\n// JSON Schema, so limit: 0 (or junk) would otherwise return an empty page\n// whose nextCursor never advances.\nexport function clampListLimit(limit: unknown): number {\n const requested = Number(limit);\n return Math.min(\n Number.isFinite(requested) && requested >= 1\n ? Math.floor(requested)\n : DEFAULT_LIST_LIMIT,\n MAX_LIST_LIMIT\n );\n}\n\n// Query for a server-paginated list: the capped limit, and the server's\n// opaque cursor verbatim. A malformed cursor is the server's to reject (422).\nexport function serverPageQuery(args: Record<string, unknown>): {\n limit: number;\n cursor?: string;\n} {\n const cursor =\n typeof args.cursor === 'string' && args.cursor !== ''\n ? args.cursor\n : undefined;\n return { limit: clampListLimit(args.limit), ...(cursor ? { cursor } : {}) };\n}\n\n// The server's pagination block, plus how many items this page returned.\nexport function serverPagination(\n pagination: { nextCursor?: string | null; hasNextPage?: boolean } | undefined,\n returned: number\n): Record<string, unknown> {\n const hasNextPage = pagination?.hasNextPage === true;\n return {\n returned,\n hasNextPage,\n nextCursor: pagination?.nextCursor ?? null,\n ...(hasNextPage\n ? { note: 'More results exist. Pass cursor=nextCursor to fetch them.' }\n : {}),\n };\n}\n\n// The cursor is a base64-encoded offset today; invalid values are treated as\n// the start so a bad cursor never throws in an agent's face.\nexport function decodeCursorOffset(cursor: string | undefined): number {\n if (!cursor) return 0;\n try {\n // Strict digits-only: parseInt would accept \"20junk\" (and Node's base64\n // decoder silently strips non-alphabet bytes first), silently paginating\n // mid-list from a mangled cursor instead of restarting.\n const decoded = Buffer.from(cursor, 'base64').toString('utf8');\n if (!/^\\d+$/.test(decoded)) return 0;\n const offset = Number.parseInt(decoded, 10);\n return Number.isFinite(offset) && offset >= 0 ? offset : 0;\n } catch {\n return 0;\n }\n}\n\nexport function encodeCursorOffset(offset: number): string {\n return Buffer.from(String(offset), 'utf8').toString('base64');\n}\n\n// Caps a list to `limit` items starting at `cursor`, returning an envelope\n// that tells the agent how much it is seeing and how to get the rest. `extra`\n// merges small aggregate sibling fields alongside items/pagination; reserved\n// keys in it are ignored so they cannot shadow the cap.\nexport function capList(\n items: unknown[],\n options: { limit?: number; cursor?: string },\n extra?: Record<string, unknown>\n): Record<string, unknown> {\n const limit = clampListLimit(options.limit);\n const offset = decodeCursorOffset(options.cursor);\n const total = items.length;\n const page = items.slice(offset, offset + limit);\n const nextOffset = offset + page.length;\n const hasMore = nextOffset < total;\n const { items: _i, pagination: _p, ...safeExtra } = extra ?? {};\n void _i;\n void _p;\n return {\n ...safeExtra,\n items: page,\n pagination: {\n total,\n returned: page.length,\n offset,\n truncated: hasMore,\n nextCursor: hasMore ? encodeCursorOffset(nextOffset) : null,\n ...(hasMore\n ? {\n note: `Showing ${page.length} of ${total}. Pass cursor=nextCursor to fetch more, or narrow the query with filters.`,\n }\n : {}),\n },\n };\n}\n","// Shared error type for the non-SDK clients (runtime, GraphQL, SSE): carries\n// the HTTP status and the response body so tool handlers can map it onto a\n// ToolResult instead of leaking a bare exception to the MCP client.\n\nexport class HttpError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly payload: unknown = undefined\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\n// The one message for a credential-less call on a credentialed surface. Every\n// client throws this instead of sending `Bearer undefined` or a silently\n// unauthenticated request — runTool maps it onto a 401 tool result.\nexport function missingKeyError(): HttpError {\n return new HttpError(\n 'No Runpod API key: the request carried no usable credential.',\n 401\n );\n}\n","// Shared helpers for curated tool handlers.\n\nimport { HttpError } from '../clients/http-error.js';\nimport type { ToolResult } from '../dispatch.js';\n\nexport function ok(payload: unknown): ToolResult {\n return { ok: true, status: 200, payload };\n}\n\nexport function badRequest(message: string): ToolResult {\n return { ok: false, status: 400, payload: { error: message } };\n}\n\n// Runs a handler body and maps a thrown HttpError onto a ToolResult; anything\n// else propagates (a bug should fail loudly, not masquerade as an API error).\nfunction isTimeout(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n if (error.name === 'TimeoutError' || error.name === 'AbortError') return true;\n const cause = (error as { cause?: unknown }).cause;\n return (\n cause instanceof Error &&\n (cause.name === 'TimeoutError' || cause.name === 'AbortError')\n );\n}\n\nexport async function runTool(\n body: () => Promise<ToolResult>\n): Promise<ToolResult> {\n try {\n return await body();\n } catch (error) {\n if (error instanceof HttpError) {\n return {\n ok: false,\n status: error.status,\n payload: { error: error.message, detail: error.payload },\n };\n }\n // A request deadline firing (boundedFetch on the SDK/GraphQL/runtime paths,\n // or the SSE reader's own controller) must come back as a retryable tool error,\n // not a protocol-level crash. undici surfaces it either as the abort\n // reason itself (TimeoutError) or wrapped as `fetch failed` with a cause.\n if (isTimeout(error)) {\n return {\n ok: false,\n status: 504,\n payload: {\n error: 'The Runpod API did not respond before the request deadline.',\n hint: 'Transient upstream stall: retry the same call once; if it persists, check https://uptime.runpod.io.',\n },\n };\n }\n throw error;\n }\n}\n","// Shared MCP annotation sets for the curated overlay. The generated tools\n// derive theirs from the HTTP method (specgen/generator/tools.ts); curated\n// tools have no method to read, so each one picks the set that matches what\n// it does. Every tool that reaches the Runpod API sets openWorldHint; the\n// knowledge tools read the bundled plugin package and do not. destructiveHint here means \"can delete a resource or work in flight\",\n// not \"can lose state\": an additive update such as a PATCH is not destructive.\nimport type { ToolAnnotations } from '../types.js';\n\n/** A pure read: safe to call without asking anyone. */\nexport const readOnly: ToolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n};\n\n/** A read of the bundled plugin knowledge: no Runpod API call. */\nexport const bundledRead: ToolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n};\n\n/** A write that creates or submits: repeating it produces another thing. */\nexport const write: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n};\n\n/** A write that sets state: repeating it lands on the same state. */\nexport const idempotentWrite: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n};\n\n/** A write that destroys work in flight (cancel, purge, delete). */\nexport const destructive: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n};\n","// Curated get-capacity tool. The per-CUDA-version stock matrix, graded stock,\n// and per-version pricing live only in GraphQL (gpuTypes.lowestPrice with\n// gpuTypeCudaVersions / allowedCudaVersions input) — the REST catalog's only\n// CUDA dimension is a floor filter — so this cannot be generated from the v2\n// spec. Ported from the official MCP server (Apache-2.0, runpod/runpod-mcp).\n// Credential-free: served by the public GraphQL endpoint.\n\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\nconst CUDA_VERSION_REGEX = /^\\d{1,2}\\.\\d{1,2}$/;\nconst MAX_PROBE_VERSIONS = 12;\n\ninterface CapacityGpu {\n id: string;\n displayName: string;\n memoryInGb: number;\n secureCloud: boolean;\n communityCloud: boolean;\n lowestPrice?: {\n stockStatus: string | null;\n uninterruptablePrice: number | null;\n gpuTypeCudaVersions?: Array<{\n cudaVersion: string;\n availability: string;\n }> | null;\n } | null;\n}\n\ninterface CapacityResponse {\n gpuTypes: CapacityGpu[];\n}\n\nconst stockPriority: Record<string, number> = { High: 3, Medium: 2, Low: 1 };\n\n// The arguments both modes share, re-validated at runtime (the low-level\n// server never validates inputSchema): gpuCount coerced to an int in [1,8],\n// secureCloud a literal, blank filter entries dropped (a schema-bypassed [\"\"]\n// must not match the whole catalog).\ninterface CapacityQuery {\n gpuCount: number;\n secureArg: string;\n includeUnavailable: boolean;\n matchesFilter: (gpu: CapacityGpu) => boolean;\n pageOpts: { limit: number | undefined; cursor: string | undefined };\n}\n\nfunction parseCapacityArgs(args: Record<string, unknown>): CapacityQuery {\n const filterTerms = ((args.gpuTypeIds as string[] | undefined) ?? [])\n .filter((t) => typeof t === 'string' && t.trim().length > 0)\n .map((t) => t.toLowerCase());\n return {\n gpuCount: Math.min(8, Math.max(1, Math.floor(Number(args.gpuCount)) || 1)),\n secureArg: args.secureCloudOnly ? ', secureCloud: true' : '',\n includeUnavailable: args.includeUnavailable !== false,\n matchesFilter: (gpu) => {\n if (filterTerms.length === 0) return true;\n const id = gpu.id.toLowerCase();\n const name = gpu.displayName.toLowerCase();\n return filterTerms.some(\n (term) => id.includes(term) || name.includes(term)\n );\n },\n pageOpts: {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n },\n };\n}\n\n// The one ranking both modes share: most versions in stock first, then the\n// strongest stock grade, then memory; drop no-stock rows unless the caller\n// asked to keep them (they sort last either way).\nfunction rankByStock<T>(\n rows: T[],\n stats: (row: T) => {\n inStock: number;\n bestPriority: number;\n memoryGb: number;\n },\n includeUnavailable: boolean\n): T[] {\n const kept = includeUnavailable\n ? rows\n : rows.filter((row) => stats(row).inStock > 0);\n return kept.sort((a, b) => {\n const sa = stats(a);\n const sb = stats(b);\n return (\n sb.inStock - sa.inStock ||\n sb.bestPriority - sa.bestPriority ||\n sb.memoryGb - sa.memoryGb\n );\n });\n}\n\nexport const getCapacity: CuratedTool = {\n name: 'get-capacity',\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n cudaVersions: {\n type: 'array',\n items: { type: 'string', pattern: '^\\\\d{1,2}\\\\.\\\\d{1,2}$' },\n minItems: 1,\n maxItems: MAX_PROBE_VERSIONS,\n description:\n 'Deep-probe these host CUDA versions (e.g. [\"12.8\", \"13.0\"], max 12): one stock lookup per version returns graded stock and price. Omit for the single-call AVAILABLE/UNAVAILABLE matrix across all versions the fleet currently reports.',\n },\n includeUnavailable: {\n type: 'boolean',\n description:\n 'Out-of-stock GPUs are included by default (explicit \"Out\" cells / all-UNAVAILABLE rows, sorted last). Set false to hide GPUs with no stock on any listed version.',\n },\n gpuTypeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"Filter to GPU types matching any of these ids or display names (case-insensitive substring, e.g. ['NVIDIA GeForce RTX 4090'] or ['4090', 'H200']).\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n maximum: 8,\n description: 'GPUs per worker/pod to check stock for (default 1).',\n },\n secureCloudOnly: {\n type: 'boolean',\n description: 'Restrict the stock lookup to Secure Cloud hosts.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(() => {\n const query = parseCapacityArgs(args);\n const cudaVersions = args.cudaVersions as string[] | undefined;\n return cudaVersions?.length\n ? probeMode(ctx, query, cudaVersions)\n : matrixMode(ctx, query);\n }),\n};\n\n// Matrix mode: one query, per-version AVAILABLE/UNAVAILABLE from the fleet.\nasync function matrixMode(ctx: ToolContext, query: CapacityQuery) {\n // The public GraphQL path takes no variables, so arguments are inlined —\n // every inlined value was re-validated in parseCapacityArgs.\n const data = await ctx.graphql.public<CapacityResponse>(`\n query {\n gpuTypes {\n id\n displayName\n memoryInGb\n secureCloud\n communityCloud\n lowestPrice(input: { gpuCount: ${query.gpuCount}${query.secureArg} }) {\n stockStatus\n uninterruptablePrice\n gpuTypeCudaVersions {\n cudaVersion\n availability\n }\n }\n }\n }\n `);\n const rows = (data.gpuTypes ?? [])\n .filter((gpu) => gpu.id !== 'unknown' && query.matchesFilter(gpu))\n .map((gpu) => {\n const cuda: Record<string, string> = {};\n for (const c of gpu.lowestPrice?.gpuTypeCudaVersions ?? []) {\n cuda[c.cudaVersion] = c.availability;\n }\n return {\n id: gpu.id,\n displayName: gpu.displayName,\n memoryGb: gpu.memoryInGb,\n secureCloud: gpu.secureCloud,\n communityCloud: gpu.communityCloud,\n stockStatus: gpu.lowestPrice?.stockStatus || 'unavailable',\n pricePerHr: gpu.lowestPrice?.uninterruptablePrice ?? null,\n cudaVersions: cuda,\n };\n });\n const ranked = rankByStock(\n rows,\n (r) => ({\n inStock: Object.values(r.cudaVersions).filter((a) => a === 'AVAILABLE')\n .length,\n bestPriority: stockPriority[r.stockStatus] || 0,\n memoryGb: r.memoryGb,\n }),\n query.includeUnavailable\n );\n return ok(capList(ranked, query.pageOpts));\n}\n\ninterface ProbeRow {\n id: string;\n displayName: string;\n memoryGb: number;\n secureCloud: boolean;\n communityCloud: boolean;\n cudaVersions: Record<string, { stock: string; pricePerHr: number | null }>;\n}\n\n// Probe mode: one stock lookup per requested version, merged per GPU. The\n// schema caps at 12, but the cap is re-enforced here because direct handler\n// calls can bypass schema validation.\nasync function probeMode(\n ctx: ToolContext,\n query: CapacityQuery,\n cudaVersions: string[]\n) {\n const versions = [...new Set(cudaVersions)].slice(0, MAX_PROBE_VERSIONS);\n const invalid = versions.filter((v) => !CUDA_VERSION_REGEX.test(v));\n if (invalid.length > 0) {\n return badRequest(\n `Invalid CUDA version format: ${invalid.join(', ')}. Use \"major.minor\" strings like \"12.8\".`\n );\n }\n // allSettled, not all: a transient failure on one probe must not discard\n // the other versions' results — failures land in probeErrors instead.\n const perVersion = await Promise.allSettled(\n versions.map((v) =>\n ctx.graphql.public<CapacityResponse>(`\n query {\n gpuTypes {\n id\n displayName\n memoryInGb\n secureCloud\n communityCloud\n lowestPrice(input: { gpuCount: ${query.gpuCount}, allowedCudaVersions: [\"${v}\"]${query.secureArg} }) {\n stockStatus\n uninterruptablePrice\n }\n }\n }\n `)\n )\n );\n\n const probeErrors: Record<string, string> = {};\n const byId = new Map<string, ProbeRow>();\n versions.forEach((v, i) => {\n const settled = perVersion[i];\n if (settled.status === 'rejected') {\n probeErrors[v] =\n settled.reason instanceof Error\n ? settled.reason.message\n : String(settled.reason);\n return;\n }\n for (const gpu of settled.value.gpuTypes ?? []) {\n if (gpu.id === 'unknown' || !query.matchesFilter(gpu)) continue;\n let row = byId.get(gpu.id);\n if (!row) {\n row = {\n id: gpu.id,\n displayName: gpu.displayName,\n memoryGb: gpu.memoryInGb,\n secureCloud: gpu.secureCloud,\n communityCloud: gpu.communityCloud,\n cudaVersions: {},\n };\n byId.set(gpu.id, row);\n }\n const stock = gpu.lowestPrice?.stockStatus;\n // No stockStatus means no hosts match this version at all — record\n // an explicit \"Out\" cell so starvation is visible rather than an\n // absence the agent has to infer.\n row.cudaVersions[v] =\n !stock || stock === 'Out'\n ? { stock: 'Out', pricePerHr: null }\n : {\n stock,\n pricePerHr: gpu.lowestPrice?.uninterruptablePrice ?? null,\n };\n }\n });\n\n const ranked = rankByStock(\n [...byId.values()],\n (r) => ({\n inStock: Object.values(r.cudaVersions).filter((c) => c.stock !== 'Out')\n .length,\n bestPriority: Math.max(\n 0,\n ...Object.values(r.cudaVersions).map((c) => stockPriority[c.stock] || 0)\n ),\n memoryGb: r.memoryGb,\n }),\n query.includeUnavailable\n );\n return ok(\n capList(ranked, query.pageOpts, {\n probedCudaVersions: versions,\n ...(Object.keys(probeErrors).length > 0 ? { probeErrors } : {}),\n })\n );\n}\n","// GPU-selection convenience tool. REST v2 supports exclusions directly, so a\n// sparse PATCH replaces the legacy GraphQL read/echo/write operation.\nimport type { components } from '@runpod/typescript-api-sdk';\nimport type { CuratedTool } from '../types.js';\nimport { restError } from '../clients/rest-result.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { idempotentWrite } from './annotations.js';\n\ntype GpuSelection = { pools: string[]; excludedTypes: string[] };\nconst CUDA_VERSION = /^\\d+\\.\\d+$/;\n\nfunction nonemptyStrings(value: unknown): value is string[] {\n return (\n Array.isArray(value) &&\n value.every((item) => typeof item === 'string' && item.trim().length > 0)\n );\n}\n\nfunction gpuSelection(args: Record<string, unknown>): GpuSelection | string {\n if (args.gpuIds !== undefined) {\n if (typeof args.gpuIds !== 'string' || !args.gpuIds.trim())\n return 'gpuIds must be a non-empty string.';\n const selection: GpuSelection = { pools: [], excludedTypes: [] };\n for (const value of args.gpuIds.split(',').map((value) => value.trim())) {\n if (!value || value === '-')\n return 'gpuIds contains an empty pool or GPU exclusion.';\n if (value.startsWith('-'))\n selection.excludedTypes.push(value.slice(1).trim());\n else selection.pools.push(value);\n }\n return selection.pools.length\n ? selection\n : 'gpuIds must include at least one GPU pool.';\n }\n if (!nonemptyStrings(args.pools) || args.pools.length === 0)\n return 'Provide gpuIds or a non-empty pools array. See list-gpu-types for pool names.';\n if (\n args.excludeGpuTypeIds !== undefined &&\n !nonemptyStrings(args.excludeGpuTypeIds)\n )\n return 'excludeGpuTypeIds must be an array of non-empty strings.';\n return {\n pools: args.pools.map((value) => value.trim()),\n excludedTypes:\n (args.excludeGpuTypeIds as string[] | undefined)?.map((value) =>\n value.trim()\n ) ?? [],\n };\n}\n\nfunction formatGpuIds(gpu: {\n pools?: string[];\n excludedTypes?: string[];\n}): string {\n return [\n ...(gpu.pools ?? []),\n ...(gpu.excludedTypes ?? []).map((id) => `-${id}`),\n ].join(',');\n}\n\nexport const setEndpointGpus: CuratedTool = {\n name: 'set-endpoint-gpus',\n annotations: idempotentWrite,\n description:\n \"Set which GPUs a Serverless endpoint's workers run on — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n type: 'string',\n description: 'ID of the Serverless endpoint to update',\n },\n gpuIds: {\n type: 'string',\n description:\n \"Raw gpuIds string, e.g. 'ADA_24' or 'AMPERE_16,-NVIDIA RTX A4500'. Takes precedence over pools/excludeGpuTypeIds.\",\n },\n pools: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"GPU pool names workers may use (e.g. ['ADA_80_PRO','AMPERE_80']). The pool field from list-gpu-types.\",\n },\n excludeGpuTypeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"GPU type ids to exclude from the allowed pools (e.g. ['NVIDIA H100 NVL']). Use with pools to pin specific SKUs.\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n description: 'GPUs per worker. Omit to keep the current value.',\n },\n minCudaVersion: {\n type: 'string',\n description:\n \"Minimum host CUDA version workers may run on (e.g. '12.4'). Omit to keep the current value; use an empty string to clear it.\",\n },\n allowedCudaVersions: {\n type: 'string',\n description:\n \"Comma-separated allowed host CUDA versions (e.g. '12.8,12.7,12.6'). Omit to keep the current value; use an empty string to clear the list. CUDA compatibility is part of GPU selection — a narrow list can leave an endpoint unable to schedule workers.\",\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const selection = gpuSelection(args);\n if (typeof selection === 'string') return badRequest(selection);\n if (typeof args.endpointId !== 'string' || !args.endpointId.trim())\n return badRequest('endpointId must be a non-empty string.');\n if (\n args.gpuCount !== undefined &&\n (!Number.isSafeInteger(args.gpuCount) || Number(args.gpuCount) < 1)\n )\n return badRequest('gpuCount must be a positive integer.');\n if (\n args.minCudaVersion !== undefined &&\n (typeof args.minCudaVersion !== 'string' ||\n (args.minCudaVersion !== '' &&\n !CUDA_VERSION.test(args.minCudaVersion)))\n )\n return badRequest(\n 'minCudaVersion must be major.minor, or an empty string to clear it.'\n );\n if (\n args.allowedCudaVersions !== undefined &&\n typeof args.allowedCudaVersions !== 'string'\n )\n return badRequest(\n 'allowedCudaVersions must be a comma-separated string.'\n );\n const allowed =\n typeof args.allowedCudaVersions === 'string'\n ? args.allowedCudaVersions\n .split(',')\n .map((value) => value.trim())\n .filter(Boolean)\n : undefined;\n if (allowed?.some((value) => !CUDA_VERSION.test(value)))\n return badRequest(\n 'allowedCudaVersions must contain major.minor versions.'\n );\n if (allowed?.length && args.minCudaVersion)\n return badRequest(\n 'Set either allowedCudaVersions or minCudaVersion, not both.'\n );\n\n const params = { path: { id: args.endpointId } };\n const current = await ctx.sdk.GET('/v2/serverless/{id}', { params });\n if (!current.response.ok)\n return restError(current.response, current.error);\n if (!current.data?.gpu)\n return badRequest('This endpoint does not have a GPU configuration.');\n const gpu: components['schemas']['UpdateEndpointGpuConfig'] = {\n ...selection,\n ...(args.gpuCount !== undefined\n ? { count: args.gpuCount as number }\n : {}),\n ...(args.minCudaVersion !== undefined\n ? { minCudaVersion: args.minCudaVersion as string }\n : {}),\n ...(allowed !== undefined ? { allowedCudaVersions: allowed } : {}),\n };\n const updated = await ctx.sdk.PATCH('/v2/serverless/{id}', {\n params,\n body: { gpu },\n });\n if (!updated.response.ok)\n return restError(updated.response, updated.error);\n const updatedGpu = updated.data?.gpu;\n if (!updated.data || !updatedGpu)\n return {\n ok: false,\n status: 502,\n payload: { error: 'The API returned no updated GPU endpoint.' },\n };\n const endpoint = updated.data;\n return ok({\n endpoint: {\n id: endpoint.id,\n name: endpoint.name,\n gpuIds: formatGpuIds(updatedGpu),\n gpuCount: updatedGpu.count,\n workersMin: endpoint.workers?.min,\n workersMax: endpoint.workers?.max,\n },\n previousGpuIds: formatGpuIds(current.data.gpu),\n });\n }),\n};\n","// Curated Hub tools. The Hub catalog and Hub deploys have no REST home: the\n// catalog is the public GraphQL `listings(input: {})` query, and a deploy is\n// the authenticated saveEndpoint mutation pinned to a hubReleaseId. Ported\n// from the official MCP server (Apache-2.0, runpod/runpod-mcp).\n\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport type { ToolResult } from '../dispatch.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { readOnly, write } from './annotations.js';\n\ninterface HubBuild {\n id: string;\n imageName: string;\n}\n\ninterface HubRelease {\n id: string;\n name: string;\n tagName: string;\n createdAt: string;\n config?: string | null;\n build?: HubBuild | null;\n}\n\ninterface HubListing {\n id: string;\n repoId: string;\n title: string;\n description: string | null;\n repoName: string;\n repoOwner: string;\n createdAt: string;\n updatedAt: string;\n views: number;\n stars: number;\n deploys: number;\n language: string | null;\n category: string | null;\n tags: string[] | null;\n type: string;\n listedRelease?: HubRelease | null;\n}\n\ninterface ListingsResponse {\n listings: HubListing[];\n}\n\n// The release `config` is the repo's .runpod/hub.json serialized as a JSON\n// string (hardware requirements + env-var input schema). Tens of KB per\n// listing, so it is only requested when needed.\nfunction parseReleaseConfig(config: string | null | undefined): unknown {\n if (!config) return undefined;\n try {\n return JSON.parse(config);\n } catch {\n return config;\n }\n}\n\ninterface HubReleaseConfig {\n runsOn?: string;\n containerDiskInGb?: number;\n gpuIds?: string;\n gpuCount?: number;\n allowedCudaVersions?: string[];\n env?: Array<{\n key: string;\n input?: {\n name?: string;\n type?: string;\n default?: unknown;\n required?: boolean;\n trueValue?: string;\n falseValue?: string;\n };\n }>;\n}\n\n// The one listings query both hub tools share. `withConfig` pulls in the\n// (large) release config only when the caller needs it.\nfunction listingsQuery(withConfig: boolean): string {\n return `\n query {\n listings(input: {}) {\n id\n repoId\n title\n description\n repoName\n repoOwner\n createdAt\n updatedAt\n views\n stars\n deploys\n language\n category\n tags\n type\n listedRelease {\n id\n name\n tagName\n createdAt${withConfig ? '\\n config' : ''}\n build {\n id\n imageName\n }\n }\n }\n }\n `;\n}\n\n// Serializes a boolean through the schema's trueValue/falseValue. Applied to\n// caller values too: an agent naturally passes 'true' where the schema\n// declares trueValue '1'. Only exact 'true'/'false' map; anything else is a\n// deliberate literal.\nfunction serializeBoolean(\n value: string,\n input: { type?: string; trueValue?: string; falseValue?: string }\n): string {\n if (value === 'true') return input.trueValue ?? 'true';\n if (value === 'false') return input.falseValue ?? 'false';\n return value;\n}\n\n// Builds the template env array a Hub deploy submits: every key from the\n// release's env schema with its default (booleans serialized through\n// trueValue/falseValue), overridden by caller values. Caller keys not in the\n// schema are appended verbatim. Returns the missing required keys so the tool\n// can fail with an actionable message instead of a broken endpoint.\nexport function buildHubEnv(\n config: HubReleaseConfig,\n overrides: Record<string, string>\n): { env: Array<{ key: string; value: string }>; missingRequired: string[] } {\n const env: Array<{ key: string; value: string }> = [];\n const missingRequired: string[] = [];\n const remaining = { ...overrides };\n\n for (const entry of config.env ?? []) {\n const input = entry.input ?? {};\n const override = entry.key in remaining ? remaining[entry.key] : undefined;\n delete remaining[entry.key];\n\n // Empty overrides retain the existing fallback to the release default.\n // Validate the final serialized value, including boolean mappings.\n let value: string | undefined;\n if (override !== undefined && override !== '') {\n value =\n input.type === 'boolean' ? serializeBoolean(override, input) : override;\n } else if (input.default !== undefined && input.default !== null) {\n value =\n typeof input.default === 'boolean'\n ? serializeBoolean(String(input.default), input)\n : String(input.default);\n }\n\n if (input.required && (value === undefined || value === '')) {\n missingRequired.push(entry.key);\n env.push({ key: entry.key, value: '' });\n continue;\n }\n if (value !== undefined) env.push({ key: entry.key, value });\n\n // Optional, no default, nothing supplied: OMIT the key rather than send ''\n // (os.environ.get('X', 'fallback') returns '' when X='', shadowing the\n // fallback).\n }\n\n for (const [key, value] of Object.entries(remaining)) {\n env.push({ key, value });\n }\n\n return { env, missingRequired };\n}\n\n// Lowest entry of the config's allowedCudaVersions (numeric-aware compare, so\n// '12.10' > '12.9'). The console submits this as minCudaVersion.\nexport function minCudaVersion(versions: string[] | undefined): string | null {\n if (!versions || versions.length === 0) return null;\n const compare = (a: string, b: string) => {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d;\n }\n return 0;\n };\n return [...versions].sort(compare)[0];\n}\n\nfunction randomSuffix(): string {\n return Math.random().toString(36).slice(2, 8);\n}\n\nexport const listHubRepos: CuratedTool = {\n name: 'list-hub-repos',\n annotations: readOnly,\n description:\n 'List repos published to the Runpod Hub (prebuilt Serverless workers and Pod templates, e.g. vLLM, ComfyUI). Public catalog — 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) — it is large, so prefer requesting it for a single repo via the repoOwner/searchTerm filters.',\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n searchTerm: {\n type: 'string',\n description:\n \"Case-insensitive search across title, description, repo name, owner, and tags (e.g. 'vllm', 'comfyui', 'fine-tuning')\",\n },\n category: {\n type: 'string',\n description:\n \"Filter by category (e.g. 'language', 'image', 'audio', 'video', 'embedding')\",\n },\n type: {\n type: 'string',\n enum: ['SERVERLESS', 'POD'],\n description:\n 'Filter by listing type: SERVERLESS (endpoint workers) or POD (pod templates)',\n },\n repoOwner: {\n type: 'string',\n description:\n \"Filter to listings from this GitHub owner/org (e.g. 'runpod-workers', 'axolotl-ai-cloud')\",\n },\n includeConfig: {\n type: 'boolean',\n description:\n 'Include the listed release config (hardware requirements + env-var input schema, parsed from .runpod/hub.json). Large — off by default.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const data = await ctx.graphql.public<ListingsResponse>(\n listingsQuery(args.includeConfig === true)\n );\n\n let listings = data.listings ?? [];\n\n if (args.type) {\n // Normalize the arg too: the server never validates inputSchema, so a\n // lowercase \"serverless\" must match, not return a silent empty page.\n const term = String(args.type).toUpperCase();\n listings = listings.filter(\n (l) => (l.type ?? '').toUpperCase() === term\n );\n }\n if (args.category) {\n const term = String(args.category).toLowerCase();\n listings = listings.filter(\n (l) => (l.category ?? '').toLowerCase() === term\n );\n }\n if (args.repoOwner) {\n const term = String(args.repoOwner).toLowerCase();\n listings = listings.filter(\n (l) => (l.repoOwner ?? '').toLowerCase() === term\n );\n }\n if (args.searchTerm) {\n const term = String(args.searchTerm).toLowerCase();\n listings = listings.filter((l) =>\n [\n l.title,\n l.description,\n l.repoName,\n l.repoOwner,\n ...(l.tags ?? []),\n ].some((field) => (field ?? '').toLowerCase().includes(term))\n );\n }\n\n // Most-deployed first, id as tiebreak. The tiebreak is load-bearing:\n // each page re-fetches the whole catalog and the query promises no\n // order, so ties would move between requests and paging would silently\n // skip and duplicate.\n listings = [...listings].sort(\n (a, b) =>\n (b.deploys ?? 0) - (a.deploys ?? 0) || a.id.localeCompare(b.id)\n );\n\n const result = listings.map((l) => ({\n id: l.id,\n repo: `${l.repoOwner}/${l.repoName}`,\n title: l.title,\n description: l.description,\n type: l.type,\n category: l.category,\n tags: l.tags,\n language: l.language,\n stars: l.stars,\n deploys: l.deploys,\n views: l.views,\n githubUrl: `https://github.com/${l.repoOwner}/${l.repoName}`,\n hubUrl: `https://console.runpod.io/hub/${l.repoOwner}/${l.repoName}`,\n createdAt: l.createdAt,\n updatedAt: l.updatedAt,\n listedRelease: l.listedRelease\n ? {\n hubReleaseId: l.listedRelease.id,\n name: l.listedRelease.name,\n tagName: l.listedRelease.tagName,\n createdAt: l.listedRelease.createdAt,\n imageName: l.listedRelease.build?.imageName,\n ...(args.includeConfig === true\n ? { config: parseReleaseConfig(l.listedRelease.config) }\n : {}),\n }\n : null,\n }));\n\n return ok(\n capList(result, {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n })\n );\n }),\n};\n\nexport const deployHubRepo: CuratedTool = {\n name: 'deploy-hub-repo',\n annotations: write,\n description:\n \"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 — 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).\",\n inputSchema: {\n type: 'object',\n properties: {\n repo: {\n type: 'string',\n description:\n 'The Hub repo to deploy as \"owner/name\" (e.g. \\'runpod-workers/worker-comfyui\\'). Deploys its currently listed release. Provide this or hubReleaseId.',\n },\n hubReleaseId: {\n type: 'string',\n description:\n 'The Hub release ID to deploy (from list-hub-repos listedRelease.hubReleaseId). Provide this or repo.',\n },\n name: {\n type: 'string',\n description:\n \"Name for the new endpoint. Defaults to '<listing title> <release tag>'.\",\n },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description:\n 'Environment variable overrides, merged over the release config defaults. Keys not in the release schema are passed through as-is.',\n },\n gpuIds: {\n type: 'string',\n description:\n \"Comma-separated GPU pool names for workers (e.g. 'ADA_24' or 'ADA_80_PRO,AMPERE_80'). To pin specific GPU SKUs within a pool, append exclusions prefixed with '-' using GPU type ids from list-gpu-types. Defaults to the release config's gpuIds; required when the config does not specify one.\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n description: 'GPUs per worker. Defaults to the release config (or 1).',\n },\n containerDiskInGb: {\n type: 'integer',\n minimum: 1,\n description:\n 'Container disk size in GB. Defaults to the release config.',\n },\n workersMin: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum workers (default 0 — scale to zero).',\n },\n workersMax: {\n type: 'integer',\n minimum: 1,\n description: 'Maximum workers (default: account default).',\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n description: 'Seconds a worker idles before scaling down (default 5).',\n },\n scalerType: {\n type: 'string',\n enum: ['QUEUE_DELAY', 'REQUEST_COUNT'],\n description: 'Autoscaler type (default QUEUE_DELAY).',\n },\n scalerValue: {\n type: 'number',\n description: 'Autoscaler target value (default 4).',\n },\n executionTimeoutMs: {\n type: 'integer',\n minimum: 1,\n description: 'Per-job execution timeout in ms (default 600000).',\n },\n flashboot: {\n type: 'string',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n description: 'FlashBoot mode (default FLASHBOOT).',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n if (!args.repo && !args.hubReleaseId) {\n return badRequest(\n 'Provide either repo (\"owner/name\") or hubReleaseId. Use list-hub-repos to discover both.'\n );\n }\n const catalog = await ctx.graphql.public<ListingsResponse>(\n listingsQuery(true)\n );\n const listing = resolveListing(catalog, args);\n if ('payload' in listing) return listing;\n const release = checkDeployable(listing);\n if ('payload' in release) return release;\n const built = buildEndpointInput(listing, release, args);\n if ('payload' in built) return built;\n const data = await ctx.graphql.authed<SaveEndpointResponse>(\n SAVE_ENDPOINT_MUTATION,\n { input: built.input }\n );\n return ok({\n endpoint: data.saveEndpoint,\n deployed: {\n repo: `${listing.repoOwner}/${listing.repoName}`,\n release: release.tagName,\n hubReleaseId: release.id,\n imageName: release.build.imageName,\n },\n note: `Endpoint created. Submit jobs with run-endpoint/runsync-endpoint using endpointId \"${data.saveEndpoint.id}\".`,\n });\n }),\n};\n\n// ---- deploy-hub-repo helpers. Each returns its value or a ToolResult error\n// (discriminated by the `payload` key, which only ToolResult carries) so the\n// handler reads as the sequence of steps it is.\n\n// Narrowed by checkDeployable: a deployable release has a built image.\ntype DeployListedRelease = NonNullable<HubListing['listedRelease']> & {\n build: { imageName: string };\n};\n\n// Resolve the listing from the public catalog. The catalog only exposes each\n// repo's currently LISTED release, so a hubReleaseId must match one of those\n// (also the only state the console deploys).\nfunction resolveListing(\n catalog: ListingsResponse,\n args: Record<string, unknown>\n): HubListing | ToolResult {\n let listing: HubListing | undefined;\n if (args.hubReleaseId) {\n listing = (catalog.listings ?? []).find(\n (l) => l.listedRelease?.id === args.hubReleaseId\n );\n } else {\n const repoKey = String(args.repo).toLowerCase();\n listing = (catalog.listings ?? []).find(\n (l) => `${l.repoOwner}/${l.repoName}`.toLowerCase() === repoKey\n );\n }\n if (!listing) {\n return badRequest(\n `No Hub listing found for ${\n args.hubReleaseId\n ? `hubReleaseId \"${args.hubReleaseId}\" (only each repo's currently listed release is deployable)`\n : `repo \"${args.repo}\"`\n }. Use list-hub-repos to see the catalog.`\n );\n }\n return listing;\n}\n\nfunction checkDeployable(\n listing: HubListing\n): DeployListedRelease | ToolResult {\n const release = listing.listedRelease;\n if (!release?.build?.imageName) {\n return badRequest(\n `Hub repo ${listing.repoOwner}/${listing.repoName} has no listed release with a built image, so it cannot be deployed.`\n );\n }\n if ((listing.type ?? '').toUpperCase() !== 'SERVERLESS') {\n return badRequest(\n `Hub repo ${listing.repoOwner}/${listing.repoName} is a ${listing.type} listing — only SERVERLESS listings deploy as endpoints.`\n );\n }\n return release as DeployListedRelease;\n}\n\nfunction buildEndpointInput(\n listing: HubListing,\n release: DeployListedRelease,\n args: Record<string, unknown>\n): { input: Record<string, unknown> } | ToolResult {\n const config = (parseReleaseConfig(release.config) ?? {}) as HubReleaseConfig;\n\n const gpuIds = (args.gpuIds as string | undefined) ?? config.gpuIds;\n if (!gpuIds) {\n return badRequest(\n 'This release does not specify a GPU pool — pass gpuIds (comma-separated pool names, e.g. \"ADA_80_PRO,AMPERE_80\"; see the pool field on list-gpu-types).'\n );\n }\n\n const { env, missingRequired } = buildHubEnv(\n config,\n (args.env as Record<string, string> | undefined) ?? {}\n );\n if (missingRequired.length > 0) {\n return badRequest(\n `Missing required environment variables for this release: ${missingRequired.join(', ')}. Pass them via the env parameter.`\n );\n }\n\n const endpointName =\n (args.name as string | undefined) ?? `${listing.title} ${release.tagName}`;\n const minCuda = minCudaVersion(config.allowedCudaVersions);\n\n return {\n input: {\n name: endpointName,\n hubReleaseId: release.id,\n type: 'QB',\n gpuIds,\n gpuCount: (args.gpuCount as number | undefined) ?? config.gpuCount ?? 1,\n workersMin: (args.workersMin as number | undefined) ?? 0,\n workersMax: (args.workersMax as number | undefined) ?? null,\n idleTimeout: (args.idleTimeout as number | undefined) ?? 5,\n scalerType: (args.scalerType as string | undefined) ?? 'QUEUE_DELAY',\n scalerValue: (args.scalerValue as number | undefined) ?? 4,\n executionTimeoutMs:\n (args.executionTimeoutMs as number | undefined) ?? 600000,\n flashBootType: (args.flashboot as string | undefined) ?? 'FLASHBOOT',\n locations: null,\n networkVolumeIds: null,\n compliance: [],\n modelReferences: [],\n ...(minCuda\n ? {\n minCudaVersion: minCuda,\n allowedCudaVersions: config.allowedCudaVersions!.join(','),\n }\n : {}),\n template: {\n name: `${endpointName}__template__${randomSuffix()}`,\n imageName: release.build.imageName,\n containerDiskInGb:\n (args.containerDiskInGb as number | undefined) ??\n config.containerDiskInGb ??\n 20,\n containerRegistryAuthId: '',\n dockerArgs: '',\n startScript: '',\n ports: '',\n env,\n },\n },\n };\n}\n\ninterface SaveEndpointResponse {\n saveEndpoint: {\n id: string;\n name: string;\n gpuIds: string;\n gpuCount: number;\n workersMin: number;\n workersMax: number | null;\n idleTimeout: number;\n scalerType: string;\n scalerValue: number;\n flashBootType: string;\n templateId: string;\n };\n}\n\nconst SAVE_ENDPOINT_MUTATION = `\n mutation saveEndpoint($input: EndpointInput!) {\n saveEndpoint(input: $input) {\n id\n name\n gpuIds\n gpuCount\n workersMin\n workersMax\n idleTimeout\n scalerType\n scalerValue\n flashBootType\n templateId\n }\n }\n`;\n\nexport const hubTools: CuratedTool[] = [listHubRepos, deployHubRepo];\n","// Curated tools for the Serverless runtime plane (job submission and\n// lifecycle at api.runpod.ai/v2/{endpointId}/...). Runpod publishes no OpenAPI\n// document for this plane, so these cannot be generated from the v2 spec;\n// behavior is ported from the official MCP server (Apache-2.0,\n// runpod/runpod-mcp). Two transports serve these tools: local stdio\n// (5-minute wait budgets) and the hosted Vercel path, where the 60s gateway\n// reaper clamps every hold to HTTP_LONG_POLL_BUDGET_MS (see HOSTED below).\n\nimport { HttpError } from '../clients/http-error.js';\nimport type { CuratedTool } from '../types.js';\nimport type { ToolContext } from '../context.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { destructive, readOnly, write } from './annotations.js';\n\nconst ID_PATTERN = '^[a-zA-Z0-9_-]+$';\nconst ID_REGEX = new RegExp(ID_PATTERN);\n\n// Upstream default the server applies when no ?wait= is sent on /runsync.\nconst RUNSYNC_UPSTREAM_DEFAULT_WAIT_MS = 90_000;\n// Client deadline slack on top of the wait the server was asked to hold — a\n// deadline at the hold aborts the reply we are waiting for.\nconst UPSTREAM_HOLD_SLACK_MS = 5_000;\n\n// stream-job polling: total budget, what an empty /stream holds for when no\n// ?wait= is sent (the stdio path omits the query), per-poll floor, pause\n// between polls, and the consecutive-error cap that ends the run.\n// Hosted (Vercel) requests are reaped at 60s (vercel.json maxDuration), so\n// every server-side hold clamps to 45s there — the response must serialize\n// before the platform kills the invocation. stdio keeps the 5-minute budgets.\nexport const HOSTED = process.env.VERCEL === '1';\nexport const HTTP_LONG_POLL_BUDGET_MS = 45_000;\nexport const STREAM_BUDGET_MS = HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : 5 * 60 * 1000;\nconst STREAM_UPSTREAM_DEFAULT_WAIT_MS = 10_000;\nconst MIN_POLL_TIMEOUT_MS = 1;\nconst STREAM_JOB_POLL_INTERVAL_MS = 1_000;\nexport const MAX_CONSECUTIVE_STREAM_ERRORS = 5;\n\n// get-job-status server-side wait: the ceiling on a single blocking call and\n// the pause between /status polls inside it. /status returns instantly (it\n// does not hold like /stream), so blocking through a cold start means polling\n// it here rather than making the agent tight-loop the tool — a turn-burn that\n// never advances wall-clock. Ceiling matches runsync's 5-minute wait cap.\nexport const STATUS_WAIT_MAX_MS = HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : 5 * 60 * 1000;\nconst STATUS_POLL_INTERVAL_MS = 4_000;\n\nconst TERMINAL_STATUSES = new Set([\n 'COMPLETED',\n 'FAILED',\n 'CANCELLED',\n 'TIMED_OUT',\n]);\n\nconst RESUME_ADVICE =\n 'Call stream-job again to continue collecting output, get-job-status to check the job without streaming, or stream without a budget by calling the runtime API directly (GET https://api.runpod.ai/v2/{endpointId}/stream/{jobId} with a Bearer API key).';\n\nfunction formatBudget(ms: number): string {\n return ms < 120_000\n ? `${Math.round(ms / 1000)} seconds`\n : `${Math.round(ms / 60_000)} minutes`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(() => resolve(), ms);\n });\n}\n\n// A poll can use only the time remaining in the caller's budget. The\n// upstream hold gets slack when available, never an extension of that budget.\nexport function streamPollTimeoutMs(\n remainingMs: number,\n holdMs: number\n): number {\n return Math.max(\n Math.min(remainingMs, holdMs + UPSTREAM_HOLD_SLACK_MS),\n MIN_POLL_TIMEOUT_MS\n );\n}\n\n// One polling driver for both wait loops (/stream and /status): poll until a\n// terminal status, the budget runs out, or the API fails\n// MAX_CONSECUTIVE_STREAM_ERRORS times IN A ROW. Only consecutive failures end\n// the run, and the error reported at the end is one still happening at the\n// end. The callers differ only in how each poll's deadline derives from the\n// remaining budget, the cadence, and the advice attached to a non-terminal\n// exit.\nasync function pollUntilTerminal(deps: {\n poll: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n // Deadline for ONE poll, derived from the budget's remaining ms.\n timeoutFor: (remainingMs: number) => number;\n pollIntervalMs: number;\n // Advice strings for the two non-terminal exits.\n abortedNote: string;\n timedOutNote: string;\n // Chunk collection seam (/stream); called on every successful reply.\n onReply?: (reply: Record<string, unknown>) => void;\n}): Promise<Record<string, unknown>> {\n const startedAt = Date.now();\n const elapsed = () => Date.now() - startedAt;\n let result: Record<string, unknown> = {};\n let consecutiveErrors = 0;\n let lastError: string | undefined;\n let lastErrorStatus = 502;\n\n while (elapsed() < deps.budgetMs) {\n try {\n const reply = await deps.poll(deps.timeoutFor(deps.budgetMs - elapsed()));\n consecutiveErrors = 0;\n lastError = undefined;\n deps.onReply?.(reply);\n result = reply;\n if (TERMINAL_STATUSES.has(reply.status as string)) return result;\n } catch (error) {\n // Retrying cannot repair client errors. Let runTool retain the status\n // and recovery hint (especially 401 re-auth and 429 Retry-After).\n // A request timeout is transient and can still use the polling budget.\n if (\n error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500 &&\n error.status !== 408\n ) {\n throw error;\n }\n consecutiveErrors++;\n lastError = error instanceof Error ? error.message : String(error);\n lastErrorStatus =\n error instanceof HttpError\n ? error.status\n : error instanceof Error &&\n ['TimeoutError', 'AbortError'].includes(error.name)\n ? 504\n : 502;\n if (consecutiveErrors >= MAX_CONSECUTIVE_STREAM_ERRORS) {\n throw new HttpError(\n `Polling aborted after ${MAX_CONSECUTIVE_STREAM_ERRORS} consecutive errors: ${lastError}`,\n lastErrorStatus,\n { ...result, note: deps.abortedNote }\n );\n }\n }\n\n const remainingMs = Math.max(0, deps.budgetMs - elapsed());\n await sleep(Math.min(deps.pollIntervalMs, remainingMs));\n // If the next poll cannot fit after its interval, this was the final wait.\n // Timers can wake slightly early; do not turn that into an extra request.\n if (remainingMs <= deps.pollIntervalMs) break;\n }\n\n if (lastError !== undefined) {\n throw new HttpError(\n `Polling budget expired after an upstream error: ${lastError}`,\n lastErrorStatus,\n {\n ...result,\n note: 'The latest job status could not be retrieved. Retry after addressing the upstream error.',\n }\n );\n }\n return { ...result, pollingTimedOut: true, note: deps.timedOutNote };\n}\n\n// Exported so a test can drive the loop through `poll` without a server.\nexport async function collectJobStream(deps: {\n poll: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n holdMs: number;\n pollIntervalMs?: number;\n}): Promise<{ result: Record<string, unknown>; chunks: unknown[] }> {\n const chunks: unknown[] = [];\n let result: Record<string, unknown>;\n try {\n result = await pollUntilTerminal({\n poll: deps.poll,\n budgetMs: deps.budgetMs,\n timeoutFor: (remainingMs) =>\n streamPollTimeoutMs(remainingMs, deps.holdMs),\n pollIntervalMs: deps.pollIntervalMs ?? STREAM_JOB_POLL_INTERVAL_MS,\n abortedNote: `Polling stopped after ${MAX_CONSECUTIVE_STREAM_ERRORS} consecutive errors with the job possibly still running. ${RESUME_ADVICE}`,\n timedOutNote: `Polling stopped after ${formatBudget(deps.budgetMs)} with the job possibly still running. ${RESUME_ADVICE}`,\n onReply: (reply) => {\n if (Array.isArray(reply.stream)) chunks.push(...reply.stream);\n },\n });\n } catch (error) {\n if (error instanceof HttpError) {\n throw new HttpError(error.message, error.status, {\n ...(error.payload && typeof error.payload === 'object'\n ? error.payload\n : { error: error.payload }),\n stream: chunks,\n });\n }\n throw error;\n }\n return { result, chunks };\n}\n\n// Block on a job by polling /status until it reaches a terminal status, the\n// wait budget runs out, or the API fails MAX_CONSECUTIVE_STREAM_ERRORS times in\n// a row. /status returns instantly, so the hold lives here, not on the server.\n// Exported so a test can drive the loop through `fetchStatus` without a server.\nexport async function pollJobStatus(deps: {\n fetchStatus: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n pollIntervalMs?: number;\n}): Promise<Record<string, unknown>> {\n return pollUntilTerminal({\n poll: deps.fetchStatus,\n budgetMs: deps.budgetMs,\n // One /status call may not outlive the budget: unbounded, a hung socket\n // holds the request past the hosted 60s reaper (the client default is\n // 30s, which a poll started at 44s of a 45s budget would exceed).\n timeoutFor: (remainingMs) => Math.max(remainingMs, MIN_POLL_TIMEOUT_MS),\n pollIntervalMs: deps.pollIntervalMs ?? STATUS_POLL_INTERVAL_MS,\n abortedNote:\n 'Polling stopped after repeated errors with the job possibly still running. Call get-job-status again to keep checking.',\n timedOutNote: `Still not terminal after waiting ${formatBudget(deps.budgetMs)} — a first-job cold start (image pull + model load) can take several minutes. Call get-job-status again (with wait) to keep blocking, or check back without waiting.`,\n });\n}\n\n// A job stuck IN_QUEUE has two very different causes its status alone cannot\n// distinguish: no host has the endpoint's GPU available (capacity), or a\n// worker DID spin up and is crash-looping. The platform SOMETIMES marks the\n// latter UNHEALTHY — but not always: a container that fails to start loops\n// while its worker keeps reporting RUNNING or THROTTLED (observed\n// 2026-09-08), so UNHEALTHY is a symptom to act on rather than a test to\n// trust, and every branch below ends by pointing at the logs. Agents read the endless IN_QUEUE as \"no\n// capacity\" and stop digging, so get-job-status best-effort attaches the\n// endpoint's worker summary and a hint. Never fails the status call itself.\ninterface WorkerSummary {\n idle?: number;\n initializing?: number;\n running?: number;\n throttled?: number;\n total?: number;\n unhealthy?: number;\n}\n\n// Cost controls ported from the official server (runpod/runpod-mcp): a stuck\n// job is polled repeatedly against the SAME endpoint, so a short TTL cache\n// makes the extra round trip effectively free across a poll loop, and a\n// dedicated timeout stops a slow /workers call from eating into the caller's\n// budget. Together these are what make diagnosing on every IN_QUEUE — v1's\n// behavior — affordable on the hosted path.\nconst DIAGNOSIS_TTL_MS = 15_000;\nconst MAX_DIAGNOSIS_ENTRIES = 500;\nexport const QUEUED_DIAGNOSIS_TIMEOUT_MS = 5_000;\n\ninterface CachedDiagnosis {\n value: { workerHealth: WorkerSummary; hint: string };\n expiresAt: number;\n}\n// A context belongs to one caller. Never reuse private worker diagnostics\n// across callers that happen to ask about the same endpoint ID.\nconst diagnosisCaches = new WeakMap<\n ToolContext,\n Map<string, CachedDiagnosis>\n>();\n\nasync function diagnoseQueuedJob(\n ctx: ToolContext,\n endpointId: string\n): Promise<{ workerHealth: WorkerSummary; hint: string } | null> {\n const diagnosisCache =\n diagnosisCaches.get(ctx) ?? new Map<string, CachedDiagnosis>();\n diagnosisCaches.set(ctx, diagnosisCache);\n const cached = diagnosisCache.get(endpointId);\n if (cached && cached.expiresAt > Date.now()) return cached.value;\n diagnosisCache.delete(endpointId);\n\n const remember = (value: { workerHealth: WorkerSummary; hint: string }) => {\n if (diagnosisCache.size >= MAX_DIAGNOSIS_ENTRIES) {\n const oldest = diagnosisCache.keys().next().value;\n if (oldest !== undefined) diagnosisCache.delete(oldest);\n }\n diagnosisCache.set(endpointId, {\n value,\n expiresAt: Date.now() + DIAGNOSIS_TTL_MS,\n });\n return value;\n };\n\n // Explicit controller + ref'd timer, not AbortSignal.timeout: that timer is\n // unref'd and never fires on an otherwise idle loop (see bounded-fetch.ts).\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n QUEUED_DIAGNOSIS_TIMEOUT_MS\n );\n try {\n const { data, error } = await ctx.sdk.GET('/v2/serverless/{id}/workers', {\n params: { path: { id: endpointId } },\n signal: controller.signal,\n });\n if (error !== undefined || !data) return null;\n const summary = (data as { summary?: WorkerSummary }).summary;\n const workers =\n (data as { workers?: Array<{ id: string; status?: string }> }).workers ??\n [];\n if (!summary) return null;\n\n if ((summary.unhealthy ?? 0) > 0) {\n const badIds = workers\n .filter((w) => w.status === 'UNHEALTHY')\n .map((w) => w.id)\n .join(', ');\n return remember({\n workerHealth: summary,\n hint: `${summary.unhealthy} of ${summary.total} worker(s) on this endpoint are UNHEALTHY — the container is likely crash-looping (repeated starts that exit before the handler runs). The job can stay IN_QUEUE indefinitely; this is a worker failure, NOT a capacity shortage. Inspect the logs with stream-worker-logs${badIds ? ` (workerId: ${badIds})` : ''}.`,\n });\n }\n if ((summary.total ?? 0) === 0) {\n return remember({\n workerHealth: summary,\n hint: 'No workers are scheduled for this endpoint yet — it may simply be scaling up from zero (normal for the first seconds of a cold start), or it is waiting for GPU capacity / its GPU-CUDA constraints exclude the currently-available hosts. If this persists, check availability with get-capacity or widen the GPU/CUDA settings.',\n });\n }\n if ((summary.initializing ?? 0) > 0) {\n return remember({\n workerHealth: summary,\n hint: 'A worker is initializing — likely a cold start (image pull / model load); the job should start soon.',\n });\n }\n // Workers exist, none UNHEALTHY, none initializing — and the job is still\n // queued. Do NOT read this as \"the workers are fine\": a container that\n // fails to start loops while its worker keeps reporting RUNNING or\n // THROTTLED and unhealthy stays 0. Observed 2026-09-08: twelve\n // `error starting container: no space left on device` cycles in 100\n // seconds, unhealthy 0 throughout. The logs are the only authority here,\n // so send the caller there rather than returning an empty hint.\n const running = summary.running ?? 0;\n const throttled = summary.throttled ?? 0;\n return remember({\n workerHealth: summary,\n hint: `${summary.total ?? 0} worker(s) exist and none report UNHEALTHY${\n throttled > 0 ? ` (${throttled} throttled)` : ''\n }, yet the job is still queued. UNHEALTHY is one symptom of a crash loop, not a test for it — a container failing to start loops while its worker still reports RUNNING. Read stream-worker-logs on ${\n running > 0 ? 'a RUNNING worker' : 'any worker'\n } (ids from list-endpoint-workers) before concluding this is only a slow cold start.`,\n });\n } catch {\n return null; // diagnosis is best-effort — never break the status call\n } finally {\n clearTimeout(timer);\n }\n}\n\nconst endpointIdProperty = {\n type: 'string',\n pattern: ID_PATTERN,\n description: 'ID of the Serverless endpoint',\n} as const;\n\nconst jobIdProperty = {\n type: 'string',\n pattern: ID_PATTERN,\n description: 'ID of the job',\n} as const;\n\nconst inputProperty = {\n type: 'object',\n additionalProperties: true,\n description:\n 'Input payload for the worker handler. The expected fields depend on the deployed model or worker.',\n} as const;\n\nconst webhookProperty = {\n type: 'string',\n description:\n 'Webhook URL to receive job completion notifications instead of polling',\n} as const;\n\nconst policyProperty = {\n type: 'object',\n description: 'Execution policy options',\n properties: {\n executionTimeout: {\n type: 'number',\n description: 'Maximum execution time in milliseconds',\n },\n lowPriority: {\n type: 'boolean',\n description: 'Submit as a low-priority job',\n },\n ttl: {\n type: 'number',\n description: 'Time-to-live for the job result in milliseconds',\n },\n },\n} as const;\n\nconst s3ConfigProperty = {\n type: 'object',\n description: 'S3-compatible storage config for large outputs',\n properties: {\n accessId: { type: 'string', description: 'S3 access key ID' },\n accessSecret: { type: 'string', description: 'S3 secret access key' },\n bucketName: { type: 'string', description: 'S3 bucket name' },\n endpointUrl: { type: 'string', description: 'S3 endpoint URL' },\n },\n required: ['accessId', 'accessSecret', 'bucketName', 'endpointUrl'],\n} as const;\n\nfunction requireIds(\n args: Record<string, unknown>,\n keys: string[]\n): string | null {\n for (const key of keys) {\n const value = args[key];\n if (typeof value !== 'string' || !ID_REGEX.test(value)) {\n return `${key} must be a string matching ${ID_PATTERN}`;\n }\n }\n return null;\n}\n\n// The low-level MCP server does not enforce the advertised input schema.\n// Reject malformed waits before they reach timeout arithmetic or the API.\nfunction validateWait(wait: unknown): string | null {\n if (wait === undefined) return null;\n return typeof wait === 'number' && Number.isFinite(wait) && wait >= 1000\n ? null\n : 'wait must be a finite number of at least 1000 milliseconds, or omitted.';\n}\n\nexport const runEndpoint: CuratedTool = {\n name: 'run-endpoint',\n annotations: write,\n description:\n 'Submit an asynchronous job to a Serverless endpoint. Returns a job ID immediately — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to run',\n },\n input: inputProperty,\n webhook: webhookProperty,\n policy: policyProperty,\n s3Config: s3ConfigProperty,\n },\n required: ['endpointId', 'input'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n const { endpointId, ...body } = args;\n return ok(\n await ctx.runtime(endpointId as string, '/run', {\n method: 'POST',\n body: body as Record<string, unknown>,\n })\n );\n }),\n};\n\nexport const runsyncEndpoint: CuratedTool = {\n name: 'runsync-endpoint',\n annotations: write,\n description:\n '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' +\n (HOSTED\n ? ` — 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.`\n : ' to up to 5 minutes (300000 ms); it defaults to 90000 (90 seconds).'),\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to run synchronously',\n },\n input: inputProperty,\n wait: {\n type: 'number',\n minimum: 1000,\n maximum: HOSTED ? HTTP_LONG_POLL_BUDGET_MS : 300000,\n description: HOSTED\n ? `How long in milliseconds the server should wait for a result (1000–${HTTP_LONG_POLL_BUDGET_MS}; higher values clamp to ${HTTP_LONG_POLL_BUDGET_MS}, the gateway ceiling).`\n : 'How long in milliseconds the server should wait for a result before returning a job ID to poll (1000–300000). Defaults to 90000 (90 seconds).',\n },\n webhook: webhookProperty,\n policy: policyProperty,\n s3Config: s3ConfigProperty,\n },\n required: ['endpointId', 'input'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n const waitError = validateWait(args.wait);\n if (waitError) return badRequest(waitError);\n const { endpointId, wait, ...body } = args;\n // Hosted: an omitted wait inherits the upstream 90s hold, which outlives\n // the 60s platform reaper — send an explicit clamped wait instead.\n const requested = wait as number | undefined;\n const clamped =\n requested === undefined\n ? HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : undefined\n : Math.min(requested, STATUS_WAIT_MAX_MS);\n // Omitted local waits retain the upstream default; hosted always sends\n // an explicit wait that fits its gateway budget.\n const waitQuery = clamped === undefined ? '' : `?wait=${clamped}`;\n return ok(\n await ctx.runtime(endpointId as string, `/runsync${waitQuery}`, {\n method: 'POST',\n body: body as Record<string, unknown>,\n // The client deadline must outlast the wait the server was asked to\n // hold, or we abort the reply we are waiting for.\n timeoutMs:\n (clamped ?? RUNSYNC_UPSTREAM_DEFAULT_WAIT_MS) +\n UPSTREAM_HOLD_SLACK_MS,\n })\n );\n }),\n};\n\nexport const getJobStatus: CuratedTool = {\n name: 'get-job-status',\n annotations: readOnly,\n description:\n '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 ' +\n STATUS_WAIT_MAX_MS +\n ') to BLOCK server-side, polling until the job reaches a terminal status or the budget expires — use it to ride out a cold start (a first job on a fresh worker pulls the image and loads the model, commonly 1–5+ 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 — call again (with `wait`) to keep blocking. IMPORTANT: a job stuck IN_QUEUE does not necessarily mean a capacity shortage — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to check' },\n wait: {\n type: 'number',\n minimum: 1000,\n maximum: STATUS_WAIT_MAX_MS,\n description: `How long in milliseconds to block server-side, polling the job until it reaches a terminal status (1000–${STATUS_WAIT_MAX_MS}). Omit for a single immediate check. Use this to wait through a cold start rather than tight-looping the tool.`,\n },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n const waitError = validateWait(args.wait);\n if (waitError) return badRequest(waitError);\n const endpointId = args.endpointId as string;\n const jobId = args.jobId as string;\n const fetchStatus = (timeoutMs?: number) =>\n ctx.runtime(endpointId, `/status/${jobId}`, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n }) as Promise<Record<string, unknown>>;\n const result =\n args.wait === undefined\n ? await fetchStatus()\n : await pollJobStatus({\n fetchStatus,\n budgetMs: Math.min(args.wait as number, STATUS_WAIT_MAX_MS),\n });\n if (\n result &&\n typeof result === 'object' &&\n (result as { status?: string }).status === 'IN_QUEUE'\n ) {\n const diagnosis = await diagnoseQueuedJob(ctx, endpointId);\n if (diagnosis) {\n return ok({\n ...(result as Record<string, unknown>),\n workerHealth: diagnosis.workerHealth,\n ...(diagnosis.hint ? { hint: diagnosis.hint } : {}),\n });\n }\n }\n return ok(result);\n }),\n};\n\nexport const streamJob: CuratedTool = {\n name: 'stream-job',\n annotations: readOnly,\n 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 — call stream-job again to resume where it left off, or get-job-status to check without streaming.`,\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: {\n ...jobIdProperty,\n description: 'ID of the job to stream results from',\n },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n const { result, chunks } = await collectJobStream({\n budgetMs: STREAM_BUDGET_MS,\n holdMs: STREAM_UPSTREAM_DEFAULT_WAIT_MS,\n poll: (timeoutMs) =>\n ctx.runtime(args.endpointId as string, `/stream/${args.jobId}`, {\n timeoutMs,\n }) as Promise<Record<string, unknown>>,\n });\n return ok({ ...result, stream: chunks });\n }),\n};\n\nexport const cancelJob: CuratedTool = {\n name: 'cancel-job',\n annotations: destructive,\n description: 'Cancel a Serverless job that is queued or in progress.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to cancel' },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, `/cancel/${args.jobId}`, {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const retryJob: CuratedTool = {\n name: 'retry-job',\n annotations: write,\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to retry' },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, `/retry/${args.jobId}`, {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const endpointHealth: CuratedTool = {\n name: 'endpoint-health',\n annotations: readOnly,\n description:\n \"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 — when a job is stuck IN_QUEUE, prefer list-endpoint-workers over this rollup for per-worker state — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to check health for',\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n return ok(await ctx.runtime(args.endpointId as string, '/health'));\n }),\n};\n\nexport const purgeEndpointQueue: CuratedTool = {\n name: 'purge-endpoint-queue',\n annotations: destructive,\n description:\n 'Remove all pending jobs from a Serverless endpoint queue. Only affects queued jobs — in-progress jobs continue running. Use this for error recovery or clearing outdated requests.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to purge the queue for',\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, '/purge-queue', {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const jobTools: CuratedTool[] = [\n runEndpoint,\n runsyncEndpoint,\n getJobStatus,\n streamJob,\n cancelJob,\n retryJob,\n endpointHealth,\n purgeEndpointQueue,\n];\n","// Curated tool overriding the generated listEndpoints (excluded in\n// specgen/generator-config.yaml): full endpoint objects carry env maps and\n// requestUrls — six URLs per endpoint, all derivable from the id — which\n// measured 56% of a real account's payload (~32k tokens for 61 endpoints).\n// This returns the identifying fields, paginated; get-endpoint has the rest.\n\nimport { restError } from '../clients/rest-result.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport {\n listPaginationProperties,\n serverPageQuery,\n serverPagination,\n} from '../pagination.js';\nimport { readOnly } from './annotations.js';\n\nexport const listEndpoints: CuratedTool = {\n name: 'list-endpoints',\n annotations: readOnly,\n description:\n 'List serverless endpoints owned by the account (trimmed: id, name, image, ' +\n 'compute config, worker counts, scaling, data centers per endpoint — env ' +\n 'vars and request URLs are omitted; use get-endpoint for the full object). ' +\n 'Returns a page; pass cursor=nextCursor for more.',\n inputSchema: {\n type: 'object',\n properties: { ...listPaginationProperties },\n },\n async handler(ctx: ToolContext, args) {\n const { data, error, response } = await ctx.sdk.GET('/v2/serverless', {\n params: { query: serverPageQuery(args) },\n });\n if (!response.ok) return restError(response, error);\n if (!data || !Array.isArray(data.endpoints)) {\n return {\n ok: false,\n status: 502,\n payload: { error: 'The Runpod API returned no list data.' },\n };\n }\n const trimmed = data.endpoints.map((endpoint) => ({\n id: endpoint.id,\n name: endpoint.name,\n type: endpoint.type,\n image: endpoint.image,\n gpu: endpoint.gpu,\n cpu: endpoint.cpu,\n workers: endpoint.workers,\n scaling: endpoint.scaling,\n dataCenterIds: endpoint.dataCenterIds,\n flashboot: endpoint.flashboot,\n createdAt: endpoint.createdAt,\n }));\n return {\n ok: true,\n status: response.status,\n payload: {\n items: trimmed,\n pagination: serverPagination(data.pagination, trimmed.length),\n },\n };\n },\n};\n","// Curated tool overriding the generated listTemplates (excluded in\n// generator-config.yaml): full template objects carry env maps and readmes\n// that blow up LLM context, so this returns the identifying fields only.\n\nimport { restError } from '../clients/rest-result.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport {\n listPaginationProperties,\n serverPageQuery,\n serverPagination,\n} from '../pagination.js';\nimport { readOnly } from './annotations.js';\n\nexport const listTemplates: CuratedTool = {\n name: 'list-templates',\n annotations: readOnly,\n description:\n 'List templates visible to the account. Returns id, name, image, and ' +\n 'serverless flag per template; use get-template for full detail. ' +\n 'Returns 20 templates per page by default. To find a template, follow ' +\n '`pagination.nextCursor` until `hasNextPage` is false: a name missing ' +\n 'from one page may be on a later one.',\n inputSchema: {\n type: 'object',\n properties: { ...listPaginationProperties },\n },\n async handler(ctx: ToolContext, args) {\n const { data, error, response } = await ctx.sdk.GET('/v2/templates', {\n params: { query: serverPageQuery(args) },\n });\n if (!response.ok) return restError(response, error);\n if (!data || !Array.isArray(data.templates)) {\n return {\n ok: false,\n status: 502,\n payload: { error: 'The Runpod API returned no list data.' },\n };\n }\n return {\n ok: true,\n status: response.status,\n payload: {\n templates: data.templates.map((template) => ({\n id: template.id,\n name: template.name,\n image: template.image,\n serverless: template.serverless,\n })),\n pagination: serverPagination(data.pagination, data.templates.length),\n },\n };\n },\n};\n","// Curated log tools. Pod logs (GET /v2/pods/{id}/logs) and worker logs\n// (GET /v2/serverless/{id}/workers/{workerId}/logs) are the same feature on\n// two resources: an SSE stream of `data: {source,line,ts}` frames that stays\n// open to tail live output. The generated JSON dispatch cannot consume\n// text/event-stream, so both operations are excluded in generator-config.yaml\n// and served here as bounded snapshots instead.\n\nimport { sdkBase } from '../../_shared/hosts.js';\nimport type { CuratedTool } from '../types.js';\nimport { collectLogSnapshot, type LogSnapshotParams } from '../clients/sse.js';\nimport { ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\nconst logStreamProperties = {\n source: {\n type: 'string',\n enum: ['container', 'system', 'both'],\n description: 'Which log source to read (default: both)',\n },\n tail: {\n type: 'integer',\n minimum: 0,\n maximum: 5000,\n description:\n 'Historical lines to backfill before live output (API default 100, max 5000; 0 = live only). Ignored when `since` is set.',\n },\n since: {\n type: 'string',\n description:\n 'RFC3339 timestamp to resume from; when set, `tail` is ignored.',\n },\n maxWaitMs: {\n type: 'integer',\n minimum: 500,\n maximum: 30000,\n description: 'How long to read the stream, in ms (default 5000, max 30000)',\n },\n} as const;\n\nfunction baseUrl(): string {\n return sdkBase(process.env);\n}\n\n// The low-level MCP server never validates inputSchema, so the schema bounds\n// above are advisory. Re-derive the params here — otherwise a hostile\n// maxWaitMs holds the SSE socket open arbitrarily and a non-numeric tail goes\n// to the wire as ?tail=garbage.\nfunction clampInt(\n value: unknown,\n min: number,\n max: number,\n fallback: number | undefined\n): number | undefined {\n const n = typeof value === 'number' ? value : Number(value);\n if (value === undefined || value === null || !Number.isFinite(n))\n return fallback;\n return Math.min(max, Math.max(min, Math.trunc(n)));\n}\n\nconst LOG_SOURCES = logStreamProperties.source.enum;\n\nfunction logParams(args: Record<string, unknown>): LogSnapshotParams {\n return {\n source: LOG_SOURCES.includes(args.source as (typeof LOG_SOURCES)[number])\n ? (args.source as LogSnapshotParams['source'])\n : undefined,\n tail: clampInt(args.tail, 0, 5000, undefined),\n since: typeof args.since === 'string' ? args.since : undefined,\n maxWaitMs: clampInt(args.maxWaitMs, 500, 30_000, undefined),\n };\n}\n\nexport const streamPodLogs: CuratedTool = {\n name: 'stream-pod-logs',\n annotations: readOnly,\n description:\n \"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.\",\n inputSchema: {\n type: 'object',\n properties: {\n podId: { type: 'string', description: 'ID of the Pod to read logs from' },\n ...logStreamProperties,\n },\n required: ['podId'],\n },\n handler: (ctx, args) =>\n runTool(async () =>\n ok(\n await collectLogSnapshot(\n ctx.sse,\n `${baseUrl()}/v2/pods/${encodeURIComponent(args.podId as string)}/logs`,\n logParams(args)\n )\n )\n ),\n};\n\nexport const streamWorkerLogs: CuratedTool = {\n name: 'stream-worker-logs',\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n type: 'string',\n description: 'ID of the Serverless endpoint the worker belongs to',\n },\n workerId: {\n type: 'string',\n description: 'ID of the worker to read logs from',\n },\n ...logStreamProperties,\n },\n required: ['endpointId', 'workerId'],\n },\n handler: (ctx, args) =>\n runTool(async () =>\n ok(\n await collectLogSnapshot(\n ctx.sse,\n `${baseUrl()}/v2/serverless/${encodeURIComponent(args.endpointId as string)}/workers/${encodeURIComponent(args.workerId as string)}/logs`,\n logParams(args)\n )\n )\n ),\n};\n\nexport const logTools: CuratedTool[] = [streamPodLogs, streamWorkerLogs];\n","// node_modules/.pnpm/openapi-fetch@0.17.0/node_modules/openapi-fetch/dist/index.mjs\nvar PATH_PARAM_RE = /\\{[^{}]+\\}/g;\nvar supportsRequestInitExt = () => {\n return typeof process === \"object\" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;\n};\nfunction randomID() {\n return Math.random().toString(36).slice(2, 11);\n}\nfunction createClient(clientOptions) {\n let {\n baseUrl = \"\",\n Request: CustomRequest = globalThis.Request,\n fetch: baseFetch = globalThis.fetch,\n querySerializer: globalQuerySerializer,\n bodySerializer: globalBodySerializer,\n pathSerializer: globalPathSerializer,\n headers: baseHeaders,\n requestInitExt = void 0,\n ...baseOptions\n } = { ...clientOptions };\n requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;\n baseUrl = removeTrailingSlash(baseUrl);\n const globalMiddlewares = [];\n async function coreFetch(schemaPath, fetchOptions) {\n const {\n baseUrl: localBaseUrl,\n fetch = baseFetch,\n Request: Request2 = CustomRequest,\n headers,\n params = {},\n parseAs = \"json\",\n querySerializer: requestQuerySerializer,\n bodySerializer = globalBodySerializer ?? defaultBodySerializer,\n pathSerializer: requestPathSerializer,\n body,\n middleware: requestMiddlewares = [],\n ...init\n } = fetchOptions || {};\n let finalBaseUrl = baseUrl;\n if (localBaseUrl) {\n finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;\n }\n let querySerializer = typeof globalQuerySerializer === \"function\" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);\n if (requestQuerySerializer) {\n querySerializer = typeof requestQuerySerializer === \"function\" ? requestQuerySerializer : createQuerySerializer({\n ...typeof globalQuerySerializer === \"object\" ? globalQuerySerializer : {},\n ...requestQuerySerializer\n });\n }\n const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;\n const serializedBody = body === void 0 ? void 0 : bodySerializer(\n body,\n // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:\n // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however,\n // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,\n // setting the content-type at the very beginning to be overwritten.\n // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers.\n mergeHeaders(baseHeaders, headers, params.header)\n );\n const finalHeaders = mergeHeaders(\n // with no body, we should not to set Content-Type\n serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression\n serializedBody instanceof FormData ? {} : {\n \"Content-Type\": \"application/json\"\n },\n baseHeaders,\n headers,\n params.header\n );\n const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];\n const requestInit = {\n redirect: \"follow\",\n ...baseOptions,\n ...init,\n body: serializedBody,\n headers: finalHeaders\n };\n let id;\n let options;\n let request = new Request2(\n createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer, pathSerializer }),\n requestInit\n );\n let response;\n for (const key in init) {\n if (!(key in request)) {\n request[key] = init[key];\n }\n }\n if (finalMiddlewares.length) {\n id = randomID();\n options = Object.freeze({\n baseUrl: finalBaseUrl,\n fetch,\n parseAs,\n querySerializer,\n bodySerializer,\n pathSerializer\n });\n for (const m of finalMiddlewares) {\n if (m && typeof m === \"object\" && typeof m.onRequest === \"function\") {\n const result = await m.onRequest({\n request,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (result instanceof Request2) {\n request = result;\n } else if (result instanceof Response) {\n response = result;\n break;\n } else {\n throw new Error(\"onRequest: must return new Request() or Response() when modifying the request\");\n }\n }\n }\n }\n }\n if (!response) {\n try {\n response = await fetch(request, requestInitExt);\n } catch (error2) {\n let errorAfterMiddleware = error2;\n if (finalMiddlewares.length) {\n for (let i = finalMiddlewares.length - 1; i >= 0; i--) {\n const m = finalMiddlewares[i];\n if (m && typeof m === \"object\" && typeof m.onError === \"function\") {\n const result = await m.onError({\n request,\n error: errorAfterMiddleware,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (result instanceof Response) {\n errorAfterMiddleware = void 0;\n response = result;\n break;\n }\n if (result instanceof Error) {\n errorAfterMiddleware = result;\n continue;\n }\n throw new Error(\"onError: must return new Response() or instance of Error\");\n }\n }\n }\n }\n if (errorAfterMiddleware) {\n throw errorAfterMiddleware;\n }\n }\n if (finalMiddlewares.length) {\n for (let i = finalMiddlewares.length - 1; i >= 0; i--) {\n const m = finalMiddlewares[i];\n if (m && typeof m === \"object\" && typeof m.onResponse === \"function\") {\n const result = await m.onResponse({\n request,\n response,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (!(result instanceof Response)) {\n throw new Error(\"onResponse: must return new Response() when modifying the response\");\n }\n response = result;\n }\n }\n }\n }\n }\n const contentLength = response.headers.get(\"Content-Length\");\n if (response.status === 204 || request.method === \"HEAD\" || contentLength === \"0\" && !response.headers.get(\"Transfer-Encoding\")?.includes(\"chunked\")) {\n return response.ok ? { data: void 0, response } : { error: void 0, response };\n }\n if (response.ok) {\n const getResponseData = async () => {\n if (parseAs === \"stream\") {\n return response.body;\n }\n if (parseAs === \"json\" && !contentLength) {\n const raw = await response.text();\n return raw ? JSON.parse(raw) : void 0;\n }\n return await response[parseAs]();\n };\n return { data: await getResponseData(), response };\n }\n let error = await response.text();\n try {\n error = JSON.parse(error);\n } catch {\n }\n return { error, response };\n }\n return {\n request(method, url, init) {\n return coreFetch(url, { ...init, method: method.toUpperCase() });\n },\n /** Call a GET endpoint */\n GET(url, init) {\n return coreFetch(url, { ...init, method: \"GET\" });\n },\n /** Call a PUT endpoint */\n PUT(url, init) {\n return coreFetch(url, { ...init, method: \"PUT\" });\n },\n /** Call a POST endpoint */\n POST(url, init) {\n return coreFetch(url, { ...init, method: \"POST\" });\n },\n /** Call a DELETE endpoint */\n DELETE(url, init) {\n return coreFetch(url, { ...init, method: \"DELETE\" });\n },\n /** Call a OPTIONS endpoint */\n OPTIONS(url, init) {\n return coreFetch(url, { ...init, method: \"OPTIONS\" });\n },\n /** Call a HEAD endpoint */\n HEAD(url, init) {\n return coreFetch(url, { ...init, method: \"HEAD\" });\n },\n /** Call a PATCH endpoint */\n PATCH(url, init) {\n return coreFetch(url, { ...init, method: \"PATCH\" });\n },\n /** Call a TRACE endpoint */\n TRACE(url, init) {\n return coreFetch(url, { ...init, method: \"TRACE\" });\n },\n /** Register middleware */\n use(...middleware) {\n for (const m of middleware) {\n if (!m) {\n continue;\n }\n if (typeof m !== \"object\" || !(\"onRequest\" in m || \"onResponse\" in m || \"onError\" in m)) {\n throw new Error(\"Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`\");\n }\n globalMiddlewares.push(m);\n }\n },\n /** Unregister middleware */\n eject(...middleware) {\n for (const m of middleware) {\n const i = globalMiddlewares.indexOf(m);\n if (i !== -1) {\n globalMiddlewares.splice(i, 1);\n }\n }\n }\n };\n}\nfunction serializePrimitiveParam(name, value, options) {\n if (value === void 0 || value === null) {\n return \"\";\n }\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren\\u2019t supported. Provide your own `querySerializer()` to handle these.\"\n );\n }\n return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;\n}\nfunction serializeObjectParam(name, value, options) {\n if (!value || typeof value !== \"object\") {\n return \"\";\n }\n const values = [];\n const joiner = {\n simple: \",\",\n label: \".\",\n matrix: \";\"\n }[options.style] || \"&\";\n if (options.style !== \"deepObject\" && options.explode === false) {\n for (const k in value) {\n values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));\n }\n const final2 = values.join(\",\");\n switch (options.style) {\n case \"form\": {\n return `${name}=${final2}`;\n }\n case \"label\": {\n return `.${final2}`;\n }\n case \"matrix\": {\n return `;${name}=${final2}`;\n }\n default: {\n return final2;\n }\n }\n }\n for (const k in value) {\n const finalName = options.style === \"deepObject\" ? `${name}[${k}]` : k;\n values.push(serializePrimitiveParam(finalName, value[k], options));\n }\n const final = values.join(joiner);\n return options.style === \"label\" || options.style === \"matrix\" ? `${joiner}${final}` : final;\n}\nfunction serializeArrayParam(name, value, options) {\n if (!Array.isArray(value)) {\n return \"\";\n }\n if (options.explode === false) {\n const joiner2 = { form: \",\", spaceDelimited: \"%20\", pipeDelimited: \"|\" }[options.style] || \",\";\n const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);\n switch (options.style) {\n case \"simple\": {\n return final;\n }\n case \"label\": {\n return `.${final}`;\n }\n case \"matrix\": {\n return `;${name}=${final}`;\n }\n // case \"spaceDelimited\":\n // case \"pipeDelimited\":\n default: {\n return `${name}=${final}`;\n }\n }\n }\n const joiner = { simple: \",\", label: \".\", matrix: \";\" }[options.style] || \"&\";\n const values = [];\n for (const v of value) {\n if (options.style === \"simple\" || options.style === \"label\") {\n values.push(options.allowReserved === true ? v : encodeURIComponent(v));\n } else {\n values.push(serializePrimitiveParam(name, v, options));\n }\n }\n return options.style === \"label\" || options.style === \"matrix\" ? `${joiner}${values.join(joiner)}` : values.join(joiner);\n}\nfunction createQuerySerializer(options) {\n return function querySerializer(queryParams) {\n const search = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n if (value === void 0 || value === null) {\n continue;\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n search.push(\n serializeArrayParam(name, value, {\n style: \"form\",\n explode: true,\n ...options?.array,\n allowReserved: options?.allowReserved || false\n })\n );\n continue;\n }\n if (typeof value === \"object\") {\n search.push(\n serializeObjectParam(name, value, {\n style: \"deepObject\",\n explode: true,\n ...options?.object,\n allowReserved: options?.allowReserved || false\n })\n );\n continue;\n }\n search.push(serializePrimitiveParam(name, value, options));\n }\n }\n return search.join(\"&\");\n };\n}\nfunction defaultPathSerializer(pathname, pathParams) {\n let nextURL = pathname;\n for (const match of pathname.match(PATH_PARAM_RE) ?? []) {\n let name = match.substring(1, match.length - 1);\n let explode = false;\n let style = \"simple\";\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n if (name.startsWith(\".\")) {\n style = \"label\";\n name = name.substring(1);\n } else if (name.startsWith(\";\")) {\n style = \"matrix\";\n name = name.substring(1);\n }\n if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {\n continue;\n }\n const value = pathParams[name];\n if (Array.isArray(value)) {\n nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));\n continue;\n }\n if (typeof value === \"object\") {\n nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));\n continue;\n }\n if (style === \"matrix\") {\n nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);\n continue;\n }\n nextURL = nextURL.replace(match, style === \"label\" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));\n }\n return nextURL;\n}\nfunction defaultBodySerializer(body, headers) {\n if (body instanceof FormData) {\n return body;\n }\n if (headers) {\n const contentType = headers.get instanceof Function ? headers.get(\"Content-Type\") ?? headers.get(\"content-type\") : headers[\"Content-Type\"] ?? headers[\"content-type\"];\n if (contentType === \"application/x-www-form-urlencoded\") {\n return new URLSearchParams(body).toString();\n }\n }\n return JSON.stringify(body);\n}\nfunction createFinalURL(pathname, options) {\n let finalURL = `${options.baseUrl}${pathname}`;\n if (options.params?.path) {\n finalURL = options.pathSerializer(finalURL, options.params.path);\n }\n let search = options.querySerializer(options.params.query ?? {});\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n finalURL += `?${search}`;\n }\n return finalURL;\n}\nfunction mergeHeaders(...allHeaders) {\n const finalHeaders = new Headers();\n for (const h of allHeaders) {\n if (!h || typeof h !== \"object\") {\n continue;\n }\n const iterator = h instanceof Headers ? h.entries() : Object.entries(h);\n for (const [k, v] of iterator) {\n if (v === null) {\n finalHeaders.delete(k);\n } else if (Array.isArray(v)) {\n for (const v2 of v) {\n finalHeaders.append(k, v2);\n }\n } else if (v !== void 0) {\n finalHeaders.set(k, v);\n }\n }\n }\n return finalHeaders;\n}\nfunction removeTrailingSlash(url) {\n if (url.endsWith(\"/\")) {\n return url.substring(0, url.length - 1);\n }\n return url;\n}\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/util.js\nvar asciiRe = /^[\\x20-\\x7E]*$/;\nvar tokenRe = /^[a-zA-Z*][:/!#$%&'*+\\-.^_`|~A-Za-z0-9]*$/;\nfunction isAscii(str) {\n return asciiRe.test(str);\n}\nfunction isValidTokenStr(str) {\n return tokenRe.test(str);\n}\nfunction base64ToArrayBuffer(b64) {\n const binaryString = atob(b64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/token.js\nvar Token = class {\n constructor(value) {\n if (!isValidTokenStr(value)) {\n throw new TypeError(\"Invalid character in Token string. Tokens must start with *, A-Z and the rest of the string may only contain a-z, A-Z, 0-9, :/!#$%&'*+-.^_`|~\");\n }\n this.value = value;\n }\n toString() {\n return this.value;\n }\n};\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/displaystring.js\nvar DisplayString = class {\n constructor(value) {\n this.value = value;\n }\n toString() {\n return this.value;\n }\n};\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/parser.js\nfunction parseList(input) {\n const parser = new Parser(input);\n return parser.parseList();\n}\nvar ParseError = class extends Error {\n constructor(position, message) {\n super(`Parse error: ${message} at offset ${position}`);\n }\n};\nvar Parser = class {\n constructor(input) {\n this.input = input;\n this.pos = 0;\n }\n parseDictionary() {\n this.skipWS();\n const dictionary = /* @__PURE__ */ new Map();\n while (!this.eof()) {\n const thisKey = this.parseKey();\n let member;\n if (this.lookChar() === \"=\") {\n this.pos++;\n member = this.parseItemOrInnerList();\n } else {\n member = [true, this.parseParameters()];\n }\n dictionary.set(thisKey, member);\n this.skipOWS();\n if (this.eof()) {\n return dictionary;\n }\n this.expectChar(\",\");\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, \"Dictionary contained a trailing comma\");\n }\n }\n return dictionary;\n }\n parseList() {\n this.skipWS();\n const members = [];\n while (!this.eof()) {\n members.push(this.parseItemOrInnerList());\n this.skipOWS();\n if (this.eof()) {\n return members;\n }\n this.expectChar(\",\");\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, \"A list may not end with a trailing comma\");\n }\n }\n return members;\n }\n parseItem(standaloneItem = true) {\n if (standaloneItem)\n this.skipWS();\n const result = [\n this.parseBareItem(),\n this.parseParameters()\n ];\n if (standaloneItem)\n this.checkTrail();\n return result;\n }\n parseItemOrInnerList() {\n if (this.lookChar() === \"(\") {\n return this.parseInnerList();\n } else {\n return this.parseItem(false);\n }\n }\n parseInnerList() {\n this.expectChar(\"(\");\n this.pos++;\n const innerList = [];\n while (!this.eof()) {\n this.skipWS();\n if (this.lookChar() === \")\") {\n this.pos++;\n return [\n innerList,\n this.parseParameters()\n ];\n }\n innerList.push(this.parseItem(false));\n const nextChar = this.lookChar();\n if (nextChar !== \" \" && nextChar !== \")\") {\n throw new ParseError(this.pos, \"Expected a whitespace or ) after every item in an inner list\");\n }\n }\n throw new ParseError(this.pos, \"Could not find end of inner list\");\n }\n parseBareItem() {\n const char = this.lookChar();\n if (char === void 0) {\n throw new ParseError(this.pos, \"Unexpected end of string\");\n }\n if (char.match(/^[-0-9]/)) {\n return this.parseIntegerOrDecimal();\n }\n if (char === '\"') {\n return this.parseString();\n }\n if (char.match(/^[A-Za-z*]/)) {\n return this.parseToken();\n }\n if (char === \":\") {\n return this.parseByteSequence();\n }\n if (char === \"?\") {\n return this.parseBoolean();\n }\n if (char === \"@\") {\n return this.parseDate();\n }\n if (char === \"%\") {\n return this.parseDisplayString();\n }\n throw new ParseError(this.pos, \"Unexpected input\");\n }\n parseParameters() {\n const parameters = /* @__PURE__ */ new Map();\n while (!this.eof()) {\n const char = this.lookChar();\n if (char !== \";\") {\n break;\n }\n this.pos++;\n this.skipWS();\n const key = this.parseKey();\n let value = true;\n if (this.lookChar() === \"=\") {\n this.pos++;\n value = this.parseBareItem();\n }\n parameters.set(key, value);\n }\n return parameters;\n }\n parseIntegerOrDecimal() {\n let type = \"integer\";\n let sign = 1;\n let inputNumber = \"\";\n if (this.lookChar() === \"-\") {\n sign = -1;\n this.pos++;\n }\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, \"Expected a digit (0-9)\");\n }\n while (!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber += char;\n } else if (type === \"integer\" && char === \".\") {\n if (inputNumber.length > 12) {\n throw new ParseError(this.pos, \"Exceeded maximum decimal length\");\n }\n inputNumber += \".\";\n type = \"decimal\";\n } else {\n this.pos--;\n break;\n }\n if (type === \"integer\" && inputNumber.length > 15) {\n throw new ParseError(this.pos, \"Exceeded maximum integer length\");\n }\n if (type === \"decimal\" && inputNumber.length > 16) {\n throw new ParseError(this.pos, \"Exceeded maximum decimal length\");\n }\n }\n if (type === \"integer\") {\n return parseInt(inputNumber, 10) * sign;\n } else {\n if (inputNumber.endsWith(\".\")) {\n throw new ParseError(this.pos, \"Decimal cannot end on a period\");\n }\n if (inputNumber.split(\".\")[1].length > 3) {\n throw new ParseError(this.pos, \"Number of digits after the decimal point cannot exceed 3\");\n }\n return parseFloat(inputNumber) * sign;\n }\n }\n parseString() {\n let outputString = \"\";\n this.expectChar('\"');\n this.pos++;\n while (!this.eof()) {\n const char = this.getChar();\n if (char === \"\\\\\") {\n if (this.eof()) {\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n const nextChar = this.getChar();\n if (nextChar !== \"\\\\\" && nextChar !== '\"') {\n throw new ParseError(this.pos, \"A backslash must be followed by another backslash or double quote\");\n }\n outputString += nextChar;\n } else if (char === '\"') {\n return outputString;\n } else if (!isAscii(char)) {\n throw new ParseError(this.pos, \"Strings must be in the ASCII range\");\n } else {\n outputString += char;\n }\n }\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n parseDisplayString() {\n const chars = this.getChars(2);\n if (chars !== '%\"') {\n throw new ParseError(this.pos, \"Unexpected character. Display strings should start with %=\");\n }\n const result = [];\n while (!this.eof()) {\n const char = this.getChar();\n if (char.charCodeAt(0) <= 31 || char.charCodeAt(0) >= 127 && char.charCodeAt(0) <= 255) {\n throw new ParseError(this.pos, \"Invalid char found in DisplayString. Did you forget to escape?\");\n }\n if (char === \"%\") {\n const hexChars = this.getChars(2);\n if (/^[0-9a-f]{2}$/.test(hexChars)) {\n result.push(parseInt(hexChars, 16));\n } else {\n throw new ParseError(this.pos, `Unexpected sequence after % in DispalyString: \"${hexChars}\". Note that hexidecimals must be lowercase`);\n }\n continue;\n }\n if (char === '\"') {\n const textDecoder = new TextDecoder(\"utf-8\", {\n fatal: true\n });\n try {\n return new DisplayString(textDecoder.decode(new Uint8Array(result)));\n } catch {\n throw new ParseError(this.pos, \"Fatal error decoding UTF-8 sequence in Display String\");\n }\n }\n result.push(char.charCodeAt(0));\n }\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n parseToken() {\n let outputString = \"\";\n while (!this.eof()) {\n const char = this.lookChar();\n if (char === void 0 || !/^[:/!#$%&'*+\\-.^_`|~A-Za-z0-9]$/.test(char)) {\n return new Token(outputString);\n }\n outputString += this.getChar();\n }\n return new Token(outputString);\n }\n parseByteSequence() {\n this.expectChar(\":\");\n this.pos++;\n const endPos = this.input.indexOf(\":\", this.pos);\n if (endPos === -1) {\n throw new ParseError(this.pos, 'Could not find a closing \":\" character to mark end of Byte Sequence');\n }\n const b64Content = this.input.substring(this.pos, endPos);\n this.pos += b64Content.length + 1;\n if (!/^[A-Za-z0-9+/=]*$/.test(b64Content)) {\n throw new ParseError(this.pos, \"ByteSequence does not contain a valid base64 string\");\n }\n try {\n return base64ToArrayBuffer(b64Content);\n } catch {\n throw new ParseError(this.pos, \"ByteSequence does not contain a valid base64 string\");\n }\n }\n parseBoolean() {\n this.expectChar(\"?\");\n this.pos++;\n const char = this.getChar();\n if (char === \"1\") {\n return true;\n }\n if (char === \"0\") {\n return false;\n }\n throw new ParseError(this.pos, 'Unexpected character. Expected a \"1\" or a \"0\"');\n }\n parseDate() {\n this.expectChar(\"@\");\n this.pos++;\n let sign = 1;\n let inputNumber = \"\";\n if (this.lookChar() === \"-\") {\n sign = -1;\n this.pos++;\n }\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, \"Expected a digit (0-9)\");\n }\n while (!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber += char;\n } else {\n throw new ParseError(this.pos, \"Expected a digit (0-9), whitespace or EOL\");\n }\n }\n if (inputNumber.length > 15) {\n throw new ParseError(this.pos, \"Exceeded max length for a date value\");\n }\n return new Date(parseInt(inputNumber, 10) * sign * 1e3);\n }\n parseKey() {\n if (!this.lookChar()?.match(/^[a-z*]/)) {\n throw new ParseError(this.pos, \"A key must begin with an asterisk or letter (a-z)\");\n }\n let outputString = \"\";\n while (!this.eof()) {\n const char = this.lookChar();\n if (char === void 0 || !/^[a-z0-9_\\-.*]$/.test(char)) {\n return outputString;\n }\n outputString += this.getChar();\n }\n return outputString;\n }\n /**\n * Looks at the next character without advancing the cursor.\n *\n * Returns undefined if we were at the end of the string.\n */\n lookChar() {\n return this.input[this.pos];\n }\n /**\n * Checks if the next character is 'char', and fail otherwise.\n */\n expectChar(char) {\n if (this.lookChar() !== char) {\n throw new ParseError(this.pos, `Expected ${char}`);\n }\n }\n getChar() {\n return this.input[this.pos++];\n }\n getChars(count) {\n const result = this.input.substr(this.pos, count);\n this.pos += count;\n return result;\n }\n eof() {\n return this.pos >= this.input.length;\n }\n // Advances the pointer to skip all whitespace.\n skipOWS() {\n while (true) {\n const c = this.input.substr(this.pos, 1);\n if (c === \" \" || c === \"\t\") {\n this.pos++;\n } else {\n break;\n }\n }\n }\n // Advances the pointer to skip all spaces\n skipWS() {\n while (this.lookChar() === \" \") {\n this.pos++;\n }\n }\n // At the end of parsing, we need to make sure there are no bytes after the\n // header except whitespace.\n checkTrail() {\n this.skipWS();\n if (!this.eof()) {\n throw new ParseError(this.pos, \"Unexpected characters at end of input\");\n }\n }\n};\nvar isDigitRegex = /^[0-9]$/;\nfunction isDigit(char) {\n if (char === void 0)\n return false;\n return isDigitRegex.test(char);\n}\n\n// src/rate-limit.ts\nfunction parseRetryAfter(header, now = Date.now()) {\n if (header === null) return void 0;\n const value = header.trim();\n if (/^\\d+$/.test(value)) {\n const ms = Number(value) * 1e3;\n return Number.isSafeInteger(ms) ? ms : void 0;\n }\n if (!/^[A-Za-z]{3},? /.test(value)) return void 0;\n const date = Date.parse(value);\n return Number.isFinite(date) ? Math.max(0, date - now) : void 0;\n}\nfunction secondsToMilliseconds(value) {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) return void 0;\n const milliseconds = value * 1e3;\n return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;\n}\nfunction getRateLimitInfo(headers, now = Date.now()) {\n const retryAfter = headers.get(\"Retry-After\");\n const retryAfterMs = parseRetryAfter(retryAfter, now);\n const info = {\n windows: [],\n retryAfterMs,\n retryDelayMs: retryAfterMs,\n incomplete: retryAfter !== null && retryAfterMs === void 0\n };\n const raw = headers.get(\"RateLimit\");\n if (raw === null) return info;\n if (!raw.trim()) return { ...info, incomplete: true };\n try {\n for (const [value, params] of parseList(raw)) {\n const name = value instanceof Token ? value.toString() : value;\n const remaining = params.get(\"r\");\n if (typeof name !== \"string\" || typeof remaining !== \"number\" || !Number.isSafeInteger(remaining) || remaining < 0) {\n info.incomplete = true;\n continue;\n }\n const resetAfterMs = secondsToMilliseconds(params.get(\"t\"));\n info.windows.push({ name, remaining, resetAfterMs });\n if (remaining !== 0) continue;\n if (resetAfterMs === void 0) {\n info.incomplete = true;\n continue;\n }\n info.retryDelayMs = Math.max(info.retryDelayMs ?? 0, resetAfterMs);\n }\n } catch {\n info.incomplete = true;\n }\n return info;\n}\n\n// src/retry.ts\nvar DEFAULTS = {\n maxAttempts: 4,\n minBackoffMs: 1e3,\n maxBackoffMs: 3e4,\n maxRetryAfterMs: 6e4\n};\nvar IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([\"GET\", \"HEAD\", \"PUT\", \"DELETE\", \"OPTIONS\"]);\nvar RETRYABLE_STATUS = /* @__PURE__ */ new Set([500, 502, 503, 504]);\nfunction isAbortError(error) {\n const name = error?.name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\nfunction shouldRetry(method, response) {\n const idempotent = IDEMPOTENT_METHODS.has(method);\n if (response === void 0) return idempotent;\n if (response.status === 429) return true;\n return idempotent && RETRYABLE_STATUS.has(response.status);\n}\nfunction sleepWithSignal(ms, signal, custom) {\n return new Promise((resolve, reject) => {\n let timer;\n const cleanup = () => {\n if (timer !== void 0) clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n };\n const onAbort = () => {\n cleanup();\n reject(signal.reason);\n };\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n const done = () => {\n cleanup();\n resolve();\n };\n if (custom) {\n Promise.resolve().then(() => {\n signal.throwIfAborted();\n return custom(ms);\n }).then(done, (error) => {\n cleanup();\n reject(error);\n });\n } else {\n timer = setTimeout(done, ms);\n }\n });\n}\nfunction createRetryFetch(options = {}) {\n const maxAttempts = options.maxAttempts ?? DEFAULTS.maxAttempts;\n const minBackoffMs = options.minBackoffMs ?? DEFAULTS.minBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetryAfterMs = options.maxRetryAfterMs ?? DEFAULTS.maxRetryAfterMs;\n const baseFetch = options.fetch ?? globalThis.fetch;\n const random = options.random ?? Math.random;\n if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1) {\n throw new RangeError(\"maxAttempts must be a positive safe integer\");\n }\n for (const [name, value] of Object.entries({ minBackoffMs, maxBackoffMs, maxRetryAfterMs })) {\n if (!Number.isFinite(value) || value < 0 || value > 2147483647) {\n throw new RangeError(`${name} must be finite and between 0 and 2147483647`);\n }\n }\n if (minBackoffMs > maxBackoffMs) {\n throw new RangeError(\"minBackoffMs must not exceed maxBackoffMs\");\n }\n return async (input, init) => {\n const original = new Request(input, init);\n for (let attempt = 1; ; attempt++) {\n original.signal.throwIfAborted();\n let response;\n let networkError;\n try {\n response = await baseFetch(original.clone());\n } catch (error) {\n original.signal.throwIfAborted();\n if (isAbortError(error)) throw error;\n networkError = error;\n }\n if (response !== void 0 && !shouldRetry(original.method, response)) return response;\n if (response === void 0 && !shouldRetry(original.method, void 0)) throw networkError;\n if (attempt >= maxAttempts) {\n if (response !== void 0) return response;\n throw networkError;\n }\n const rateLimit = response ? getRateLimitInfo(response.headers) : void 0;\n let delay = rateLimit?.retryDelayMs;\n if (response && (rateLimit?.incomplete || delay !== void 0 && delay > maxRetryAfterMs)) return response;\n if (delay === void 0) {\n const shift = Math.min(attempt - 1, 20);\n const backoff = Math.min(minBackoffMs * 2 ** shift, maxBackoffMs);\n delay = backoff / 2 + random() * (backoff / 2);\n }\n await response?.body?.cancel();\n await sleepWithSignal(delay, original.signal, options.sleep);\n }\n };\n}\n\n// src/abort.ts\nfunction abortable(operation, signal) {\n if (!signal) return operation;\n return new Promise((resolve, reject) => {\n const onAbort = () => reject(signal.reason);\n const cleanup = () => signal.removeEventListener(\"abort\", onAbort);\n if (signal.aborted) onAbort();\n else signal.addEventListener(\"abort\", onAbort, { once: true });\n operation.then(\n (value) => {\n cleanup();\n resolve(value);\n },\n (error) => {\n cleanup();\n reject(error);\n }\n );\n });\n}\n\n// src/deadline.ts\nfunction wrapResponse(response, signal, cleanup) {\n const reader = response.body.getReader();\n let finished = false;\n let bodyController;\n function finish() {\n finished = true;\n signal.removeEventListener(\"abort\", onAbort);\n cleanup();\n }\n function cancelReader(reason) {\n void reader.cancel(reason).catch(() => {\n });\n reader.releaseLock();\n }\n function onAbort() {\n if (finished) return;\n finish();\n bodyController.error(signal.reason);\n cancelReader(signal.reason);\n }\n const body = new ReadableStream({\n start(controller) {\n bodyController = controller;\n signal.addEventListener(\"abort\", onAbort, { once: true });\n if (signal.aborted) onAbort();\n },\n async pull(controller) {\n try {\n const chunk = await reader.read();\n if (finished) return;\n if (!chunk.done) {\n controller.enqueue(chunk.value);\n return;\n }\n finish();\n reader.releaseLock();\n controller.close();\n } catch (error) {\n if (finished) return;\n finish();\n reader.releaseLock();\n controller.error(error);\n }\n },\n cancel(reason) {\n finish();\n cancelReader(reason);\n }\n });\n const wrapped = new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers\n });\n for (const key of [\"url\", \"redirected\", \"type\"]) {\n Object.defineProperty(wrapped, key, { value: response[key] });\n }\n return wrapped;\n}\nfunction createDeadlineFetch(fetchImpl, timeoutMs) {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647) {\n throw new RangeError(\"timeoutMs must be positive and at most 2147483647\");\n }\n return async (input, init) => {\n const original = new Request(input, init);\n original.signal.throwIfAborted();\n const controller = new AbortController();\n const onCallerAbort = () => controller.abort(original.signal.reason);\n const timer = setTimeout(() => {\n controller.abort(new DOMException(`Runpod request exceeded ${timeoutMs}ms`, \"TimeoutError\"));\n }, timeoutMs);\n const cleanup = () => {\n clearTimeout(timer);\n original.signal.removeEventListener(\"abort\", onCallerAbort);\n };\n original.signal.addEventListener(\"abort\", onCallerAbort, { once: true });\n try {\n const operation = Promise.resolve().then(async () => {\n controller.signal.throwIfAborted();\n const response2 = await fetchImpl(new Request(original, { signal: controller.signal }));\n if (controller.signal.aborted) void response2.body?.cancel().catch(() => {\n });\n controller.signal.throwIfAborted();\n return response2;\n });\n const response = await abortable(operation, controller.signal);\n if (response.body) return wrapResponse(response, controller.signal, cleanup);\n cleanup();\n return response;\n } catch (error) {\n cleanup();\n throw error;\n }\n };\n}\n\n// src/logs.ts\nfunction parseLogEntry(raw) {\n try {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return { raw };\n const entry = parsed;\n const valid = [\"source\", \"line\", \"ts\", \"raw\"].every(\n (key) => !(key in entry) || typeof entry[key] === \"string\"\n );\n return valid ? entry : { raw };\n } catch {\n return { raw };\n }\n}\nfunction utf8Size(character) {\n const codePoint = character.codePointAt(0);\n if (codePoint <= 127) return 1;\n if (codePoint <= 2047) return 2;\n return codePoint <= 65535 ? 3 : 4;\n}\nvar LogEventParser = class {\n constructor(maxEventBytes) {\n this.maxEventBytes = maxEventBytes;\n }\n maxEventBytes;\n line = \"\";\n dataLines = [];\n eventName = \"\";\n lastEventId;\n eventBytes = 0;\n afterCR = false;\n push(character) {\n if (this.afterCR && character === \"\\n\") {\n this.afterCR = false;\n return;\n }\n this.afterCR = character === \"\\r\";\n this.eventBytes += utf8Size(character);\n if (this.eventBytes > this.maxEventBytes) {\n throw new RangeError(\"SSE log event exceeds maxEventBytes\");\n }\n if (character === \"\\r\" || character === \"\\n\") return this.consumeLine();\n this.line += character;\n }\n consumeLine() {\n const line = this.line;\n this.line = \"\";\n if (line === \"\") return this.finishEvent();\n if (line.startsWith(\":\")) return;\n const colon = line.indexOf(\":\");\n const field = colon < 0 ? line : line.slice(0, colon);\n const value = colon < 0 ? \"\" : line.slice(colon + 1).replace(/^ /, \"\");\n switch (field) {\n case \"data\":\n this.dataLines.push(value);\n break;\n case \"event\":\n this.eventName = value;\n break;\n case \"id\":\n if (!value.includes(\"\\0\")) this.lastEventId = value;\n break;\n }\n }\n finishEvent() {\n const event = this.dataLines.length ? {\n event: this.eventName || \"message\",\n id: this.lastEventId,\n data: parseLogEntry(this.dataLines.join(\"\\n\"))\n } : void 0;\n this.dataLines = [];\n this.eventName = \"\";\n this.eventBytes = 0;\n return event;\n }\n};\nasync function* iterateLogEvents(stream, options = {}) {\n const maxEventBytes = options.maxEventBytes ?? 1048576;\n if (!Number.isSafeInteger(maxEventBytes) || maxEventBytes <= 0) {\n throw new RangeError(\"maxEventBytes must be a positive safe integer\");\n }\n const parser = new LogEventParser(maxEventBytes);\n const decoder = new TextDecoder();\n const reader = stream.getReader();\n const signal = options.signal;\n const onAbort = () => {\n void reader.cancel(signal?.reason).catch(() => {\n });\n };\n let finished = false;\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n while (true) {\n signal?.throwIfAborted();\n const chunk = await abortable(reader.read(), signal);\n signal?.throwIfAborted();\n if (chunk.done) {\n finished = true;\n return;\n }\n for (const character of decoder.decode(chunk.value, { stream: true })) {\n signal?.throwIfAborted();\n const event = parser.push(character);\n if (event) yield event;\n }\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!finished) void reader.cancel().catch(() => {\n });\n reader.releaseLock();\n }\n}\n\n// src/index.ts\nvar DEFAULT_TIMEOUT_MS = 3e4;\nvar DEFAULT_BASE_URL = \"https://api.runpod.io\";\nfunction createRunpodClient(options = {}) {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n if (!apiKey) {\n throw new Error(\"runpod: API key required (set RUNPOD_API_KEY or pass apiKey)\");\n }\n const baseUrl = options.baseUrl?.trim() || process.env.RUNPOD_API_BASE_URL?.trim() || DEFAULT_BASE_URL;\n const baseFetch = options.fetch ?? globalThis.fetch;\n const retryFetch = options.retry === false ? baseFetch : createRetryFetch({ ...options.retry, fetch: baseFetch });\n const requestFetch = options.timeoutMs === false ? retryFetch : createDeadlineFetch(retryFetch, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n return createClient({\n baseUrl,\n fetch: requestFetch,\n // Generation rejects contracts with a different array query encoding.\n querySerializer: { array: { style: \"form\", explode: false } },\n headers: { Authorization: `Bearer ${apiKey}` }\n });\n}\nexport {\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n createDeadlineFetch,\n createRetryFetch,\n createRunpodClient,\n getRateLimitInfo,\n iterateLogEvents,\n parseRetryAfter\n};\n","import { iterateLogEvents, type LogEntry } from '@runpod/typescript-api-sdk';\nexport type { LogEntry } from '@runpod/typescript-api-sdk';\n\n// Bounded SSE reader for the v2 log endpoints (GET /v2/pods/{id}/logs and\n// GET /v2/serverless/{id}/workers/{workerId}/logs). Both serve\n// text/event-stream and hold the connection open to tail live output, so the\n// generated JSON dispatch cannot consume them; the curated log tools read a\n// time- and byte-bounded snapshot instead. Ported from the official MCP\n// server's reader (Apache-2.0, runpod/runpod-mcp).\n\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\nimport { HttpError, missingKeyError } from './http-error.js';\nimport { boundedFetch } from './bounded-fetch.js';\n\nexport const LOG_STREAM_DEFAULT_WAIT_MS = 5_000;\nexport const LOG_STREAM_MAX_BYTES = 256 * 1024;\n\nexport type SseReader = (\n url: string,\n opts: { maxWaitMs: number; maxBytes: number }\n) => Promise<{ raw: string; truncated: boolean }>;\n\n// Time-bounded by maxWaitMs (the stream stays open to tail live output) and\n// byte-bounded by maxBytes; whichever fires first aborts and returns what was\n// collected. A deadline ends an established stream normally; a timeout before\n// response headers arrive is a failed request. Bytes are concatenated and decoded\n// once at the end so a UTF-8 char split across chunks is never corrupted.\nexport function createSseReader(\n options: { apiKey?: string; fetchImpl?: typeof fetch } = {}\n): SseReader {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async (url, opts) => {\n if (!apiKey) throw missingKeyError();\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n let truncated = false;\n let streamEstablished = false;\n try {\n const response = await boundedFetch(fetchImpl, opts.maxWaitMs)(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n },\n });\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new HttpError(\n `Runpod API error (${response.status})`,\n response.status,\n response.status === 429\n ? withRateLimitHint({ error: body }, response.headers)\n : body\n );\n }\n streamEstablished = true;\n if (response.body) {\n for await (const chunk of response.body as unknown as AsyncIterable<Uint8Array>) {\n const boundedChunk = chunk.subarray(0, opts.maxBytes - bytes);\n chunks.push(boundedChunk);\n bytes += boundedChunk.length;\n if (bytes >= opts.maxBytes) {\n truncated = true;\n break;\n }\n }\n }\n } catch (err) {\n // The request deadline ends an established stream normally.\n // Before headers, there is no successful log read to return; runTool\n // maps the timeout to a retryable 504 instead of an empty success.\n if (\n !(\n streamEstablished &&\n err instanceof Error &&\n err.name === 'TimeoutError'\n )\n ) {\n throw err;\n }\n }\n return { raw: Buffer.concat(chunks).toString('utf8'), truncated };\n };\n}\n\nexport interface LogSnapshotParams {\n source?: 'container' | 'system' | 'both';\n tail?: number;\n since?: string;\n maxWaitMs?: number;\n}\n\n// Read a bounded snapshot of a log endpoint and return the parsed frames.\n// `source: 'both'` (or omitted) sends no source param — the endpoint returns\n// both streams when it is absent (the wire enum is only container|system).\nexport async function collectLogSnapshot(\n reader: SseReader,\n logsUrl: string,\n params: LogSnapshotParams\n): Promise<{ items: LogEntry[]; count: number; truncated: boolean }> {\n const qs = new URLSearchParams();\n if (params.source && params.source !== 'both')\n qs.append('source', params.source);\n if (params.tail !== undefined) qs.append('tail', String(params.tail));\n if (params.since) qs.append('since', params.since);\n const query = qs.toString() ? `?${qs}` : '';\n const { raw, truncated } = await reader(`${logsUrl}${query}`, {\n maxWaitMs: params.maxWaitMs ?? LOG_STREAM_DEFAULT_WAIT_MS,\n maxBytes: LOG_STREAM_MAX_BYTES,\n });\n // The SDK handles SSE framing and discards an incomplete final event.\n // MCP keeps ownership of its time and total-byte snapshot limits above.\n const items: LogEntry[] = [];\n for await (const event of iterateLogEvents(new Response(raw).body!)) {\n items.push(event.data);\n }\n return { items, count: items.length, truncated };\n}\n","// Curated list-public-endpoints tool. Runpod Public Endpoints (managed\n// pay-per-use model APIs) have no REST home — the catalog is the public\n// GraphQL query allAiApiPublicConfigs, served unauthenticated. Ported from\n// the official MCP server (Apache-2.0, runpod/runpod-mcp).\n\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport { ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\ninterface PublicEndpointConfig {\n id: string;\n aiApiId: string;\n modelName: string;\n displayName: string;\n description: string | null;\n metadata: string | null;\n isLive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface PublicEndpointsResponse {\n allAiApiPublicConfigs: PublicEndpointConfig[];\n}\n\n// `metadata` is a JSON string carrying pricing and classification. Parsed\n// defensively — a malformed value falls back to undefined fields.\ninterface PublicEndpointMetadata {\n cost?: number;\n owner?: string;\n source?: string;\n tag?: string;\n priceString?: string;\n}\n\nfunction parseMetadata(\n metadata: string | null | undefined\n): PublicEndpointMetadata {\n if (!metadata) return {};\n try {\n const parsed = JSON.parse(metadata) as unknown;\n return parsed && typeof parsed === 'object'\n ? (parsed as PublicEndpointMetadata)\n : {};\n } catch {\n return {};\n }\n}\n\nexport const listPublicEndpoints: CuratedTool = {\n name: 'list-public-endpoints',\n annotations: readOnly,\n description:\n 'List Runpod Public Endpoints — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n searchTerm: {\n type: 'string',\n description:\n \"Case-insensitive search across display name, model name, endpoint id, description, owner, and tag (e.g. 'kimi', 'video', 'flux')\",\n },\n modality: {\n type: 'string',\n description:\n \"Filter by modality/category (the metadata source field, e.g. 'language', 'image', 'video', 'audio')\",\n },\n owner: {\n type: 'string',\n description:\n \"Filter by model owner (e.g. 'moonshot', 'minimax', 'google')\",\n },\n includeOffline: {\n type: 'boolean',\n description:\n 'Include endpoints that are not currently live (isLive:false). Default false — only live endpoints are listed.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const data = await ctx.graphql.public<PublicEndpointsResponse>(`\n query {\n allAiApiPublicConfigs {\n id\n aiApiId\n modelName\n displayName\n description\n metadata\n isLive\n createdAt\n updatedAt\n }\n }\n `);\n\n let configs = data.allAiApiPublicConfigs.map((c) => ({\n config: c,\n meta: parseMetadata(c.metadata),\n }));\n\n if (!args.includeOffline) {\n configs = configs.filter(({ config }) => config.isLive);\n }\n if (args.modality) {\n const term = String(args.modality).toLowerCase();\n configs = configs.filter(\n ({ meta }) => (meta.source ?? '').toLowerCase() === term\n );\n }\n if (args.owner) {\n const term = String(args.owner).toLowerCase();\n configs = configs.filter(\n ({ meta }) => (meta.owner ?? '').toLowerCase() === term\n );\n }\n if (args.searchTerm) {\n const term = String(args.searchTerm).toLowerCase();\n configs = configs.filter(({ config, meta }) =>\n [\n config.displayName,\n config.modelName,\n config.aiApiId,\n config.description,\n meta.owner,\n meta.tag,\n meta.source,\n ].some((field) => (field ?? '').toLowerCase().includes(term))\n );\n }\n\n // Stable, scannable order for the catalog.\n configs = [...configs].sort((a, b) =>\n a.config.displayName.localeCompare(b.config.displayName)\n );\n\n const result = configs.map(({ config, meta }) => ({\n endpointId: config.aiApiId,\n displayName: config.displayName,\n modelName: config.modelName,\n description: config.description,\n modality: meta.source,\n tag: meta.tag,\n owner: meta.owner,\n pricing: meta.priceString,\n isLive: config.isLive,\n baseUrl: `https://api.runpod.ai/v2/${config.aiApiId}`,\n createdAt: config.createdAt,\n updatedAt: config.updatedAt,\n }));\n\n return ok(\n capList(result, {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n })\n );\n }),\n};\n","// Knowledge tools: the official Runpod plugin's skills, reference docs, golden\n// paths and concept graph, served from the @runpod/plugin-knowledge bundle so an\n// agent without the plugin installed can read them. Read-only and offline:\n// nothing here calls the Runpod API.\n\nimport {\n loadKnowledge,\n type Concept,\n type Guide,\n type Rule,\n} from '@runpod/plugin-knowledge';\nimport type { CuratedTool } from '../types.js';\nimport { bundledRead } from './annotations.js';\nimport { badRequest, ok } from './util.js';\n\nconst knowledge = loadKnowledge();\n\nconst GUIDE_KINDS = ['skill', 'reference', 'golden-path'] as const;\nconst STOPWORDS = new Set(\n 'a an and are as at be by can do does for from how i in is it my of on or the to what when why with you your'.split(\n ' '\n )\n);\n\n/** Drop a simple English plural, so \"pods\" matches \"pod\" and \"policies\" \"policy\". */\nconst singular = (word: string) => {\n if (word.length > 4 && word.endsWith('ies')) return `${word.slice(0, -3)}y`;\n if (word.length > 3 && word.endsWith('s') && !word.endsWith('ss'))\n return word.slice(0, -1);\n return word;\n};\n\nconst words = (text: string) =>\n text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((word) => word.length > 1 && !STOPWORDS.has(word))\n .map(singular);\n\n/** Levenshtein distance, giving up once it passes max. */\nfunction editDistance(a: string, b: string, max: number): number {\n if (Math.abs(a.length - b.length) > max) return max + 1;\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n previous[j] + 1,\n current[j - 1] + 1,\n previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)\n );\n }\n if (Math.min(...current) > max) return max + 1;\n previous = current;\n }\n return previous[b.length];\n}\n\n/** Typos tolerated in a word or name: none under 4 letters, two from 8. */\nconst typoBudget = (text: string) =>\n text.length >= 8 ? 2 : text.length >= 4 ? 1 : 0;\n\n/** A search term five letters or longer also matches a word one typo away. */\nconst oneTypo = (word: string, term: string) =>\n term.length >= 5 && editDistance(word, term, 1) <= 1;\n\n/** A search term matches a word it starts, or one typo away from it. */\nconst termMatches = (word: string, term: string) =>\n word.startsWith(term) || oneTypo(word, term);\n\n/** A search term matches a concept name word exactly, or one typo away. */\nconst nameMatches = (name: string, term: string) =>\n name === term || oneTypo(name, term);\n\nconst guideSummary = ({\n id,\n kind,\n title,\n description,\n lanes,\n mcp,\n needs_shell,\n concepts,\n}: Guide) => ({\n id,\n kind,\n title,\n description,\n lanes,\n mcp,\n needs_shell,\n concepts,\n});\n\n/** Guides linked to a concept, split into golden-path examples and docs. */\nfunction linkedGuides(conceptId: string) {\n const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));\n const seen = new Set<string>();\n const examples: { id: string; title: string; mcp: Guide['mcp'] }[] = [];\n const docs: { id: string; title: string; rules?: string[] }[] = [];\n for (const link of knowledge.links) {\n if (link.to !== conceptId || seen.has(link.from)) continue;\n seen.add(link.from);\n const guide = byId.get(link.from);\n if (!guide) continue;\n if (guide.kind === 'golden-path')\n examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });\n else\n docs.push({\n id: guide.id,\n title: guide.title,\n ...(link.rules ? { rules: link.rules } : {}),\n });\n }\n return { examples, docs };\n}\n\n/** Concept ids by lower-cased id, name and alias. */\nconst conceptIndex = new Map<string, Concept>();\nfor (const concept of knowledge.concepts) {\n for (const key of [concept.id, concept.name, ...concept.aliases]) {\n if (!conceptIndex.has(key.toLowerCase()))\n conceptIndex.set(key.toLowerCase(), concept);\n }\n}\n/** The same keys, lower-cased with plurals dropped: \"Instant Clusters\" -> \"instant cluster\". */\nconst conceptKey = (text: string) =>\n text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter(Boolean)\n .map(singular)\n .join(' ');\nconst conceptKeyIndex = new Map<string, Concept>();\nfor (const [key, concept] of conceptIndex) {\n if (!conceptKeyIndex.has(conceptKey(key)))\n conceptKeyIndex.set(conceptKey(key), concept);\n}\n\n/**\n * Resolve a concept reference: exact id, name or alias first, then with\n * plurals dropped, then the one key within typo range. `matchedAs` is set\n * when the match was not exact.\n */\nfunction resolveConcept(\n input: string\n): { concept: Concept; matchedAs?: string } | undefined {\n const exact = conceptIndex.get(input.trim().toLowerCase());\n if (exact) return { concept: exact };\n const key = conceptKey(input);\n const plural = conceptKeyIndex.get(key);\n if (plural) return { concept: plural, matchedAs: key };\n const budget = typoBudget(key);\n let best: { concept: Concept; key: string; distance: number } | undefined;\n let tied = false;\n for (const [candidate, concept] of conceptKeyIndex) {\n const distance = editDistance(key, candidate, budget);\n if (distance > budget) continue;\n if (!best || distance < best.distance) {\n best = { concept, key: candidate, distance };\n tied = false;\n } else if (distance === best.distance && concept.id !== best.concept.id) {\n tied = true;\n }\n }\n return best && !tied\n ? { concept: best.concept, matchedAs: best.key }\n : undefined;\n}\n\nconst ruleIndex = new Map<string, { rule: Rule; concept: Concept }>();\nfor (const concept of knowledge.concepts) {\n for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });\n}\n\nconst source = {\n plugin_version: knowledge.version,\n plugin_commit: knowledge.commit,\n};\n\nexport const listGuides: CuratedTool = {\n name: 'list-guides',\n annotations: bundledRead,\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n kind: {\n type: 'string',\n enum: [...GUIDE_KINDS],\n description: 'Only this kind of guide.',\n },\n query: {\n type: 'string',\n description: 'Words to match against the id, title and description.',\n },\n concept: {\n type: 'string',\n description:\n 'Only guides linked to this concept id, for example \"network-volume\".',\n },\n },\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const kind = args.kind as Guide['kind'] | undefined;\n const terms = words(String(args.query ?? ''));\n const concept = args.concept ? String(args.concept).trim() : undefined;\n const guides = knowledge.guides\n .filter((guide) => !kind || guide.kind === kind)\n .filter((guide) => !concept || guide.concepts.includes(concept))\n .filter((guide) => {\n if (!terms.length) return true;\n const haystack =\n `${guide.id} ${guide.title} ${guide.description}`.toLowerCase();\n return terms.some((term) => haystack.includes(term));\n })\n .map(guideSummary);\n return ok({ ...source, count: guides.length, guides });\n },\n};\n\nexport const readGuide: CuratedTool = {\n name: 'read-guide',\n annotations: bundledRead,\n description:\n 'Read one official Runpod guide in full, by the id list-guides returns (for example \"runpod-usage/storage\" or \"golden-path/06-dev-pod\").',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'The guide id from list-guides.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const id = String(args.id).trim();\n const guide = knowledge.guides.find((candidate) => candidate.id === id);\n if (!guide) {\n const close = knowledge.guides\n .filter(\n (candidate) => candidate.id.includes(id) || id.includes(candidate.id)\n )\n .map((candidate) => candidate.id);\n return {\n ok: false,\n status: 404,\n payload: {\n error: `No guide with id \"${id}\".`,\n hint: close.length\n ? `Did you mean: ${close.join(', ')}?`\n : 'Call list-guides for the ids.',\n },\n };\n }\n return ok({\n ...source,\n ...guideSummary(guide),\n parent: guide.parent,\n path: guide.path,\n body: guide.body,\n });\n },\n};\n\nexport const lookupConcept: CuratedTool = {\n name: 'lookup-concept',\n annotations: bundledRead,\n description:\n 'Look up one Runpod concept (pod, network volume, machine, worker, template, …) 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\".',\n inputSchema: {\n type: 'object',\n properties: {\n concept: {\n type: 'string',\n description:\n 'An id, name or alias, such as \"pod\", \"Network volume\" or \"volume disk\".',\n },\n },\n required: ['concept'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const resolved = resolveConcept(String(args.concept));\n if (!resolved) {\n const ref = conceptKey(String(args.concept));\n const close = [...conceptKeyIndex.keys()]\n .filter(\n (key) =>\n key.includes(ref) ||\n editDistance(key, ref, typoBudget(ref) + 1) <= typoBudget(ref) + 1\n )\n .slice(0, 10);\n return {\n ok: false,\n status: 404,\n payload: {\n error: `No concept matches \"${args.concept}\".`,\n hint: close.length\n ? `Close matches: ${close.join(', ')}.`\n : 'Try search-concepts with a few words instead.',\n },\n };\n }\n const { concept, matchedAs } = resolved;\n const pointedAtBy = knowledge.concepts.flatMap((other) => [\n ...(other.is_a === concept.id\n ? [{ concept: other.id, type: 'is_a' }]\n : []),\n ...(other.part_of === concept.id\n ? [{ concept: other.id, type: 'part_of' }]\n : []),\n ...other.relations\n .filter((relation) => relation.target === concept.id)\n .map((relation) => ({ concept: other.id, type: relation.type })),\n ]);\n const linkedRules = [...new Set(concept.rules.flatMap((rule) => rule.see))]\n .map((id) => ruleIndex.get(id))\n .filter((entry) => entry !== undefined)\n .map(({ rule, concept: owner }) => ({\n concept: owner.id,\n id: rule.id,\n statement: rule.statement.trim(),\n }));\n return ok({\n ...source,\n ...(matchedAs ? { matched_as: matchedAs } : {}),\n ...concept,\n pointed_at_by: pointedAtBy,\n linked_rules: linkedRules,\n ...linkedGuides(concept.id),\n });\n },\n};\n\nexport const searchConcepts: CuratedTool = {\n name: 'search-concepts',\n annotations: bundledRead,\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'A few words describing the question.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 25,\n description: 'Most rules to return. Default 8.',\n },\n },\n required: ['query'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const terms = words(String(args.query));\n if (!terms.length) return badRequest('query needs at least one word.');\n const limit = Math.min(Math.max(Number(args.limit) || 8, 1), 25);\n const hits = [...ruleIndex.values()]\n .map(({ rule, concept }) => {\n const statement = words(rule.statement);\n const names = words(\n [concept.id, concept.name, ...concept.aliases].join(' ')\n );\n const ruleId = words(rule.id);\n // Statement matches count once per occurrence; concept names weigh more,\n // since a question usually names the thing it is about.\n const score = terms.reduce(\n (total, term) =>\n total +\n statement.filter((word) => termMatches(word, term)).length +\n (names.some((name) => nameMatches(name, term)) ? 3 : 0) +\n (ruleId.includes(term) ? 1 : 0),\n 0\n );\n const matched = terms.filter(\n (term) =>\n statement.some((word) => termMatches(word, term)) ||\n names.some((name) => nameMatches(name, term))\n ).length;\n return { rule, concept, score: score * matched };\n })\n .filter((hit) => hit.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ rule, concept }) => ({\n concept: concept.id,\n concept_name: concept.name,\n id: rule.id,\n statement: rule.statement.trim(),\n status: rule.status,\n conflict: rule.conflict,\n evidence: rule.evidence,\n }));\n return ok({ ...source, count: hits.length, rules: hits });\n },\n};\n\nexport const knowledgeTools: CuratedTool[] = [\n listGuides,\n readGuide,\n lookupConcept,\n searchConcepts,\n];\n\n/** The plugin guides as MCP resources, for clients that read resources. */\nexport const GUIDE_URI_PREFIX = 'runpod://guides/';\nexport const guideResources = knowledge.guides.map((guide) => ({\n uri: `${GUIDE_URI_PREFIX}${guide.id}`,\n name: guide.id,\n title: guide.title,\n description: guide.description,\n mimeType: 'text/markdown',\n text: guide.body,\n}));\n","// Anonymous product analytics (PostHog), hosted-path only.\n//\n// OFF BY DEFAULT: every capture is a no-op unless POSTHOG_API_KEY is set —\n// it never is locally or in CI, so only a deployment that deliberately sets\n// it (the Vercel project) sends anything. Users opt out per client with the\n// `X-Runpod-Analytics: off` header (see README), and the stdio transport\n// never captures at all.\n//\n// SECURITY: the event payload is the closed set of fields in ToolCallEvent —\n// never the API key, the Authorization header, tool arguments, resource ids,\n// or response payloads. The caller identity is an HMAC of the key with a\n// server-side salt (MCP_ANALYTICS_SALT): stable across instances so per-user\n// frequency works in PostHog, irreversible without the salt, and never\n// joinable to the key itself. $process_person_profile stays false — no\n// person profiles, just anonymous distinct ids.\n\nimport { createHmac } from 'node:crypto';\n\nexport interface ToolCallEvent {\n tool: string;\n ok: boolean;\n status: number;\n durationMs: number;\n transport: 'stdio' | 'http';\n serverVersion: string;\n /** Sanitized client token from the User-Agent (never the raw header). */\n clientName?: string;\n /** Stable account id (the pre-flight's myself.id). Preferred identity:\n * keys rotate on every OAuth sign-in, the account does not. Hashed like\n * the key — the raw id never leaves the process. */\n accountId?: string;\n}\n\nconst CAPTURE_TIMEOUT_MS = 3_000;\n\n// Durable generation marker for v1-vs-v2 attribution, independent of the npm\n// package version: '2' is the spec-generated surface (v1 was the hand-written\n// tool set). Bump on surface generations ('3') or notable revisions ('2.1').\n// Keep in sync with the `surface=` User-Agent token in _shared/tracking.ts.\nexport const SURFACE_VERSION = '2';\n\nfunction posthogHost(): string {\n return process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n}\n\n// Stable anonymous caller id. Identity source, best first: the account id\n// (stable across key rotations and OAuth re-auths), then the API key (a\n// per-key identity is better than none when the pre-flight was skipped).\n// Without MCP_ANALYTICS_SALT the HMAC key falls back to the PostHog key —\n// still server-side and secret, so the id stays non-reversible; set the salt\n// to rotate identities independently of the PostHog project.\nexport function analyticsCallerId(\n apiKey: string | undefined,\n accountId?: string\n): string {\n const identity = accountId ?? apiKey;\n if (!identity) return 'anonymous';\n const salt =\n process.env.MCP_ANALYTICS_SALT || process.env.POSTHOG_API_KEY || '';\n const prefix = accountId ? 'a:' : 'k:';\n return (\n prefix +\n createHmac('sha256', salt).update(identity).digest('hex').slice(0, 16)\n );\n}\n\n// Fire-and-forget: never throws, never blocks the tool response. A lost\n// event is fine; a failed tool call because of analytics is not.\nexport function captureToolCall(\n apiKey: string | undefined,\n event: ToolCallEvent\n): void {\n const posthogKey = process.env.POSTHOG_API_KEY;\n if (!posthogKey) return;\n void fetch(`${posthogHost()}/capture/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: posthogKey,\n event: 'runpod_mcp_tool_call',\n distinct_id: analyticsCallerId(apiKey, event.accountId),\n timestamp: new Date().toISOString(),\n properties: {\n tool: event.tool,\n ok: event.ok,\n status: event.status,\n duration_ms: event.durationMs,\n transport: event.transport,\n server_version: event.serverVersion,\n surface_version: SURFACE_VERSION,\n ...(event.clientName ? { client_name: event.clientName } : {}),\n $process_person_profile: false,\n },\n }),\n signal: AbortSignal.timeout(CAPTURE_TIMEOUT_MS),\n }).catch(() => {\n // Dropped events are acceptable; noisy logs on every blip are not.\n });\n}\n","import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { createSpecgenServer } from './specgen/server.js';\nimport { createToolContext as createSpecgenContext } from './specgen/context.js';\nimport { SERVER_VERSION } from './server.js';\nimport { sanitizeUaToken } from './_shared/tracking.js';\nimport {\n createCredentialChecker,\n type CredentialChecker,\n type CredentialCheckerHandle,\n} from './_shared/credential-check.js';\nimport {\n sdkBase,\n serverlessBase,\n authedGraphqlBase,\n type Env,\n} from './_shared/hosts.js';\nimport { IncomingMessage, ServerResponse } from 'node:http';\n\n/**\n * Extract the bearer token from an HTTP request's Authorization header.\n * Returns null if the header is missing or malformed.\n */\nfunction extractBearerToken(req: IncomingMessage): string | null {\n const authHeader = req.headers.authorization;\n if (!authHeader) return null;\n const parts = authHeader.split(' ');\n if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') return null;\n return parts[1];\n}\n\n// Per-request analytics opt-out: any client can send\n// `X-Runpod-Analytics: off` (or 0/false) and no usage event is captured for\n// its calls. Checked case-insensitively; absence means opted in (the capture\n// itself is still a no-op unless the deployment sets POSTHOG_API_KEY).\nfunction analyticsOptedOut(req: IncomingMessage): boolean {\n const raw = req.headers['x-runpod-analytics'];\n const value = (Array.isArray(raw) ? raw[0] : raw)?.trim().toLowerCase();\n return value === 'off' || value === '0' || value === 'false';\n}\n\n// Structural request type so the Vercel adapter (api/index.ts) can share this\n// proxy-header parsing instead of keeping a second copy.\nexport function getBaseUrl(req: {\n headers: { host?: string; 'x-forwarded-proto'?: string | string[] };\n}): string {\n const protoHeader = req.headers['x-forwarded-proto'];\n const proto =\n (Array.isArray(protoHeader) ? protoHeader[0] : protoHeader)?.split(\n ','\n )[0] ?? 'https';\n const host = req.headers.host;\n if (!host) {\n throw new Error('Missing Host header');\n }\n return `${proto}://${host}`;\n}\n\nfunction writeUnauthorized(\n req: IncomingMessage,\n res: ServerResponse,\n error: string,\n // A credential was supplied and rejected, as opposed to none being sent. RFC\n // 6750 §3.1 puts error=\"invalid_token\" on that case and requires it be omitted\n // otherwise, so a client can tell \"never authenticated\" from \"re-authenticate\".\n invalidToken = false\n): void {\n // Always advertise the protected-resource metadata so OAuth-capable clients\n // (e.g. Claude) know to start the \"Sign in with Runpod\" flow.\n const challenge = [\n 'Bearer realm=\"mcp\"',\n ...(invalidToken\n ? [\n 'error=\"invalid_token\"',\n 'error_description=\"The credential was rejected; re-authenticate.\"',\n ]\n : []),\n `resource_metadata=\"${getBaseUrl(\n req\n )}/.well-known/oauth-protected-resource\"`,\n ].join(', ');\n\n res.writeHead(401, {\n 'Content-Type': 'application/json',\n 'WWW-Authenticate': challenge,\n });\n res.end(JSON.stringify({ error }));\n}\n\n// The GraphQL host the pre-flight authenticates against. This call carries the\n// CALLER'S key, so it uses authedGraphqlBase (RUNPOD_AUTHED_GRAPHQL_URL) — the\n// variable backend.ts reserves for key-bearing GraphQL — NOT the freely\n// repointable OAuth flash-auth var (RUNPOD_GRAPHQL_URL): repointing that one\n// must never redirect every caller's key to an arbitrary host. One resolver so\n// the checker and the environment guard below cannot disagree about defaults.\n// Shared across requests so the verdict cache helps on a warm instance. Uses the\n// global fetch (Node >= 18) — this runs before any MCP/tool wiring exists.\nexport const defaultCredentialChecker: CredentialCheckerHandle =\n createCredentialChecker({\n fetch: (url, init) => fetch(url, init),\n url: () => authedGraphqlBase(process.env as Env),\n });\n\nconst sameHost = (a: string, b: string) => normalizeUrl(a) === normalizeUrl(b);\n\n// Hosts that are the same backend under a different name. `v2-rest.runpod.io`\n// served as the REST v2 default before `api.runpod.io` became canonical, and a\n// deployment that pinned it back then must not read as \"REST moved\" — that\n// disagreement with the (unmoved) GraphQL host would silently switch the\n// pre-flight off. Prod pair only: `v2-rest.runpod.dev` is genuinely a different\n// environment and must NOT normalize into prod.\nconst HOST_ALIASES: Record<string, string> = {\n 'v2-rest.runpod.io': 'api.runpod.io',\n};\n\n// Lowercased origin + path with any trailing slash removed, so cosmetic\n// differences in an env var do not read as a different environment.\nfunction normalizeUrl(raw: string): string {\n try {\n const u = new URL(raw);\n const host = u.host.toLowerCase();\n return `${u.protocol}//${HOST_ALIASES[host] ?? host}${u.pathname.replace(/\\/+$/, '')}`;\n } catch {\n return raw.trim().toLowerCase().replace(/\\/+$/, '');\n }\n}\n\n// The pre-flight checks the token against RUNPOD_AUTHED_GRAPHQL_URL; the tools\n// authenticate against the REST/Serverless hosts. Those are independent, so a\n// deployment pointing REST at a dev environment while GraphQL stays on prod\n// would validate a dev key against prod and reject EVERY request — though every\n// tool would have worked. Skipping on that ambiguity is the safer error: a wrong\n// 401 rejects everything, a missed one only restores the prior behaviour.\n//\n// UNVERIFIED: nobody has confirmed what the hosted deployment actually sets.\n// There is no .env in the repo, no `env` block in vercel.json, and CI sets no\n// RUNPOD_* vars — the values live only in the Vercel dashboard. If production\n// points any REST host somewhere non-default without also setting\n// RUNPOD_AUTHED_GRAPHQL_URL, this guard is silently disabling the gate in production\n// right now. Run `vercel env ls production` to settle it.\nfunction credentialCheckMayBeWrongEnvironment(env = process.env): boolean {\n // Compare normalized destinations so formatting differences do not disable\n // the credential preflight. Host resolvers treat blank overrides as unset.\n const envWithoutEmpties = Object.fromEntries(\n Object.entries(env).filter(([, v]) => v !== '')\n ) as Record<string, string | undefined>;\n const restMoved =\n !sameHost(sdkBase(envWithoutEmpties), sdkBase({})) ||\n !sameHost(serverlessBase(envWithoutEmpties), serverlessBase({}));\n const graphqlMoved = !sameHost(\n authedGraphqlBase(envWithoutEmpties as Env),\n authedGraphqlBase({})\n );\n // Skip whenever REST and the auth-GraphQL host DISAGREE about whether they are\n // on the default (prod) environment — in EITHER direction. Validating a key\n // against an auth backend from a different environment than the tools use\n // rejects every request while every tool would have worked, and OAuth clients\n // answer that 401 by re-authenticating in a loop. Only when both sides agree\n // (both default, or both moved) is the pre-flight validating against the same\n // environment the tools will call. An earlier version only caught REST-moved-\n // but-GraphQL-default, so moving only RUNPOD_GRAPHQL_URL (its documented dev\n // override) still 401'd every good credential.\n return restMoved !== graphqlMoved;\n}\n\n// Requires `method`, so a JSON-RPC *response* ({jsonrpc, id, result}) does not\n// qualify — a client posting one invokes no tool, so there is no credential to\n// check. Erring toward \"skip\" only loses a 401 we did not need.\nfunction looksLikeMcpMessage(value: unknown): boolean {\n if (typeof value !== 'object' || value === null) return false;\n const msg = value as { jsonrpc?: unknown; method?: unknown };\n return msg.jsonrpc === '2.0' && typeof msg.method === 'string';\n}\n\n// On a host that pre-parses bodies, `undefined` means the platform declined to\n// parse this content type (Vercel returns undefined for everything outside\n// json/text/urlencoded/octet-stream), so the body is unverifiable and must not be\n// treated as MCP — otherwise a caller reopens the credential oracle by changing\n// one header. On a host that never parses (plain node:http), there is nothing to\n// inspect without consuming the stream the SDK needs, so the gate is skipped.\n// Either way `undefined` is NOT checkable; only an actual MCP body is.\n//\n// `some`, not `every`: a JSON-RPC batch may legitimately mix a response element\n// (no `method`) with a request that invokes a tool. `every` let one response\n// element mark the whole batch un-checkable while the SDK still ran the tool\n// call — a one-element opt-out of the pre-flight. If any element invokes a\n// method, the batch must be checked. `some` on an empty array is false, so an\n// empty batch (which invokes nothing) is correctly not checkable.\nexport function bodyIsCheckable(body: unknown): boolean {\n const messages = Array.isArray(body) ? body : [body];\n return messages.some(looksLikeMcpMessage);\n}\n\n// The gate must be at least as permissive as the SDK's own content-type check,\n// or any type the SDK accepts but the gate rejects is a bypass window: the gate\n// skips, then the SDK parses and runs the tool with an unverified credential.\n// The SDK uses `ct.includes('application/json')` (streamableHttp.js), so\n// `application/json-patch+json` and `application/jsonx` reach a tool — an exact\n// match here missed them. Mirror the SDK's substring test (lowercased, so the\n// gate is a superset and stays safe even if the SDK never normalises case). A\n// type the SDK 415s that we happen to check only costs one needless probe.\nfunction isJsonContentType(req: IncomingMessage): boolean {\n const ct = req.headers['content-type'];\n if (!ct) return false;\n return ct.toLowerCase().includes('application/json');\n}\n\n// Match the SDK's own body limit (MAXIMUM_MESSAGE_SIZE, '4mb'). A body the SDK\n// would reject as too large is one we must not buffer either.\nconst MAX_BODY_BYTES = 4 * 1024 * 1024;\n// readJsonBody's distinct \"over the cap\" result, kept separate from undefined\n// (absent/unparseable) so the caller answers 413 rather than falling through to\n// the skip path and handing a partial stream back to the SDK.\nconst BODY_TOO_LARGE = Symbol('body_too_large');\n\n// Buffer and parse a JSON body when the host did not already. Without this the\n// gate cannot run on a plain node:http host — the published ./http export and\n// scripts/serve-http.local.ts — because there is nothing to inspect, which would\n// silently disable the pre-flight for those consumers. The parsed value is handed\n// to transport.handleRequest afterwards, so the SDK never needs the stream this\n// consumed. Returns undefined when the body is absent or not JSON (the caller\n// then skips), or BODY_TOO_LARGE past the cap (the caller answers 413).\n//\n// Capped, and only ever called after the cheap skip checks pass, so a non-JSON,\n// kill-switched or oversized request never buffers: on the un-pre-parsed\n// node:http path this replaces the SDK's own getRawBody, which enforced the same\n// 4mb limit — without the cap an unauthenticated caller could stream unbounded\n// bytes into memory, and reading before the content-type check let a slow\n// non-JSON upload hold the request slot open.\nasync function readJsonBody(\n req: IncomingMessage\n): Promise<unknown | typeof BODY_TOO_LARGE> {\n const existing = (req as { body?: unknown }).body;\n if (existing !== undefined) return existing;\n const declared = Number(req.headers['content-length']);\n if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {\n return BODY_TOO_LARGE;\n }\n try {\n const chunks: Buffer[] = [];\n let total = 0;\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n total += buf.length;\n // Covers a chunked upload or a lying Content-Length: stop the moment the\n // bytes on the wire exceed the cap, before growing the buffer further.\n if (total > MAX_BODY_BYTES) return BODY_TOO_LARGE;\n chunks.push(buf);\n }\n const raw = Buffer.concat(chunks).toString('utf8').trim();\n return raw ? JSON.parse(raw) : undefined;\n } catch {\n return undefined;\n }\n}\n\ntype SkipReason =\n | 'skip_env_var'\n | 'skip_env_mismatch'\n | 'skip_not_post'\n | 'skip_not_json'\n | 'skip_not_mcp_body';\n\n// Body-independent skip reasons, decided before the body is read (see\n// readJsonBody). Only well-formed MCP POSTs are ever checked. This does NOT close\n// the credential oracle — a caller who speaks the protocol still learns\n// 401-vs-otherwise from a well-formed tools/list — but it stops an\n// unauthenticated scanner probing stolen keys through us with arbitrary requests,\n// and avoids an upstream query per junk request. Closing it properly needs rate\n// limiting, which this does not add. GET and DELETE make no authenticated\n// upstream call, so a dead credential breaks nothing there. The cheap header\n// checks precede the env-mismatch scan (which parses several URLs) so the common\n// non-POST path stays cheap, and the kill switch comes first so it also prevents\n// the body read.\nfunction earlyCredentialCheckSkip(req: IncomingMessage): SkipReason | null {\n if (process.env.MCP_SKIP_CREDENTIAL_CHECK === 'true') return 'skip_env_var';\n if (req.method !== 'POST') return 'skip_not_post';\n if (!isJsonContentType(req)) return 'skip_not_json';\n if (credentialCheckMayBeWrongEnvironment()) return 'skip_env_mismatch';\n return null;\n}\n\nfunction logCredentialCheck(\n outcome: SkipReason | 'pass' | 'reject' | 'fail_open'\n): void {\n // 'pass' is the bulk of traffic and is pure log spend; everything else —\n // rejections, fail-open guesses, every skip reason — always logs, because those\n // are the only way to notice the gate misbehaving or silently not running.\n if (outcome === 'pass' && process.env.MCP_VERBOSE_LOGS !== 'true') return;\n console.log('credential_check', { outcome });\n}\n\n/**\n * Handle an incoming HTTP request as a streamable MCP session.\n *\n * Each request gets its own McpServer + transport. The caller's Bearer token\n * is forwarded directly to the Runpod API as the credential — it may be a\n * Runpod API key (set manually by the caller) or a token obtained through the\n * OAuth \"Sign in with Runpod\" flow. The server holds no credential of its own\n * and never shares one across users.\n *\n * The token is pre-flight verified (cached) before the MCP request is\n * handled: a dead credential — e.g. an OAuth-minted key revoked mid-session —\n * must surface as an HTTP 401 + WWW-Authenticate so\n * OAuth-capable clients re-run their auth flow automatically. Without this,\n * the upstream 401 is wrapped into a 200 JSON-RPC tool error and the client\n * never re-authenticates. Set MCP_SKIP_CREDENTIAL_CHECK=true to disable.\n *\n * The gate also self-disables when the REST hosts are overridden without a\n * matching RUNPOD_AUTHED_GRAPHQL_URL — see credentialCheckMayBeWrongEnvironment.\n */\nexport async function handleMcpRequest(\n req: IncomingMessage,\n res: ServerResponse,\n opts: {\n serverVersion?: string;\n // Test seams — production uses the shared default checker.\n verifyCredential?: CredentialChecker;\n invalidateCredential?: (token: string) => void;\n } = {}\n): Promise<void> {\n const bearerToken = extractBearerToken(req);\n console.log('mcp_request', {\n method: req.method,\n url: req.url,\n hasBearerToken: !!bearerToken,\n });\n // Stateless server: there are no server-initiated messages, so the standalone\n // GET SSE stream has nothing to carry. Per spec, answer 405 instead of letting\n // the SDK hold an idle stream open until the platform kills it.\n if (req.method === 'GET') {\n res.writeHead(405, {\n Allow: 'POST, DELETE',\n 'Content-Type': 'application/json',\n });\n res.end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message:\n 'Method Not Allowed: this server does not offer a standalone SSE stream.',\n },\n id: null,\n })\n );\n return;\n }\n if (!bearerToken) {\n writeUnauthorized(\n req,\n res,\n 'Missing or invalid Authorization header. Provide a Bearer token.'\n );\n return;\n }\n\n // The body is read only when the pre-flight might actually run. The cheap,\n // body-independent skips are decided first (earlyCredentialCheckSkip) so a\n // non-JSON, kill-switched or wrong-environment request never buffers a body —\n // an earlier version read every body up front, which removed the SDK's 4mb cap\n // and let a slow or oversized non-JSON upload hold the request slot open. For a\n // skipped request `body` stays whatever the host pre-parsed (undefined on plain\n // node:http, where the SDK then reads the stream itself).\n let body: unknown = (req as { body?: unknown }).body;\n // Stable account identity from the pre-flight's `myself { id }` probe —\n // carried into anonymous analytics so a user keeps one identity across key\n // rotations. Absent when the check is skipped or fails open.\n let accountId: string | undefined;\n const early = earlyCredentialCheckSkip(req);\n if (early) {\n logCredentialCheck(early);\n } else {\n const read = await readJsonBody(req);\n if (read === BODY_TOO_LARGE) {\n res.writeHead(413, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Request body too large.' }));\n return;\n }\n body = read;\n if (!bodyIsCheckable(body)) {\n // Absent, unparseable, or not an MCP message — nothing to check, and\n // checking it anyway would reopen the credential oracle.\n logCredentialCheck('skip_not_mcp_body');\n } else {\n const verify = opts.verifyCredential ?? defaultCredentialChecker.verify;\n const verdict = await verify(bearerToken);\n if (verdict.status === 'valid') accountId = verdict.accountId;\n // 'unknown' is logged distinctly from 'pass': both let the request through,\n // but one is an answer and the other a guess made because the auth backend\n // could not be reached. Silently merging them hides an outage upstream.\n logCredentialCheck(\n verdict.status === 'invalid'\n ? 'reject'\n : verdict.status === 'valid'\n ? 'pass'\n : 'fail_open'\n );\n if (verdict.status === 'invalid') {\n writeUnauthorized(\n req,\n res,\n `${verdict.reason} Re-authenticate to continue.`,\n true\n );\n return;\n }\n }\n }\n\n // SPEC-GENERATED SURFACE (feat/specgen-server): the tool set generated from\n // the v2 OpenAPI spec plus its curated overlay, mounted behind this shell's\n // existing auth/transport. Per-request context from the caller's bearer\n // token — nothing credential-bearing lives at module scope.\n const server = createSpecgenServer(\n createSpecgenContext({\n apiKey: bearerToken,\n tracking: {\n // Stateless HTTP never sees the MCP clientInfo; the inbound\n // User-Agent is the best identity available.\n clientName: req.headers['user-agent'],\n transport: 'http',\n serverVersion: opts.serverVersion ?? SERVER_VERSION,\n },\n }),\n opts.serverVersion ?? SERVER_VERSION,\n {\n // Anonymous usage analytics: hosted-only, no-op unless POSTHOG_API_KEY\n // is set on the deployment, and any client can opt out per request\n // with the X-Runpod-Analytics: off header.\n ...(analyticsOptedOut(req)\n ? {}\n : {\n analytics: {\n transport: 'http' as const,\n serverVersion: opts.serverVersion ?? SERVER_VERSION,\n clientName: sanitizeUaToken(\n String(req.headers['user-agent'] ?? 'unknown')\n ),\n accountId,\n },\n }),\n // ALP write tools: advertised only when this deployment can actually\n // store submissions (the sink is configured). The ingest endpoint is\n // this deployment's own /api/alp/submit — one write path, both\n // transports (docs/agent-learning-protocol.md).\n ...(process.env.ALP_SINK_URL && process.env.ALP_SINK_SECRET\n ? {\n alp: {\n ingestUrl: `${getBaseUrl(req)}/api/alp/submit`,\n transport: 'http' as const,\n harness: sanitizeUaToken(\n String(req.headers['user-agent'] ?? 'unknown')\n ),\n harnessSource: 'user_agent' as const,\n },\n }\n : {}),\n // A tool call that 401s proves a cached \"valid\" verdict wrong before\n // its TTL — drop it so the next request re-checks and re-auths.\n onUnauthorized: () =>\n (opts.invalidateCredential ?? defaultCredentialChecker.invalidate)(\n bearerToken\n ),\n }\n );\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined, // stateless — no session persistence\n });\n\n // This per-request server/transport pair is single-use; dispose it when the\n // response closes so listeners don't accumulate on a warm serverless instance.\n res.on('close', () => {\n transport.close().catch(() => {});\n server.close().catch(() => {});\n });\n\n await server.connect(transport);\n // Pass the already-parsed body when the host provides one (e.g. Vercel's\n // VercelRequest exposes `req.body`); the SDK reads the raw stream otherwise.\n // Pass the body we already resolved: readJsonBody may have consumed the stream.\n await transport.handleRequest(req, res, body);\n}\n","// The shared context threaded into every curated tool handler: the generated\n// SDK client for the v2 management API, plus the clients for the two planes\n// the spec does not cover (Serverless runtime, GraphQL) and the bounded SSE\n// reader for the log endpoints.\n//\n// TENANCY: on the hosted (HTTP) path every request builds its own context\n// from the caller's bearer token — nothing here may be cached at module\n// scope. The stdio path builds one context per process from RUNPOD_API_KEY.\n\nimport { randomUUID } from 'node:crypto';\nimport {\n createRunpodClient,\n type RetryOptions,\n type RunpodClient,\n} from '@runpod/typescript-api-sdk';\nimport { sdkBase } from '../_shared/hosts.js';\nimport { buildTrackingHeaders } from '../_shared/tracking.js';\nimport { createGraphqlClient, type GraphqlClient } from './clients/graphql.js';\nimport { missingKeyError } from './clients/http-error.js';\nimport { createRuntimeClient, type RuntimeClient } from './clients/runtime.js';\nimport { createSseReader, type SseReader } from './clients/sse.js';\n\nexport interface ToolContext {\n sdk: RunpodClient;\n runtime: RuntimeClient;\n graphql: GraphqlClient;\n sse: SseReader;\n /** The key this context authenticates with (hosted: the caller's bearer token). */\n apiKey: string | undefined;\n /** Late-bind the calling client's identity into the tracking User-Agent.\n * The stdio transport only learns it from the MCP initialize handshake,\n * which happens after this context is built. No-op without tracking. */\n setClientInfo?: (name: string, version?: string) => void;\n}\n\nexport interface ToolContextOptions {\n /** Per-caller credential. Falls back to RUNPOD_API_KEY (stdio path). */\n apiKey?: string;\n /** Caller identity stamped on every outbound API call (User-Agent +\n * X-Runpod-Session-Id). Ported from the pre-specgen server. */\n tracking?: {\n clientName?: string;\n clientVersion?: string;\n transport: 'stdio' | 'http';\n serverVersion: string;\n };\n /** Test seam: deadline for one SDK (generated-tool) request. */\n sdkTimeoutMs?: number;\n /** Test seam: SDK retry tuning (false disables the retry layer). */\n sdkRetry?: RetryOptions | false;\n}\n\n// Deadline for one SDK request. The generated tools are plain CRUD calls —\n// nothing on that surface legitimately takes longer, and without a signal a\n// host that accepts the connection then goes silent parks the invocation\n// until the platform reaper (the leak PR #83 fixed on the old surface). The\n// long-hold paths (job waits, SSE streams) do NOT go through the SDK; their\n// clients carry their own bounded signals.\nconst SDK_TIMEOUT_MS = 30_000;\n\n// Bound the SDK's retry layer: its defaults honor Retry-After up to 60s per\n// sleep across 4 attempts, which alone can outlive the hosted invocation's\n// 45s budget. Retries here are for transient blips only — a real 429 must\n// come back to the agent quickly, carrying the header-derived wait hint, so\n// the AGENT decides how long to pause (dispatch enriches it; a server-side\n// sleep would just burn the budget silently).\nconst SDK_RETRY: RetryOptions = {\n maxAttempts: 3,\n maxBackoffMs: 2_000,\n maxRetryAfterMs: 5_000,\n};\n\nexport function createToolContext(\n options: ToolContextOptions = {}\n): ToolContext {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n\n // One wrapped fetch shared by all four clients: identifies the calling MCP\n // client on every outbound API request. The session id is per-context —\n // per-request on hosted, per-process on stdio.\n let fetchImpl: typeof fetch = fetch;\n let setClientInfo: ToolContext['setClientInfo'];\n if (options.tracking) {\n // Mutable so the stdio handshake can late-bind clientInfo; headers are\n // rebuilt only when it changes.\n const tracking = { ...options.tracking, sessionId: randomUUID() };\n let headers = buildTrackingHeaders(tracking);\n setClientInfo = (name, version) => {\n tracking.clientName = name;\n tracking.clientVersion = version;\n headers = buildTrackingHeaders(tracking);\n };\n fetchImpl = (input, init) => {\n // openapi-fetch calls fetch with a fully-built Request as `input`\n // (headers inside it, no init); other clients pass (url, init). Fold\n // both into one Request, then add the tracking headers only where\n // absent — passing a headers init alongside a Request would REPLACE\n // the request's own headers and drop Authorization.\n const request = new Request(input, init);\n for (const [name, value] of Object.entries(headers)) {\n if (!request.headers.has(name)) request.headers.set(name, value);\n }\n return fetch(request);\n };\n }\n\n let sdk: RunpodClient | undefined;\n\n return {\n apiKey,\n setClientInfo,\n // Built on first use, not at startup. The SDK client constructor throws\n // when no API key is present, and the MCP handshake plus tools/list are a\n // credential-free surface — a client must be able to start the server and\n // read its tool list without a key. A key-less call then fails as a 401\n // tool result instead of killing the process.\n get sdk(): RunpodClient {\n if (!sdk) {\n if (!apiKey) throw missingKeyError();\n sdk = createRunpodClient({\n apiKey,\n baseUrl: sdkBase(process.env),\n fetch: fetchImpl,\n timeoutMs: options.sdkTimeoutMs ?? SDK_TIMEOUT_MS,\n retry: options.sdkRetry ?? SDK_RETRY,\n });\n }\n return sdk;\n },\n runtime: createRuntimeClient({ apiKey, fetchImpl }),\n graphql: createGraphqlClient({ apiKey, fetchImpl }),\n sse: createSseReader({ apiKey, fetchImpl }),\n };\n}\n","// ============== CALLER TRACKING (pure header construction) ==============\n// The structured User-Agent + session id that identify the calling MCP client\n// on every outbound API call. Pure functions here so they're unit-testable\n// without the MCP SDK; the SDK-touching part (reading clientInfo off the\n// handshake) stays at the call site and is reduced to plain strings before\n// reaching `buildTrackingHeaders`.\n\n// Sanitizes a value for inclusion in a User-Agent token. RFC 7230 reserves\n// parens and a few other chars; strip them so the structured UA stays\n// parseable, and bound the length so a hostile client can't blow up a header.\nexport function sanitizeUaToken(value: string): string {\n return value.replace(/[()<>@,;:\\\\\"/[\\]?={}\\s]/g, '_').slice(0, 64);\n}\n\nexport interface TrackingInput {\n // Client identity resolved from the MCP `initialize` handshake's clientInfo,\n // or the inbound HTTP User-Agent as a fallback (stateless HTTP).\n clientName?: string;\n clientVersion?: string;\n transport: 'stdio' | 'http';\n serverVersion: string;\n sessionId: string;\n}\n\n// Builds the `User-Agent` + `X-Runpod-Session-Id` headers. The clientInfo →\n// fallback → 'unknown' resolution is the caller's job (it owns the SDK handle);\n// this function just sanitizes and formats whatever identity it's given.\nexport function buildTrackingHeaders(\n input: TrackingInput\n): Record<string, string> {\n const name = sanitizeUaToken(input.clientName || 'unknown');\n const version = sanitizeUaToken(input.clientVersion || 'unknown');\n // `surface=v2` is the durable generation marker for warehouse attribution\n // (the spec-generated surface; v1 was the hand-written tool set). Bump it\n // with the surface, independently of the npm package version. Keep in sync\n // with SURFACE_VERSION in src/specgen/analytics.ts.\n const userAgent = `runpod-mcp-server/${input.serverVersion} (caller=mcp; surface=v2; client=${name}; client_version=${version}; transport=${input.transport})`;\n return {\n 'User-Agent': userAgent,\n 'X-Runpod-Session-Id': input.sessionId,\n };\n}\n","// Client for the Runpod GraphQL API, used by the curated tools whose\n// capability has no REST v2 home yet (Hub, capacity matrix, public endpoints,\n// endpoint GPU pinning). Two deliberately separate seams, mirroring the\n// official MCP server:\n//\n// - public: credential-free discovery queries (the server answers them\n// unauthenticated). Host from RUNPOD_PUBLIC_GRAPHQL_URL.\n// - authed: the caller's API key as a Bearer token (the GraphQL gateway\n// accepts the same key REST uses). Host from RUNPOD_AUTHED_GRAPHQL_URL.\n//\n// Separate env vars despite the identical default, so the credential-free\n// path can be pointed at a stub without the key following it.\n\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\nimport { authedGraphqlBase, publicGraphqlBase } from '../../_shared/hosts.js';\nimport { boundedFetch } from './bounded-fetch.js';\nimport { HttpError, missingKeyError } from './http-error.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport interface GraphqlClient {\n public<T>(query: string): Promise<T>;\n authed<T>(query: string, variables?: Record<string, unknown>): Promise<T>;\n}\n\nexport interface GraphqlClientOptions {\n apiKey?: string;\n publicUrl?: string;\n authedUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function createGraphqlClient(\n options: GraphqlClientOptions = {}\n): GraphqlClient {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n // Resolved through _shared/hosts.ts so '' reads as unset here exactly like\n // it does in the hosted wrong-environment guard.\n const publicUrl = options.publicUrl ?? publicGraphqlBase(process.env);\n const authedUrl = options.authedUrl ?? authedGraphqlBase(process.env);\n const fetchImpl = options.fetchImpl ?? fetch;\n\n async function request<T>(\n url: string,\n query: string,\n variables?: Record<string, unknown>,\n bearer?: string\n ): Promise<T> {\n const response = await boundedFetch(fetchImpl, DEFAULT_TIMEOUT_MS)(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),\n },\n body: JSON.stringify(variables ? { query, variables } : { query }),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new HttpError(\n `Runpod GraphQL HTTP error (${response.status})`,\n response.status,\n response.status === 429\n ? withRateLimitHint({ error: body }, response.headers)\n : body\n );\n }\n\n const result = (await response.json()) as {\n data?: T;\n errors?: Array<{ message: string }>;\n };\n if (result.errors && result.errors.length > 0) {\n throw new HttpError(\n `GraphQL error: ${result.errors.map((e) => e.message).join(', ')}`,\n response.status,\n result.errors\n );\n }\n if (result.data === undefined || result.data === null) {\n throw new HttpError('GraphQL response carried no data', response.status);\n }\n return result.data;\n }\n\n return {\n public: (query) => request(publicUrl, query),\n authed: async (query, variables) => {\n // A key-less authed call must 401 up front, not go out unauthenticated\n // and come back as an opaque gateway error that never trips\n // onUnauthorized. async so the 401 is a rejection, matching the\n // Promise-returning signature (a sync throw escapes Promise.race/\n // fire-then-await callers).\n if (!apiKey) throw missingKeyError();\n return request(authedUrl, query, variables, apiKey);\n },\n };\n}\n","// Client for the Serverless runtime plane (job submission and lifecycle at\n// api.runpod.ai/v2/{endpointId}/...). This is a separate API from the v2\n// management spec the generated tools cover — Runpod publishes no OpenAPI\n// document for it, so the tools that use it are curated (src/specgen/tools/jobs.ts).\n\nimport { serverlessBase } from '../../_shared/hosts.js';\nimport { boundedFetch } from './bounded-fetch.js';\nimport { HttpError, missingKeyError } from './http-error.js';\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\n\nexport const DEFAULT_SERVERLESS_BASE_URL = 'https://api.runpod.ai/v2';\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport interface RuntimeRequestOptions {\n method?: string;\n body?: Record<string, unknown>;\n timeoutMs?: number;\n}\n\nexport type RuntimeClient = (\n endpointId: string,\n path: string,\n options?: RuntimeRequestOptions\n) => Promise<unknown>;\n\nexport interface RuntimeClientOptions {\n apiKey?: string;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function createRuntimeClient(\n options: RuntimeClientOptions = {}\n): RuntimeClient {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n const baseUrl = options.baseUrl || serverlessBase(process.env);\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async (endpointId, path, opts = {}) => {\n if (!apiKey) throw missingKeyError();\n if (typeof endpointId !== 'string' || !/^[A-Za-z0-9_-]+$/.test(endpointId))\n throw new HttpError(\n 'endpointId must contain only letters, digits, underscores or hyphens.',\n 400,\n {}\n );\n const response = await boundedFetch(\n fetchImpl,\n opts.timeoutMs ?? DEFAULT_TIMEOUT_MS\n )(`${baseUrl}/${endpointId}${path}`, {\n method: opts.method ?? 'GET',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n ...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),\n });\n\n const text = await response.text();\n let payload: unknown = text;\n try {\n payload = text ? JSON.parse(text) : {};\n } catch {\n // non-JSON body stays verbatim\n }\n if (!response.ok) {\n // 429: turn the RateLimit/Retry-After headers into a wait instruction.\n const detail =\n response.status === 429\n ? withRateLimitHint(payload, response.headers)\n : payload;\n throw new HttpError(\n `Runpod runtime API error (${response.status})`,\n response.status,\n detail\n );\n }\n return payload;\n };\n}\n","// ============== HOSTED CREDENTIAL PRE-FLIGHT ==============\n// The hosted HTTP server forwards the caller's Bearer token straight to the\n// Runpod API. When that credential dies mid-session (the OAuth-minted key\n// is revoked), every tool call fails upstream with a 401 — but the\n// MCP SDK wraps thrown tool errors into a 200 JSON-RPC tool result, so the\n// client never sees an HTTP 401 and never re-runs its OAuth flow. The user is\n// stuck with bare \"Unauthorized\" tool errors until they manually reconnect.\n//\n// This module verifies the credential BEFORE the MCP request is handled, so\n// a dead credential turns into a proper HTTP 401 + WWW-Authenticate response\n// (src/http.ts writeUnauthorized) — the signal OAuth-capable MCP clients use\n// to re-authenticate automatically.\n//\n// Verification is one authenticated `myself { id }` GraphQL query. Observed live:\n// - never-valid key → HTTP 401\n// - anonymous (no ident) → HTTP 200 with `myself: null`\n// - valid key → HTTP 200 with `myself.id`\n//\n// NOT yet observed: what a once-valid, since-REVOKED key returns. The assumption\n// is HTTP 401, same as a key that never existed — but if it instead answers\n// `{data: null, errors: [...]}` that lands in the indeterminate branch below and\n// the gate fails open, silently never firing for the case it exists for. Probe a\n// genuinely revoked key to settle it.\n// Verdicts are cached in-memory by token hash (never the raw token) so a warm\n// instance adds no per-request latency: valid verdicts live for a few minutes,\n// invalid ones briefly (a just-reauthorized user shouldn't wait long). Network\n// failures and 5xx responses FAIL OPEN — the request proceeds and the tools\n// surface the real upstream error — so an auth-backend blip can't take down\n// the whole server.\n\nimport { createHash } from 'node:crypto';\n\n// `unknown` is the fail-open case: the request proceeds, but it is a GUESS and is\n// never cached — caching one lets a revoked credential skip the 401 for a full\n// TTL, which is the behaviour this module exists to remove.\nexport type CredentialVerdict =\n // accountId is the probe's `myself.id` — the stable account identity behind\n // the token. Carried so consumers (anonymous analytics) can identify a USER\n // across key rotations without any additional API call; may be absent when\n // the check was skipped or failed open.\n | { status: 'valid'; accountId?: string }\n | { status: 'invalid'; reason: string }\n | { status: 'unknown' };\n\nexport type CredentialChecker = (token: string) => Promise<CredentialVerdict>;\n\n// A checker plus the hook needed to correct a stale verdict (see invalidate).\nexport interface CredentialCheckerHandle {\n verify: CredentialChecker;\n // Drop a cached verdict. Called when a tool's own upstream call 401s, which\n // proves the cached \"valid\" wrong sooner than its TTL would.\n invalidate: (token: string) => void;\n}\n\n// Named AuthProbeFetch/AuthProbeResponse, not FetchLike: kept distinct from\n// the fetch-shaped types the specgen clients use, since this probe needs only\n// this narrow shape.\ninterface AuthProbeResponse {\n ok: boolean;\n status: number;\n json(): Promise<unknown>;\n}\n\ntype AuthProbeFetch = (\n url: string,\n init: {\n method: string;\n headers: Record<string, string>;\n body: string;\n signal?: AbortSignal;\n }\n) => Promise<AuthProbeResponse>;\n\n// A valid verdict is short-lived on purpose. It bounds how long a key revoked\n// mid-session keeps passing the gate and failing upstream instead — the exact\n// experience this module exists to remove — for the cost of one cheap query a\n// minute per active token.\nconst VALID_TTL_MS = 60_000;\nconst INVALID_TTL_MS = 30_000;\n// The pre-flight blocks the MCP request, so a slow auth backend must not be\n// able to hold it open. Without this the request hangs until the platform's own\n// limit (Vercel maxDuration 60s) turns it into a 504 — failing OPEN covers an\n// erroring backend but not a slow one. Mirrors the old backend resolver's probe deadline.\nconst REQUEST_TIMEOUT_MS = 4000;\n// Cap so a stream of one-off tokens cannot grow the map without bound: entries\n// expire lazily (only on a repeat lookup of the same token), and an unauthed\n// caller can mint arbitrarily many distinct tokens.\nconst MAX_CACHE_ENTRIES = 1000;\n\nfunction hashToken(token: string): string {\n return createHash('sha256').update(token).digest('hex');\n}\n\nexport function createCredentialChecker(deps: {\n fetch: AuthProbeFetch;\n // Resolved per call so an env change takes effect without a module reload\n // (matches how the tool runtime resolves its base URLs).\n url: () => string;\n now?: () => number;\n validTtlMs?: number;\n invalidTtlMs?: number;\n timeoutMs?: number;\n maxEntries?: number;\n}): CredentialCheckerHandle {\n // Monotonic by default, not Date.now: TTLs are elapsed-time bounds, and a\n // wall-clock step backwards (NTP/VM correction) against an absolute Date.now\n // stamp would silently extend a cached verdict well past its TTL — turning the\n // documented ~60s revocation bound into minutes. Tests inject their own `now`.\n const now = deps.now ?? (() => performance.now());\n const validTtl = deps.validTtlMs ?? VALID_TTL_MS;\n const invalidTtl = deps.invalidTtlMs ?? INVALID_TTL_MS;\n const timeoutMs = deps.timeoutMs ?? REQUEST_TIMEOUT_MS;\n // Clamped so the two call sites below need no degenerate-case guards.\n const maxEntries = Math.max(1, deps.maxEntries ?? MAX_CACHE_ENTRIES);\n // ONE entry per token: either a check in flight or a settled verdict. A\n // settling check writes its result only if the entry it started with is still\n // the one in the map, and invalidate() removes the entry — so a check already\n // running when a credential is rejected cannot resurrect its stale verdict.\n //\n // Insertion-ordered, so this doubles as the LRU: a hit re-inserts to move the\n // key to the back (see verify), and eviction takes the front.\n interface Entry {\n // Set while a check is running; cleared once it settles.\n promise?: Promise<CredentialVerdict>;\n // Set once a DEFINITIVE answer arrives. An indeterminate fail-open is never\n // stored — it is a guess, and caching a guess for a full TTL lets a dead\n // credential skip the 401 for that window, the bug this module exists to fix.\n verdict?: CredentialVerdict;\n expiresAt: number;\n }\n const entries = new Map<string, Entry>();\n\n async function fetchVerdict(token: string): Promise<CredentialVerdict> {\n try {\n const response = await deps.fetch(deps.url(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ query: 'query { myself { id } }' }),\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (response.status === 401) {\n return {\n status: 'invalid',\n reason:\n 'The Runpod API rejected the credential (it may have been revoked).',\n };\n }\n // 403 is NOT a dead credential. This host sits behind Cloudflare, so a\n // WAF/bot block answers 403 with no relation to the token, and a\n // permission-scoped key can 403 while still working for other calls.\n // Treating it as dead sent a 401 back, the client re-ran OAuth, and that\n // MINTS A NEW API KEY on every attempt — a loop that never recovers and\n // fills the user's dashboard with keys. Fail open and let the tool\n // surface the real error.\n if (!response.ok) return { status: 'unknown' };\n\n const result = (await response.json()) as {\n data?: { myself?: { id?: string } | null };\n errors?: unknown[];\n };\n if (result?.data?.myself?.id)\n return { status: 'valid', accountId: result.data.myself.id };\n // A GraphQL response that carries errors is NOT authoritative about the\n // credential. Per the GraphQL spec a resolver failure on the nullable\n // `myself` field answers HTTP 200 with `myself: null` AND an `errors`\n // array — that null reflects a server-side fault, not a dead token. The\n // shape is identical for every caller during a backend blip, so treating\n // it as `invalid` would 401 EVERY valid credential at once and drive every\n // OAuth client into the re-auth key-minting loop the 403 branch above\n // exists to prevent — and it fails closed, which is worse than 403's\n // fail-open. So fail open on any errors; a genuine anonymous token returns\n // a clean `myself: null` with no errors (verified live).\n if (Array.isArray(result?.errors) && result.errors.length > 0) {\n return { status: 'unknown' };\n }\n if (result?.data && result.data.myself === null) {\n // The backend treated the request as anonymous — the token carries no\n // identity, so every downstream call would 401.\n return {\n status: 'invalid',\n reason: 'The credential does not resolve to a Runpod account.',\n };\n }\n // Unrecognized shape (including a bare {data: null}) — fail open.\n return { status: 'unknown' };\n } catch {\n // Network error, or the timeout above aborting — fail open.\n return { status: 'unknown' };\n }\n }\n\n function evictIfFull(): void {\n // Never evict an entry whose check is still in flight. Doing so disowns a\n // registered check — its settle handler then fails the `entries.get(key) ===\n // entry` identity test and drops its verdict — which breaks the one-in-flight-\n // check-per-token invariant that makes last-writer-wins safe. Without this a\n // flood of distinct tokens (each cached as a definitive `invalid`, so they\n // hold the map full) could evict a legitimate user's in-flight check and let\n // a since-revoked key cache as `valid` for a full TTL, and duplicate the\n // upstream call. Only settled entries are evicted, oldest first (insertion\n // order = LRU). If every entry is in flight we allow a brief, bounded\n // overshoot: in-flight count is capped by request concurrency and each check\n // self-clears within the request timeout.\n while (entries.size >= maxEntries) {\n let victim: string | undefined;\n for (const [k, e] of entries) {\n if (!e.promise) {\n victim = k;\n break;\n }\n }\n if (victim === undefined) return;\n entries.delete(victim);\n }\n }\n\n async function verify(token: string): Promise<CredentialVerdict> {\n const key = hashToken(token);\n const existing = entries.get(key);\n\n if (existing?.verdict) {\n if (existing.expiresAt > now()) {\n // Refresh recency so a hot token is not evicted ahead of a cold one.\n entries.delete(key);\n entries.set(key, existing);\n return existing.verdict;\n }\n entries.delete(key);\n } else if (existing?.promise) {\n // Join the check already running for this token rather than duplicating it.\n return existing.promise;\n }\n\n const entry: Entry = { expiresAt: 0 };\n entry.promise = fetchVerdict(token).then((verdict) => {\n // Only RECORD the result if this entry is still the one registered. A\n // different entry means invalidate() removed ours, or a newer check\n // replaced it, so this answer must not be stored — and must not delete the\n // newer entry either. The caller that started this check is still served\n // its own result; only the shared state is protected.\n if (entries.get(key) === entry) {\n if (verdict.status !== 'unknown') {\n entry.verdict = verdict;\n entry.expiresAt =\n now() + (verdict.status === 'valid' ? validTtl : invalidTtl);\n entry.promise = undefined;\n } else {\n entries.delete(key);\n }\n }\n return verdict;\n });\n\n evictIfFull();\n entries.set(key, entry);\n return entry.promise;\n }\n\n return {\n verify,\n invalidate: (token: string) => {\n // Removing the entry is the whole mechanism: a check already in flight can\n // no longer match it on settle, so it cannot resurrect the verdict this\n // call just rejected. Nothing to prune afterwards, so nothing can leak.\n entries.delete(hashToken(token));\n },\n };\n}\n","// ALP journal read-back: POST /api/alp/journal (see docs/agent-learning-protocol.md,\n// \"The tool pair\"). The one read path, for the one route that is readable.\n//\n// SCOPE IS THE TOKEN, NOT THE REQUEST. Identity is resolved from the caller's\n// Bearer key exactly as ingest does, and that resolved id is the ONLY filter\n// sent to the sink. The request body is read for `limit` and nothing else — an\n// `identity` field in it is ignored, so no caller can name whose journal to\n// read. Holding a valid key for an account is the only way to see its journal,\n// and a key holder already has that account's pods and billing.\n//\n// FAIL-CLOSED, CALMLY. Anything that prevents a scoped read (no token verdict,\n// no sink, sink down, unrecognized reply) returns a non-error result with zero\n// entries and a note. It never guesses an identity and never falls back to a\n// wider query. Only a missing or invalid credential is a real 401.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { defaultCredentialChecker } from '../http.js';\nimport { isSinkUrl } from './ingest.js';\n\nexport const DEFAULT_JOURNAL_LIMIT = 20;\nexport const MAX_JOURNAL_LIMIT = 50;\nconst SINK_TIMEOUT_MS = 5_000;\n\nexport interface JournalEntry {\n content: string;\n intention?: string;\n trigger?: string;\n tool?: string;\n receivedAt: string;\n}\n\ninterface VerifyResult {\n status: 'valid' | 'invalid' | 'unknown';\n accountId?: string;\n}\n\nexport interface AlpReadOptions {\n /** Test seams. Production uses the shared checker + global fetch + env. */\n verify?: (token: string) => Promise<VerifyResult>;\n sinkFetch?: typeof fetch;\n env?: Record<string, string | undefined>;\n}\n\n/** The read door sits beside the write door on the same Convex deployment. */\nexport function journalSinkUrl(submitUrl: string): string | null {\n if (!isSinkUrl(submitUrl)) return null;\n const url = new URL(submitUrl);\n url.pathname = '/alp/journal';\n return url.toString();\n}\n\n/** Clamp a caller-supplied limit; anything unusable becomes the default. */\nexport function clampLimit(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) return DEFAULT_JOURNAL_LIMIT;\n return Math.min(Math.max(Math.trunc(n), 1), MAX_JOURNAL_LIMIT);\n}\n\nfunction unavailable(reason: string): Record<string, unknown> {\n return {\n available: false,\n entries: [],\n note: `Journal unavailable (${reason}). Do not retry — continue your task.`,\n };\n}\n\nexport async function handleAlpJournalRead(\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n opts: AlpReadOptions = {}\n): Promise<void> {\n const env = opts.env ?? process.env;\n const send = (code: number, body: unknown) => {\n res.writeHead(code, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(body));\n };\n\n const auth = req.headers.authorization;\n const token = auth?.startsWith('Bearer ') ? auth.slice(7).trim() : undefined;\n if (!token) {\n send(401, {\n available: false,\n entries: [],\n error: 'Authenticate with your Runpod API key as a Bearer token.',\n });\n return;\n }\n\n const body = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n limit?: unknown;\n };\n const limit = clampLimit(body.limit);\n\n const verify = opts.verify ?? defaultCredentialChecker.verify;\n const verdict = await verify(token);\n if (verdict.status === 'invalid') {\n send(401, {\n available: false,\n entries: [],\n error:\n 'This Runpod API key is not valid. Re-authenticate and retry once.',\n });\n return;\n }\n if (verdict.status !== 'valid' || !verdict.accountId) {\n send(200, unavailable('identity could not be resolved right now'));\n return;\n }\n\n const submitUrl = env.ALP_SINK_URL;\n const sinkSecret = env.ALP_SINK_SECRET;\n const readUrl = submitUrl ? journalSinkUrl(submitUrl) : null;\n if (!submitUrl || !sinkSecret) {\n send(200, unavailable('the journal is not configured on this deployment'));\n return;\n }\n if (!readUrl) {\n console.warn('alp_sink_misconfigured');\n send(200, unavailable('the journal is misconfigured on this deployment'));\n return;\n }\n\n try {\n const sinkFetch = opts.sinkFetch ?? fetch;\n const response = await sinkFetch(readUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-ALP-Secret': sinkSecret,\n },\n // The resolved account id, never anything from the request body.\n body: JSON.stringify({ identity: verdict.accountId, limit }),\n signal: AbortSignal.timeout(SINK_TIMEOUT_MS),\n });\n if (!response.ok) {\n console.warn('alp_journal_sink_error', { status: response.status });\n send(200, unavailable('the store did not answer the read'));\n return;\n }\n const sinkBody = (await response.json().catch(() => null)) as {\n ok?: boolean;\n entries?: unknown;\n } | null;\n if (sinkBody?.ok !== true || !Array.isArray(sinkBody.entries)) {\n console.warn('alp_journal_sink_unrecognized', {\n status: response.status,\n });\n send(200, unavailable('the store did not confirm the read'));\n return;\n }\n // Same privacy rule as alp_submit: count, never content.\n console.log(\n 'alp_journal_read',\n JSON.stringify({ entries: sinkBody.entries.length, limit })\n );\n send(200, { available: true, entries: sinkBody.entries as JournalEntry[] });\n } catch {\n console.warn('alp_journal_sink_unreachable');\n send(200, unavailable('the store is unreachable right now'));\n }\n}\n","// ALP tools (Agent Learning Protocol): report_feedback, save_to_journal,\n// ask_question write; read_journal reads back the caller's own journal. See\n// docs/agent-learning-protocol.md, \"The tool pair\".\n//\n// All four are thin clients of the hosted endpoints (POST /api/alp/submit and\n// POST /api/alp/journal) — the npm package holds no storage credentials, so\n// both transports go there with the caller's own key. The journal is the ONE\n// route that is served back, and only to the identity that wrote it; feedback\n// and questions return nothing, and every description and response says so\n// honestly — an ambiguous ack is a false affordance the model may plan around\n// (waiting, polling, re-asking).\n//\n// FAIL-SOFT: these tools are side quests. Whatever goes wrong, the result is\n// a calm non-error saying the entry was not recorded and not to retry —\n// never a tool failure that derails the agent's actual task.\n\nimport type { AlpRoute } from '../../alp/ingest.js';\nimport {\n clampLimit,\n DEFAULT_JOURNAL_LIMIT,\n MAX_JOURNAL_LIMIT,\n type JournalEntry,\n} from '../../alp/read.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport { ok } from './util.js';\nimport { readOnly, write } from './annotations.js';\n\n// HOSTED-ONLY by decision (2026-09-03): src/http.ts registers these tools\n// whenever the deployment configures its sink (ALP_SINK_URL + ALP_SINK_SECRET);\n// the stdio entrypoint never does, so local users cannot enable them. Absent\n// from tools/list is the disabled state — absent is unambiguous and free,\n// present-but-failing costs context and invites retries.\n\nconst NOT_RECORDED =\n 'The entry was NOT recorded. Do not retry — continue your task.';\n\nasync function submit(\n ctx: ToolContext,\n ingestUrl: string,\n route: AlpRoute,\n args: Record<string, unknown>,\n extra: {\n transport: 'stdio' | 'http';\n harness?: string;\n harnessSource?: string;\n }\n): Promise<{ recorded: boolean }> {\n try {\n const response = await fetch(ingestUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(ctx.apiKey ? { Authorization: `Bearer ${ctx.apiKey}` } : {}),\n },\n body: JSON.stringify({\n route,\n content: args.content,\n intention: args.intention,\n modelType: args.modelType,\n severity: args.severity,\n tool: args.tool,\n workaround: args.workaround,\n trigger: args.trigger,\n ...extra,\n }),\n signal: AbortSignal.timeout(10_000),\n });\n const body = (await response.json().catch(() => ({}))) as {\n recorded?: boolean;\n };\n return { recorded: response.ok && body.recorded === true };\n } catch {\n return { recorded: false };\n }\n}\n\n// The read endpoint sits beside the write endpoint on the same deployment.\n// Derived, not configured, so the two can never point at different servers.\nexport function journalReadUrl(ingestUrl: string): string {\n return ingestUrl.replace(/\\/submit$/, '/journal');\n}\n\nasync function readJournal(\n ctx: ToolContext,\n readUrl: string,\n limit: number\n): Promise<{ available: boolean; entries: JournalEntry[] }> {\n try {\n const response = await fetch(readUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(ctx.apiKey ? { Authorization: `Bearer ${ctx.apiKey}` } : {}),\n },\n // Only the page size crosses the wire. Whose journal this is comes from\n // the Bearer token, resolved server-side — there is no argument for it.\n body: JSON.stringify({ limit }),\n signal: AbortSignal.timeout(10_000),\n });\n const body = (await response.json().catch(() => ({}))) as {\n available?: boolean;\n entries?: unknown;\n };\n if (\n !response.ok ||\n body.available !== true ||\n !Array.isArray(body.entries)\n ) {\n return { available: false, entries: [] };\n }\n return { available: true, entries: body.entries as JournalEntry[] };\n } catch {\n return { available: false, entries: [] };\n }\n}\n\n// Shared input schema. `content` stays the only required field — fewer required\n// args means a higher call-through rate (design doc, Fields) — and everything\n// added since is optional and mechanical, answerable from what the agent\n// already did rather than from fresh reasoning.\n//\n// The first 21 production submissions showed prose was never the shortfall:\n// 233-1794 characters each, `intention` filled on 20 of 21, several tracing a\n// contradiction across five paired reads. What was missing was any dimension to\n// sort or route them by, so a total blocker sat beside a docs nit and telling\n// them apart meant opening both. Hence structure, not longer prose.\nconst SEVERITY = ['blocked', 'degraded', 'cosmetic'] as const;\n\nconst TOOL_FIELD = {\n type: 'string' as const,\n description:\n '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.',\n};\n\nconst alpInputSchema = (\n contentDescription: string,\n extra: Record<string, unknown> = {}\n) => ({\n type: 'object' as const,\n properties: {\n content: {\n type: 'string' as const,\n description: contentDescription,\n },\n intention: {\n type: 'string' as const,\n description:\n 'One short sentence: what you were trying to accomplish when this came up.',\n },\n ...extra,\n modelType: {\n type: 'string' as const,\n description:\n 'Your best identification of the model you are running as, and the product running it if you know that too — 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.',\n },\n },\n required: ['content'],\n});\n\nexport interface AlpToolsOptions {\n ingestUrl: string;\n transport: 'stdio' | 'http';\n harness?: string;\n harnessSource?: 'client_info' | 'user_agent';\n}\n\nexport function createAlpTools(opts: AlpToolsOptions): CuratedTool[] {\n // Read from `opts` at CALL time, not creation time: on stdio the harness\n // (MCP clientInfo) only arrives with the initialize handshake, after these\n // tools are built — the server updates opts.harness then.\n const extra = () => ({\n transport: opts.transport,\n harness: opts.harness,\n harnessSource: opts.harnessSource,\n });\n\n const reportFeedback: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'report_feedback',\n annotations: write,\n description:\n '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 — 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 — 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.',\n inputSchema: alpInputSchema(\n 'The observation: what happened, what you expected, and the exact error or response text if you have it.',\n {\n severity: {\n type: 'string' as const,\n enum: [...SEVERITY],\n description:\n 'How much this cost you: blocked (you could not complete the task at all), degraded (you completed it the slow or awkward way), cosmetic (correct but confusing or badly worded). Report the effect on your task, not how bad the underlying bug looks.',\n },\n tool: TOOL_FIELD,\n workaround: {\n type: 'string' as const,\n description:\n 'What you did instead, if anything worked. Leave this out when nothing did — an absent workaround is read as fully blocked.',\n },\n }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'feedback',\n args,\n extra()\n );\n return ok({\n recorded,\n note: recorded\n ? 'Recorded for internal review. No reply will arrive in this session — continue your task.'\n : NOT_RECORDED,\n });\n },\n };\n\n const saveToJournal: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'save_to_journal',\n annotations: write,\n description:\n \"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 — an entry with no stated trigger cannot be surfaced to the session that needs it. Never include API keys or secrets.\",\n inputSchema: alpInputSchema(\n 'The learning, stated so a future agent can act on it: the situation, what turned out to be true, and how you verified it.',\n {\n trigger: {\n type: 'string' as const,\n description:\n 'The situation in which a future agent should recall this — the circumstances that make it relevant, not a restatement of the lesson. This is what makes the entry findable later, so write it as the condition you would want matched.',\n },\n tool: TOOL_FIELD,\n }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'journal',\n args,\n extra()\n );\n return ok({\n recorded,\n note: recorded\n ? \"Saved to this account's private journal. A future session on this account can read it back with read_journal. Continue your task.\"\n : NOT_RECORDED,\n });\n },\n };\n\n const askQuestion: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'ask_question',\n annotations: write,\n description:\n 'Record a question about Runpod that you could not answer with the available tools, skills, and docs. NO ANSWER WILL COME BACK — 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 — if you have no Runpod question, do not call it.',\n inputSchema: alpInputSchema(\n 'The question, with enough context that someone reading it later understands what you were blocked on.',\n { tool: TOOL_FIELD }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'question',\n args,\n extra()\n );\n return ok({\n recorded,\n answer: null,\n note: recorded\n ? 'Recorded. No answer is coming — not now, not later in this session. Do not wait, poll, or retry. Check list-guides and read-guide for existing guidance and continue with your best judgment.'\n : NOT_RECORDED,\n });\n },\n };\n\n const readUrl = journalReadUrl(opts.ingestUrl);\n const readJournalTool: CuratedTool = {\n lenientArguments: true,\n name: 'read_journal',\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'integer' as const,\n minimum: 1,\n maximum: MAX_JOURNAL_LIMIT,\n description: `How many of the newest entries to return. Default ${DEFAULT_JOURNAL_LIMIT}, maximum ${MAX_JOURNAL_LIMIT}.`,\n },\n },\n },\n handler: async (ctx, args) => {\n const { available, entries } = await readJournal(\n ctx,\n readUrl,\n clampLimit(args.limit)\n );\n return ok({\n available,\n count: entries.length,\n entries,\n note: !available\n ? 'The journal could not be read right now. Do not retry — continue your task.'\n : entries.length === 0\n ? 'This account has no journal entries yet. Continue your task; save what you learn with save_to_journal.'\n : \"These are earlier sessions' own notes, not verified documentation: confirm anything time-sensitive (stock, prices, versions) with a live read before acting on it.\",\n });\n },\n };\n\n return [reportFeedback, saveToJournal, askQuestion, readJournalTool];\n}\n","// Operational seam for the hosted path: per-tool-call structured logging and\n// the rate-limit gate. The rate limiter is a deliberate STUB — it defines the\n// seat in the request path (keyed on a caller identity, consulted before any\n// tool work) so real enforcement (e.g. a KV-backed counter) can land without\n// touching the dispatch pipeline. Until then it always admits.\n//\n// SECURITY: nothing in this file may log the API key, the Authorization\n// header, or tool arguments (which can carry payload secrets). Callers are\n// identified by a short salted hash of the token — stable within one warm\n// instance for correlation, useless for recovering the credential.\n\nimport { createHash, randomBytes } from 'node:crypto';\n\n// Per-process salt: caller ids correlate within an instance's log window but\n// cannot be joined across instances or replayed offline against a key list.\nconst SALT = randomBytes(16).toString('hex');\n\nexport function callerId(token: string | undefined): string {\n if (!token) return 'anonymous';\n return createHash('sha256')\n .update(SALT)\n .update(token)\n .digest('hex')\n .slice(0, 12);\n}\n\n// ---- rate limiting (stub) ----\n\nexport interface RateLimitVerdict {\n allowed: boolean;\n /** Seconds the caller should wait; only set when denied. */\n retryAfterS?: number;\n}\n\nexport type RateLimiter = (\n caller: string,\n toolName: string\n) => Promise<RateLimitVerdict>;\n\n// Always admits. Replace with a KV/Upstash-backed counter to enforce; the\n// http handler already turns a denial into a JSON-RPC tool error with a\n// retry hint, so enforcement is a one-function change.\nexport const noopRateLimiter: RateLimiter = async () => ({ allowed: true });\n\n// ---- structured tool-call logging ----\n\nexport interface ToolCallLog {\n tool: string;\n caller: string;\n ok: boolean;\n status: number;\n durationMs: number;\n}\n\n// One line per tool call, visible in Vercel's logs and on local stderr.\n// stdout belongs exclusively to the MCP JSON-RPC transport on stdio.\nexport function logToolCall(entry: ToolCallLog): void {\n console.error('tool_call', JSON.stringify(entry));\n}\n"],"mappings":"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","names":["SERVER_NAME","p","homedir","home","spinner","subcommand","import_child_process","import_server","value","resolve","baseUrl","fetch","resolve","import_node_crypto","DEFAULT_TIMEOUT_MS","DEFAULT_TIMEOUT_MS","baseUrl","path","import_node_crypto","import_node_crypto","runWizard"]}
|
|
1
|
+
{"version":3,"sources":["../src/_shared/hosts.ts","../src/install/clients.ts","../src/install/verify-key.ts","../src/install/args.ts","../src/install/wizard.ts","../src/stdio.ts","../src/server.ts","../src/specgen/server.ts","../src/_shared/rate-limit.ts","../src/specgen/clients/rest-result.ts","../src/specgen/dispatch.ts","../src/specgen/generated/tools.gen.ts","../src/specgen/pagination.ts","../src/specgen/clients/http-error.ts","../src/specgen/tools/util.ts","../src/specgen/tools/annotations.ts","../src/specgen/tools/capacity.ts","../src/specgen/tools/endpoint-gpus.ts","../src/specgen/tools/hub.ts","../src/specgen/tools/jobs.ts","../src/specgen/tools/list-endpoints.ts","../src/specgen/tools/list-templates.ts","../src/specgen/tools/logs.ts","../node_modules/.pnpm/@runpod+typescript-api-sdk@0.3.0/node_modules/@runpod/typescript-api-sdk/dist/index.js","../src/specgen/clients/sse.ts","../src/specgen/tools/public-endpoints.ts","../src/specgen/tools/knowledge.ts","../src/specgen/prose.ts","../src/specgen/on-demand.ts","../src/specgen/tools/describe.ts","../src/specgen/analytics.ts","../src/http.ts","../src/specgen/context.ts","../src/_shared/tracking.ts","../src/specgen/clients/graphql.ts","../src/specgen/clients/runtime.ts","../src/specgen/ops.ts","../src/search/knowledge.ts","../src/_shared/credential-check.ts","../src/alp/read.ts","../src/specgen/tools/alp.ts","../src/specgen/tools/search.ts"],"sourcesContent":["// Env-resolved API base URLs, extracted from the retired dual-version backend\n// resolver (backend.ts) when the spec-generated surface became the only one.\n// The credential preflight compares only active SDK and runtime destinations.\n\nexport type Env = Record<string, string | undefined>;\n\n// '' reads as unset everywhere: the wrong-environment guard already strips\n// empty vars before comparing, and every consumer (the credential checker's\n// probe URL, the GraphQL/log clients) must resolve identically or the\n// guard's \"checker and guard cannot disagree\" invariant breaks.\nfunction pick(value: string | undefined, fallback: string): string {\n return value?.trim().replace(/\\/+$/, '') || fallback;\n}\n\n// Generated paths include /v2, so the SDK base is the API origin.\nexport function sdkBase(env: Env): string {\n return pick(env.RUNPOD_API_BASE_URL, 'https://api.runpod.io');\n}\nexport function serverlessBase(env: Env): string {\n return pick(env.RUNPOD_SERVERLESS_API_URL, 'https://api.runpod.ai/v2');\n}\nexport function publicGraphqlBase(env: Env): string {\n return pick(env.RUNPOD_PUBLIC_GRAPHQL_URL, 'https://api.runpod.io/graphql');\n}\n// A separate var from publicGraphqlBase despite the identical default:\n// RUNPOD_PUBLIC_GRAPHQL_URL is the documented credential-free discovery\n// override and gets pointed at stubs freely, so routing authed calls through it\n// would turn \"point this anywhere\" into \"send the caller's API key there\".\nexport function authedGraphqlBase(env: Env): string {\n return pick(env.RUNPOD_AUTHED_GRAPHQL_URL, 'https://api.runpod.io/graphql');\n}\n/** The hosted MCP server: install target, and stdio's search-docs backend. */\nexport function hostedMcpBase(env: Env): string {\n return pick(env.RUNPOD_MCP_URL, 'https://mcp.getrunpod.io');\n}\n/** The runpod-assistant Convex site serving /v1/search. No default: unset\n * means search is not configured. */\nexport function knowledgeSearchBase(env: Env): string | undefined {\n return pick(env.KNOWLEDGE_SEARCH_URL, '') || undefined;\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { execSync, spawnSync } from 'child_process';\nimport * as jsonc from 'jsonc-parser';\nimport { hostedMcpBase } from '../_shared/hosts.js';\n\n// The npm package and the name the server is registered under in client config.\nexport const SERVER_NAME = 'runpod';\nexport const NPM_PACKAGE = '@runpod/mcp-server@latest';\n\n// The hosted Streamable HTTP endpoint. Clients point here and authenticate with\n// the OAuth \"Sign in with Runpod\" flow — no API key is stored in their config.\n// Overridable so a non-production deployment can be targeted during testing.\nexport const HOSTED_URL = `${hostedMcpBase(process.env)}/`;\n\n// How the user wants the server wired up:\n// - local: run via npx on this machine, authenticated by an API key in the env.\n// - hosted: connect to the hosted HTTP server and sign in with Runpod (OAuth).\nexport type AddMode =\n | { kind: 'local'; apiKey: string }\n | { kind: 'hosted'; url: string };\n\nexport interface AddResult {\n success: boolean;\n message?: string;\n}\n\nexport interface McpClient {\n // Stable id used as the multiselect value.\n id: string;\n // Human-readable label shown in the picker.\n name: string;\n // True when the client appears to be installed on this machine.\n detect(): Promise<boolean>;\n // Write (or update) the Runpod server entry in the client's config.\n add(mode: AddMode): Promise<AddResult>;\n // Remove the Runpod server entry from the client's config.\n remove(): Promise<AddResult>;\n // Where the config lives, for display and manual fallback.\n describeTarget(): string;\n // How this client parses its config, for clients that own a JSON file. Exposed so the\n // per-client wiring is assertable: reverting it to a single shared default left every\n // test green while Cursor was misclassified, because upsertJsonServer was only ever\n // exercised with an explicit dialect. Absent for Claude Code, which is driven by CLI.\n dialect?: ConfigDialect;\n}\n\n// The local stdio config: Runpod's MCP server runs via npx and reads the API\n// key from the environment. VS Code's `servers` map requires an explicit\n// transport type for stdio servers (mcpServers-style clients infer it).\nfunction localServerConfig(apiKey: string, serverProperty: string) {\n const config = {\n command: 'npx',\n args: ['-y', NPM_PACKAGE],\n env: { RUNPOD_API_KEY: apiKey },\n };\n return serverProperty === 'servers' ? { type: 'stdio', ...config } : config;\n}\n\n// The hosted config. Clients with native remote-MCP support take the URL\n// directly (VS Code additionally needs `type: 'http'`); the rest reach the\n// hosted server through the `mcp-remote` stdio bridge, which also drives OAuth.\nfunction hostedServerConfig(\n strategy: 'http' | 'mcp-remote',\n serverProperty: string,\n url: string\n) {\n if (strategy === 'mcp-remote') {\n return { command: 'npx', args: ['-y', 'mcp-remote', url] };\n }\n return serverProperty === 'servers' ? { type: 'http', url } : { url };\n}\n\n/**\n * How the client that owns a config parses it. This decides what \"valid\" means, so\n * every value here is a claim about a specific shipped parser and must be read out of\n * that client's own code — not inferred from \"it's an Electron app\".\n *\n * 'jsonc' comments and trailing commas are accepted.\n * 'json' strict `JSON.parse`; both are fatal.\n * 'unverified' tolerance not established. Validated leniently (so a config the\n * client may well load is never refused) and any reliance on that\n * leniency is disclosed to the user instead of being asserted away.\n *\n * Getting a value wrong breaks a user either way round: too strict refuses a healthy\n * config and leaves the client unconfigured, too lenient reports \"configured\" for a\n * file the client silently never loads. Verified against the shipped code:\n *\n * Cursor 'jsonc'. Not strict, despite being an Electron app — a VS Code fork,\n * and its reader keeps VS Code's tolerance. `parseMcpServersFromFile`\n * → `t$t(content)`, which is\n * `stripComments` → `JSON.parse`, and on failure\n * `.replace(/,\\s*([}\\]])/g,'$1')` → `JSON.parse` again.\n * So comments and trailing commas both survive.\n * (workbench.desktop.main.js; a BOM is still fatal, hence the strip\n * on write below.)\n * Claude Desktop 'json'. `wxr()` is `JSON.parse(Et.readFileSync(t,'utf8'))` with no\n * preprocessing and no retry (app.asar).\n * VS Code 'jsonc'. Reads mcp.json as JSONC by design.\n * Windsurf 'unverified' — not installed here, so its parser was never read.\n * It is a VS Code fork like Cursor, so it is probably lenient, but\n * \"probably\" is not a fact to put in a success message.\n * opencode 'jsonc'. Run, not inferred: opencode 1.19.0 `mcp list` loaded an\n * opencode.json holding a `//` comment and trailing commas and listed\n * its servers. Its docs also state JSON and JSONC are both accepted.\n * Pi 'json'. Run, not inferred: Pi 1.2.0 `mcp list` on an mcp.json with\n * one `//` comment reported \"Expected property name or '}' in JSON\"\n * and loaded nothing.\n */\nexport type ConfigDialect = 'json' | 'jsonc' | 'unverified';\n\nfunction describeDialect(dialect: ConfigDialect): string {\n return dialect === 'json' ? 'JSON' : 'JSONC';\n}\n\nfunction parseFailure(\n content: string,\n dialect: ConfigDialect\n): string | undefined {\n if (dialect === 'json') {\n try {\n JSON.parse(content);\n return undefined;\n } catch (error) {\n return errMessage(error);\n }\n }\n const errors: jsonc.ParseError[] = [];\n jsonc.parse(content, errors, { allowTrailingComma: true });\n return errors.length > 0\n ? `JSONC parse error at offset ${errors[0].offset}`\n : undefined;\n}\n\n// Parse the way the owning client parses, to answer \"what will the client actually\n// see?\" rather than \"is this file well-formed?\". The two differ: duplicate keys are\n// legal JSON, and every parser here keeps the LAST occurrence while `jsonc.modify`\n// edits the FIRST.\nfunction parseAsClient(content: string, dialect: ConfigDialect): unknown {\n // Lenient for 'unverified' as well as 'jsonc'. Using the strict parser here made a\n // commented config look as though the entry were absent, so the duplicate-key guard\n // below refused a perfectly good write — the same false-refusal defect as the Cursor\n // misclassification, introduced by the fix for it. This question is only \"which\n // duplicate block wins\", which is independent of comment tolerance.\n if (dialect !== 'json') {\n return jsonc.parse(content, [], { allowTrailingComma: true });\n }\n try {\n return JSON.parse(content);\n } catch {\n return undefined;\n }\n}\n\n// What the client will read at `[serverProperty][SERVER_NAME]` — undefined when absent.\nfunction readBackEntry(\n content: string,\n serverProperty: string,\n dialect: ConfigDialect\n): unknown {\n const parsed = parseAsClient(content, dialect);\n if (typeof parsed !== 'object' || parsed === null) return undefined;\n const servers = (parsed as Record<string, unknown>)[serverProperty];\n if (typeof servers !== 'object' || servers === null) return undefined;\n return (servers as Record<string, unknown>)[SERVER_NAME];\n}\n\n// A file that only parses because the reader is lenient. Used to disclose the risk for\n// 'unverified' clients rather than silently betting on it.\nfunction reliesOnLeniency(content: string): boolean {\n if (content.trim() === '') return false;\n try {\n JSON.parse(content);\n return false;\n } catch {\n return parseFailure(content, 'jsonc') === undefined;\n }\n}\n\n// Read, edit, and write a JSON config while preserving the user's existing\n// formatting and comments (jsonc). Creates the file and parent dirs if missing.\n// Exported for tests: the client wrappers hardcode real config paths under $HOME, and\n// a test must never write there.\nexport function upsertJsonServer(\n configPath: string,\n serverProperty: string,\n value: unknown,\n // Required, with no default: the default used to be the lenient value, so a caller\n // that forgot it silently got the very behaviour this parameter exists to prevent.\n dialect: ConfigDialect\n): AddResult {\n // Refuse a relative target outright rather than trusting every caller to have\n // resolved one. This function creates directories and writes a plaintext API key, so\n // a relative path means creating a folder and leaking a credential into whatever\n // directory the wizard happened to be launched from. Guarding here closes the class\n // for every client at once, however the path was computed.\n if (!path.isAbsolute(configPath)) {\n return {\n success: false,\n message: `refusing to write \"${configPath}\": not an absolute path, so it would resolve against the current directory. This usually means an environment variable (APPDATA, XDG_CONFIG_HOME) is set to an empty or relative value.`,\n };\n }\n try {\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n const content = fs.existsSync(configPath)\n ? fs.readFileSync(configPath, 'utf8')\n : '';\n const edits = jsonc.modify(content, [serverProperty, SERVER_NAME], value, {\n formattingOptions: { tabSize: 2, insertSpaces: true },\n });\n // Strip a leading BOM from what gets WRITTEN, not just from the validity check.\n // `JSON.parse` throws `Unexpected token '\\uFEFF'` on one, and Cursor / Windsurf /\n // Claude Desktop are Node/Electron apps doing exactly that — so keeping the BOM\n // would report success for a config the client silently never loads, which is the\n // one thing this guard exists to prevent. Only VS Code (jsonc) tolerates it.\n const updated = jsonc.applyEdits(content, edits).replace(/^\\uFEFF/, '');\n // jsonc edits a malformed file on a best-effort basis: it will happily insert the\n // entry into a config with an unbalanced brace and hand back something still\n // unparseable, which the client then silently never loads. Refuse instead of\n // reporting success over a file we just confirmed is broken.\n // Checked with the parser the OWNING CLIENT uses, not a lenient one. PowerShell's\n // Set-Content and Notepad write BOMs by default on the platform this targets, so the\n // BOM is stripped above rather than refused; double or trailing BOMs still fail here.\n const failure = parseFailure(updated, dialect);\n if (failure) {\n // Distinguish \"we would break it\" from \"it was already broken\", because the second\n // is the user's pre-existing problem and the advice differs.\n const wasAlreadyBroken =\n content.trim() !== '' && parseFailure(content, dialect) !== undefined;\n return {\n success: false,\n message: wasAlreadyBroken\n ? `${configPath} could not be parsed as ${describeDialect(dialect)} before this change either (${failure}), so it was left untouched — this client would not load the entry. Fix the file (or move it aside) and re-run.`\n : `writing to ${configPath} would leave it unparseable (${failure}), so it was left untouched.`,\n };\n }\n // Valid is not the same as effective. `jsonc.modify` edits the FIRST occurrence of a\n // duplicated key; every parser here keeps the LAST. Duplicate keys are legal JSON, so\n // the validity check above passes and the entry lands in a block nothing reads —\n // reporting success while writing a plaintext API key that never takes effect. Ask\n // the client's own parser what it will see instead of trusting that an edit applied.\n const landed = readBackEntry(updated, serverProperty, dialect);\n if (JSON.stringify(landed) !== JSON.stringify(value)) {\n return {\n success: false,\n message: `${configPath} was left untouched: the entry would have been written where this client does not read it, so it would have had no effect. This usually means \"${serverProperty}\" appears more than once in the file — the last one wins, so merge them into a single block and re-run.`,\n };\n }\n // mode is honoured only when the file is created; an existing config keeps its\n // own. 0600 because this file holds a plaintext API key, and a freshly created\n // Claude Code config is 0600 — a config this wizard creates should not be looser.\n // No effect on Windows, which has no POSIX mode bits (only the read-only flag is\n // real); there the ACL on the user profile directory is what governs access.\n fs.writeFileSync(configPath, updated, { encoding: 'utf8', mode: 0o600 });\n // The entry is written and this client's parser accepts the file. When that\n // acceptance rests on leniency we have not actually verified, say so rather than\n // print an unqualified tick: refusing would leave a probably-fine client\n // unconfigured, and claiming success would be asserting the thing we do not know.\n if (dialect === 'unverified' && reliesOnLeniency(updated)) {\n return {\n success: true,\n message:\n 'written, but this config uses comments or trailing commas and whether this client accepts them is unverified — if the Runpod server does not appear, remove them',\n };\n }\n return { success: true };\n } catch (error) {\n return { success: false, message: errMessage(error) };\n }\n}\n\n// Exported for the same reason as upsertJsonServer: the client wrappers hardcode real\n// config paths under $HOME. Untested while unexported, which is how the relative-path\n// guard here — and the trailing-comma corruption below — went unnoticed.\nexport function removeJsonServer(\n configPath: string,\n serverProperty: string,\n dialect: ConfigDialect\n): AddResult {\n if (!path.isAbsolute(configPath)) {\n return {\n success: false,\n message: `refusing to touch \"${configPath}\": not an absolute path. Check APPDATA / XDG_CONFIG_HOME.`,\n };\n }\n try {\n if (!fs.existsSync(configPath)) {\n return { success: true, message: 'nothing to remove' };\n }\n const content = fs.readFileSync(configPath, 'utf8');\n if (content.trim() === '') {\n return { success: true, message: 'nothing to remove' };\n }\n const existingFailure = parseFailure(content, dialect);\n if (existingFailure !== undefined) {\n return {\n success: false,\n message: `could not safely remove the Runpod entry from ${configPath}: the existing config is not valid ${describeDialect(dialect)} (${existingFailure}). The original file was left unchanged; repair it or delete the entry by hand.`,\n };\n }\n let edits;\n try {\n edits = jsonc.modify(content, [serverProperty, SERVER_NAME], undefined, {\n formattingOptions: { tabSize: 2, insertSpaces: true },\n });\n } catch (error) {\n // jsonc throws `Can not delete in empty document` whenever the FIRST path segment\n // is absent — `{}`, an empty file, whitespace, an array root, and also a\n // populated object with no `mcpServers` key. Its message is a misnomer; in every\n // such case there is genuinely no runpod entry to remove. Reporting those as failures is the same class of bug as\n // reporting a failure as a success, just pointed the other way: the user is told\n // cleanup broke when the desired end state already held.\n if (/empty document/i.test(errMessage(error))) {\n return { success: true, message: 'nothing to remove' };\n }\n throw error;\n }\n // Zero edits normally means the entry is absent. It can also mean `jsonc.modify`\n // targeted a duplicate `serverProperty` block that does not contain it while the\n // block the client actually reads does — reporting \"nothing to remove\" over a\n // plaintext key still on disk. Confirm absence with the client's parser.\n if (edits.length === 0) {\n return readBackEntry(content, serverProperty, dialect) === undefined\n ? { success: true, message: 'nothing to remove' }\n : {\n success: false,\n message: `the Runpod entry is still present in ${configPath} and could not be removed automatically — \"${serverProperty}\" appears more than once, so the edit targeted a block this client does not read. Delete the entry by hand.`,\n };\n }\n const updated = jsonc.applyEdits(content, edits);\n // A surgical delete can leave a hole the parser rejects: removing the sole member of\n // `servers` that is followed by a trailing comma yields `{ , }`. Verified turning a\n // clean VS Code mcp.json into one with a parse error while reporting success. Both\n // VS Code and Cursor happen to recover from that shape, but a strict client would\n // stop loading every other server in the file, so it cannot be left behind.\n //\n // Do not fall back to a structural rewrite. JSON.stringify would make the file\n // parseable, but it would also erase comments and formatting from unrelated user\n // configuration without asking. The edit has not been written yet, so failing\n // closed leaves the original recoverable and gives the user a manual path.\n const brokeIt = parseFailure(updated, dialect) !== undefined;\n const stillThere =\n readBackEntry(updated, serverProperty, dialect) !== undefined;\n if (brokeIt || stillThere) {\n return {\n success: false,\n message: `could not remove the Runpod entry from ${configPath} without ${brokeIt ? 'making the config unparseable' : 'leaving the entry present'}. The original file was left unchanged so its comments and formatting are preserved; delete the Runpod entry by hand.`,\n };\n }\n fs.writeFileSync(configPath, updated, 'utf8');\n return { success: true };\n } catch (error) {\n return { success: false, message: errMessage(error) };\n }\n}\n\nfunction errMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction exists(p: string): boolean {\n try {\n return fs.existsSync(p);\n } catch {\n return false;\n }\n}\n\n// A JSON-config client that differs only in config path, server property, and\n// how it reaches the hosted server.\nfunction jsonClient(opts: {\n id: string;\n name: string;\n serverProperty?: string;\n // How the owning client parses its config — see ConfigDialect for the evidence\n // behind each value. Deliberately required and un-defaulted: Cursor was misread as\n // strict purely by inheriting a default here, which refused configs Cursor loads fine\n // and left it unconfigured. A wrong value breaks users in one direction or the other,\n // so every client has to state its own.\n dialect: ConfigDialect;\n // Native HTTP support, or the `mcp-remote` bridge for stdio-only clients.\n hostedStrategy?: 'http' | 'mcp-remote';\n configPath: () => string;\n detectPaths?: () => string[];\n // The entry to write, for a client whose server schema is not the common\n // `command`/`args`/`env` or `url` shape (opencode).\n serverValue?: (mode: AddMode) => unknown;\n}): McpClient {\n const serverProperty = opts.serverProperty ?? 'mcpServers';\n const hostedStrategy = opts.hostedStrategy ?? 'http';\n return {\n id: opts.id,\n name: opts.name,\n detect: () =>\n Promise.resolve(\n (opts.detectPaths?.() ?? [path.dirname(opts.configPath())]).some(exists)\n ),\n add: (mode) => {\n const value = opts.serverValue\n ? opts.serverValue(mode)\n : mode.kind === 'local'\n ? localServerConfig(mode.apiKey, serverProperty)\n : hostedServerConfig(hostedStrategy, serverProperty, mode.url);\n return Promise.resolve(\n upsertJsonServer(opts.configPath(), serverProperty, value, opts.dialect)\n );\n },\n dialect: opts.dialect,\n remove: () =>\n Promise.resolve(\n removeJsonServer(opts.configPath(), serverProperty, opts.dialect)\n ),\n describeTarget: () => opts.configPath(),\n };\n}\n\n// A direct install location to probe, paired with the root its canonical target must\n// stay inside. Pairing them here — rather than re-deriving the root from the\n// candidate's position in a list, as an earlier revision did — means inserting or\n// reordering a candidate cannot silently confine it to the wrong root.\nexport interface ClaudeCandidate {\n path: string;\n trustedRoot: string;\n}\n\n/**\n * Install locations to probe before the POSIX-only PATH lookup. Windows uses win32\n * path semantics regardless of the host so the branch is testable anywhere.\n *\n * `.local\\bin\\claude.exe` is the documented native-installer location and comes\n * first deliberately: it is a real executable and launches with no shell at all.\n * It also covers installs where the native installer failed to add\n * itself to PATH, which the lookup below could never find.\n */\nexport function claudeCandidates(\n platform: string,\n homedir: string,\n appdata?: string\n): ClaudeCandidate[] {\n if (platform === 'win32') {\n const win = path.win32;\n // Automatic credential-bearing execution is limited to the standard per-user\n // roaming root, whatever APPDATA says: an arbitrary redirected APPDATA has no\n // trustworthy provenance merely because it is absolute.\n const defaultAppdata = win.join(homedir, 'AppData', 'Roaming');\n return [\n {\n path: win.join(homedir, '.local', 'bin', 'claude.exe'),\n trustedRoot: homedir,\n },\n // npm -g installs a .cmd shim. runClaude bypasses it and resolves the real\n // native or JavaScript target from the installed package manifest.\n //\n // absoluteEnvDir, not `?? `: an empty or relative APPDATA yielded the relative\n // `npm\\claude.cmd`. Candidates are probed before any lookup, so a relative\n // candidate would resolve against the current directory and receive the live\n // API key.\n {\n path: win.join(\n absoluteEnvDir(appdata, () => defaultAppdata),\n 'npm',\n 'claude.cmd'\n ),\n trustedRoot: defaultAppdata,\n },\n ];\n }\n return [\n // Where the current native installer puts it (verified on a real install:\n // ~/.local/bin/claude -> versions/2.1.220). Same reasoning as the Windows\n // .local\\bin\\claude.exe entry — it also covers an install whose PATH entry is\n // missing, which the lookup can never find. Without it, POSIX detection depended\n // entirely on PATH.\n {\n path: path.posix.join(homedir, '.local', 'bin', 'claude'),\n trustedRoot: homedir,\n },\n {\n path: path.posix.join(homedir, '.claude', 'local', 'claude'),\n trustedRoot: homedir,\n },\n { path: '/usr/local/bin/claude', trustedRoot: '/usr/local' },\n { path: '/opt/homebrew/bin/claude', trustedRoot: '/opt/homebrew' },\n ];\n}\n\n// The probe locations alone. Kept as the stable test surface for \"which paths does\n// each platform look at\".\nexport function claudeCandidatePaths(\n platform: string,\n homedir: string,\n appdata?: string\n): string[] {\n return claudeCandidates(platform, homedir, appdata).map((c) => c.path);\n}\n\nfunction pathIsInside(\n candidate: string,\n directory: string,\n pathApi: typeof path.posix | typeof path.win32\n): boolean {\n const relative = pathApi.relative(\n pathApi.resolve(directory),\n pathApi.resolve(candidate)\n );\n return (\n relative === '' ||\n (!relative.startsWith(`..${pathApi.sep}`) &&\n relative !== '..' &&\n !pathApi.isAbsolute(relative))\n );\n}\n\nfunction isNodeModulesBin(candidate: string): boolean {\n return /(^|[\\\\/])node_modules[\\\\/]\\.bin([\\\\/]|$)/i.test(candidate);\n}\n\n/**\n * Picks a trustworthy absolute result from POSIX `command -v` output.\n *\n * Windows never calls this helper: its two standard install locations are probed\n * directly, avoiding both a shadowable lookup executable and project-local PATH\n * entries. POSIX still needs a fallback for package-manager/custom installs, but\n * relative paths, cwd descendants, and node_modules/.bin shims are rejected before\n * the canonical project-boundary check in findClaudeBinary.\n */\nexport function pickClaudeBinary(\n stdout: string,\n platform: string,\n cwd?: string\n): string | null {\n if (platform === 'win32') return null;\n\n const hits = stdout\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n return (\n hits.find(\n (hit) =>\n path.posix.isAbsolute(hit) &&\n !isNodeModulesBin(hit) &&\n (cwd === undefined || !pathIsInside(hit, cwd, path.posix))\n ) ?? null\n );\n}\n\nconst PROJECT_BOUNDARY_MARKERS = [\n '.git',\n 'package.json',\n 'pnpm-workspace.yaml',\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'bun.lock',\n 'bun.lockb',\n] as const;\n\n/**\n * The outermost source/workspace boundary containing cwd, never $HOME itself.\n *\n * `.git` alone is insufficient: release archives and copied workspaces routinely\n * omit VCS metadata. A nested package can have its own package.json, so keep\n * walking and retain the outermost ancestor carrying a project marker.\n *\n * The walk stops at `home` (canonical) without counting it. $HOME routinely carries\n * project markers that make it no repository at all — a stray `package.json` from an\n * accidental `npm install`, a dotfiles `.git` — and treating it as a boundary rejects\n * every candidate underneath it, including `~/.local/bin/claude` itself: the wizard\n * then reports Claude Code not found on exactly the standard installs it probes for.\n * A repository can only plant files inside its own tree, so a boundary above the\n * outermost marked directory *below* home defends nothing. Deliberately still the\n * OUTERMOST marked ancestor below home, not the nearest: in a monorepo whose package\n * dirs carry their own package.json, \"nearest\" would trust a tool planted at the repo\n * root.\n */\nfunction projectBoundary(cwd: string, home?: string): string | null {\n let current = cwd;\n let boundary: string | null = null;\n while (true) {\n if (current === home) return boundary;\n if (\n PROJECT_BOUNDARY_MARKERS.some((marker) =>\n exists(path.join(current, marker))\n )\n ) {\n boundary = current;\n }\n const parent = path.dirname(current);\n if (parent === current) return boundary;\n current = parent;\n }\n}\n\n/**\n * Canonical trust check for every Claude executable candidate.\n *\n * Direct user-level candidates are not automatically trusted: the path can be a\n * symlink/junction into the repository, and APPDATA/HOME can be redirected. PATH\n * results are rejected when they resolve inside an identifiable source/workspace\n * boundary. An unmarked cwd cannot be treated as a project root: doing so rejects\n * ordinary nvm/asdf/Volta installs when the wizard is launched from $HOME. Nor can a\n * MARKED $HOME — see projectBoundary, which never counts home itself.\n */\nfunction trustedClaudeBinary(\n binary: string,\n cwd: string,\n home?: string,\n requiredRoot?: string\n): string | null {\n try {\n const canonicalBinary = fs.realpathSync.native(binary);\n const canonicalCwd = fs.realpathSync.native(cwd);\n // Canonical, because the walk compares it against ancestors of a canonical cwd. A\n // home that cannot be canonicalized falls back to no cap — the stricter direction.\n let canonicalHome: string | undefined;\n if (home !== undefined) {\n try {\n canonicalHome = fs.realpathSync.native(home);\n } catch {\n canonicalHome = undefined;\n }\n }\n const projectRoot = projectBoundary(canonicalCwd, canonicalHome);\n const canonicalRequiredRoot =\n requiredRoot === undefined\n ? undefined\n : fs.realpathSync.native(requiredRoot);\n if (\n isNodeModulesBin(canonicalBinary) ||\n (canonicalRequiredRoot !== undefined &&\n !pathIsInside(canonicalBinary, canonicalRequiredRoot, path)) ||\n (projectRoot !== null && pathIsInside(canonicalBinary, projectRoot, path))\n ) {\n return null;\n }\n return canonicalBinary;\n } catch {\n // A lookup result that cannot be canonicalized is not safe to execute with a\n // credential, even if command -v reported it successfully.\n return null;\n }\n}\n\n// cmd.exe metacharacters used only when rendering a manual command for display.\nconst CMD_META = /[()\\][%!^\"`<>&|;, *?\\t\\n\\v\\r]/;\n\nexport interface FindClaudeBinaryOptions {\n platform?: string;\n // `null` means \"known unavailable\" — what a failed os.userInfo() lookup produces.\n // Distinct from `undefined` (= resolve it here), so a test can drive the\n // no-home-directory path without mocking os.userInfo across module boundaries.\n homedir?: string | null;\n appdata?: string;\n cwd?: string;\n}\n\n// Locate the Claude Code CLI binary across common install locations and PATH.\n// Claude Code is the only client here detected by locating its executable rather\n// than by an existing config file. `command -v` remains the POSIX fallback.\n// Windows intentionally has no executable-lookup fallback: both the implicit\n// current-directory search and npm/npx's project-local PATH entries can resolve a\n// repository-supplied executable, and even a bare `where.exe` can itself be\n// shadowed. The documented native and global-npm locations cover the standard\n// Windows installs without executing anything discovered from the project.\n// Exported for tests: the platform decisions are pure, so both branches can be\n// exercised on any host without spawning anything or faking process.platform.\nexport function findClaudeBinary(\n options: FindClaudeBinaryOptions = {}\n): string | null {\n const platform = options.platform ?? process.platform;\n let homedir = options.homedir;\n if (homedir === undefined) {\n try {\n // os.homedir() honors HOME/USERPROFILE environment overrides. userInfo()\n // asks the OS for the account profile instead, so a launching project cannot\n // redirect an automatic credential-bearing candidate through those variables.\n homedir = os.userInfo().homedir;\n } catch {\n // No passwd entry for the process UID (arbitrary-UID containers, some CI\n // sandboxes). NOT os.homedir(): its answer is exactly the env-redirectable one\n // userInfo() exists to avoid. Home-anchored candidates are skipped, but the\n // POSIX PATH lookup below needs no homedir — returning here regressed those\n // environments from working (on main, via `command -v`) to undetectable.\n homedir = null;\n }\n }\n const appdata = options.appdata ?? process.env.APPDATA;\n const cwd = options.cwd ?? process.cwd();\n\n const candidates =\n homedir == null ? [] : claudeCandidates(platform, homedir, appdata);\n for (const candidate of candidates) {\n // Absolute only. `exists()` resolves a relative candidate against the CURRENT\n // DIRECTORY, and candidates are probed before the POSIX PATH lookup — so a\n // relative one would win outright and receive the live API key.\n if (\n !path.isAbsolute(candidate.path) &&\n !path.win32.isAbsolute(candidate.path)\n )\n continue;\n if (exists(candidate.path)) {\n // `?? undefined` only for the type: candidates is empty when homedir is null.\n const trusted = trustedClaudeBinary(\n candidate.path,\n cwd,\n homedir ?? undefined,\n candidate.trustedRoot\n );\n if (trusted !== null) return trusted;\n }\n }\n\n try {\n // Do not fall back to PATH on Windows. A repository can influence PATH and the\n // current-directory executable search, including shadowing the lookup program\n // itself. The standard native and global-npm locations above cover issue #56.\n if (platform === 'win32') return null;\n\n const out = execSync('command -v claude', {\n stdio: ['ignore', 'pipe', 'ignore'],\n encoding: 'utf8',\n });\n // `pickClaudeBinary` still rejects relative and node_modules/.bin results. Do\n // not pass cwd here: an unmarked cwd might be $HOME, with a legitimate\n // nvm/asdf/Volta executable beneath it. The canonical check below rejects a\n // result inside cwd whenever cwd is actually part of a marked project.\n const binary = pickClaudeBinary(out, platform);\n return binary === null\n ? null\n : trustedClaudeBinary(binary, cwd, homedir ?? undefined);\n } catch {\n return null;\n }\n}\n\n/**\n * Renders a command for a human to copy, quoting only what needs it. Display only:\n * this string is never executed. Plain double-quote wrapping, NOT JSON.stringify —\n * the latter escapes the backslashes in a Windows path, which is exactly wrong for\n * something the user will paste.\n */\nexport function describeCommand(binary: string, args: string[]): string {\n // Quote on cmd.exe metacharacters, not just whitespace. This function renders the\n // command printed when the wizard REFUSES to spawn something because an argument\n // holds a metacharacter — so quoting on whitespace alone handed the user a command\n // broken by the very character that triggered the refusal: with a URL override, a\n // bare `?a=1&b=2` makes cmd.exe split `&b=2` into a second command.\n const quote = (s: string) =>\n /\\s/.test(s) || CMD_META.test(s) ? `\"${s}\"` : s;\n return [binary, ...args].map(quote).join(' ');\n}\n\n// Placeholder substituted for the key when a command is printed for the user.\n// No cmd.exe metacharacters: this string is printed for a user to paste into\n// cmd.exe, and `<`/`>` would be parsed as redirection — turning the wizard's own\n// remediation command into an error.\nexport const KEY_PLACEHOLDER = 'YOUR_RUNPOD_API_KEY';\n\n/**\n * Same as describeCommand, with the API key replaced by a placeholder. Anything\n * printed to the terminal ends up in scrollback, and in a support thread or CI log\n * the moment someone pastes wizard output — so a command shown to a user names the\n * variable but not its value. The user knows their own key.\n */\nexport function describeCommandRedacted(\n binary: string,\n args: string[]\n): string {\n return describeCommand(\n binary,\n args.map((arg) =>\n arg.startsWith('RUNPOD_API_KEY=')\n ? `RUNPOD_API_KEY=${KEY_PLACEHOLDER}`\n : arg\n )\n );\n}\n\n/**\n * Runs the Claude Code CLI.\n *\n * A Windows npm-global `claude.cmd` is never executed. Its package manifest names\n * the real entrypoint. Current releases point at a native `bin/claude.exe`; older\n * releases may point at a JavaScript entrypoint. The target is canonicalized inside\n * the installed package, then spawned directly (native) or through this\n * already-running Node process (JavaScript). This avoids cmd.exe, COMSPEC, PATH\n * lookup, `%*` re-parsing, and command-line escaping entirely.\n */\n// `refused` marks \"we declined to run this\", as opposed to \"we ran it and it\n// failed\" — `remove` treats those differently.\nexport interface RunResult extends AddResult {\n refused?: boolean;\n // Raw combined stdout+stderr, for callers that must inspect what the CLI said.\n // INTERNAL ONLY — never surface this to a user: `claude mcp get` prints\n // `Environment: RUNPOD_API_KEY=<plaintext>`.\n output?: string;\n}\n\n/**\n * Strips a secret from text that is about to be shown to a user.\n *\n * The redaction above works on argv shape (`RUNPOD_API_KEY=<value>`); this works on\n * the value, which is what actually matters. Needed because `runClaude` surfaces the\n * CLI's own stdout/stderr, and that CLI does echo `-e` tokens back on some errors\n * (observed: `Invalid environment variable format: RUNPOD_API_KEY_rpa_…`). A\n * shape-based guard cannot cover output produced by another program.\n */\nexport function redactSecret(text: string, secret?: string): string {\n if (!secret) return text;\n return text.split(secret).join(KEY_PLACEHOLDER);\n}\n\nfunction sanitizedClaudeEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env };\n for (const key of Object.keys(env)) {\n if (\n ['path', 'comspec', 'pathext', 'node_options', 'node_path'].includes(\n key.toLowerCase()\n )\n ) {\n delete env[key];\n }\n }\n if (process.platform === 'win32') {\n env.Path = path.dirname(process.execPath);\n } else {\n env.PATH = [\n path.dirname(process.execPath),\n '/usr/local/bin',\n '/opt/homebrew/bin',\n '/usr/bin',\n '/bin',\n ].join(path.delimiter);\n }\n return env;\n}\n\ninterface WindowsNpmClaudeTarget {\n command: string;\n argsPrefix: string[];\n}\n\nfunction windowsNpmClaudeTarget(binary: string): WindowsNpmClaudeTarget | null {\n if (process.platform !== 'win32' || !binary.toLowerCase().endsWith('.cmd')) {\n return null;\n }\n try {\n const npmRoot = fs.realpathSync.native(path.dirname(binary));\n const packageRoot = fs.realpathSync.native(\n path.join(npmRoot, 'node_modules', '@anthropic-ai', 'claude-code')\n );\n if (!pathIsInside(packageRoot, npmRoot, path)) return null;\n\n const manifestPath = fs.realpathSync.native(\n path.join(packageRoot, 'package.json')\n );\n if (!pathIsInside(manifestPath, packageRoot, path)) return null;\n const manifest = JSON.parse(\n fs.readFileSync(manifestPath, 'utf8')\n ) as unknown;\n if (manifest === null || typeof manifest !== 'object') return null;\n const bin = (manifest as { bin?: unknown }).bin;\n const target =\n typeof bin === 'string'\n ? bin\n : bin !== null && typeof bin === 'object'\n ? (bin as Record<string, unknown>).claude\n : undefined;\n if (typeof target !== 'string' || target.trim() === '') return null;\n\n const entrypoint = fs.realpathSync.native(\n path.resolve(packageRoot, target)\n );\n if (!pathIsInside(entrypoint, packageRoot, path)) return null;\n if (/\\.(?:exe|com)$/i.test(entrypoint)) {\n return { command: entrypoint, argsPrefix: [] };\n }\n if (/\\.(?:c?js|mjs)$/i.test(entrypoint)) {\n return { command: process.execPath, argsPrefix: [entrypoint] };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function runClaude(\n binary: string,\n args: string[],\n secret?: string\n): RunResult {\n const isWindowsCmd =\n process.platform === 'win32' && binary.toLowerCase().endsWith('.cmd');\n const npmTarget = windowsNpmClaudeTarget(binary);\n if (isWindowsCmd && npmTarget === null) {\n return {\n success: false,\n refused: true,\n message: `could not locate a trusted Claude Code npm entrypoint beside ${binary}. Run the shim yourself, substituting your key:\\n ${describeCommandRedacted(binary, args)}`,\n };\n }\n const command = npmTarget?.command ?? binary;\n const commandArgs = [...(npmTarget?.argsPrefix ?? []), ...args];\n const result = spawnSync(command, commandArgs, {\n stdio: 'pipe',\n encoding: 'utf8',\n env: sanitizedClaudeEnv(),\n });\n if (result.error)\n return {\n success: false,\n message: redactSecret(errMessage(result.error), secret),\n };\n const stdio = `${result.stdout ?? ''}${result.stderr ?? ''}`;\n if (result.status === 0) return { success: true, output: stdio };\n if (result.status === null) {\n return { success: false, message: `killed by ${result.signal}` };\n }\n // The CLI reports \"already exists\" on stderr with a non-zero exit. Re-running the\n // wizard should be idempotent, not an error — but it is NOT an update: the CLI\n // leaves the existing entry alone, so a user re-running the wizard after rotating\n // their API key still has the old key. Say so rather than reporting a bare\n // success. Observed with claude 2.1.220 at the scope this wizard actually writes:\n // `MCP server runpod already exists in user config`, exit 1, stored key unchanged.\n // The remediation command carries the full binary path, because the first candidate\n // path exists precisely to cover installs that are not on PATH.\n if (stdio.includes('already exists')) {\n return {\n success: true,\n // Deliberately not \"to replace the API key\": this branch is also reached in\n // hosted mode, where there is no key — and the pre-existing entry may be of the\n // other kind entirely, which is exactly what the user needs to know.\n message: `already configured, existing entry left unchanged — it was NOT updated to what you just chose (to replace it, run \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'user'])}\\` first, then re-run this wizard)`,\n };\n }\n return {\n success: false,\n message: redactSecret(\n stdio.trim() ||\n `${path.basename(binary)} exited with code ${result.status}`,\n secret\n ),\n };\n}\n\n// What Claude Code's own config says about the runpod entry. Read from the file\n// rather than inferred from `claude mcp get`, because that command answers \"what\n// would Claude Code use from here\" — it reports only the WINNING scope, and local\n// shadows user. Verified with claude 2.1.220: with a user-scope AND a local-scope\n// entry both on disk, `mcp get` prints only `Scope: Local config`. So one scope\n// string cannot distinguish \"user entry present, shadowed by a local one\" from \"user\n// entry absent, local one present\" — and those need opposite verdicts. Two revisions\n// of this file got that wrong in both directions.\n//\n// `--scope user` writes exactly one place: the top-level `mcpServers` of\n// `.claude.json`. Reading it is exact, needs no spawn, and cannot be shadowed.\n//\n// VERSION COUPLING: that storage location is a claim about claude 2.1.x. If a future\n// Claude Code moves user-scope entries elsewhere, this reader will report \"absent\"\n// after every successful add — turning each one into a false \"Nothing was configured\"\n// failure in interpretAddResult. If that starts happening on a new CLI version, check\n// where `--scope user` writes before suspecting the wizard.\nexport interface ClaudeConfigState {\n // The file this state was read from. Carried so a message names the file actually\n // consulted — the reader is injectable, so `claudeUserConfigPath()` is not\n // necessarily it.\n configPath: string;\n // Is there a runpod entry in USER scope — the only scope this wizard writes?\n // undefined when the file cannot be read or parsed, i.e. \"unknown\", never a guess.\n userScope: boolean | undefined;\n // Directories whose local-scope config (projects[dir].mcpServers) also carries one.\n // This wizard never touches those, so a removal names them rather than implying the\n // key is gone. NOTE: project scope (`<dir>/.mcp.json`) is a separate file per\n // directory and is NOT covered here — a checked-in team entry can still shadow the\n // one this writes. Every message therefore scopes its claim to the user config.\n localScopeDirs: string[];\n}\n\n/**\n * An environment-provided directory, or the fallback when it is unusable.\n *\n * Unusable means unset, empty, or relative. The XDG spec says exactly this for its own\n * variables (\"must be treated as unset\", \"relative paths should be considered invalid\n * and ignored\"), and the same reasoning applies to APPDATA: a relative directory resolves\n * against the process's cwd, and every path built from these either stores a plaintext\n * API key or gets executed.\n *\n * NOT for CLAUDE_CONFIG_DIR — see claudeUserConfigPath. That names a file the Claude Code\n * CLI owns and resolves relatively itself, so ignoring a relative value there would point\n * this code at a file the CLI never touched.\n */\nexport function absoluteEnvDir(\n value: string | undefined,\n fallback: () => string\n): string {\n if (!value || !value.trim()) return fallback();\n // Check with both flavours: a Windows path is not absolute under path.posix and vice\n // versa, and this module deliberately computes win32 paths on any host for testing.\n if (!path.isAbsolute(value) && !path.win32.isAbsolute(value))\n return fallback();\n return value;\n}\n\nexport function claudeUserConfigPath(): string {\n const configured = process.env.CLAUDE_CONFIG_DIR;\n // Deliberately NOT absoluteEnvDir, unlike XDG_CONFIG_HOME and APPDATA. Those name\n // paths this wizard invents, where a relative value can only mean writing a credential\n // into the current directory — so refusing it is right. This one names a file another\n // program owns, and that program resolves a relative value against its own cwd:\n // verified with claude 2.1.220, `CLAUDE_CONFIG_DIR=relcfg claude mcp add … --scope\n // user` prints `File modified: relcfg/.claude.json` and creates ./relcfg. Treating it\n // as unset would point this at $HOME/.claude.json — a file the CLI never touched — and\n // then report a DEFINITE verdict about it, which is precisely how a false success gets\n // built. So resolve it the way the CLI does. Only a truly empty value is unset, which\n // the CLI also falls back to $HOME for (verified).\n return path.join(\n configured ? path.resolve(configured) : os.homedir(),\n '.claude.json'\n );\n}\n\nexport function readClaudeConfigState(configPath: string): ClaudeConfigState {\n const unknown: ClaudeConfigState = {\n configPath,\n userScope: undefined,\n localScopeDirs: [],\n };\n // Belt and braces on top of claudeUserConfigPath's own resolution: a relative path\n // is never the file the CLI would use, so answering \"absent\" from it would be a\n // guess. Say unknown.\n if (!path.isAbsolute(configPath)) return unknown;\n\n let raw: string;\n try {\n if (!fs.existsSync(configPath)) {\n // No config at all is a definite \"no user-scope entry\", not an unknown.\n return { configPath, userScope: false, localScopeDirs: [] };\n }\n raw = fs.readFileSync(configPath, 'utf8');\n } catch {\n // Unreadable (permissions) — say unknown rather than \"absent\", which would let a\n // caller announce that a key is gone when it cannot see the file at all.\n return unknown;\n }\n const errors: jsonc.ParseError[] = [];\n const parsed = jsonc.parse(raw.replace(/^\\uFEFF/, ''), errors, {\n allowTrailingComma: true,\n }) as\n | {\n mcpServers?: Record<string, unknown>;\n projects?: Record<string, { mcpServers?: Record<string, unknown> }>;\n }\n | undefined;\n // An array or a scalar at the root is not a config this code understands; saying\n // \"no user entry\" about it would be a guess dressed as a fact.\n if (\n errors.length > 0 ||\n typeof parsed !== 'object' ||\n parsed === null ||\n Array.isArray(parsed)\n ) {\n return unknown;\n }\n\n const has = (servers: unknown): boolean =>\n typeof servers === 'object' &&\n servers !== null &&\n Object.prototype.hasOwnProperty.call(servers, SERVER_NAME);\n\n // Own-property, so a config with a `__proto__` key cannot conjure an mcpServers map.\n const own = (key: string): unknown =>\n Object.prototype.hasOwnProperty.call(parsed, key)\n ? (parsed as Record<string, unknown>)[key]\n : undefined;\n\n const projects = own('projects');\n // A plain object only: an array would yield index keys (\"0\", \"1\") that then get\n // printed to the user as directories to cd into.\n const localScopeDirs =\n typeof projects === 'object' &&\n projects !== null &&\n !Array.isArray(projects)\n ? Object.entries(projects as Record<string, { mcpServers?: unknown }>)\n .filter(([, project]) => has(project?.mcpServers))\n .map(([dir]) => dir)\n : [];\n\n return { configPath, userScope: has(own('mcpServers')), localScopeDirs };\n}\n// Lists directories without dumping twenty paths into one line.\nfunction describeDirs(dirs: string[]): string {\n if (dirs.length === 1) return dirs[0];\n return `${dirs.length} project directories (${dirs.slice(0, 3).join(', ')}${dirs.length > 3 ? ', …' : ''})`;\n}\n\n/**\n * Turns a `claude mcp remove` run plus the config's own state into an outcome.\n *\n * Neither the exit code nor a `claude mcp get` probe can decide this. Four facts, all\n * observed with claude 2.1.220, each of which produced a false result in an earlier\n * revision of this file:\n *\n * 1. With an unwritable config, `mcp remove` prints `Removed MCP server runpod from\n * user config / File modified: …` and exits **0** having written nothing.\n * 2. `claude mcp add` defaults to LOCAL scope while this removes from USER scope, so\n * a hand-added entry reports `No MCP server named \"runpod\" in user scope`, exit 1.\n * 3. `mcp get` is cwd-pinned: an entry added in another directory is invisible.\n * 4. `mcp get` reports only the WINNING scope, and local shadows user — so a local\n * entry hides a user entry that is still on disk.\n *\n * Reading `.claude.json` sidesteps all four: `--scope user` writes exactly one place,\n * and local-scope entries are enumerable across every directory rather than only the\n * current one.\n */\nexport function interpretRemoveResult(\n result: RunResult,\n state: ClaudeConfigState,\n binary = 'claude'\n): AddResult {\n // A refusal ran nothing, so there is nothing to verify.\n if (result.refused) return result;\n\n const alsoElsewhere =\n state.localScopeDirs.length > 0\n ? ` A separate local-scope ${SERVER_NAME} entry (which may carry its own API key) also exists in ${describeDirs(state.localScopeDirs)} — this wizard does not touch those. Remove with \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'local'])}\\` from each.`\n : '';\n\n if (state.userScope === true) {\n // Cause (1): the CLI reported whatever it reported, and the entry is still there.\n return {\n success: false,\n message: `the ${SERVER_NAME} entry is STILL in Claude Code's user config (${state.configPath}), so your API key is still on disk. ${\n result.success\n ? 'Most likely that file is not writable — the CLI reports success anyway.'\n : `The removal command itself failed: ${result.message ?? 'no output'}`\n }${alsoElsewhere}`,\n };\n }\n\n if (state.userScope === false) {\n // Exact, not inferred: the file was read and has no user-scope entry.\n return {\n success: true,\n message:\n (result.success\n ? 'removed from your user config'\n : 'nothing to remove in your user config') + alsoElsewhere,\n };\n }\n\n // Config unreadable/unparseable — do not claim either way.\n if (result.success) {\n return {\n success: true,\n message: `removal reported success, but ${state.configPath} could not be read to confirm it`,\n };\n }\n return { success: false, message: result.message };\n}\n\n/**\n * Turns a `claude mcp add` run plus the config's own state into an outcome.\n *\n * Same reason as above, and the mirror failure is why the scope-string approach was\n * abandoned: with a pre-existing LOCAL entry in the current directory, `mcp get`\n * reports `local` even after a perfectly successful user-scope write — so keying off\n * it reported \"nothing was configured\" for a key that had just been written.\n */\nexport function interpretAddResult(\n result: RunResult,\n state: ClaudeConfigState,\n // Threaded through for the same reason interpretRemoveResult takes it: the\n // remediation command has to name the binary that was actually found. A bare\n // `claude` fails for exactly the not-on-PATH installs the candidate paths exist\n // to serve.\n binary: string\n): AddResult {\n if (result.refused || !result.success) return result;\n\n if (state.userScope === false) {\n return {\n success: false,\n message: `Claude Code reported success but no ${SERVER_NAME} entry is in its user config afterwards (${state.configPath}) — that file is most likely not writable. Nothing was configured.`,\n };\n }\n\n if (state.userScope === true && state.localScopeDirs.length > 0) {\n // Local scope SHADOWS user scope, so in these directories the entry just written is\n // inert and Claude Code keeps using the local one, with its own possibly stale key.\n // That shadowing is the entire reason this reader exists, and the add path was\n // dropping the fact while the remove path reported it. The \"already exists\" caveat\n // cannot cover it: `mcp add --scope user` exits 0 when a local entry is present,\n // because the collision is per-scope.\n return {\n success: true,\n message: `${result.message ? `${result.message}; ` : ''}note a local-scope ${SERVER_NAME} entry also exists in ${describeDirs(state.localScopeDirs)} and takes precedence over the user config there, so Claude Code will keep using it in those projects — remove it with \\`${describeCommand(binary, ['mcp', 'remove', SERVER_NAME, '--scope', 'local'])}\\` run from each`,\n };\n }\n\n if (state.userScope === undefined) {\n // Accepted — failing closed would break every user whose config this cannot parse,\n // for a problem that may not exist — but not reported as a clean success, or the\n // user has no way to know the write went unconfirmed.\n return {\n success: true,\n message: `${result.message ? `${result.message}; ` : ''}could not read ${state.configPath} to confirm the entry landed`,\n };\n }\n\n return { success: true, message: result.message };\n}\n\n/**\n * Built around an injectable binary resolver.\n *\n * The injection is not decoration: tests that drive this client must NOT be able to\n * reach a real `claude`. `findClaudeBinary` probes `~/.claude/local/claude`,\n * `/usr/local/bin/claude` and `/opt/homebrew/bin/claude` BEFORE consulting PATH, so a\n * harness that merely prepends a fake to PATH still runs the contributor's real CLI on\n * any machine with a native-installer or Homebrew install — executing\n * `claude mcp remove --scope user runpod` against their live config. CI cannot catch\n * that, because clean runner images have none of those paths.\n */\nexport function createClaudeCodeClient(\n resolveBinary: () => string | null,\n // Injected for the same reason as the binary: a test must not read — or draw\n // conclusions from — the developer's real ~/.claude.json.\n readState: () => ClaudeConfigState = () =>\n readClaudeConfigState(claudeUserConfigPath())\n): McpClient {\n return {\n id: 'claude-code',\n name: 'Claude Code',\n detect: () => Promise.resolve(resolveBinary() !== null),\n add: (mode) => {\n const args =\n mode.kind === 'local'\n ? [\n 'mcp',\n 'add',\n SERVER_NAME,\n '--scope',\n 'user',\n '-e',\n `RUNPOD_API_KEY=${mode.apiKey}`,\n '--',\n 'npx',\n '-y',\n NPM_PACKAGE,\n ]\n : [\n 'mcp',\n 'add',\n '--transport',\n 'http',\n '--scope',\n 'user',\n SERVER_NAME,\n mode.url,\n ];\n const binary = resolveBinary();\n if (!binary) {\n // Automatic detection deliberately covers only the standard install\n // locations (see findClaudeBinary) — a custom npm prefix or redirected\n // profile still works, the user just registers it themselves from their own\n // shell, where their own PATH applies and this wizard's trust rules do not.\n return Promise.resolve({\n success: false,\n message: `claude CLI not found in the standard install locations. If Claude Code is installed somewhere custom, register it yourself${mode.kind === 'local' ? ', substituting your key' : ''}:\\n ${describeCommandRedacted('claude', args)}`,\n });\n }\n // The key is passed in only so any message built from the CLI's output can have\n // it stripped — see redactSecret.\n const result = runClaude(\n binary,\n args,\n mode.kind === 'local' ? mode.apiKey : undefined\n );\n // interpretAddResult passes failures and refusals through verbatim, so only a\n // success needs the config read to confirm it.\n if (!result.success) return Promise.resolve(result);\n // Verified against the config, not the exit code — see interpretAddResult.\n return Promise.resolve(interpretAddResult(result, readState(), binary));\n },\n remove: () => {\n const binary = resolveBinary();\n if (!binary) {\n return Promise.resolve({\n success: false,\n message: `claude CLI not found in the standard install locations. If Claude Code is installed somewhere custom, remove the entry yourself:\\n ${describeCommand('claude', ['mcp', 'remove', SERVER_NAME, '--scope', 'user'])}`,\n });\n }\n // Through runClaude so this shares the spawn handling: previously it called\n // execFileSync directly, which cannot spawn a .cmd — and its catch reported\n // success regardless, so a failed removal printed a tick while the entry\n // stayed in the user's config.\n const result = runClaude(binary, [\n 'mcp',\n 'remove',\n '--scope',\n 'user',\n SERVER_NAME,\n ]);\n // A refusal ran nothing, so there is nothing to verify — and reading the config\n // anyway would let interpretRemoveResult convert an unexecuted removal into\n // \"nothing to remove\".\n if (result.refused) return Promise.resolve(result);\n return Promise.resolve(\n interpretRemoveResult(result, readState(), binary)\n );\n },\n describeTarget: () => 'Claude Code user config (via `claude mcp` CLI)',\n };\n}\n\nconst claudeCodeClient = createClaudeCodeClient(findClaudeBinary);\n\nconst home = os.homedir();\n// `absoluteEnvDir` rather than `??`: an empty OR relative value must be treated as\n// unset. `path.join('', 'Claude', …)` yields a RELATIVE path, and every consumer here\n// either writes a plaintext API key to it or spawns it — so a relative value means\n// writing the key into whatever directory the wizard was launched from, or executing a\n// file out of it. This is the same defect three env vars have now produced\n// (CLAUDE_CONFIG_DIR, XDG_CONFIG_HOME, APPDATA), so it is resolved in one place.\n// A function, not a module-level const: read at call time so a test can exercise the\n// guard at all. As an import-time const, a test mutating process.env.APPDATA proved\n// nothing — reverting the guard to `??` left the entire suite green.\nfunction appDataDir(): string {\n return absoluteEnvDir(process.env.APPDATA, () =>\n path.join(home, 'AppData', 'Roaming')\n );\n}\n\n// Claude Desktop stores its config in an OS-specific location.\nexport function claudeDesktopConfigPath(): string {\n if (process.platform === 'win32') {\n return path.join(appDataDir(), 'Claude', 'claude_desktop_config.json');\n }\n if (process.platform === 'darwin') {\n return path.join(\n home,\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json'\n );\n }\n // Linux followed the XDG location. Previously this returned the macOS path on\n // Linux, so a Linux user was told `✓ Claude Desktop configured` for a file under\n // ~/Library that nothing reads.\n return path.join(\n absoluteEnvDir(process.env.XDG_CONFIG_HOME, () =>\n path.join(home, '.config')\n ),\n 'Claude',\n 'claude_desktop_config.json'\n );\n}\n\n// VS Code uses a `servers` property (not `mcpServers`) in a per-user mcp.json.\nexport function vsCodeConfigPath(): string {\n if (process.platform === 'win32') {\n return path.join(appDataDir(), 'Code', 'User', 'mcp.json');\n }\n if (process.platform === 'darwin') {\n return path.join(\n home,\n 'Library',\n 'Application Support',\n 'Code',\n 'User',\n 'mcp.json'\n );\n }\n // Honours XDG_CONFIG_HOME like the Claude Desktop path does. Hardcoding ~/.config\n // meant an XDG user got `✓ Visual Studio Code configured` for a file VS Code does not\n // read — the same defect this PR fixed for Claude Desktop on Linux.\n return path.join(\n absoluteEnvDir(process.env.XDG_CONFIG_HOME, () =>\n path.join(home, '.config')\n ),\n 'Code',\n 'User',\n 'mcp.json'\n );\n}\n\nfunction xdgConfigHome(): string {\n return absoluteEnvDir(process.env.XDG_CONFIG_HOME, () =>\n path.join(home, '.config')\n );\n}\n\n// opencode's global config: ~/.config/opencode/opencode.json (the path its\n// docs give), honouring XDG_CONFIG_HOME. It loads opencode.jsonc too, so an\n// existing .jsonc is the file to edit; otherwise write opencode.json.\nexport function opencodeConfigPath(): string {\n const dir = path.join(xdgConfigHome(), 'opencode');\n const jsoncPath = path.join(dir, 'opencode.jsonc');\n return exists(jsoncPath) ? jsoncPath : path.join(dir, 'opencode.json');\n}\n\n// opencode's MCP entries live under `mcp` with their own schema: `type`\n// remote/local, `command` as one array, `environment` instead of `env`. A\n// remote entry needs no auth block: opencode runs the OAuth sign-in itself.\nfunction opencodeServerValue(mode: AddMode) {\n return mode.kind === 'local'\n ? {\n type: 'local',\n command: ['npx', '-y', NPM_PACKAGE],\n environment: { RUNPOD_API_KEY: mode.apiKey },\n enabled: true,\n }\n : { type: 'remote', url: mode.url, enabled: true };\n}\n\n// Pi's global MCP config: <agent dir>/mcp.json, where the agent dir is\n// PI_CODING_AGENT_DIR (a leading ~ expanded, as Pi's getAgentDir does) or\n// ~/.pi/agent. A relative value is returned as-is so upsertJsonServer refuses\n// it instead of writing a key into the current directory.\nexport function piMcpConfigPath(): string {\n const configured = process.env.PI_CODING_AGENT_DIR?.trim();\n if (!configured) return path.join(home, '.pi', 'agent', 'mcp.json');\n const expanded =\n configured === '~'\n ? home\n : configured.startsWith('~/')\n ? path.join(home, configured.slice(2))\n : configured;\n return path.join(expanded, 'mcp.json');\n}\n\nexport const CLIENTS: McpClient[] = [\n claudeCodeClient,\n jsonClient({\n id: 'cursor',\n name: 'Cursor',\n // A VS Code fork, and its MCP reader keeps VS Code's tolerance — comments and\n // trailing commas both parse. Read out of the shipped bundle, not assumed from\n // \"Electron app\"; see ConfigDialect.\n dialect: 'jsonc',\n configPath: () => path.join(home, '.cursor', 'mcp.json'),\n }),\n jsonClient({\n id: 'windsurf',\n name: 'Windsurf',\n // Not installed on any machine this was checked on, so its parser was never read.\n // Lenient-and-disclosed rather than a guess in either direction.\n dialect: 'unverified',\n // Windsurf is stdio-only, so it reaches the hosted server via mcp-remote.\n hostedStrategy: 'mcp-remote',\n configPath: () =>\n path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),\n }),\n jsonClient({\n id: 'claude-desktop',\n name: 'Claude Desktop',\n // Genuinely strict: its reader is a bare `JSON.parse(readFileSync(...))` with no\n // preprocessing and no retry, so a comment or trailing comma is fatal.\n dialect: 'json',\n // Claude Desktop config files are stdio-only; use the mcp-remote bridge.\n hostedStrategy: 'mcp-remote',\n configPath: claudeDesktopConfigPath,\n // Detect by the application/support directory, which exists once the app runs.\n detectPaths: () => [path.dirname(claudeDesktopConfigPath())],\n }),\n jsonClient({\n id: 'vscode',\n name: 'Visual Studio Code',\n serverProperty: 'servers',\n // The one client that genuinely reads JSONC — comments and trailing commas in\n // mcp.json are supported and common.\n dialect: 'jsonc',\n configPath: vsCodeConfigPath,\n detectPaths: () => [path.dirname(vsCodeConfigPath())],\n }),\n jsonClient({\n id: 'opencode',\n name: 'opencode',\n serverProperty: 'mcp',\n // Loaded a commented, trailing-comma config when run; see ConfigDialect.\n dialect: 'jsonc',\n configPath: opencodeConfigPath,\n detectPaths: () => [path.dirname(opencodeConfigPath())],\n serverValue: opencodeServerValue,\n }),\n jsonClient({\n id: 'pi',\n name: 'Pi',\n // Rejected a single comment when run; see ConfigDialect.\n dialect: 'json',\n // Native Streamable HTTP (`pi mcp add --url` writes exactly `{ url }`).\n configPath: piMcpConfigPath,\n detectPaths: () => [path.dirname(piMcpConfigPath())],\n }),\n];\n","// Keep key verification independent of the interactive wizard.\nimport { sdkBase } from '../_shared/hosts.js';\n\n// Interactive: the user is watching a spinner, so fail fast enough to retype a\n// key rather than wait out a network stall.\nexport const VERIFY_API_KEY_TIMEOUT_MS = 10_000;\n\n// Verify the API key works by calling a read-only REST endpoint. Returns true\n// on success, false on auth failure, and null when the check itself failed\n// (offline, timed out, etc.) so we can warn without blocking. The deadline is a\n// parameter so a test can drive the stall in milliseconds; the wizard always\n// takes the default.\nexport async function verifyApiKey(\n apiKey: string,\n timeoutMs: number = VERIFY_API_KEY_TIMEOUT_MS\n): Promise<boolean | null> {\n try {\n const response = await fetch(`${sdkBase(process.env)}/v2/pods`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n // Without this the wizard sits at \"Verifying…\" forever against a host\n // that accepts the connection and goes quiet, with no way out but ^C.\n // An abort lands in the catch below and is reported as \"check failed\",\n // which is exactly what it is.\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (response.ok) return true;\n if (response.status === 401 || response.status === 403) return false;\n return null;\n } catch {\n return null;\n }\n}\n","// Flags for `npx @runpod/mcp-server <add|remove>`. Parsing is pure so the\n// non-interactive contract is testable without a terminal.\n//\n// The wizard used to be prompts only. An agent shell has no TTY, so the\n// multiselect drew once and the process exited 0 having written nothing, and\n// the agent reported success. With `--client` the same install runs with no\n// prompts at all; without it, a non-TTY run fails loudly instead.\n\nexport interface WizardArgs {\n help: boolean;\n list: boolean;\n // Client ids to configure, in the order given. Undefined means \"ask\".\n clients?: string[];\n // How to connect. Undefined means \"ask\" (interactive) or hosted (flags).\n mode?: 'hosted' | 'local';\n errors: string[];\n}\n\nexport function parseWizardArgs(\n argv: readonly string[],\n knownIds: readonly string[]\n): WizardArgs {\n const parsed: WizardArgs = { help: false, list: false, errors: [] };\n const addClients = (raw: string | undefined, flag: string) => {\n if (raw === undefined || raw.startsWith('-')) {\n parsed.errors.push(`${flag} needs a value, e.g. ${flag} cursor`);\n return;\n }\n for (const id of raw.split(',').map((s) => s.trim().toLowerCase())) {\n if (!id) continue;\n if (!knownIds.includes(id)) {\n parsed.errors.push(\n `unknown client \"${id}\". Supported: ${knownIds.join(', ')}`\n );\n continue;\n }\n parsed.clients ??= [];\n if (!parsed.clients.includes(id)) parsed.clients.push(id);\n }\n };\n const setMode = (mode: 'hosted' | 'local') => {\n if (parsed.mode && parsed.mode !== mode)\n parsed.errors.push('--hosted and --local cannot be combined');\n parsed.mode = mode;\n };\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === '-h' || arg === '--help') parsed.help = true;\n else if (arg === '--list') parsed.list = true;\n else if (arg === '--hosted') setMode('hosted');\n else if (arg === '--local') setMode('local');\n else if (arg === '--client' || arg === '-c') addClients(argv[++i], arg);\n else if (arg.startsWith('--client='))\n addClients(arg.slice('--client='.length), '--client');\n else parsed.errors.push(`unknown option \"${arg}\"`);\n }\n return parsed;\n}\n\nexport function wizardUsage(knownIds: readonly string[]): string {\n return [\n 'Usage:',\n ' npx @runpod/mcp-server@latest add interactive setup (needs a terminal)',\n ' npx @runpod/mcp-server@latest add --client <ids> no prompts: configure these clients',\n ' npx @runpod/mcp-server@latest remove --client <ids> no prompts: remove Runpod from them',\n ' npx @runpod/mcp-server@latest add --list list clients, whether each is detected, and its config file',\n '',\n 'Options:',\n ` -c, --client <ids> comma-separated or repeated: ${knownIds.join(', ')}`,\n ' --hosted connect to the hosted server and sign in with Runpod (OAuth); the default',\n ' --local run the server locally with the API key in RUNPOD_API_KEY',\n ' (read from the environment only, never from an argument)',\n ' -h, --help show this help',\n '',\n 'Exit codes: 0 configured, 1 a client failed, 2 bad usage or no terminal for prompts.',\n ].join('\\n');\n}\n","import { execFileSync } from 'child_process';\nimport * as p from '@clack/prompts';\nimport {\n CLIENTS,\n HOSTED_URL,\n type AddMode,\n type McpClient,\n} from './clients.js';\nimport { verifyApiKey } from './verify-key.js';\nimport { parseWizardArgs, wizardUsage } from './args.js';\n\nconst API_KEYS_URL = 'https://www.runpod.io/console/user/settings';\n\n// Open a URL in the user's default browser. Best-effort and non-fatal.\nfunction openBrowser(url: string): void {\n try {\n // The URL is a literal arg, not an interpolated string. The Windows branch is\n // the exception: `start` is a cmd built-in, so that one does go through a shell\n // (the first quoted arg is the window title, hence the empty ''). Safe only\n // because every URL reaching here is a compile-time constant — do not extend\n // this to a URL from user input without escaping it.\n if (process.platform === 'darwin') {\n execFileSync('open', [url], { stdio: 'ignore' });\n } else if (process.platform === 'win32') {\n execFileSync('cmd', ['/c', 'start', '', url], { stdio: 'ignore' });\n } else {\n execFileSync('xdg-open', [url], { stdio: 'ignore' });\n }\n } catch {\n // Ignore — the user can open the URL manually.\n }\n}\n\nfunction bail(message = 'Cancelled.'): never {\n p.cancel(message);\n process.exit(0);\n}\n\nasync function promptForApiKey(): Promise<string> {\n // Trimmed like the pasted path below. An env var picked up from a shell profile\n // or a .env file can carry a trailing newline, which would otherwise be written\n // verbatim into every client config and, on Windows, reach a shim's `%*`.\n const fromEnv = process.env.RUNPOD_API_KEY?.trim();\n if (fromEnv) {\n const useEnv = await p.confirm({\n message: 'Use the RUNPOD_API_KEY from your environment?',\n });\n if (p.isCancel(useEnv)) bail();\n if (useEnv) return fromEnv;\n }\n\n const create = await p.confirm({\n message: 'Open the Runpod console to create or copy an API key?',\n });\n if (p.isCancel(create)) bail();\n if (create) {\n openBrowser(API_KEYS_URL);\n p.log.info(`Opening ${API_KEYS_URL}`);\n }\n\n const apiKey = await p.password({\n message: 'Paste your Runpod API key',\n validate: (value) =>\n !value || value.trim().length === 0\n ? 'API key cannot be empty'\n : undefined,\n });\n if (p.isCancel(apiKey)) bail();\n return apiKey.trim();\n}\n\nasync function selectClients(\n detected: Map<string, boolean>,\n verb: string\n): Promise<McpClient[]> {\n const options = CLIENTS.map((client) => ({\n value: client.id,\n label: client.name,\n hint: detected.get(client.id) ? 'detected' : undefined,\n }));\n\n const selected = await p.multiselect<string>({\n message: `Which agents should we ${verb}?`,\n options,\n // Pre-select detected clients so the common case is a single Enter press.\n initialValues: CLIENTS.filter((c) => detected.get(c.id)).map((c) => c.id),\n required: true,\n });\n if (p.isCancel(selected)) bail();\n\n return CLIENTS.filter((c) => selected.includes(c.id));\n}\n\nasync function detectAll(): Promise<Map<string, boolean>> {\n const entries = await Promise.all(\n CLIENTS.map(async (c) => [c.id, await c.detect()] as const)\n );\n return new Map(entries);\n}\n\n// Ask how the server should be wired up, then collect what that mode needs.\n// Hosted is the default: the client signs in with Runpod over OAuth and no key\n// is ever written to disk. Local runs the server via npx with an API key.\nasync function selectMode(): Promise<AddMode> {\n const kind = await p.select({\n message: 'How do you want to connect to Runpod?',\n options: [\n {\n value: 'hosted',\n label: 'Sign in with Runpod (recommended)',\n hint: 'hosted, OAuth, no API key stored',\n },\n {\n value: 'local',\n label: 'Run locally with an API key',\n hint: 'runs on this machine via npx',\n },\n ],\n initialValue: 'hosted',\n });\n if (p.isCancel(kind)) bail();\n\n if (kind === 'hosted') {\n return { kind: 'hosted', url: HOSTED_URL };\n }\n\n const apiKey = await promptForApiKey();\n\n const verifySpinner = p.spinner();\n verifySpinner.start('Verifying API key');\n const valid = await verifyApiKey(apiKey);\n if (valid === true) {\n verifySpinner.stop('API key verified.');\n } else if (valid === false) {\n verifySpinner.stop('API key rejected by Runpod.');\n const proceed = await p.confirm({\n message: 'The key did not authenticate. Continue anyway?',\n initialValue: false,\n });\n if (p.isCancel(proceed) || !proceed) bail();\n } else {\n verifySpinner.stop('Could not verify the key (offline?). Continuing.');\n }\n\n return { kind: 'local', apiKey };\n}\n\nasync function runAdd(): Promise<void> {\n const detected = await detectAll();\n const clients = await selectClients(detected, 'set up');\n const mode = await selectMode();\n\n const results: string[] = [];\n for (const client of clients) {\n const spinner = p.spinner();\n spinner.start(`Configuring ${client.name}`);\n const result = await client.add(mode);\n if (result.success) {\n spinner.stop(`${client.name} configured.`);\n // A success can still carry a caveat — notably \"the entry already existed, so\n // your key was NOT updated\". Dropping the message turned that into an\n // unqualified tick, which is how a user rotating their key would end up with\n // the old one still in place.\n results.push(\n `✓ ${client.name} — ${result.message ? `${result.message}; ` : ''}${client.describeTarget()}`\n );\n } else {\n spinner.stop(`${client.name} failed.`);\n results.push(`✗ ${client.name} — ${result.message ?? 'unknown error'}`);\n }\n }\n\n p.note(results.join('\\n'), 'Results');\n p.outro(\n mode.kind === 'hosted'\n ? 'Restart your agent, then complete \"Sign in with Runpod\" when it connects.'\n : 'Restart your agent (or reconnect MCP) to load the Runpod tools.'\n );\n}\n\nasync function runRemove(): Promise<void> {\n const detected = await detectAll();\n const clients = await selectClients(detected, 'remove Runpod from');\n\n const results: string[] = [];\n for (const client of clients) {\n const spinner = p.spinner();\n spinner.start(`Removing from ${client.name}`);\n const result = await client.remove();\n spinner.stop(\n result.success ? `${client.name} cleaned up.` : `${client.name} failed.`\n );\n results.push(\n `${result.success ? '✓' : '✗'} ${client.name}${\n result.message ? ` — ${result.message}` : ''\n }`\n );\n }\n\n p.note(results.join('\\n'), 'Results');\n p.outro('Done.');\n}\n\n// How each client finishes the hosted OAuth sign-in, for the result lines.\nconst SIGN_IN: Record<string, string> = {\n 'claude-code': 'in Claude Code run /mcp → runpod → Sign in with Runpod',\n opencode: 'run `opencode mcp auth runpod`',\n pi: 'run `pi mcp login runpod`',\n};\n\nfunction signInStep(client: McpClient): string {\n return (\n SIGN_IN[client.id] ??\n 'restart it; it opens \"Sign in with Runpod\" when it connects'\n );\n}\n\n// The flag-driven path: no prompts, plain output, and an exit code that says\n// what happened, so an agent or a script can rely on it.\nasync function runNonInteractive(\n subcommand: string,\n clientIds: string[],\n requestedMode: 'hosted' | 'local' | undefined\n): Promise<number> {\n const clients = clientIds.map((id) => CLIENTS.find((c) => c.id === id)!);\n\n if (subcommand === 'remove') {\n let failed = 0;\n for (const client of clients) {\n const result = await client.remove();\n if (!result.success) failed++;\n console.log(\n `${result.success ? '✓' : '✗'} ${client.name}${result.message ? ` — ${result.message}` : ''}`\n );\n }\n return failed ? 1 : 0;\n }\n\n let mode: AddMode = { kind: 'hosted', url: HOSTED_URL };\n if (requestedMode === 'local') {\n const apiKey = process.env.RUNPOD_API_KEY?.trim();\n if (!apiKey) {\n console.error(\n '--local reads the API key from RUNPOD_API_KEY, which is not set. Export it, or use --hosted to sign in with Runpod instead.'\n );\n return 2;\n }\n const valid = await verifyApiKey(apiKey);\n if (valid === false) {\n console.error(\n 'RUNPOD_API_KEY was rejected by Runpod. Nothing was configured.'\n );\n return 1;\n }\n if (valid === null)\n console.error('Could not verify RUNPOD_API_KEY (offline?). Continuing.');\n mode = { kind: 'local', apiKey };\n }\n\n let failed = 0;\n for (const client of clients) {\n const result = await client.add(mode);\n if (result.success) {\n console.log(\n `✓ ${client.name} — ${result.message ? `${result.message}; ` : ''}${client.describeTarget()}`\n );\n } else {\n failed++;\n console.log(`✗ ${client.name} — ${result.message ?? 'unknown error'}`);\n }\n }\n for (const client of clients) {\n console.log(\n mode.kind === 'hosted'\n ? `Next for ${client.name}: ${signInStep(client)}.`\n : `Next for ${client.name}: restart it (or reconnect MCP) to load the Runpod tools.`\n );\n }\n return failed ? 1 : 0;\n}\n\nasync function listClients(): Promise<void> {\n const detected = await detectAll();\n for (const client of CLIENTS) {\n console.log(\n `${client.id.padEnd(15)} ${detected.get(client.id) ? 'detected ' : 'not detected'} ${client.describeTarget()}`\n );\n }\n}\n\n// Entry point for `npx @runpod/mcp-server <add|remove> [flags]`. Resolves to\n// the process exit code.\nexport async function runWizard(\n subcommand: string,\n argv: readonly string[] = process.argv.slice(3),\n isInteractive: boolean = Boolean(process.stdin.isTTY && process.stdout.isTTY)\n): Promise<number> {\n const ids = CLIENTS.map((c) => c.id);\n const args = parseWizardArgs(argv, ids);\n if (args.errors.length) {\n for (const error of args.errors) console.error(`error: ${error}`);\n console.error(`\\n${wizardUsage(ids)}`);\n return 2;\n }\n if (args.help) {\n console.log(wizardUsage(ids));\n return 0;\n }\n if (args.list) {\n await listClients();\n return 0;\n }\n if (args.clients) {\n return runNonInteractive(subcommand, args.clients, args.mode);\n }\n if (!isInteractive) {\n // Exiting 0 here is what let an agent report \"configured\" for a run that\n // wrote nothing. Say what happened and how to do it without prompts.\n console.error(\n `This installer needs an interactive terminal to show its prompts, and none is attached. Nothing was configured.\\nTo run it without prompts, name the clients: npx @runpod/mcp-server@latest ${subcommand} --client <ids>\\n\\n${wizardUsage(ids)}`\n );\n return 2;\n }\n\n p.intro('Runpod MCP server installer');\n if (subcommand === 'remove') {\n await runRemove();\n } else {\n await runAdd();\n }\n return 0;\n}\n","import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { SERVER_VERSION } from './server.js';\nimport { createSpecgenServer } from './specgen/server.js';\nimport { createToolContext } from './specgen/context.js';\nimport { hostedSearch } from './search/knowledge.js';\nimport { hostedMcpBase } from './_shared/hosts.js';\n\n// search-docs goes through the hosted server, which holds the knowledge\n// index's service key (src/search/knowledge.ts).\nconst SEARCH_URL = `${hostedMcpBase(process.env)}/api/search`;\n\n// Detect the install wizard subcommand (`add` / `remove`). In this mode we run\n// the interactive installer instead of starting the stdio server, and the API\n// key is collected by the wizard rather than required up front.\nconst WIZARD_SUBCOMMANDS = ['add', 'remove'];\nconst subcommand = process.argv[2];\nconst isWizardMode = WIZARD_SUBCOMMANDS.includes(subcommand);\n\nasync function main(apiKey: string): Promise<void> {\n // One surface everywhere: stdio serves the same spec-generated tool set\n // and skill resources the hosted path serves (see specgen/DESIGN.md).\n // stdio keeps the 5-minute wait budgets — no gateway reaper applies here.\n // ALP write tools are hosted-only by decision (docs/agent-learning-protocol.md):\n // the stdio path never registers them, so local users cannot enable them.\n const server = createSpecgenServer(\n createToolContext({\n apiKey,\n tracking: { transport: 'stdio', serverVersion: SERVER_VERSION },\n }),\n SERVER_VERSION,\n { search: hostedSearch(SEARCH_URL) }\n );\n await server.connect(new StdioServerTransport());\n}\n\nif (subcommand === '--version' || subcommand === '-v') {\n console.log(SERVER_VERSION);\n} else if (subcommand === '--help' || subcommand === '-h') {\n console.log(\n [\n `@runpod/mcp-server ${SERVER_VERSION}`,\n '',\n 'Usage:',\n ' RUNPOD_API_KEY=<key> npx @runpod/mcp-server@latest run the MCP server over stdio',\n ' npx @runpod/mcp-server@latest add [--client <ids>] configure your agents (see add --help)',\n ' npx @runpod/mcp-server@latest remove --client <ids> remove Runpod from your agents',\n ].join('\\n')\n );\n} else if (isWizardMode) {\n import('./install/wizard.js')\n .then(async ({ runWizard }) => {\n process.exitCode = await runWizard(subcommand);\n })\n .catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n} else {\n // Get API key from environment variable\n const API_KEY = process.env.RUNPOD_API_KEY;\n if (!API_KEY) {\n console.error('RUNPOD_API_KEY environment variable is required');\n process.exit(1);\n }\n\n main(API_KEY).catch((error) => {\n console.error('Failed to start Runpod MCP server:', error);\n process.exit(1);\n });\n}\n","// `__PACKAGE_VERSION__` is replaced at build time by tsup's `define` with the\n// current `version` from package.json. Falls back to `'dev'` when the\n// substitution doesn't happen (e.g. running via tsx).\ndeclare const __PACKAGE_VERSION__: string;\n\nexport const SERVER_NAME = 'Runpod API Server';\nexport const SERVER_VERSION =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : 'dev';\n","// MCP server wiring: the generated tool set plus the curated overlay, served\n// over the low-level protocol Server so generated JSON Schemas pass through\n// without a Zod round-trip.\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolContext } from './context.js';\nimport {\n dispatchGeneratedTool,\n validateArguments,\n type ToolResult,\n} from './dispatch.js';\nimport { generatedTools } from './generated/tools.gen.js';\nimport { getCapacity } from './tools/capacity.js';\nimport { setEndpointGpus } from './tools/endpoint-gpus.js';\nimport { hubTools } from './tools/hub.js';\nimport { jobTools } from './tools/jobs.js';\nimport { listEndpoints } from './tools/list-endpoints.js';\nimport { listTemplates } from './tools/list-templates.js';\nimport { logTools } from './tools/logs.js';\nimport { listPublicEndpoints } from './tools/public-endpoints.js';\nimport {\n GUIDE_URI_PREFIX,\n guideResources,\n knowledgeTools,\n} from './tools/knowledge.js';\nimport { runTool } from './tools/util.js';\nimport { createDescribeTool } from './tools/describe.js';\nimport { STATUS_WAIT_MAX_MS } from './tools/jobs.js';\nimport { SERVER_NAME } from '../server.js';\nimport {\n captureResourceCall,\n captureToolCall,\n recordedArgumentValues,\n} from './analytics.js';\nimport { createAlpTools, type AlpToolsOptions } from './tools/alp.js';\nimport { createSearchDocsTool } from './tools/search.js';\nimport type { SearchFn } from '../search/knowledge.js';\nimport {\n callerId,\n logToolCall,\n noopRateLimiter,\n type RateLimiter,\n} from './ops.js';\n\nimport type { CuratedTool } from './types.js';\nimport { DESCRIBE_TOOL_NAME, listTool } from './on-demand.js';\nexport type { CuratedTool } from './types.js';\n\n// The curated overlay: tools whose backing plane the v2 spec does not cover\n// (Serverless runtime, GraphQL), plus targeted replacements for generated\n// tools that need shaping (list-templates) or a non-JSON transport (the SSE\n// log tools).\nexport const curatedTools: CuratedTool[] = [\n listEndpoints,\n listTemplates,\n ...jobTools,\n ...logTools,\n getCapacity,\n ...hubTools,\n setEndpointGpus,\n listPublicEndpoints,\n ...knowledgeTools,\n];\n\n// Usage briefing delivered to connecting agents at initialize (the MCP\n// `instructions` field). The official server ships one; agents without it\n// tend to answer account questions from memory instead of calling tools.\n// This block is the maintained EXCERPT of the answer contract; the canonical\n// full text lives in the plugin's runpod-mcp skill, served here as the\n// runpod-mcp guide from @runpod/plugin-knowledge.\n// Tools whose handler may hold the response longer than a client's request\n// timeout; the hosted transport answers these over SSE and everything else as\n// JSON (src/http.ts). ALP tools answer immediately and are not included.\nexport const responseHoldingTools: ReadonlySet<string> = new Set(\n curatedTools.filter((tool) => tool.holdsResponse).map((tool) => tool.name)\n);\n\nexport const 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.\n\nAnswer 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 — 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 — an honest empty answer is complete.\n\nCommit; don't hedge, don't defer. Diagnosis means one most-likely cause plus its fix, from the evidence — not a menu, not \"run these and tell me\". For jobs, submit with run-endpoint and block server-side with get-job-status wait (up to ${STATUS_WAIT_MAX_MS} ms); use runsync-endpoint only for a warm endpoint and a fast job. Expect first-job cold starts of minutes, and check worker states between holds; when a wait outlasts what the tools can hold, report the evidenced state — what was created, what was submitted, what the worker states show — and the recommended next step. Offering to keep watching is fine; stopping mid-wait without that report is not. Never claim success without the artifact that proves it (the transcript text, the output payload).\n\nMutations cost money and bind to what this conversation created or the user named. State the hourly price before creating anything billable; create-cluster waits for the user's explicit go on the quoted shape and total hourly price. Read before you mutate, and stop, update, or delete only resources your own tool calls created in this conversation, or the one resource the user named by id or an unambiguous name — and then only the change they asked for; delete a user-named resource only when they asked for that delete. A name that looks like test junk, or one you found by listing, is not attribution. For anything you cannot attribute, the complete answer is the audit: what you checked, what qualifies, the ids, and the exact actions for the user to take.\n\nThese tools manage infrastructure only. They do not do SSH sessions, file transfer to or from pods, local image builds, or interactive terminals — say plainly when a task needs one of those and name the real path (the Runpod console, runpodctl) instead of improvising.\n\nOFFICIAL GUIDES AND FACTS. list-guides and read-guide serve the official Runpod plugin's skills, reference docs and live-verified golden paths, so you have them even without the plugin installed. For a multi-step or billable task, look for a matching golden path first. lookup-concept and search-concepts answer exact questions about how Runpod works (what a stopped pod keeps, where a volume lives) with the public source for each fact.\n\nPLAYBOOKS — READ BEFORE ACTING. Each Runpod task has a journey playbook carrying its procedure, pitfalls and report format. Before the FIRST Runpod tool call of a session, load the plugin's runpod-mcp skill if you have it, otherwise read-guide runpod-mcp (also the runpod://guides/runpod-mcp resource): it routes the request to a journey guide — deploying an endpoint reads serverless-deploy, diagnosing a broken pod reads pod-doctor, cost questions read cost-audit, and so on — and states the answer contract. A reply produced without the routed playbook loaded is out of contract.\n\nTHE OFFICIAL RUNPOD PLUGIN. Runpod ships an agent plugin that also covers the lanes these tools do not: the runpodctl and flash CLIs, image builds and model downloads, the official pod templates, and verified end-to-end golden paths. Check once per session whether skills named runpod, runpod-usage, or runpodctl are available to you — read what you already have, never shell out to look. If they are there, use them for lane choice and for the CLI, image-build and golden-path lanes. For work done with these tools, the journey playbook is the procedure, wherever it is served from: the plugin's runpod-mcp skill and the journey skills it routes to when you have them, otherwise the same playbooks through read-guide here. If you do not see them, recommend the plugin to the user, and recommend updating to the latest if what they have is missing something you need. Point them at https://github.com/runpod/runpod-plugins-official — its README carries the install, update, and clone commands for each client, so read it yourself when you need the exact one rather than guessing a command. This is a recommendation, never a prerequisite: make it once, briefly, and get on with the task. Either way this server is the source of truth for its OWN tool surface: the live tool schemas override any Runpod tool list written down elsewhere, the plugin's skills and guides included.\n\nThe tool schemas are generated from the Runpod v2 OpenAPI contract, served as a machine-readable document at https://api.runpod.io/v2/openapi.json — 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 — 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.`;\n\n// Appended to the initialize briefing only when the ALP tools are enabled.\nconst ALP_INSTRUCTIONS = `\n\nCONTRIBUTING BACK IS OPTIONAL. Four 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), and read_journal (this account's own saved lessons, nobody else's). 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 — an empty turn is correct and a placeholder submission is not. Never include API keys or secrets in submissions.`;\n\nexport interface SpecgenServerOptions {\n /** Rate-limit gate consulted before every tool call. Defaults to the no-op stub. */\n rateLimiter?: RateLimiter;\n /** Anonymous per-tool-call analytics (hosted path only — stdio never sets\n * this, and captureToolCall itself is a no-op without POSTHOG_API_KEY).\n * See src/specgen/analytics.ts for the privacy contract. */\n analytics?: {\n transport: 'stdio' | 'http';\n serverVersion: string;\n /** Sanitized client token (never a raw header). */\n clientName?: string;\n /** Stable account id from the credential pre-flight (myself.id) — the\n * preferred identity source; hashed before it leaves the process. */\n accountId?: string;\n };\n /** Called when a tool result is a 401: the hosted path uses it to drop the\n * cached credential verdict so the NEXT request re-checks and can emit the\n * HTTP 401 that makes OAuth clients re-authenticate. */\n onUnauthorized?: () => void;\n /** Called with every tool result's status (hosted loop breaker,\n * src/specgen/not-found-limiter.ts). */\n onToolResult?: (tool: string, status: number) => void;\n /** ALP write tools (report_feedback / save_to_journal / ask_question).\n * Enablement follows configuration: when absent, the tools do not appear\n * in tools/list at all. See docs/agent-learning-protocol.md. */\n alp?: AlpToolsOptions;\n /** Backs search-docs (src/specgen/tools/search.ts). When absent, the tool\n * is not listed. */\n search?: SearchFn;\n}\n\nexport function createSpecgenServer(\n ctx: ToolContext,\n version = '0.1.0',\n opts: SpecgenServerOptions = {}\n): Server {\n const rateLimiter = opts.rateLimiter ?? noopRateLimiter;\n const caller = callerId(ctx.apiKey);\n // The served curated set: the static surface, the config-gated search-docs\n // and ALP write tools, and describe-tool over all of it. Everything\n // downstream (list, routing) reads this, so a disabled tool is truly absent,\n // not present-and-failing.\n const servedCuratedTools: CuratedTool[] = [\n ...curatedTools,\n ...(opts.search ? [createSearchDocsTool(opts.search)] : []),\n ...(opts.alp ? createAlpTools(opts.alp) : []),\n createDescribeTool(() => [...servedCuratedTools, ...generatedTools]),\n ];\n const callShapeOnlyTools = new Set(\n [...servedCuratedTools, ...generatedTools]\n .filter((tool) => tool.schemaOnDemand)\n .map((tool) => tool.name)\n );\n const server = new Server(\n { name: SERVER_NAME, version: `${version} [specgen]` },\n {\n capabilities: { tools: {}, resources: {} },\n instructions: opts.alp\n ? SERVER_INSTRUCTIONS + ALP_INSTRUCTIONS\n : SERVER_INSTRUCTIONS,\n }\n );\n\n // The stdio transport only learns which client is driving from the MCP\n // initialize handshake — feed it into the outbound tracking User-Agent\n // (the hosted path already resolves identity from the inbound UA).\n server.oninitialized = () => {\n const clientInfo = server.getClientVersion();\n if (clientInfo?.name) {\n ctx.setClientInfo?.(clientInfo.name, clientInfo.version);\n // ALP submissions attribute the harness the same way the tracking UA\n // does; the ALP tools read opts.alp at call time, so this late bind\n // reaches them.\n if (opts.alp) {\n opts.alp.harness = clientInfo.version\n ? `${clientInfo.name}/${clientInfo.version}`\n : clientInfo.name;\n opts.alp.harnessSource = 'client_info';\n }\n }\n };\n\n // annotations travel with every tool: hosts use readOnlyHint and\n // destructiveHint to decide what a human has to approve, so dropping them\n // here would make delete-pod indistinguishable from list-pods. Generated\n // tools derive theirs from the HTTP method; curated ones declare theirs.\n // A tool flagged schemaOnDemand is listed with its call shape only.\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [...servedCuratedTools, ...generatedTools].map(listTool),\n }));\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: guideResources.map(({ text: _text, ...resource }) => resource),\n }));\n\n // Some clients probe templates unconditionally; answer empty instead of -32601.\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({\n resourceTemplates: [],\n }));\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const guide = guideResources.find(\n (candidate) => candidate.uri === request.params.uri\n );\n // Reads get their own usage event: a client reading runpod://guides/*\n // directly never goes through read-guide. Lists are not recorded, since\n // most clients send them on every session start.\n if (opts.analytics) {\n captureResourceCall(ctx.apiKey, {\n method: 'resources/read',\n uri: guide ? guide.uri : 'unknown',\n ok: Boolean(guide),\n ...opts.analytics,\n });\n }\n if (!guide) {\n throw new Error(\n `Unknown resource ${request.params.uri}. Resources are the plugin guides under ${GUIDE_URI_PREFIX}; call list-guides for the guide ids.`\n );\n }\n return {\n contents: [\n { uri: guide.uri, mimeType: 'text/markdown', text: guide.text },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n // Rate-limit seat: consulted before any tool work. The stub always admits;\n // a denial comes back as a retryable tool error, not a protocol failure.\n const verdict = await rateLimiter(caller, request.params.name);\n if (!verdict.allowed) {\n logToolCall({\n tool: request.params.name,\n caller,\n ok: false,\n status: 429,\n durationMs: 0,\n });\n // Still counted, so a blocked loop stays visible on the dashboard.\n if (opts.analytics) {\n captureToolCall(ctx.apiKey, {\n tool: request.params.name,\n ok: false,\n status: 429,\n durationMs: 0,\n ...(verdict.reason ? { blockedBy: verdict.reason } : {}),\n ...opts.analytics,\n });\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: 'Rate limited by this MCP server.',\n hint: `Pause${verdict.retryAfterS ? ` ~${verdict.retryAfterS}s` : ' briefly'}, then retry the same call.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const startedAt = Date.now();\n const curated = servedCuratedTools.find(\n (tool) => tool.name === request.params.name\n );\n // runTool here as well as inside the curated handlers: it maps an HttpError\n // raised outside a handler body — a missing API key when the SDK client is\n // first built (src/specgen/context.ts) — onto a 401 tool result instead of a\n // protocol-level crash.\n // Curated tools get the same argument-shape gate as generated ones, from\n // their own inputSchema. Before this they read only the keys they knew,\n // so a misnamed argument produced a confident wrong answer (see\n // validateArguments). Generated tools run the gate inside dispatch.\n const rejected =\n curated && !curated.lenientArguments\n ? validateArguments(\n curated.inputSchema as { required?: unknown; properties?: unknown },\n args\n )\n : null;\n const result =\n rejected ??\n (await runTool(() =>\n curated\n ? curated.handler(ctx, args)\n : dispatchTool(request.params.name, args)\n ));\n logToolCall({\n tool: request.params.name,\n caller,\n ok: result.ok,\n status: result.status,\n durationMs: Date.now() - startedAt,\n });\n if (opts.analytics) {\n captureToolCall(ctx.apiKey, {\n tool: request.params.name,\n ok: result.ok,\n status: result.status,\n durationMs: Date.now() - startedAt,\n args: recordedArgumentValues(curated?.recordedArguments, args),\n guideKind: curated?.recordedGuideKind?.(args),\n ...opts.analytics,\n });\n }\n opts.onToolResult?.(request.params.name, result.status);\n // A 401 from the API proves a cached \"valid\" credential verdict wrong\n // before its TTL — let the shell drop it.\n if (!result.ok && result.status === 401) opts.onUnauthorized?.();\n\n // On errors, attach a recovery hint by status class — the bare-client\n // (no-skills) path self-corrects from these instead of dead-ending. A hint\n // already on the payload wins: dispatch/runtime derive precise 429 wait\n // instructions from the response headers, and the generic \"pause briefly\"\n // text must not clobber them.\n const payload = result.ok\n ? result.payload\n : withRecoveryHint(result, callShapeOnlyTools.has(request.params.name));\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n isError: !result.ok,\n };\n });\n\n async function dispatchTool(\n name: string,\n args: Record<string, unknown>\n ): Promise<ToolResult> {\n const tool = generatedTools.find((candidate) => candidate.name === name);\n if (!tool)\n return {\n ok: false,\n status: 404,\n payload: { error: `unknown tool ${name}` },\n };\n return dispatchGeneratedTool(ctx.sdk, tool, args);\n }\n\n return server;\n}\n\nconst SHAPE_HINT =\n \"Input shape mismatch: check this tool's schema for required fields. For job payloads, the worker's release config defines the expected input object — fix the payload and retry; don't abandon the task.\";\n\n// Upstream answers business-rule failures with a 400 too: no capacity, no\n// balance, conflicting filters. Calling those an input-shape mismatch sent\n// agents re-reading a schema they had followed exactly, so a 400 whose detail\n// names one of those causes gets a hint about that cause instead. The shape\n// hint stays for real validation failures (a 422, or a 400 carrying field\n// errors) and for anything unrecognised.\nconst DETAIL_HINTS: ReadonlyArray<readonly [RegExp, string]> = [\n [\n /no longer any instances available|not enough free GPUs/i,\n \"Capacity, not input: the request is valid but no machine can take it right now. Don't change the payload shape. Retry with another GPU type, data center, cloud, CUDA version or count, or try again later. For a stopped Pod, its host's GPUs are taken; that Pod can only start once they free up.\",\n ],\n [\n /at least \\$\\d|insufficient (?:funds|balance)|\\bbalance\\b/i,\n 'Account balance, not input: this operation needs funds on the account. Ask the user to add credit in the Runpod console; list-billing shows recent spend.',\n ],\n [\n /mutually exclusive|cannot be combined with/i,\n 'Two arguments conflict: send only one of them and leave the other out entirely. Do not change anything else.',\n ],\n];\n\nfunction errorHint(status: number, detail?: string): string | undefined {\n if (status === 400 && detail) {\n for (const [pattern, hint] of DETAIL_HINTS)\n if (pattern.test(detail)) return hint;\n // A 400 with a bare \"Unauthorized\" detail from a write the same key can\n // otherwise make is upstream's answer for an unfunded account.\n if (/^unauthorized$/i.test(detail.trim()))\n return 'Upstream refused this write. With a key that can read, this usually means the account has no balance: ask the user to check their balance in the Runpod console before retrying.';\n }\n if (status === 400 || status === 422) return SHAPE_HINT;\n if (status === 401) return 'The Runpod API key is missing or invalid.';\n if (status === 402)\n return 'Check your account balance in the Runpod console before retrying billable operations; list-billing shows the recent spend behind it.';\n if (status === 403)\n return 'Check that this API key has permission for the requested resource and operation. Review its permissions in the Runpod console before retrying. A permission error on a resource you did not create is final: report it rather than retrying.';\n if (status === 404)\n return 'No such resource on this account: verify the id with the matching list- tool before retrying.';\n if (status === 429)\n return 'Rate limited: pause briefly, then retry the same call.';\n if (status >= 500)\n return 'Upstream Runpod error: retry once; if it persists, report it as an API-side failure.';\n return undefined;\n}\n\nconst CALL_SHAPE_ONLY_HINT = `This tool lists its call shape only; ${DESCRIBE_TOOL_NAME} serves the full argument schema.`;\n\nfunction withRecoveryHint(\n result: ToolResult,\n listsCallShapeOnly = false\n): Record<string, unknown> {\n const payload = asRecord(result.payload) ?? { error: result.payload };\n const hint =\n payload.hint ??\n asRecord(payload.detail)?.hint ??\n errorHint(result.status, detailText(payload));\n const shapeRejected = result.status === 400 || result.status === 422;\n return {\n ...payload,\n hint:\n listsCallShapeOnly && shapeRejected\n ? [hint, CALL_SHAPE_ONLY_HINT].filter(Boolean).join(' ')\n : hint,\n };\n}\n\n// The upstream reason, wherever the error payload carries it. Field-level\n// validation errors are not a detail: they mean the shape really is wrong.\nfunction detailText(payload: Record<string, unknown>): string | undefined {\n if (Array.isArray(payload.errors) && payload.errors.length) return undefined;\n const detail = payload.detail ?? payload.error;\n if (typeof detail === 'string') return detail;\n const nested = asRecord(detail);\n return typeof nested?.detail === 'string' ? nested.detail : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","// ============== 429 RATE-LIMIT HINT ==============\n// A 429's bare \"rate limit exceeded\" invites the worst possible agent\n// response: retrying immediately. This turns one into a wait instruction,\n// reading the IETF `RateLimit` field and `Retry-After`. Kept out of the HTTP\n// client because it shares nothing with it — two strings in, one string out —\n// and because both the client and the SSE log reader need it.\n\n// No window names or numbers here: this same client serves the serverless host\n// (api.runpod.ai), whose quota shape this repo doesn't document, so naming\n// minute/hour/day windows would assert a REST fact somewhere it may not hold.\nconst GENERIC_RATE_LIMIT_HINT =\n 'rate limited — back off before retrying, and pace bulk operations';\n\n// The longest window this API documents is a day; the slack covers an\n// undocumented serverless policy without printing \"~1157407408 days\" for a\n// broken or hostile header, which the digit count alone would not bound.\n// Rejecting is cheap either way: a discarded reset never shortens the wait —\n// it hedges it when another source still answers, and otherwise leaves the\n// \"no usable reset time\" clause to say so outright.\nconst MAX_PLAUSIBLE_WAIT_S = 7 * 86400;\n\n// One window reporting zero requests left. `window` is null when the name was\n// unreadable — the reset is independently trustworthy, and dropping the item\n// would throw away a correct number to avoid printing a doubtful name.\n// `resetS` is null when the window sent no readable `t`: the parameter is\n// optional, and a value that is unparseable (`t=1.5`), implausible (past the\n// cap) or valueless (`t` alone) all read the same way — absent. The member\n// still counts, because its `r` is what said the window is out.\ninterface ExhaustedWindow {\n window: string | null;\n resetS: number | null;\n}\n\n// A count of remaining requests. Only ever compared against zero, so its\n// magnitude doesn't matter — but blank must not pass: `Number('')` is 0, which\n// would read `\"hour\";r=;t=` as a real exhausted window.\nfunction remainingRequests(raw: string | undefined): number | null {\n const value = raw?.trim();\n return value && /^\\d+$/.test(value) ? Number(value) : null;\n}\n\n// A number of seconds to wait, from `t` or from `Retry-After`. Both are plain\n// digit strings — `1.5`, `-30`, `0x10` and `1e3` are not, and `Number()` would\n// happily coerce every one of them.\nfunction waitSeconds(raw: string | null | undefined): number | null {\n const value = raw?.trim();\n if (!value || !/^\\d+$/.test(value)) return null;\n const seconds = Number(value);\n return seconds <= MAX_PLAUSIBLE_WAIT_S ? seconds : null;\n}\n\n// A window name, or null if it isn't one. The name lands verbatim in an error\n// message an agent reads, so validate rather than sanitize — including its\n// length. Truncating would print a name that isn't in the header, which is the\n// same defect as stripping the parts that don't belong: `\"a,b\"` reported as\n// \"the b quota\". A quoted name takes any UNESCAPED string character, so\n// `\"gpu hour\"` is named rather than dropped; a `\\`-escape or a display string\n// is legal but unsupported, and dropping the name beats printing one we\n// haven't unescaped. Bare names follow the token grammar.\nconst WINDOW_NAME_RE =\n /^(?:\"([\\x20-\\x21\\x23-\\x5b\\x5d-\\x7e]{1,32})\"|([A-Za-z*][A-Za-z0-9!#$%&'*+.^_`|~:/-]{0,31}))$/;\nfunction windowName(raw: string): string | null {\n const match = WINDOW_NAME_RE.exec(raw.trim());\n return match ? (match[1] ?? match[2]) : null;\n}\n\n// A parameter value that is a complete quoted string and nothing else. Testing\n// only the first and last character would pass `pk=\"x\" \"minute\"`, where a\n// second item was glued on after a legal value — the same merge as below, one\n// quote further along.\nconst QUOTED_VALUE_RE = /^\"(?:[\\x20-\\x21\\x23-\\x5b\\x5d-\\x7e]|\\\\[\"\\\\])*\"$/;\n// A display string is a legal parameter value too (`%\"caf%c3%a9\"`). Reading it\n// as malformed would silently collapse every hint on the day the API adds one,\n// which is the failure this file exists to avoid — so match it, still whole.\nconst DISPLAY_VALUE_RE =\n /^%\"(?:[\\x20-\\x21\\x23-\\x24\\x26-\\x5b\\x5d-\\x7e]|\\\\|%[0-9a-f]{2})*\"$/;\n\n// Whether a `;`-separated chunk is a well-formed parameter. A dropped comma\n// glues the next item onto the previous parameter's VALUE — `t=3600 \"minute\"`,\n// or `t=3600 minute` in the token form — and last-wins then merges the two\n// items under the FIRST one's name and the SECOND one's reset, which is how a\n// 3600s lockout gets answered with \"wait ~10s\". A bare value can hold no\n// whitespace (every unquoted item type excludes it) and no quote, so either\n// means two items ran together. The draft says a malformed field MUST be\n// ignored wholesale; dropping just the item keeps more signal and still never\n// over-reports, because `dropped` forces the \"at least\".\nfunction isWellFormedParam(param: string): boolean {\n const eq = param.indexOf('=');\n const key = (eq === -1 ? param : param.slice(0, eq)).trim();\n if (key.includes('\"')) return false;\n if (eq === -1) return true;\n const value = param.slice(eq + 1).trim();\n if (value.startsWith('\"')) return QUOTED_VALUE_RE.test(value);\n if (value.startsWith('%\"')) return DISPLAY_VALUE_RE.test(value);\n return !/[\\s\"]/.test(value);\n}\n\n// Split on `sep` only where it isn't inside a quoted string. A plain\n// `String.split` cuts `\"a,b\";r=0;t=1812` — a legal window name — in half,\n// losing that window's r/t entirely, and if a shorter window survives alongside\n// it the hint confidently reports the shorter wait. Same for a vendor parameter\n// the draft leaves untyped (`acme-scope=\"a,b\"`). Strings are the only construct\n// that can hide a delimiter: `pk` is a byte sequence (`pk=:QXBwLTk5OQ==:`),\n// whose base64 alphabet holds neither. An unterminated quote yields one chunk,\n// which then fails validation — as a name if the quote opened in the name\n// position, as a parameter otherwise. Malformed in, generic out.\nfunction splitOutsideStrings(input: string, sep: ',' | ';'): string[] {\n const parts: string[] = [];\n let current = '';\n let inString = false;\n // A display string opens with `%\"`, and inside one a backslash is a literal\n // character rather than an escape — treating it as an escape would eat the\n // closing quote and swallow the rest of the field.\n let inDisplay = false;\n let escaped = false;\n let prev = '';\n for (const ch of input) {\n if (escaped) escaped = false;\n else if (inString && !inDisplay && ch === '\\\\') escaped = true;\n else if (ch === '\"') {\n if (!inString) inDisplay = prev === '%';\n inString = !inString;\n } else if (ch === sep && !inString) {\n parts.push(current);\n current = '';\n prev = ch;\n continue;\n }\n current += ch;\n prev = ch;\n }\n parts.push(current);\n return parts;\n}\n\n// Split-based rather than one regex: the field is a structured-field list, so\n// params may be reordered (`\"hour\";t=1724;r=0`), spaced, or carry unknown\n// vendor keys, and `t` may be absent — a pattern pinned to `r=<n>;t=<n>` yields\n// nothing on variants that mean the same thing, and silence here costs the\n// specifics exactly when they matter. Never throws.\n//\n// `dropped` reports whether anything was thrown away unread — only a malformed\n// item, since an unreadable name keeps its numbers. It has to reach the caller:\n// otherwise a discarded `r=0;t=3600` lets a readable 10-second sibling answer\n// as if it were the whole truth.\ninterface ParsedWindows {\n windows: ExhaustedWindow[];\n dropped: boolean;\n}\n\n// A member's parameters, and whether reading them left `r` or `t` unreadable.\n// Three tells, the first two being shapes a lost comma produces:\n// - a valueless parameter FOLLOWED BY `r` or `t`. Valueless is the only legal\n// way to send a Boolean-true flag (RFC 9651 §3.1.2: a true value MUST be\n// omitted), but it is also exactly what a glued bare-token name looks like —\n// `\"minute\";t=10;hour;r=0` is one item with an `hour` flag, or two items and\n// a lost comma, and nothing in the field tells them apart. Only a number\n// AFTER the flag can have been misattributed, so a trailing flag\n// (`\"hour\";r=0;t=3600;acme-flag`) costs nothing and is kept.\n// - `r` or `t` twice. RFC 9651's note on parsing parameters — \"when duplicate\n// parameter keys are encountered, all but the last instance are ignored\" —\n// carries no RFC 2119 keyword, and `minute;r=0;t=2876;minute;r=0;t=1641` is\n// the same glue, where last-wins answers a 2876s lockout with 1641s.\n// - `r` or `t` sent valueless at all, glue or not. A bare flag is Boolean\n// true, so `\"hour\";r=0;t` states no reset and `\"hour\";r=0;r` never says\n// the window is out — the value simply isn't there to read.\n// In every case we can't say what the number is, or whether it is ours, so\n// don't pick one.\nfunction readParams(params: string[]): {\n values: Map<string, string>;\n unreadable: boolean;\n} {\n const values = new Map<string, string>();\n let unreadable = false;\n let valuelessAt = -1;\n for (const [index, param] of params.entries()) {\n const eq = param.indexOf('=');\n // Keys are lowercase in the grammar; fold case rather than miss an\n // exhausted window over a server sending `R=0`.\n const key = (eq === -1 ? param : param.slice(0, eq)).trim().toLowerCase();\n if (!key) continue;\n if (eq === -1) {\n // A bare `r`/`t` is Boolean true, and parameters are last-wins, so the\n // member's own count or reset is not there to read — `t=3599;t` must not\n // quote 3599 as fact, nor `r=0;t=3599;r` call a window exhausted unasked.\n // Checked before the `continue`, or neither would be caught at all.\n //\n // The two differ in what survives. `r` is REQUIRED, so losing it loses\n // the only thing that says the window is out: nothing to report. `t` is\n // optional, and a member that states `r=0` with no readable reset is an\n // ordinary \"exhausted, reset unknown\" — already modelled, and already\n // what an unparseable `t=1.5` produces. Dropping the whole member there\n // would throw away a readable `r=0` to avoid an unreadable `t`.\n if (key === 'r') unreadable = true;\n if (key === 't') values.delete('t');\n valuelessAt = index;\n continue;\n }\n // A repeated `r`/`t`, or one that follows a valueless flag: either way\n // we can't say which name the number belongs to.\n if (\n (key === 'r' || key === 't') &&\n (values.has(key) || (valuelessAt !== -1 && index > valuelessAt))\n ) {\n unreadable = true;\n }\n values.set(key, param.slice(eq + 1));\n }\n return { values, unreadable };\n}\n\nfunction parseExhaustedWindows(header: string | null): ParsedWindows {\n if (!header) return { windows: [], dropped: false };\n const windows: ExhaustedWindow[] = [];\n let dropped = false;\n for (const item of splitOutsideStrings(header, ',')) {\n if (item.trim() === '') continue;\n const [rawName, ...params] = splitOutsideStrings(item, ';');\n if (!params.every(isWellFormedParam)) {\n dropped = true;\n continue;\n }\n const { values, unreadable } = readParams(params);\n if (unreadable) {\n dropped = true;\n continue;\n }\n // draft-11 §4.1 makes `r` REQUIRED, so a member without a readable one is\n // malformed: we know a window exists but not whether it is exhausted, which\n // hides at least as much as an item rejected outright. A readable non-zero\n // `r` is different — that window simply has requests left.\n const remaining = remainingRequests(values.get('r'));\n if (remaining === null) {\n dropped = true;\n continue;\n }\n if (remaining !== 0) continue;\n // A name we can't read costs us the name, not the reset behind it.\n windows.push({\n window: windowName(rawName),\n resetS: waitSeconds(values.get('t')),\n });\n }\n return { windows, dropped };\n}\n\n// \"1724s\" is easy to skim past; \"~29 minutes\" is not, and an agent that grasps\n// the scale is the one that stops retrying. Exact seconds stay in the string,\n// so the unit is only ever a reading aid — but an agent that skims the unit and\n// not the parenthesis must not be sent back early, so each tier rounds UP: 140s\n// reads \"~3 minutes\", never \"~2 minutes\". The minute and hour tiers hand over\n// before their count reaches three digits, a reading as hard to skim as the raw\n// seconds it would replace.\nfunction humanWait(seconds: number): string {\n if (seconds < 120) return `~${seconds}s`;\n if (seconds < 3600)\n return `~${Math.ceil(seconds / 60)} minutes (${seconds}s)`;\n if (seconds < 2 * 86400) {\n const hours = Math.ceil(seconds / 3600);\n return `~${hours} hour${hours === 1 ? '' : 's'} (${seconds}s)`;\n }\n // The days tier opens at two days, so it is never singular.\n return `~${Math.ceil(seconds / 86400)} days (${seconds}s)`;\n}\n\n// Name the exhausted quota and say how long to wait, from the two headers v2\n// sends on a 429 — `Retry-After` (seconds) and `RateLimit` (live per-window\n// state, `\"minute\";r=0;t=12, \"hour\";r=2800;t=1812`, where r = calls left and\n// t = seconds to reset).\n//\n// Report the LONGEST wait either header justifies. draft-11 §7 says Retry-After\n// MUST take precedence, but §6 says a server SHOULD NOT send one earlier than\n// the end of the effective window, and this API's is documented \"per the\n// exceeded window\" (see the vendored spec) — i.e. it can be earlier.\n// RFC 9110 §10.2.3 defines Retry-After as how long a client \"ought to wait\" and\n// sets no upper bound (its \"minimum time\" wording is scoped to 3xx), so waiting\n// longer conforms. §7's \"MAY be ignored\" is permission, not obligation, and\n// max() never waits less than Retry-After asks — so this declines the\n// permission rather than violating the precedence. Windows can read r=0\n// together — a loop pacing itself at the 60/min quota sits at minute r=0, and\n// 3000/hr is an exact multiple of 60, so the call that zeroes the hour is also\n// the 60th of its minute — and Retry-After then describes only the window that\n// rejected THIS request. Obeying it alone sends the agent back in 12s to a\n// quota that is out for another half hour. Hence \"wait ~N\" rather than \"the\n// hour quota resets in ~N\": the number is an instruction, not a claim about the\n// named window, so the two can never contradict each other. Generic guidance\n// when neither header is usable — the v1 REST API sends neither, and this\n// client also serves the serverless host, which this repo doesn't document.\nexport function rateLimitHint(\n rateLimitHeader: string | null,\n retryAfterHeader?: string | null\n): string {\n const { windows, dropped } = parseExhaustedWindows(rateLimitHeader);\n // Longest reset first; a window that sent no `t` sorts last, since an\n // unknown reset can't outrank a known one. Ties keep header order.\n windows.sort((a, b) => (b.resetS ?? -1) - (a.resetS ?? -1));\n // Typed explicitly: `strict` is on but `noUncheckedIndexedAccess` is not, so\n // `windows[0]` types as non-optional and every `?.` below reads as dead. It\n // isn't — `windows` is empty on every generic-hint path.\n const longestWindow: ExhaustedWindow | undefined = windows[0];\n // A wait of zero — from `t` or from `Retry-After` — is the one instruction a\n // 429 can't mean, so it is not a wait on offer from either source. An\n // HTTP-date Retry-After (legal per RFC 9110, not what this API sends) or\n // junk is likewise rejected, leaving the RateLimit reset to answer.\n const waitCandidates = [\n waitSeconds(retryAfterHeader),\n longestWindow?.resetS,\n ].filter((n): n is number => typeof n === 'number' && n > 0);\n const waitS = waitCandidates.length ? Math.max(...waitCandidates) : null;\n // A Retry-After we couldn't read is a missed instruction, not an absent one:\n // the server named a delay, we don't know it, and it may be far longer than\n // anything RateLimit says. An HTTP-date, `3600.5`, `+1800` and a value past\n // the plausibility cap all land here, hedging the same way they would if the\n // unreadable value had arrived in `t`. A readable `0` is not unreadable.\n const retryAfterUnreadable =\n typeof retryAfterHeader === 'string' &&\n retryAfterHeader.trim() !== '' &&\n waitSeconds(retryAfterHeader) === null;\n // The generic hint is for a response that withheld nothing: no header, no\n // exhausted window, no delay stated. It must not absorb a response that DID\n // state something we failed to read — that would hand back the file's mildest\n // wording precisely when the most was hidden, and a header stating an\n // unreadable day-long lockout would read softer than one stating no reset at\n // all. Anything unread falls through to \"no usable reset time\" instead.\n if (!longestWindow && waitS === null) {\n if (!retryAfterUnreadable) return GENERIC_RATE_LIMIT_HINT;\n }\n // \"the hour quota is exhausted\" rather than \"rate limited on the hour quota\":\n // the response body names the window that rejected THIS request, which in the\n // co-exhaustion case is a different one. Both statements are true, and this\n // phrasing doesn't claim to be the other.\n const namedClause = longestWindow?.window\n ? `the ${longestWindow.window} quota is exhausted`\n : '';\n // Exhausted, but nothing usable said when it clears. A number here would be\n // invented, which is the defect this function exists to avoid.\n if (waitS === null) {\n const cause = namedClause\n ? `${namedClause}, but the response gave no usable reset time`\n : 'the response gave no usable reset time';\n return `rate limited — ${cause}; back off substantially before retrying, and pace bulk operations`;\n }\n // This number is a floor, not the answer, whenever the header held something\n // we couldn't read: another exhausted window that omitted its reset, or an\n // item dropped whole. A quantified 10s window must not speak for a silent\n // day-long one.\n const hedge =\n dropped || retryAfterUnreadable || windows.some((w) => w.resetS === null)\n ? 'at least '\n : '';\n const wait = `wait ${hedge}${humanWait(waitS)} before retrying, and pace bulk operations`;\n return `rate limited — ${namedClause ? `${namedClause}; ` : ''}${wait}`;\n}\n\n// The one 429-enrichment used by both the generated-tool dispatcher and the\n// runtime client: spread the upstream error payload and attach the concrete\n// wait instruction derived from the response headers. Kept here so a change\n// to hint precedence lands in every consumer at once.\nexport function withRateLimitHint(\n payload: unknown,\n headers: { get(name: string): string | null }\n): unknown {\n // Gateways can send plain text or JSON primitives. Preserve that detail\n // inside an object so every 429 can carry the same recovery hint.\n const detail =\n typeof payload === 'object' && payload !== null\n ? (payload as Record<string, unknown>)\n : { error: payload };\n return {\n ...detail,\n hint: rateLimitHint(headers.get('ratelimit'), headers.get('retry-after')),\n };\n}\n","import type { ToolResult } from '../dispatch.js';\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\n\n/** Preserve status even when the API error has no body; attach quota guidance. */\nexport function restError(response: Response, error: unknown): ToolResult {\n const payload = error ?? {\n error: response.statusText || `HTTP ${response.status}`,\n };\n return {\n ok: false,\n status: response.status,\n payload:\n response.status === 429\n ? withRateLimitHint(payload, response.headers)\n : payload,\n };\n}\n","// Executes a generated tool call by mapping its arguments onto the SDK client:\n// path params substitute into the URL template, query params pass through, and\n// the optional \"body\" argument becomes the request body.\n\nimport type { RunpodClient } from '@runpod/typescript-api-sdk';\nimport type { GeneratedTool } from './generated/tools.gen.js';\nimport { restError } from './clients/rest-result.js';\n\n// A client caches tools/list when it connects. If the served surface changes\n// under a live session — a release, or a deployment alias moving — the client\n// keeps validating calls against the OLD schema and silently strips arguments\n// the new schema requires. The agent cannot see this: from inside the session\n// its schema looks authoritative, so it retries variations of a shape the\n// server will never accept. A production report burned a session that way,\n// sending flat v1 arguments (gpuTypeIds, imageName) at a body-shaped\n// create-pod and then re-sending them nested under a `body` key its own client\n// dropped, leaving `received: []`. Reconnecting is the only fix, so name it on\n// exactly the two errors a stale schema produces.\nconst STALE_SCHEMA_HINT =\n 'If this disagrees with the schema you hold, your tool list may be cached from an earlier version of this server. Reconnect the Runpod MCP server (in Claude Code, /mcp) to refresh tools/list, then call again — do not retry variations of the same argument shape.';\n\nexport interface ToolResult {\n ok: boolean;\n status: number;\n payload: unknown;\n}\n\n// Argument-shape gate, shared by every tool on the server. Two checks, both\n// read from the tool's own JSON Schema so no tool needs per-tool code:\n//\n// Missing required argument. Without this an unresolved path placeholder\n// reaches the API and comes back as a resource 404 (\"gpu type not found\"),\n// sending the agent off to re-verify an id that was never sent.\n//\n// Unknown argument. Handlers only read declared keys, so an argument with a\n// plausible-but-wrong name used to vanish in silence and the call still went\n// out — `includeAvailability` (the v1 spelling) on list-gpu-types returned a\n// 200 with no availability fields at all, which reads as \"priced and in stock\"\n// if you trust the request you thought you made. The curated tools had the\n// same hole until the 2026-09-09 release smoke: stream-pod-logs called with\n// `id` instead of `podId` fetched /pods/undefined/logs and answered 404\n// \"pod not found\" with a hint to re-verify the id. A wrong answer is worse\n// than an error, so name the key and list what the tool accepts.\nexport function validateArguments(\n inputSchema: { required?: unknown; properties?: unknown },\n args: Record<string, unknown>\n): ToolResult | null {\n const required = (inputSchema.required ?? []) as string[];\n const missing = required.filter(\n (name) => args[name] === undefined || args[name] === null\n );\n if (missing.length) {\n return {\n ok: false,\n status: 400,\n payload: {\n error: `Missing required argument${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}`,\n expected: required,\n received: Object.keys(args),\n // A missing path/query param is an ordinary omission. A missing `body`\n // is the shape a stale schema produces, so only that one earns the hint.\n ...(missing.includes('body') ? { hint: STALE_SCHEMA_HINT } : {}),\n },\n };\n }\n const allowed = new Set(\n Object.keys((inputSchema.properties ?? {}) as Record<string, unknown>)\n );\n const unknown = Object.keys(args).filter((name) => !allowed.has(name));\n if (unknown.length) {\n return {\n ok: false,\n status: 400,\n payload: {\n error: `Unknown argument${unknown.length > 1 ? 's' : ''}: ${unknown.join(', ')}`,\n accepted: [...allowed],\n hint: STALE_SCHEMA_HINT,\n },\n };\n }\n return null;\n}\n\nexport async function dispatchGeneratedTool(\n client: RunpodClient,\n tool: GeneratedTool,\n args: Record<string, unknown>\n): Promise<ToolResult> {\n const rejected = validateArguments(tool.inputSchema, args);\n if (rejected) return rejected;\n\n const required = new Set((tool.inputSchema.required ?? []) as string[]);\n const pathParams: Record<string, unknown> = {};\n const query: Record<string, unknown> = {};\n for (const param of tool.params) {\n if (args[param.name] === undefined) continue;\n // Clients that run OpenAI-style strict tool schemas must send every\n // property, so an optional filter they mean to leave out arrives as null,\n // \"\" or []. Upstream counts any present value as supplied: cudaVersions: []\n // next to minCudaVersion is a 400 \"mutually exclusive\", lastN: null next to\n // startTime is \"lastN cannot be combined\", and cursor: \"\" is a 422 invalid\n // cursor on the first page. None of those can be meant as a value, so an\n // empty optional query param is treated as omitted.\n if (\n param.location === 'query' &&\n !required.has(param.name) &&\n isEmptyValue(args[param.name])\n )\n continue;\n if (param.location === 'path') {\n pathParams[param.name] = args[param.name];\n continue;\n }\n const value = args[param.name];\n // `explode: false` in the spec means form style with ONE comma-joined\n // value. openapi-fetch's default serializer repeats the key per array\n // item instead, and upstream rejects that with \"parameter 'x' is not\n // exploded, but is specified multiple times\" — so a multi-value filter\n // fails while a single value passes, which is exactly the shape of bug\n // that survives casual testing.\n query[param.name] =\n param.explode === false && Array.isArray(value) ? value.join(',') : value;\n }\n\n // Some MCP clients serialize a nested object argument as a JSON string\n // rather than an object. Forwarding that verbatim makes upstream reject the\n // whole request with \"$: got string, want object\" — which never mentions\n // that the body was stringified, so the agent re-reads the schema it already\n // followed and retries the same shape. Accept the string and parse it; a\n // body that is not valid JSON is the client's error, so name it plainly.\n let requestBody = args.body;\n if (tool.hasBody && typeof requestBody === 'string') {\n try {\n requestBody = JSON.parse(requestBody);\n } catch {\n return {\n ok: false,\n status: 400,\n payload: {\n error:\n 'The body argument arrived as a string that is not valid JSON. Send body as an object.',\n },\n };\n }\n }\n\n // Some clients stringify every scalar inside a nested body (disk: \"20\",\n // workers.max: \"1\"), and upstream rejects each one with \"$.disk: got string,\n // want integer\". The body schema says what each field is, so a string that\n // is exactly a number or boolean where the schema wants one is converted\n // back. Anything else is forwarded untouched for upstream to judge.\n if (tool.hasBody && requestBody !== undefined) {\n const properties = (tool.inputSchema.properties ?? {}) as Record<\n string,\n unknown\n >;\n const defs = ((tool.inputSchema as { $defs?: unknown }).$defs ??\n {}) as Record<string, unknown>;\n requestBody = coerceScalars(requestBody, properties.body, defs);\n }\n\n // openapi-fetch is typed per literal path; generated dispatch is generic by\n // construction, so the client is narrowed to the structural shape of a verb\n // call rather than asserted to any.\n type VerbCall = (\n path: string,\n init: Record<string, unknown>\n ) => Promise<{ data?: unknown; error?: unknown; response: Response }>;\n const verbs = client as unknown as Record<string, VerbCall>;\n const { data, error, response } = await verbs[tool.method](tool.path, {\n params: { path: pathParams, query },\n ...(tool.hasBody && requestBody !== undefined ? { body: requestBody } : {}),\n });\n\n // Branch on the RESPONSE, not on `error`: openapi-fetch returns\n // `{ error: undefined }` for a non-OK response with an empty body\n // (Content-Length: 0 — a WAF/edge answering a bare 429/403/502 does this),\n // and treating that as success would tell the agent a failed call worked\n // and bypass the 401 onUnauthorized gate.\n if (!response.ok) return restError(response, error);\n return {\n ok: true,\n status: response.status,\n payload: data ?? { status: response.status },\n };\n}\n\nfunction isEmptyValue(value: unknown): boolean {\n return (\n value === null || value === '' || (Array.isArray(value) && !value.length)\n );\n}\n\ntype Schema = Record<string, unknown>;\n\nfunction asSchema(value: unknown): Schema | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Schema)\n : undefined;\n}\n\n// Follows local `#/$defs/Name` refs. Depth-capped so a self-referencing\n// definition cannot loop.\nfunction resolveSchema(\n schema: unknown,\n defs: Record<string, unknown>,\n depth = 0\n): Schema | undefined {\n const node = asSchema(schema);\n if (!node || depth > 16) return node;\n const ref = node.$ref;\n if (typeof ref === 'string' && ref.startsWith('#/$defs/'))\n return resolveSchema(defs[ref.slice('#/$defs/'.length)], defs, depth + 1);\n return node;\n}\n\n// Every schema that applies to a value: the node itself plus its allOf,\n// anyOf and oneOf branches, refs resolved.\nfunction branches(\n schema: unknown,\n defs: Record<string, unknown>,\n depth = 0\n): Schema[] {\n const node = resolveSchema(schema, defs);\n if (!node || depth > 16) return [];\n const out = [node];\n for (const key of ['allOf', 'anyOf', 'oneOf']) {\n const list = node[key];\n if (Array.isArray(list))\n for (const sub of list) out.push(...branches(sub, defs, depth + 1));\n }\n return out;\n}\n\nfunction types(schemas: Schema[]): Set<string> {\n const out = new Set<string>();\n for (const s of schemas) {\n if (typeof s.type === 'string') out.add(s.type);\n else if (Array.isArray(s.type))\n for (const t of s.type) if (typeof t === 'string') out.add(t);\n }\n return out;\n}\n\nconst NUMERIC = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/;\n\nexport function coerceScalars(\n value: unknown,\n schema: unknown,\n defs: Record<string, unknown>,\n depth = 0\n): unknown {\n if (depth > 32) return value;\n const applicable = branches(schema, defs);\n if (!applicable.length) return value;\n const allowed = types(applicable);\n\n if (typeof value === 'string') {\n // A string field stays a string even when it looks like a number.\n if (allowed.has('string')) return value;\n if (\n (allowed.has('integer') || allowed.has('number')) &&\n NUMERIC.test(value)\n ) {\n const n = Number(value);\n if (allowed.has('number') || Number.isInteger(n)) return n;\n }\n if (allowed.has('boolean') && (value === 'true' || value === 'false'))\n return value === 'true';\n return value;\n }\n\n if (Array.isArray(value)) {\n const items = applicable.map((s) => s.items).filter(Boolean);\n if (!items.length) return value;\n return value.map((item) =>\n coerceScalars(item, { anyOf: items }, defs, depth + 1)\n );\n }\n\n const object = asSchema(value);\n if (!object) return value;\n const out: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(object)) {\n const childSchemas: unknown[] = [];\n for (const s of applicable) {\n const props = asSchema(s.properties);\n if (props && key in props) childSchemas.push(props[key]);\n else if (asSchema(s.additionalProperties))\n childSchemas.push(s.additionalProperties);\n }\n out[key] = childSchemas.length\n ? coerceScalars(child, { anyOf: childSchemas }, defs, depth + 1)\n : child;\n }\n return out;\n}\n","// Code generated from specgen/spec/openapi.yaml by specgen/generator/generate-tools.ts; DO NOT EDIT.\n\nexport interface GeneratedToolParam {\n name: string;\n location: 'path' | 'query';\n /** Spec-declared `explode: false`: serialize an array as one comma-joined value. */\n explode?: false;\n}\n\n/** MCP tool annotations (tools/list `annotations`): behavioral hints hosts use\n * to decide what needs human approval. */\nexport interface ToolAnnotations {\n readOnlyHint: boolean;\n destructiveHint: boolean;\n idempotentHint: boolean;\n openWorldHint: boolean;\n}\n\nexport interface GeneratedTool {\n name: string;\n operationId: string;\n description: string;\n method: string;\n path: string;\n params: GeneratedToolParam[];\n hasBody: boolean;\n annotations: ToolAnnotations;\n /** Listed with its call shape only; describe-tool serves the full schema. */\n schemaOnDemand?: true;\n inputSchema: Record<string, unknown>;\n}\n\nexport const generatedTools: GeneratedTool[] = [\n {\n name: 'create-cluster',\n operationId: 'createCluster',\n description:\n \"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 — 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 — a bare registry property is rejected. Delete with delete-cluster when finished.\",\n method: 'POST',\n path: '/v2/clusters',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateClusterRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseMounts: {\n type: 'object',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n ClusterCompute: {\n type: 'object',\n additionalProperties: false,\n description:\n 'The homogeneous compute shape of a cluster. Every pod in the cluster is identical: `podCount` pods, each with `gpuCountPerPod` GPUs of type `gpuTypeId`. Total GPUs = `podCount` * `gpuCountPerPod`.',\n required: ['gpuTypeId', 'gpuCountPerPod', 'podCount'],\n properties: {\n gpuTypeId: {\n type: 'string',\n minLength: 1,\n description:\n 'GPU type for every pod in the cluster, as returned by GET /v2/catalog/gpus.',\n examples: ['NVIDIA H100 80GB HBM3'],\n },\n gpuCountPerPod: {\n type: 'integer',\n minimum: 1,\n description:\n \"Number of GPUs on each pod. Bounded above by the GPU type's per-cloud maximum (GpuType.maxCount); the upstream rejects values beyond it.\",\n examples: [8],\n },\n podCount: {\n type: 'integer',\n minimum: 2,\n maximum: 250,\n description: 'Number of pods (nodes) in the cluster.',\n examples: [4],\n },\n },\n },\n ClusterMounts: {\n description:\n 'Storage mounts for a cluster create: `persistent` or `network`, not both. Clusters cannot mount global volumes, so `global` is rejected.',\n allOf: [\n {\n $ref: '#/$defs/BaseMounts',\n },\n ],\n unevaluatedProperties: false,\n },\n ClusterType: {\n type: 'string',\n description:\n 'Cluster type. TRAINING is the generic distributed-training cluster; SLURM provisions a managed Slurm controller/compute topology; RAY provisions a managed Ray head/worker topology; APPLICATION is a general multi-node application cluster.',\n enum: ['APPLICATION', 'TRAINING', 'SLURM', 'RAY'],\n examples: ['TRAINING'],\n },\n CreateClusterRequest: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n required: ['name', 'type', 'compute'],\n description:\n 'Request body for creating a cluster. `compute` defines the homogeneous pod shape; the container configuration (image, env, ports, …) applies to every pod.',\n properties: {\n compute: {\n $ref: '#/$defs/ClusterCompute',\n },\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-training-cluster'],\n },\n type: {\n $ref: '#/$defs/ClusterType',\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n 'ID of a pod template to provision every member pod from: it supplies the container settings (image, args, disk, env, ports) and the registry credential for private images — the only private-image path for clusters. Mutually exclusive with the inline container fields (`image`, `args`, `entrypoint`, `cmd`, `disk`, `env`, `ports`, `mounts`). Must be a non-serverless template you can access.',\n examples: ['30zmvf89kd'],\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose. A cluster is always placed within a single data center.',\n example: ['US-TX-3'],\n },\n mounts: {\n $ref: '#/$defs/ClusterMounts',\n },\n startJupyter: {\n type: 'boolean',\n default: false,\n description:\n 'Start Jupyter on every member pod, as on pod create.',\n },\n startSsh: {\n type: 'boolean',\n default: false,\n description:\n \"Provision SSH access on every member pod: injects a PUBLIC_KEY environment variable carrying your account's registered SSH public key. Same semantics as the pod create flag.\",\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-delegation',\n operationId: 'createDelegation',\n description: 'Register an ECR delegation',\n method: 'POST',\n path: '/v2/registries/delegations',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateDelegationRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateDelegationRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['resource'],\n properties: {\n resource: {\n type: 'string',\n description: 'ECR resource ARN',\n examples: [\n 'arn:aws:ecr:us-east-2:418399314813:repository/runpod/deployment',\n ],\n },\n name: {\n type: ['string', 'null'],\n description: 'Optional name for the delegation',\n examples: ['my-delegation'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-endpoint',\n operationId: 'createEndpoint',\n description:\n \"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.\",\n method: 'POST',\n path: '/v2/serverless',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateEndpointRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseEndpointGpuConfig: {\n type: 'object',\n properties: {\n pools: {\n type: 'array',\n minItems: 1,\n description:\n 'Serverless GPU pool IDs (the `pool` field of `list-gpu-types`). Workers are placed on whichever listed pool has capacity; narrow to specific cards with `excludedTypes`. On update, `pools` and `excludedTypes` are replaced together, so sending `pools` alone clears the exclusions.',\n items: {\n type: 'string',\n },\n examples: [['ADA_24']],\n },\n excludedTypes: {\n type: 'array',\n uniqueItems: true,\n description:\n 'GPU type IDs to subtract from the selected pools — the `id` field of `list-gpu-types`, the same identifiers pods take in `gpu.id`. Workers run on every type in `pools` except these; omit to use the whole pool. A value outside `pools` is rejected. On update, restate them whenever you send `pools`, or they are cleared.',\n items: {\n type: 'string',\n pattern: '^\\\\s*[^-\\\\s]',\n },\n examples: [['NVIDIA L40']],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'GPUs per worker',\n examples: [1],\n },\n },\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n CreateEndpointGpuConfig: {\n description:\n \"GPU request for an endpoint create. Carries the CUDA constraints, which live here rather than at the body's top level so they are unrepresentable on a CPU endpoint.\",\n allOf: [\n {\n $ref: '#/$defs/BaseEndpointGpuConfig',\n },\n {\n type: 'object',\n required: ['pools'],\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n \"Acceptable CUDA versions for worker placement, as `major.minor`. Omit to accept any version (or inherit the template's constraint when creating from `templateId`).\",\n examples: [['12.8', '12.6']],\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for worker placement, as `major.minor`, compared numerically rather than as a decimal — so 12.11 is above 12.2. Use this for an open-ended floor and allowedCudaVersions for an exact set.',\n examples: ['12.1'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n CreateEndpointRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n if: {\n not: {\n required: ['templateId'],\n },\n },\n then: {\n required: ['image'],\n },\n },\n {\n type: 'object',\n required: ['name', 'type', 'scaling'],\n properties: {\n gpu: {\n $ref: '#/$defs/CreateEndpointGpuConfig',\n },\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-inference'],\n },\n scaling: {\n $ref: '#/$defs/EndpointScaling',\n },\n type: {\n allOf: [\n {\n $ref: '#/$defs/EndpointType',\n },\n ],\n description:\n 'Request-routing model. Required — it determines the valid scaler and request URLs, so it must be chosen explicitly on every create.',\n },\n cpu: {\n type: 'array',\n minItems: 1,\n uniqueItems: true,\n description:\n \"Eligible CPU configurations for each worker. Memory is derived from the selected flavor's catalog RAM multiplier. Exact duplicate configurations are rejected; the same flavor may be listed at different vCPU counts.\",\n items: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.',\n },\n flashboot: {\n allOf: [\n {\n $ref: '#/$defs/FlashBoot',\n },\n ],\n default: 'OFF',\n },\n networkVolumes: {\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'Network volume IDs.',\n deprecated: true,\n },\n mounts: {\n $ref: '#/$defs/EndpointMountsInput',\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n 'ID of a serverless template to base this endpoint on (must be serverless). Its container settings (image, args, disk, ports, env, registry) fill in what this body omits; body fields win, and `env` merges per key with body winning. Its allowedCudaVersions seeds `gpu.allowedCudaVersions` when the body omits it; pod-only flags are ignored. Copied once: later edits do not apply.',\n examples: ['30zmvf89kd'],\n },\n timeout: {\n type: 'integer',\n default: 300000,\n },\n workers: {\n allOf: [\n {\n $ref: '#/$defs/EndpointWorkers',\n },\n ],\n properties: {\n min: {\n type: 'integer',\n default: 0,\n },\n max: {\n type: 'integer',\n default: 3,\n },\n idleTimeout: {\n type: 'integer',\n default: 10,\n },\n },\n },\n },\n },\n ],\n unevaluatedProperties: false,\n if: {\n required: ['type'],\n properties: {\n type: {\n const: 'LOAD_BALANCER',\n },\n },\n },\n then: {\n properties: {\n scaling: {\n $ref: '#/$defs/RequestCountScaling',\n },\n },\n },\n },\n EndpointMount: {\n type: 'object',\n required: ['volumeId'],\n additionalProperties: false,\n description:\n 'A volume mounted on every worker, always at `/runpod-volume`. Custom paths are not supported yet.',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of a NetworkVolume (under `network`) or GlobalVolume (under `global`).',\n examples: ['vol_abc'],\n },\n },\n },\n EndpointMountsInput: {\n type: 'object',\n additionalProperties: false,\n description:\n \"Volumes to mount on the endpoint's workers. A `network` or `global` list that is present replaces the endpoint's current list of that kind; an empty list detaches it, and an omitted list is left unchanged.\",\n properties: {\n network: {\n type: 'array',\n description: 'Network volumes, at most one per data center.',\n items: {\n $ref: '#/$defs/EndpointMount',\n },\n },\n global: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/EndpointMount',\n },\n },\n },\n },\n EndpointScaling: {\n description:\n \"Autoscaling signal — a discriminated union on `type`: `QUEUE_DELAY` (queue-based endpoints only) or `REQUEST_COUNT`. The scaler is chosen independently of the endpoint's routing `type` and can be switched on update.\",\n oneOf: [\n {\n $ref: '#/$defs/QueueDelayScaling',\n },\n {\n $ref: '#/$defs/RequestCountScaling',\n },\n ],\n discriminator: {\n propertyName: 'type',\n mapping: {\n QUEUE_DELAY: '#/$defs/QueueDelayScaling',\n REQUEST_COUNT: '#/$defs/RequestCountScaling',\n },\n },\n },\n EndpointType: {\n type: 'string',\n description:\n 'Request-routing semantics for a modern serverless endpoint. `QUEUE` — submit asynchronous or synchronous jobs through the managed queue. `LOAD_BALANCER` — send requests directly to worker-defined HTTP paths.',\n 'x-enum-varnames': ['EndpointTypeQueue', 'EndpointTypeLoadBalancer'],\n enum: ['QUEUE', 'LOAD_BALANCER'],\n },\n EndpointWorkers: {\n type: 'object',\n additionalProperties: false,\n properties: {\n min: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum number of workers.',\n examples: [0],\n },\n max: {\n type: 'integer',\n minimum: 0,\n description: 'Maximum number of workers.',\n examples: [5],\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n maximum: 3600,\n description:\n 'Seconds before idle workers scale down. Not applicable to queue-based endpoints scaling on `requestCount` — rejected on create/update and omitted from responses for that combination.',\n examples: [5],\n },\n },\n },\n FlashBoot: {\n type: 'string',\n description:\n 'FlashBoot cold-start acceleration mode. `OFF` — disabled. `FLASHBOOT` — enabled. `PRIORITY_FLASHBOOT` — enabled with priority capacity',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n },\n QueueDelayScaling: {\n type: 'object',\n additionalProperties: false,\n description: 'Scale on queue wait time. Queue-based endpoints only.',\n required: ['type', 'queueDelay'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `QUEUE_DELAY` for this variant.',\n enum: ['QUEUE_DELAY'],\n },\n queueDelay: {\n type: 'number',\n format: 'float',\n minimum: 0.5,\n description:\n 'Adjusts the number of workers based on how long requests wait in the queue.',\n examples: [4],\n },\n },\n },\n RequestCountScaling: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Scale on concurrent in-flight requests per worker. Required for load-balancing endpoints; also selectable for queue-based.',\n required: ['type', 'requestCount'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `REQUEST_COUNT` for this variant.',\n enum: ['REQUEST_COUNT'],\n },\n requestCount: {\n type: 'integer',\n minimum: 1,\n description:\n 'Adjusts the number of workers based on active in-flight requests.',\n examples: [4],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-global-volume',\n operationId: 'createGlobalVolume',\n description:\n 'Create a global volume. Provisions a new global volume — 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`.',\n method: 'POST',\n path: '/v2/global-volumes',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateGlobalVolumeRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateGlobalVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n pattern: '[^\\\\p{Z}\\\\t-\\\\r
]',\n description:\n 'Human-readable name, 1–191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed.',\n examples: ['training-data'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-network-volume',\n operationId: 'createNetworkVolume',\n description:\n 'Create a network volume. Provisions a new network volume — 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`.',\n method: 'POST',\n path: '/v2/network-volumes',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateNetworkVolumeRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateNetworkVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'size', 'dataCenter'],\n properties: {\n dataCenter: {\n type: 'string',\n minLength: 1,\n description: 'Data center in which to create the volume',\n examples: ['EU-RO-1'],\n },\n name: {\n type: 'string',\n minLength: 1,\n description: 'Human-readable name',\n examples: ['my-dataset'],\n },\n size: {\n type: 'integer',\n minimum: 10,\n maximum: 4096,\n description: 'Storage to allocate in GB',\n examples: [50],\n },\n type: {\n allOf: [\n {\n $ref: '#/$defs/VolumeType',\n },\n ],\n description:\n \"Storage tier for the volume. Optional. When omitted, the volume is provisioned using the requested data center's default (primary) storage tier.\",\n },\n },\n },\n VolumeType: {\n type: 'string',\n description: 'Data center network volume storage type.',\n enum: ['STANDARD', 'HIGH_PERFORMANCE'],\n },\n },\n },\n },\n {\n name: 'create-pod',\n operationId: 'createPod',\n description:\n '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.',\n method: 'POST',\n path: '/v2/pods',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreatePodRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseGpuConfig: {\n type: 'object',\n required: ['id'],\n properties: {\n id: {\n type: 'string',\n description: 'GPU type identifier',\n examples: ['NVIDIA GeForce RTX 4090'],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'Number of GPUs',\n examples: [1],\n },\n },\n },\n BaseMounts: {\n type: 'object',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n Cloud: {\n type: 'string',\n description:\n 'Cloud tier. `SECURE` — Runpod-owned datacenter hardware. `COMMUNITY` — community-hosted hardware',\n enum: ['SECURE', 'COMMUNITY'],\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n CreateGpuConfig: {\n description:\n \"GPU request for a pod create. Carries the CUDA host constraints, which live here rather than at the body's top level so they are unrepresentable on a CPU pod.\",\n allOf: [\n {\n $ref: '#/$defs/BaseGpuConfig',\n },\n {\n type: 'object',\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for the host machine, as `major.minor`. Omit to accept any version.',\n examples: [['12.8', '12.6']],\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for the host machine, as `major.minor`, compared numerically rather than as a decimal — so 12.11 is above 12.2. Use this for an open-ended floor and allowedCudaVersions for an exact set.',\n examples: ['12.1'],\n },\n minRamPerGpu: {\n type: 'integer',\n minimum: 1,\n description:\n 'Minimum host system RAM in GB per requested GPU. This is a placement filter, not a resource request. The actual total allocated system RAM may be higher and is returned in gpu.memory.',\n examples: [8],\n },\n minVcpuCountPerGpu: {\n type: 'integer',\n minimum: 1,\n description:\n 'Minimum host vCPU count per requested GPU. This is a placement filter, not a resource request. The actual total allocated vCPU count may be higher and is returned in gpu.vcpuCount.',\n examples: [2],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n CreatePodRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n required: ['name'],\n description:\n 'Request body for creating a pod. Exactly one of `gpu` or `cpu` must be set — enforced at the handler layer.',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['my-training-pod'],\n },\n cloud: {\n allOf: [\n {\n $ref: '#/$defs/Cloud',\n },\n ],\n default: 'SECURE',\n description: 'Cloud tier. Defaults to `SECURE` when omitted.',\n },\n cpu: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.',\n examples: [['US-TX-3']],\n },\n globalNetworking: {\n type: 'boolean',\n default: false,\n description:\n 'Enable global networking, giving the pod a private IP reachable across data centers. Requires an NVIDIA GPU and a global-networking-enabled data center (both enforced upstream).',\n examples: [false],\n },\n gpu: {\n $ref: '#/$defs/CreateGpuConfig',\n },\n mounts: {\n $ref: '#/$defs/Mounts',\n },\n startJupyter: {\n type: 'boolean',\n default: false,\n description:\n 'Create-time flag: starts JupyterLab by injecting a generated `JUPYTER_PASSWORD` environment variable, unless the request sets one. Expose `8888/http` in `ports` to reach it.',\n examples: [true],\n },\n startSsh: {\n type: 'boolean',\n default: false,\n description:\n \"Create-time flag: sets up SSH access by injecting a `PUBLIC_KEY` environment variable with your account's registered SSH keys (`update-ssh-keys`), unless the request sets one. With no registered keys it does nothing and the pod has no SSH access. Direct SSH also needs a `22/tcp` entry in `ports`.\",\n examples: [true],\n },\n templateId: {\n type: 'string',\n minLength: 1,\n description:\n \"ID of a pod template to base this pod on (not a serverless one). Its container settings (image, args, disk, ports, env, registry, persistent mount) fill in what this body omits; body fields win, and `env` merges per key with body winning. A CUDA field in `gpu` replaces the template's CUDA constraint; CPU pods ignore its mount. Copied once: later template edits do not affect the pod.\",\n examples: ['30zmvf89kd'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n if: {\n not: {\n required: ['templateId'],\n },\n },\n then: {\n required: ['image'],\n },\n },\n GlobalMount: {\n type: 'object',\n required: ['volumeId'],\n additionalProperties: false,\n description:\n 'Reference to a GlobalVolume. Usage-billed, so it has no size. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.',\n properties: {\n volumeId: {\n type: 'string',\n description: 'ID of an existing GlobalVolume.',\n examples: ['gsb_abc'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. Optional on create, where a default is chosen for you; a PATCH that omits it leaves the path unchanged.',\n examples: ['/data'],\n },\n },\n },\n Mounts: {\n description:\n \"Storage mounts for the pod: `persistent` (size + path) excludes both `network` and `global`; `network` (volumeId + path) and `global` (volumeId, optional path) take one entry each and can be combined. Every entry needs its full shape. On update, omit the field to leave the mounts as they are; the mount kind and a volume's volumeId cannot change, and mounts cannot be cleared.\",\n allOf: [\n {\n $ref: '#/$defs/BaseMounts',\n },\n {\n type: 'object',\n properties: {\n global: {\n type: 'array',\n maxItems: 1,\n description:\n 'At most one global volume, on GPU and CPU pods, with no data center constraint. Combinable with `network` but not with `persistent` (rejected): upstream drops a persistent disk whenever a volume is attached.',\n items: {\n $ref: '#/$defs/GlobalMount',\n },\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-registry',\n operationId: 'createRegistry',\n description:\n 'Create a container registry credential. Stores credentials for a private container registry. Credentials are write-only.',\n method: 'POST',\n path: '/v2/registries',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateRegistryRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateRegistryRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'username', 'password'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n examples: ['my-private-registry'],\n },\n password: {\n type: 'string',\n minLength: 1,\n maxLength: 16384,\n description:\n 'Registry password (write-only, not returned in responses)',\n },\n username: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n description:\n 'Registry username (write-only, not returned in responses)',\n },\n },\n },\n },\n },\n },\n {\n name: 'create-secret',\n operationId: 'createSecret',\n description:\n \"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> }}` — 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.\",\n method: 'POST',\n path: '/v2/account/secrets',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateSecretRequest',\n },\n },\n required: ['body'],\n $defs: {\n CreateSecretRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'value'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n pattern: '^[a-zA-Z_][a-zA-Z0-9_.\\\\-/]*$',\n description:\n 'Unique name for the secret — referenced from environment variables as `{{ RUNPOD_SECRET_<name> }}`; immutable after creation. Maximum 191 characters, must start with a letter or underscore, and may contain letters, digits, and `_.-/`.',\n examples: ['hf-token'],\n },\n value: {\n type: 'string',\n minLength: 1,\n maxLength: 16777216,\n description:\n 'The secret value. Write-only — never returned by the API. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes).',\n },\n description: {\n type: 'string',\n maxLength: 65535,\n description:\n 'Optional human-readable description, at most 65,535 bytes of UTF-8 text.',\n examples: ['Hugging Face read token'],\n },\n },\n },\n },\n },\n },\n {\n name: 'create-template',\n operationId: 'createTemplate',\n description:\n 'Create a template. Creates a reusable container-configuration preset — image, disk, ports, env, registry, and mount settings — 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.',\n method: 'POST',\n path: '/v2/templates',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/CreateTemplateRequest',\n },\n },\n required: ['body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateTemplateRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n required: ['name', 'image'],\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['My PyTorch Template'],\n },\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for containers created from this template, as `major.minor`. Omit to accept any version — see the same field on `createPod` for matching semantics.',\n examples: [['12.8', '12.6']],\n },\n category: {\n description: 'Optional. Defaults to `NVIDIA` when omitted.',\n allOf: [\n {\n $ref: '#/$defs/TemplateCategory',\n },\n ],\n default: 'NVIDIA',\n },\n mounts: {\n $ref: '#/$defs/TemplateMounts',\n },\n public: {\n type: 'boolean',\n default: false,\n },\n serverless: {\n type: 'boolean',\n default: false,\n },\n startJupyter: {\n type: 'boolean',\n default: true,\n description:\n 'Start JupyterLab in containers created from this template: injects a generated `JUPYTER_PASSWORD` environment variable, unless `env` already sets one.',\n examples: [false],\n },\n startSsh: {\n type: 'boolean',\n default: true,\n description:\n \"Provision SSH access in containers created from this template: injects a `PUBLIC_KEY` environment variable carrying the deployer's registered SSH public keys (`update-ssh-keys` — with none registered the flag does nothing), unless `env` already sets one.\",\n examples: [true],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n TemplateCategory: {\n type: 'string',\n description:\n 'Controls how the template is grouped and filtered in the Runpod console. It does not affect hardware selection, scheduling, or billing. `CPU` — CPU-only workloads. `NVIDIA` — NVIDIA GPU workloads. `AMD` — AMD GPU workloads',\n enum: ['CPU', 'NVIDIA', 'AMD'],\n },\n TemplateMounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts for containers from this template: a single `persistent` mount only (`network` is rejected). On update, omitting `mounts` or sending `{}` leaves the existing mount unchanged.',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n },\n },\n },\n },\n },\n {\n name: 'delete-cluster',\n operationId: 'deleteCluster',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-endpoint',\n operationId: 'deleteEndpoint',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-global-volume',\n operationId: 'deleteGlobalVolume',\n description:\n '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.',\n method: 'DELETE',\n path: '/v2/global-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Global volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-network-volume',\n operationId: 'deleteNetworkVolume',\n description:\n 'Delete a network volume. Permanently deletes a network volume and releases its storage.',\n method: 'DELETE',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-pod',\n operationId: 'deletePod',\n description:\n 'Terminate a pod permanently — 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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-registry',\n operationId: 'deleteRegistry',\n description:\n '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 — they silently lose the reference (`registry` becomes null) instead of blocking the delete.',\n method: 'DELETE',\n path: '/v2/registries/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-secret',\n operationId: 'deleteSecret',\n description:\n '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 — a name found by listing is not attribution.',\n method: 'DELETE',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'delete-template',\n operationId: 'deleteTemplate',\n description:\n 'Delete a template permanently. Verify with get-template first; a template referenced by a live endpoint should not be deleted.',\n method: 'DELETE',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-cluster',\n operationId: 'getCluster',\n description:\n '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.',\n method: 'GET',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-cpu-type',\n operationId: 'getCpuType',\n description:\n 'Get a CPU type. Returns a single CPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/cpus/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'vcpuCount',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/CpuProduct',\n },\n example: ['POD', 'SERVERLESS'],\n description:\n 'Comma-separated availability product contexts. Supported values for CPUs: POD, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: availability differs by product.',\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Availability vCPU count. Valid only with include=AVAILABILITY. Must be a power of two.',\n },\n },\n required: ['id'],\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n CpuProduct: {\n type: 'string',\n description:\n 'CPU catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'get-data-center',\n operationId: 'getDataCenter',\n description:\n 'Get a data center. Returns a single data center. Availability is included only when requested with include=GPU_AVAILABILITY or include=CPU_AVAILABILITY.',\n method: 'GET',\n path: '/v2/catalog/datacenters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterInclude',\n },\n example: ['GPU_AVAILABILITY'],\n description:\n 'Comma-separated optional expansions. Supported value: GPU_AVAILABILITY, CPU_AVAILABILITY.',\n },\n },\n required: ['id'],\n $defs: {\n DataCenterInclude: {\n type: 'string',\n description: 'Data center catalog availability expansion.',\n enum: ['GPU_AVAILABILITY', 'CPU_AVAILABILITY'],\n },\n },\n },\n },\n {\n name: 'get-endpoint',\n operationId: 'getEndpoint',\n description:\n 'Get a serverless endpoint. Returns a single serverless endpoint by ID.',\n method: 'GET',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-endpoint-build',\n operationId: 'getEndpointBuild',\n description:\n \"Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age — no need to page through `GET /v2/serverless/{id}/builds` to reach it.\",\n method: 'GET',\n path: '/v2/serverless/{id}/builds/{buildId}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'buildId',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n buildId: {\n type: 'string',\n description:\n \"GitHub build identifier (from `list-endpoint-builds` or a release's `buildId`)\",\n },\n },\n required: ['id', 'buildId'],\n },\n },\n {\n name: 'get-global-volume',\n operationId: 'getGlobalVolume',\n description: 'Get a global volume. Returns a single global volume by ID.',\n method: 'GET',\n path: '/v2/global-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Global volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-gpu-type',\n operationId: 'getGpuType',\n description:\n 'Get a GPU type. Returns a single GPU type with pricing. Availability details are included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/gpus/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'count',\n location: 'query',\n },\n {\n name: 'cloud',\n location: 'query',\n },\n {\n name: 'countryCodes',\n location: 'query',\n explode: false,\n },\n {\n name: 'cudaVersions',\n location: 'query',\n explode: false,\n },\n {\n name: 'minCudaVersion',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/Product',\n },\n description:\n 'Comma-separated availability product contexts. Supported values: POD, CLUSTER, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way).',\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description:\n 'GPU count for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Defaults to 1.',\n },\n cloud: {\n $ref: '#/$defs/GpuCloudFilter',\n description:\n 'Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.',\n },\n countryCodes: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^[A-Z]{2}$',\n },\n description:\n 'Comma-separated ISO 3166-1 alpha-2 country codes, uppercase, to constrain availability to — e.g. FR or FR,DE. Values within this filter use OR semantics. Valid only with include=AVAILABILITY; a malformed entry is a 422.',\n },\n cudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Comma-separated CUDA versions to scope availability and lowest-price calculations to, matched exactly. Format: major.minor, e.g. 12.8 — a bare major is rejected here because it identifies no version.',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+(\\\\.\\\\d+)?$',\n description:\n 'Lowest acceptable CUDA version to scope availability and lowest-price calculations to, compared numerically.',\n },\n },\n required: ['id'],\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n GpuCloudFilter: {\n type: 'string',\n description: 'GPU availability cloud filter.',\n enum: ['SECURE', 'COMMUNITY'],\n },\n Product: {\n type: 'string',\n description:\n 'Catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'CLUSTER', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'get-network-volume',\n operationId: 'getNetworkVolume',\n description: 'Get a network volume. Returns a single network volume by ID.',\n method: 'GET',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-organization',\n operationId: 'getOrganization',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/organization',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'get-pod',\n operationId: 'getPod',\n description: 'Get a pod. Returns a single pod by ID.',\n method: 'GET',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-registry',\n operationId: 'getRegistry',\n description:\n 'Get a container registry credential. Returns a single container registry credential by ID. `username` and `password` are never included in the response — credentials are write-only, matching `createRegistry`.',\n method: 'GET',\n path: '/v2/registries/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-secret',\n operationId: 'getSecret',\n description:\n \"Get a secret. Returns a single secret's metadata by ID. The value is write-only and never returned.\",\n method: 'GET',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'get-ssh-keys',\n operationId: 'getSshKeys',\n description:\n \"List registered SSH public keys. Returns the account's registered SSH public keys — the keys provisioned into pods created with `startSsh` and used to authenticate the SSH connections reported in a pod's `ssh` block.\",\n method: 'GET',\n path: '/v2/account/ssh-keys',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'get-template',\n operationId: 'getTemplate',\n description:\n 'Get a template. Returns the full configuration of a single template by ID. Serves both templates you own and public catalog templates — everything you can read. Updates and deletes remain restricted to templates you own.',\n method: 'GET',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-billing',\n operationId: 'listBilling',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/billing',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-cluster-billing',\n operationId: 'listClusterBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/clusters',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'clusterId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n clusterId: {\n type: 'string',\n description: 'Filter to a specific cluster.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-cluster-pods',\n operationId: 'listClusterPods',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/clusters/{id}/pods',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-clusters',\n operationId: 'listClusters',\n description:\n '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.',\n method: 'GET',\n path: '/v2/clusters',\n params: [\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n },\n },\n {\n name: 'list-cpu-types',\n operationId: 'listCpuTypes',\n description:\n 'List CPU types. Returns available CPU flavors. Availability is included only when requested with include=AVAILABILITY, which requires `product` — stock differs by product context.',\n method: 'GET',\n path: '/v2/catalog/cpus',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'vcpuCount',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/CpuProduct',\n },\n example: ['POD', 'SERVERLESS'],\n description:\n 'Comma-separated availability product contexts. Supported values for CPUs: POD, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way). There is no default: availability differs by product.',\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Availability vCPU count. Valid only with include=AVAILABILITY. Must be a power of two.',\n },\n },\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n CpuProduct: {\n type: 'string',\n description:\n 'CPU catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'list-data-centers',\n operationId: 'listDataCenters',\n description:\n '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.',\n method: 'GET',\n path: '/v2/catalog/datacenters',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'regions',\n location: 'query',\n explode: false,\n },\n {\n name: 'networkVolumeTypes',\n location: 'query',\n explode: false,\n },\n {\n name: 'compliance',\n location: 'query',\n explode: false,\n },\n {\n name: 'globalNetwork',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterInclude',\n },\n example: ['GPU_AVAILABILITY'],\n description:\n 'Comma-separated optional expansions. Supported value: GPU_AVAILABILITY, CPU_AVAILABILITY.',\n },\n regions: {\n type: 'array',\n items: {\n $ref: '#/$defs/DataCenterRegion',\n },\n example: ['EUROPE', 'ASIA'],\n description:\n 'Comma-separated DataCenterRegion enum values. Values within this filter use OR semantics. Different filter families combine with AND.',\n },\n networkVolumeTypes: {\n type: 'array',\n items: {\n $ref: '#/$defs/VolumeType',\n },\n example: ['STANDARD', 'HIGH_PERFORMANCE'],\n description:\n 'Comma-separated volume types. Supported values: STANDARD, HIGH_PERFORMANCE. Values within this filter use AND semantics; volumes=STANDARD,HIGH_PERFORMANCE requires both storage types. Different filter families combine with AND.',\n },\n compliance: {\n type: 'array',\n items: {\n $ref: '#/$defs/Compliance',\n },\n example: ['GDPR', 'SOC_2_TYPE_2'],\n description:\n 'Comma-separated Compliance enum values. Values within this filter use AND semantics; compliance=GDPR,SOC_2_TYPE_2 requires both certifications. Different filter families combine with AND.',\n },\n globalNetwork: {\n type: 'boolean',\n description:\n 'Filter by global networking support. true returns only data centers that support global networking; false only those that do not. Different filter families combine with AND.',\n },\n },\n $defs: {\n Compliance: {\n type: 'string',\n description: 'Compliance certifications.',\n enum: [\n 'GDPR',\n 'ISO_IEC_27001',\n 'ISO_14001',\n 'PCI_DSS',\n 'HITRUST',\n 'SOC_1_TYPE_2',\n 'SOC_2_TYPE_2',\n 'SOC_3_TYPE_2',\n 'ITAR',\n 'FISMA_HIGH',\n 'HIPAA',\n 'RENEWABLE',\n ],\n },\n DataCenterInclude: {\n type: 'string',\n description: 'Data center catalog availability expansion.',\n enum: ['GPU_AVAILABILITY', 'CPU_AVAILABILITY'],\n },\n DataCenterRegion: {\n type: 'string',\n description: 'Continental region containing the data center.',\n examples: ['EUROPE'],\n enum: [\n 'NORTH_AMERICA',\n 'SOUTH_AMERICA',\n 'EUROPE',\n 'ASIA',\n 'MIDDLE_EAST',\n 'AFRICA',\n 'OCEANIA',\n 'ANTARCTICA',\n 'UNKNOWN',\n ],\n },\n VolumeType: {\n type: 'string',\n description: 'Data center network volume storage type.',\n enum: ['STANDARD', 'HIGH_PERFORMANCE'],\n },\n },\n },\n },\n {\n name: 'list-delegations',\n operationId: 'listDelegations',\n description: 'List all ECR delegations',\n method: 'GET',\n path: '/v2/registries/delegations',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-endpoint-billing',\n operationId: 'listEndpointBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/endpoints',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-endpoint-builds',\n operationId: 'listEndpointBuilds',\n description:\n \"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`.\",\n method: 'GET',\n path: '/v2/serverless/{id}/builds',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Page size, 1–100. Defaults to 100 when omitted.',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-endpoint-releases',\n operationId: 'listEndpointReleases',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/serverless/{id}/releases',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-endpoint-workers',\n operationId: 'listEndpointWorkers',\n description:\n \"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.\",\n method: 'GET',\n path: '/v2/serverless/{id}/workers',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'list-global-volumes',\n operationId: 'listGlobalVolumes',\n description:\n '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.',\n method: 'GET',\n path: '/v2/global-volumes',\n params: [\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n },\n },\n {\n name: 'list-gpu-types',\n operationId: 'listGpuTypes',\n description:\n 'List GPU types. Returns available GPU types with pricing. Availability is included only when requested with include=AVAILABILITY, which requires `product` — 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.',\n method: 'GET',\n path: '/v2/catalog/gpus',\n params: [\n {\n name: 'include',\n location: 'query',\n explode: false,\n },\n {\n name: 'product',\n location: 'query',\n explode: false,\n },\n {\n name: 'count',\n location: 'query',\n },\n {\n name: 'cloud',\n location: 'query',\n },\n {\n name: 'countryCodes',\n location: 'query',\n explode: false,\n },\n {\n name: 'cudaVersions',\n location: 'query',\n explode: false,\n },\n {\n name: 'minCudaVersion',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n include: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/CatalogInclude',\n },\n description:\n 'Comma-separated optional expansions. Supported value today: AVAILABILITY. This may expand with more include values in the future.',\n },\n product: {\n type: 'array',\n items: {\n $ref: '#/$defs/Product',\n },\n description:\n 'Comma-separated availability product contexts. Supported values: POD, CLUSTER, SERVERLESS. Required with include=AVAILABILITY, and valid only with it (400 either way).',\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description:\n 'GPU count for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Defaults to 1.',\n },\n cloud: {\n $ref: '#/$defs/GpuCloudFilter',\n description:\n 'Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.',\n },\n countryCodes: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^[A-Z]{2}$',\n },\n description:\n 'Comma-separated ISO 3166-1 alpha-2 country codes, uppercase, to constrain availability to — e.g. FR or FR,DE. Values within this filter use OR semantics. Valid only with include=AVAILABILITY; a malformed entry is a 422.',\n },\n cudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Comma-separated CUDA versions to scope availability and lowest-price calculations to, matched exactly. Format: major.minor, e.g. 12.8 — a bare major is rejected here because it identifies no version.',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^\\\\d+(\\\\.\\\\d+)?$',\n description:\n 'Lowest acceptable CUDA version to scope availability and lowest-price calculations to, compared numerically.',\n },\n },\n $defs: {\n CatalogInclude: {\n type: 'string',\n description:\n 'Catalog include expansion. Only AVAILABILITY is supported today; additional include values may be added in the future.',\n enum: ['AVAILABILITY'],\n },\n GpuCloudFilter: {\n type: 'string',\n description: 'GPU availability cloud filter.',\n enum: ['SECURE', 'COMMUNITY'],\n },\n Product: {\n type: 'string',\n description:\n 'Catalog product availability context. Availability is product-specific, so this is required whenever availability is requested.',\n enum: ['POD', 'CLUSTER', 'SERVERLESS'],\n },\n },\n },\n },\n {\n name: 'list-network-volume-billing',\n operationId: 'listNetworkVolumeBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/network-volumes',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'networkVolumeId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n networkVolumeId: {\n type: 'string',\n description: 'Filter to a specific network volume.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-network-volumes',\n operationId: 'listNetworkVolumes',\n description:\n '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.',\n method: 'GET',\n path: '/v2/network-volumes',\n params: [\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n },\n },\n {\n name: 'list-pod-billing',\n operationId: 'listPodBilling',\n description:\n '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.',\n method: 'GET',\n path: '/v2/billing/pods',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'podId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n podId: {\n type: 'string',\n description: 'Filter to a specific pod (GPU or CPU).',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'list-pods',\n operationId: 'listPods',\n description:\n '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.',\n method: 'GET',\n path: '/v2/pods',\n params: [\n {\n name: 'includeClusterPods',\n location: 'query',\n },\n {\n name: 'cursor',\n location: 'query',\n },\n {\n name: 'limit',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n includeClusterPods: {\n type: 'boolean',\n default: false,\n description:\n 'Include cluster member pods in the result. Defaults to false.',\n },\n cursor: {\n type: 'string',\n minLength: 1,\n description:\n \"Opaque resume cursor — pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected.\",\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 1000,\n description: 'Page size, 1–1000. Defaults to 1000 when omitted.',\n },\n },\n },\n },\n {\n name: 'list-public-templates',\n operationId: 'listPublicTemplates',\n description:\n \"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 — 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 — catalog or owned — 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`).\",\n method: 'GET',\n path: '/v2/catalog/templates',\n params: [\n {\n name: 'source',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n source: {\n type: 'string',\n enum: ['official', 'verified', 'community'],\n default: 'official',\n description:\n 'Which slice of the catalog to return: `official` for Runpod-curated templates (default), `verified` for Runpod-verified community templates, or `community` for all other publicly shared templates.',\n },\n },\n },\n },\n {\n name: 'list-registries',\n operationId: 'listRegistries',\n description:\n 'List container registries. Returns all container registry credentials owned by the authenticated user.',\n method: 'GET',\n path: '/v2/registries',\n params: [],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'list-secrets',\n operationId: 'listSecrets',\n description:\n \"List secrets. Returns the account's secrets — 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.\",\n method: 'GET',\n path: '/v2/account/secrets',\n params: [\n {\n name: 'name',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description:\n 'When provided, returns only the secret with this name (case-insensitive).',\n },\n },\n },\n },\n {\n name: 'list-serverless-billing',\n operationId: 'listServerlessBilling',\n description:\n 'Get serverless billing history, split into time buckets. SIZE WARNING: with defaults this emits one record per endpoint PER BUCKET — 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.',\n method: 'GET',\n path: '/v2/billing/serverless',\n params: [\n {\n name: 'startTime',\n location: 'query',\n },\n {\n name: 'endTime',\n location: 'query',\n },\n {\n name: 'bucketSize',\n location: 'query',\n },\n {\n name: 'lastN',\n location: 'query',\n },\n {\n name: 'serverlessId',\n location: 'query',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n startTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'Start of the billing period (RFC 3339). Defaults to 30 days ago.',\n },\n endTime: {\n type: 'string',\n format: 'date-time',\n description:\n 'End of the billing period (RFC 3339), exclusive. Defaults to now. Snapped up to the end of the bucketSize bucket it lands in (unless already on a boundary) so the window aligns with the returned records.',\n },\n bucketSize: {\n $ref: '#/$defs/BillingBucketSize',\n description: 'Length of each billing time bucket. Defaults to day.',\n },\n lastN: {\n type: 'integer',\n minimum: 1,\n description:\n 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket — e.g. lastN=100 with bucketSize=day is \"last 100 days\".',\n },\n serverlessId: {\n type: 'string',\n description: 'Filter to a specific serverless endpoint.',\n },\n },\n $defs: {\n BillingBucketSize: {\n type: 'string',\n enum: ['hour', 'day', 'week', 'month', 'year'],\n 'x-enum-varnames': [\n 'BillingBucketSizeHour',\n 'BillingBucketSizeDay',\n 'BillingBucketSizeWeek',\n 'BillingBucketSizeMonth',\n 'BillingBucketSizeYear',\n ],\n default: 'day',\n description: 'Length of each billing time bucket.',\n examples: ['day'],\n },\n },\n },\n },\n {\n name: 'pod-action',\n operationId: 'podAction',\n description:\n '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` — boot a stopped pod (`EXITED` or `ERROR`) back toward `RUNNING`. - `stop` — stop a running or provisioning pod, releasing GPU/CPU compute while keeping its disk. The pod moves to `EXITED`. - `restart` — restart a `RUNNING` pod\\'s container in place. - `terminate` — 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`.',\n method: 'POST',\n path: '/v2/pods/{id}/action',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n body: {\n $ref: '#/$defs/PodActionRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n PodAction: {\n type: 'string',\n description: 'State transition to trigger on a pod.',\n enum: ['start', 'stop', 'restart', 'terminate'],\n },\n PodActionRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['action'],\n properties: {\n action: {\n $ref: '#/$defs/PodAction',\n },\n },\n },\n },\n },\n },\n {\n name: 'revoke-delegation',\n operationId: 'revokeDelegation',\n description: 'Revoke an ECR delegation',\n method: 'DELETE',\n path: '/v2/registries/delegations/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: false,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'update-cluster',\n operationId: 'updateCluster',\n description:\n 'Rename a cluster. Renames a cluster. This endpoint only changes the cluster name — compute shape, type, and container configuration are fixed at creation and cannot be updated.',\n method: 'PATCH',\n path: '/v2/clusters/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Cluster identifier',\n },\n body: {\n $ref: '#/$defs/UpdateClusterRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateClusterRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n 'Request body for updating a cluster. Only the cluster name can be changed — this endpoint is a rename. Compute shape, type, and container configuration are fixed at creation.',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n examples: ['renamed-cluster'],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-endpoint',\n operationId: 'updateEndpoint',\n description:\n \"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) — 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 — 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.\",\n method: 'PATCH',\n path: '/v2/serverless/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Serverless endpoint identifier',\n },\n body: {\n $ref: '#/$defs/UpdateEndpointRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseCpuConfig: {\n type: 'object',\n required: ['id', 'vcpuCount'],\n properties: {\n id: {\n type: 'string',\n description:\n 'CPU flavor identifier, as returned by GET /v2/catalog/cpus.',\n examples: ['cpu5c'],\n minLength: 1,\n },\n vcpuCount: {\n type: 'integer',\n minimum: 2,\n description:\n 'Number of vCPUs. Must be valid for the selected CPU flavor and must be a power of two.',\n examples: [4],\n },\n },\n },\n BaseEndpointGpuConfig: {\n type: 'object',\n properties: {\n pools: {\n type: 'array',\n minItems: 1,\n description:\n 'Serverless GPU pool IDs (the `pool` field of `list-gpu-types`). Workers are placed on whichever listed pool has capacity; narrow to specific cards with `excludedTypes`. On update, `pools` and `excludedTypes` are replaced together, so sending `pools` alone clears the exclusions.',\n items: {\n type: 'string',\n },\n examples: [['ADA_24']],\n },\n excludedTypes: {\n type: 'array',\n uniqueItems: true,\n description:\n 'GPU type IDs to subtract from the selected pools — the `id` field of `list-gpu-types`, the same identifiers pods take in `gpu.id`. Workers run on every type in `pools` except these; omit to use the whole pool. A value outside `pools` is rejected. On update, restate them whenever you send `pools`, or they are cleared.',\n items: {\n type: 'string',\n pattern: '^\\\\s*[^-\\\\s]',\n },\n examples: [['NVIDIA L40']],\n },\n count: {\n type: 'integer',\n minimum: 1,\n default: 1,\n description: 'GPUs per worker',\n examples: [1],\n },\n },\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n CreateCpuConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseCpuConfig',\n },\n ],\n unevaluatedProperties: false,\n },\n EndpointMount: {\n type: 'object',\n required: ['volumeId'],\n additionalProperties: false,\n description:\n 'A volume mounted on every worker, always at `/runpod-volume`. Custom paths are not supported yet.',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of a NetworkVolume (under `network`) or GlobalVolume (under `global`).',\n examples: ['vol_abc'],\n },\n },\n },\n EndpointMountsInput: {\n type: 'object',\n additionalProperties: false,\n description:\n \"Volumes to mount on the endpoint's workers. A `network` or `global` list that is present replaces the endpoint's current list of that kind; an empty list detaches it, and an omitted list is left unchanged.\",\n properties: {\n network: {\n type: 'array',\n description: 'Network volumes, at most one per data center.',\n items: {\n $ref: '#/$defs/EndpointMount',\n },\n },\n global: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/EndpointMount',\n },\n },\n },\n },\n EndpointScaling: {\n description:\n \"Autoscaling signal — a discriminated union on `type`: `QUEUE_DELAY` (queue-based endpoints only) or `REQUEST_COUNT`. The scaler is chosen independently of the endpoint's routing `type` and can be switched on update.\",\n oneOf: [\n {\n $ref: '#/$defs/QueueDelayScaling',\n },\n {\n $ref: '#/$defs/RequestCountScaling',\n },\n ],\n discriminator: {\n propertyName: 'type',\n mapping: {\n QUEUE_DELAY: '#/$defs/QueueDelayScaling',\n REQUEST_COUNT: '#/$defs/RequestCountScaling',\n },\n },\n },\n EndpointWorkers: {\n type: 'object',\n additionalProperties: false,\n properties: {\n min: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum number of workers.',\n examples: [0],\n },\n max: {\n type: 'integer',\n minimum: 0,\n description: 'Maximum number of workers.',\n examples: [5],\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n maximum: 3600,\n description:\n 'Seconds before idle workers scale down. Not applicable to queue-based endpoints scaling on `requestCount` — rejected on create/update and omitted from responses for that combination.',\n examples: [5],\n },\n },\n },\n FlashBoot: {\n type: 'string',\n description:\n 'FlashBoot cold-start acceleration mode. `OFF` — disabled. `FLASHBOOT` — enabled. `PRIORITY_FLASHBOOT` — enabled with priority capacity',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n },\n QueueDelayScaling: {\n type: 'object',\n additionalProperties: false,\n description: 'Scale on queue wait time. Queue-based endpoints only.',\n required: ['type', 'queueDelay'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `QUEUE_DELAY` for this variant.',\n enum: ['QUEUE_DELAY'],\n },\n queueDelay: {\n type: 'number',\n format: 'float',\n minimum: 0.5,\n description:\n 'Adjusts the number of workers based on how long requests wait in the queue.',\n examples: [4],\n },\n },\n },\n RequestCountScaling: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Scale on concurrent in-flight requests per worker. Required for load-balancing endpoints; also selectable for queue-based.',\n required: ['type', 'requestCount'],\n properties: {\n type: {\n type: 'string',\n description:\n 'Scaler discriminator. Always `REQUEST_COUNT` for this variant.',\n enum: ['REQUEST_COUNT'],\n },\n requestCount: {\n type: 'integer',\n minimum: 1,\n description:\n 'Adjusts the number of workers based on active in-flight requests.',\n examples: [4],\n },\n },\n },\n UpdateEndpointGpuConfig: {\n description:\n 'Partial GPU update — every field is optional and an omitted one is left unchanged. `pools` is optional here, so a CUDA-only change does not resend the pool list; `excludedTypes` needs `pools` in the same request, and `pools` sent alone clears the exclusions.',\n allOf: [\n {\n $ref: '#/$defs/BaseEndpointGpuConfig',\n },\n {\n type: 'object',\n dependentRequired: {\n excludedTypes: ['pools'],\n },\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for worker placement, as `major.minor`. An explicit `[]` clears the constraint; omitting the field leaves it unchanged. A non-empty set cannot be sent with minCudaVersion, and setting one does not clear the other: clear the other explicitly in the same patch. Takes effect as workers are replaced.',\n },\n minCudaVersion: {\n type: 'string',\n pattern: '^$|^\\\\d+\\\\.\\\\d+$',\n description:\n 'Lowest acceptable CUDA version for worker placement, as `major.minor`. An explicit `\"\"` clears the floor; omitting the field leaves it unchanged. Cannot be sent with a non-empty allowedCudaVersions (an explicit `[]` there is fine); clear that explicitly in the same patch if the endpoint carries one. Takes effect as workers are replaced.',\n examples: ['12.1'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n UpdateEndpointRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n description: 'Only provided fields are changed.',\n properties: {\n cpu: {\n type: 'array',\n minItems: 1,\n uniqueItems: true,\n description:\n 'Complete replacement CPU selection. Valid only for an existing CPU endpoint; endpoint compute family cannot be changed.',\n items: {\n $ref: '#/$defs/CreateCpuConfig',\n },\n },\n dataCenterIds: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Preferred data centers for placement. Omit or pass an empty array to let the scheduler choose.',\n },\n flashboot: {\n $ref: '#/$defs/FlashBoot',\n },\n gpu: {\n $ref: '#/$defs/UpdateEndpointGpuConfig',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n networkVolumes: {\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'Network volume IDs. Pass `[]` to detach.',\n deprecated: true,\n },\n mounts: {\n $ref: '#/$defs/EndpointMountsInput',\n },\n scaling: {\n $ref: '#/$defs/EndpointScaling',\n },\n templateId: {\n type: 'string',\n description:\n \"ID of a serverless template whose container settings (image, args, disk, ports, env, registry) are applied as if sent in this PATCH body; explicit body fields win. `env` merges template and body per key (body wins) and replaces the endpoint's existing env. Applied once; must be a serverless template you can access.\",\n examples: ['30zmvf89kd'],\n },\n timeout: {\n type: 'integer',\n },\n workers: {\n $ref: '#/$defs/EndpointWorkers',\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n {\n name: 'update-global-volume',\n operationId: 'updateGlobalVolume',\n description:\n 'Update a global volume. Updates mutable fields on a global volume. Only provided fields are changed.',\n method: 'PATCH',\n path: '/v2/global-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Global volume identifier',\n },\n body: {\n $ref: '#/$defs/UpdateGlobalVolumeRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateGlobalVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n 'Only the provided fields are updated. At least one field must be present; an empty body is rejected.',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n maxLength: 191,\n pattern: '[^\\\\p{Z}\\\\t-\\\\r
]',\n description:\n 'New human-readable name, 1–191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed.',\n examples: ['renamed-volume'],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-network-volume',\n operationId: 'updateNetworkVolume',\n description:\n '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.',\n method: 'PATCH',\n path: '/v2/network-volumes/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Network volume identifier',\n },\n body: {\n $ref: '#/$defs/UpdateNetworkVolumeRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateNetworkVolumeRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n 'Only the provided fields are updated. At least one field must be present; an empty body is rejected.',\n properties: {\n name: {\n type: 'string',\n minLength: 1,\n description: 'New human-readable name',\n examples: ['renamed-volume'],\n },\n size: {\n type: 'integer',\n minimum: 10,\n maximum: 4096,\n description:\n 'New size in GB. Must be greater than or equal to the current size — network volume storage cannot be reduced.',\n examples: [100],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-pod',\n operationId: 'updatePod',\n description:\n \"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 — manage them through `/v2/clusters/{id}`. Returns `200` with the full updated pod.\",\n method: 'PATCH',\n path: '/v2/pods/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Pod identifier',\n },\n body: {\n $ref: '#/$defs/UpdatePodRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n BaseMounts: {\n type: 'object',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n network: {\n type: 'array',\n maxItems: 1,\n items: {\n $ref: '#/$defs/NetworkMount',\n },\n },\n },\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n GlobalMount: {\n type: 'object',\n required: ['volumeId'],\n additionalProperties: false,\n description:\n 'Reference to a GlobalVolume. Usage-billed, so it has no size. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.',\n properties: {\n volumeId: {\n type: 'string',\n description: 'ID of an existing GlobalVolume.',\n examples: ['gsb_abc'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. Optional on create, where a default is chosen for you; a PATCH that omits it leaves the path unchanged.',\n examples: ['/data'],\n },\n },\n },\n Mounts: {\n description:\n \"Storage mounts for the pod: `persistent` (size + path) excludes both `network` and `global`; `network` (volumeId + path) and `global` (volumeId, optional path) take one entry each and can be combined. Every entry needs its full shape. On update, omit the field to leave the mounts as they are; the mount kind and a volume's volumeId cannot change, and mounts cannot be cleared.\",\n allOf: [\n {\n $ref: '#/$defs/BaseMounts',\n },\n {\n type: 'object',\n properties: {\n global: {\n type: 'array',\n maxItems: 1,\n description:\n 'At most one global volume, on GPU and CPU pods, with no data center constraint. Combinable with `network` but not with `persistent` (rejected): upstream drops a persistent disk whenever a volume is attached.',\n items: {\n $ref: '#/$defs/GlobalMount',\n },\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n NetworkMount: {\n type: 'object',\n required: ['volumeId', 'path'],\n additionalProperties: false,\n description:\n 'Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.',\n properties: {\n volumeId: {\n type: 'string',\n description:\n 'ID of an existing NetworkVolume in the same data center as the pod.',\n examples: ['vol_xyz'],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. No default — must be specified explicitly.',\n examples: ['/runpod-volume'],\n },\n },\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n UpdatePodRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n properties: {\n globalNetworking: {\n type: 'boolean',\n description:\n 'Enable (true) or disable (false) global networking. Takes effect on the next pod start/restart, not live. Requires an NVIDIA GPU and a global-networking-enabled data center (both enforced upstream).',\n },\n locked: {\n type: 'boolean',\n description:\n 'Lock the pod (true) or unlock it (false). Locked pods cannot be stopped or reset.',\n },\n mounts: {\n $ref: '#/$defs/Mounts',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n templateId: {\n type: 'string',\n description:\n \"ID of a pod template whose container settings (image, args, disk, ports, env, registry; not mounts) are applied as if sent in this PATCH body; explicit body fields win. `env` merges template and body per key (body wins) and replaces the pod's existing env. Applied once; must be a non-serverless template you can access.\",\n examples: ['30zmvf89kd'],\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n {\n name: 'update-secret',\n operationId: 'updateSecret',\n description:\n \"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 — 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.\",\n method: 'PATCH',\n path: '/v2/account/secrets/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Secret identifier',\n },\n body: {\n $ref: '#/$defs/UpdateSecretRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n UpdateSecretRequest: {\n type: 'object',\n additionalProperties: false,\n minProperties: 1,\n description:\n \"Only the provided fields are updated; at least one field is required. The secret's `name` is immutable.\",\n properties: {\n value: {\n type: 'string',\n minLength: 1,\n maxLength: 16777216,\n description:\n 'New secret value, replacing the current one. Write-only. Must be smaller than 16 MiB of UTF-8 text (strictly under 16,777,216 bytes).',\n },\n description: {\n type: 'string',\n maxLength: 65535,\n description:\n 'New human-readable description, at most 65,535 bytes of UTF-8 text. Send `\"\"` to clear.',\n },\n },\n },\n },\n },\n },\n {\n name: 'update-ssh-keys',\n operationId: 'updateSshKeys',\n description:\n \"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` — running pods are not updated.\",\n method: 'PUT',\n path: '/v2/account/ssh-keys',\n params: [],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n },\n inputSchema: {\n type: 'object',\n properties: {\n body: {\n $ref: '#/$defs/UpdateSshKeysRequest',\n },\n },\n required: ['body'],\n $defs: {\n UpdateSshKeysRequest: {\n type: 'object',\n additionalProperties: false,\n required: ['keys'],\n properties: {\n keys: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^(ssh|ecdsa|sk)-[^\\\\s]+ [^\\\\s]+([ \\\\t][^\\\\n\\\\r]*)?$',\n },\n description:\n 'The full set of SSH public keys to register — this is a complete replacement, not a merge. Each entry is an authorized_keys-style line: `<type> <base64-key> [comment]`, e.g. from `~/.ssh/id_ed25519.pub`. Send `[]` to remove all keys.',\n examples: [\n [\n 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILXGDN/SclOozk1xsDztpmhGiKkkrfQB9SKoO8dSIQQZ me@example.com',\n ],\n ],\n },\n },\n },\n },\n },\n },\n {\n name: 'update-template',\n operationId: 'updateTemplate',\n description:\n \"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 — the template is a snapshot applied at creation time.\",\n method: 'PATCH',\n path: '/v2/templates/{id}',\n params: [\n {\n name: 'id',\n location: 'path',\n },\n ],\n hasBody: true,\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n schemaOnDemand: true,\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n },\n body: {\n $ref: '#/$defs/UpdateTemplateRequest',\n },\n },\n required: ['id', 'body'],\n $defs: {\n BaseContainerConfig: {\n type: 'object',\n properties: {\n args: {\n type: 'string',\n description:\n 'The container\\'s command as one raw string: a bare shell string is treated as CMD and split into arguments; a JSON object `{\"entrypoint\":[...],\"cmd\":[...]}` sets either or both. Send `\"\"` to clear; omit to leave unchanged.',\n examples: [\n '--model meta-llama/Llama-3-8B --max-model-len 8192',\n '{\"entrypoint\":[\"/bin/bash\",\"-c\"],\"cmd\":[\"python -u main.py\"]}',\n '',\n ],\n },\n cmd: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n 'Container CMD in exec form: when the image defines an ENTRYPOINT, the argument list passed to it. Encoded into `args`; supply both only when they describe the same command. Send `[]` to clear; omit to leave unchanged.',\n examples: [\n ['--model', 'meta-llama/Llama-3-8B', '--max-model-len', '8192'],\n ],\n },\n entrypoint: {\n type: 'array',\n items: {\n type: 'string',\n },\n description:\n \"Container ENTRYPOINT in exec form, overriding the image's own. Encoded into `args` field; supplying both is allowed only when they describe the same command. Send `[]` to clear, omit to leave unchanged.\",\n examples: [['/bin/bash', '-c']],\n },\n disk: {\n type: 'integer',\n minimum: 1,\n description: 'Container disk in GB (ephemeral, wiped on restart)',\n examples: [50],\n },\n env: {\n type: 'object',\n additionalProperties: {\n type: 'string',\n },\n description: 'Environment variables as key-value pairs',\n examples: [\n {\n JUPYTER_PASSWORD: 'hunter2',\n },\n ],\n },\n image: {\n type: 'string',\n description: 'Docker image reference',\n examples: ['runpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404'],\n },\n ports: {\n type: 'array',\n description: 'Exposed ports, formatted as port/protocol',\n items: {\n type: 'string',\n },\n examples: [['8888/http', '22/tcp']],\n },\n },\n },\n ContainerConfig: {\n allOf: [\n {\n $ref: '#/$defs/BaseContainerConfig',\n },\n {\n type: 'object',\n properties: {\n registry: {\n type: ['string', 'null'],\n description:\n 'Container registry credential ID (for private images)',\n examples: [null],\n },\n },\n },\n ],\n },\n PersistentMount: {\n type: 'object',\n required: ['size', 'path'],\n additionalProperties: false,\n description:\n \"Host-local persistent storage. Pinned to the pod's host machine — data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.\",\n properties: {\n size: {\n type: 'integer',\n minimum: 10,\n description:\n 'Host-local persistent storage in GB. Upstream enforces a 10 GB floor.',\n examples: [20],\n },\n path: {\n type: 'string',\n description:\n 'Mount path inside the container. May be changed via PATCH.',\n examples: ['/workspace'],\n },\n },\n },\n TemplateCategory: {\n type: 'string',\n description:\n 'Controls how the template is grouped and filtered in the Runpod console. It does not affect hardware selection, scheduling, or billing. `CPU` — CPU-only workloads. `NVIDIA` — NVIDIA GPU workloads. `AMD` — AMD GPU workloads',\n enum: ['CPU', 'NVIDIA', 'AMD'],\n },\n TemplateMounts: {\n type: 'object',\n additionalProperties: false,\n description:\n 'Storage mounts for containers from this template: a single `persistent` mount only (`network` is rejected). On update, omitting `mounts` or sending `{}` leaves the existing mount unchanged.',\n properties: {\n persistent: {\n $ref: '#/$defs/PersistentMount',\n },\n },\n },\n UpdateTemplateRequest: {\n allOf: [\n {\n $ref: '#/$defs/ContainerConfig',\n },\n {\n type: 'object',\n properties: {\n allowedCudaVersions: {\n type: 'array',\n items: {\n type: 'string',\n pattern: '^\\\\d+\\\\.\\\\d+$',\n },\n description:\n 'Acceptable CUDA versions for pods created from this template. An explicit `[]` clears the constraint; omitting the field leaves it unchanged.',\n },\n category: {\n $ref: '#/$defs/TemplateCategory',\n },\n mounts: {\n $ref: '#/$defs/TemplateMounts',\n },\n name: {\n type: 'string',\n minLength: 1,\n },\n public: {\n type: 'boolean',\n },\n serverless: {\n type: 'boolean',\n },\n startJupyter: {\n type: 'boolean',\n description:\n 'Start JupyterLab at container startup (`JUPYTER_PASSWORD` env injection). See the create-time field for details.',\n },\n startSsh: {\n type: 'boolean',\n description:\n 'Provision SSH access at container startup (`PUBLIC_KEY` env injection). See the create-time field for details.',\n },\n },\n },\n ],\n unevaluatedProperties: false,\n },\n },\n },\n },\n];\n","// List caps so a large account's response cannot exceed an LLM's context\n// window. Curated tools over a paginated v2 list endpoint (list-endpoints,\n// list-templates) pass the server's `limit`/`cursor` through with\n// serverPageQuery and return its `pagination` block via serverPagination.\n// Tools whose data has no server pagination (hub, public endpoints, capacity)\n// cap client-side with capList, whose cursors are offsets into one response.\n\nexport const DEFAULT_LIST_LIMIT = 20;\nexport const MAX_LIST_LIMIT = 100;\n\n// JSON Schema fragments for the shared list parameters (spread into a curated\n// tool's inputSchema properties).\nexport const listPaginationProperties = {\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: MAX_LIST_LIMIT,\n description: `Maximum number of items to return (default ${DEFAULT_LIST_LIMIT}, max ${MAX_LIST_LIMIT}). Use the returned nextCursor to fetch the next page.`,\n },\n cursor: {\n type: 'string',\n description:\n 'Opaque pagination cursor from a previous response (nextCursor). Omit to start from the beginning.',\n },\n} as const;\n\n// Coerce, floor at 1, and cap: the low-level server never validates the\n// JSON Schema, so limit: 0 (or junk) would otherwise return an empty page\n// whose nextCursor never advances.\nexport function clampListLimit(limit: unknown): number {\n const requested = Number(limit);\n return Math.min(\n Number.isFinite(requested) && requested >= 1\n ? Math.floor(requested)\n : DEFAULT_LIST_LIMIT,\n MAX_LIST_LIMIT\n );\n}\n\n// Query for a server-paginated list: the capped limit, and the server's\n// opaque cursor verbatim. A malformed cursor is the server's to reject (422).\nexport function serverPageQuery(args: Record<string, unknown>): {\n limit: number;\n cursor?: string;\n} {\n const cursor =\n typeof args.cursor === 'string' && args.cursor !== ''\n ? args.cursor\n : undefined;\n return { limit: clampListLimit(args.limit), ...(cursor ? { cursor } : {}) };\n}\n\n// The server's pagination block, plus how many items this page returned.\nexport function serverPagination(\n pagination: { nextCursor?: string | null; hasNextPage?: boolean } | undefined,\n returned: number\n): Record<string, unknown> {\n const hasNextPage = pagination?.hasNextPage === true;\n return {\n returned,\n hasNextPage,\n nextCursor: pagination?.nextCursor ?? null,\n ...(hasNextPage\n ? { note: 'More results exist. Pass cursor=nextCursor to fetch them.' }\n : {}),\n };\n}\n\n// The cursor is a base64-encoded offset today; invalid values are treated as\n// the start so a bad cursor never throws in an agent's face.\nexport function decodeCursorOffset(cursor: string | undefined): number {\n if (!cursor) return 0;\n try {\n // Strict digits-only: parseInt would accept \"20junk\" (and Node's base64\n // decoder silently strips non-alphabet bytes first), silently paginating\n // mid-list from a mangled cursor instead of restarting.\n const decoded = Buffer.from(cursor, 'base64').toString('utf8');\n if (!/^\\d+$/.test(decoded)) return 0;\n const offset = Number.parseInt(decoded, 10);\n return Number.isFinite(offset) && offset >= 0 ? offset : 0;\n } catch {\n return 0;\n }\n}\n\nexport function encodeCursorOffset(offset: number): string {\n return Buffer.from(String(offset), 'utf8').toString('base64');\n}\n\n// Caps a list to `limit` items starting at `cursor`, returning an envelope\n// that tells the agent how much it is seeing and how to get the rest. `extra`\n// merges small aggregate sibling fields alongside items/pagination; reserved\n// keys in it are ignored so they cannot shadow the cap.\nexport function capList(\n items: unknown[],\n options: { limit?: number; cursor?: string },\n extra?: Record<string, unknown>\n): Record<string, unknown> {\n const limit = clampListLimit(options.limit);\n const offset = decodeCursorOffset(options.cursor);\n const total = items.length;\n const page = items.slice(offset, offset + limit);\n const nextOffset = offset + page.length;\n const hasMore = nextOffset < total;\n const { items: _i, pagination: _p, ...safeExtra } = extra ?? {};\n void _i;\n void _p;\n return {\n ...safeExtra,\n items: page,\n pagination: {\n total,\n returned: page.length,\n offset,\n truncated: hasMore,\n nextCursor: hasMore ? encodeCursorOffset(nextOffset) : null,\n ...(hasMore\n ? {\n note: `Showing ${page.length} of ${total}. Pass cursor=nextCursor to fetch more, or narrow the query with filters.`,\n }\n : {}),\n },\n };\n}\n","// Shared error type for the non-SDK clients (runtime, GraphQL, SSE): carries\n// the HTTP status and the response body so tool handlers can map it onto a\n// ToolResult instead of leaking a bare exception to the MCP client.\n\nexport class HttpError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly payload: unknown = undefined\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\n// The one message for a credential-less call on a credentialed surface. Every\n// client throws this instead of sending `Bearer undefined` or a silently\n// unauthenticated request — runTool maps it onto a 401 tool result.\nexport function missingKeyError(): HttpError {\n return new HttpError(\n 'No Runpod API key: the request carried no usable credential.',\n 401\n );\n}\n","// Shared helpers for curated tool handlers.\n\nimport { HttpError } from '../clients/http-error.js';\nimport type { ToolResult } from '../dispatch.js';\n\nexport function ok(payload: unknown): ToolResult {\n return { ok: true, status: 200, payload };\n}\n\nexport function badRequest(message: string): ToolResult {\n return { ok: false, status: 400, payload: { error: message } };\n}\n\n// Runs a handler body and maps a thrown HttpError onto a ToolResult; anything\n// else propagates (a bug should fail loudly, not masquerade as an API error).\nfunction isTimeout(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n if (error.name === 'TimeoutError' || error.name === 'AbortError') return true;\n const cause = (error as { cause?: unknown }).cause;\n return (\n cause instanceof Error &&\n (cause.name === 'TimeoutError' || cause.name === 'AbortError')\n );\n}\n\nexport async function runTool(\n body: () => Promise<ToolResult>\n): Promise<ToolResult> {\n try {\n return await body();\n } catch (error) {\n if (error instanceof HttpError) {\n return {\n ok: false,\n status: error.status,\n payload: { error: error.message, detail: error.payload },\n };\n }\n // A request deadline firing (boundedFetch on the SDK/GraphQL/runtime paths,\n // or the SSE reader's own controller) must come back as a retryable tool error,\n // not a protocol-level crash. undici surfaces it either as the abort\n // reason itself (TimeoutError) or wrapped as `fetch failed` with a cause.\n if (isTimeout(error)) {\n return {\n ok: false,\n status: 504,\n payload: {\n error: 'The Runpod API did not respond before the request deadline.',\n hint: 'Transient upstream stall: retry the same call once; if it persists, check https://uptime.runpod.io.',\n },\n };\n }\n throw error;\n }\n}\n","// Shared MCP annotation sets for the curated overlay. The generated tools\n// derive theirs from the HTTP method (specgen/generator/tools.ts); curated\n// tools have no method to read, so each one picks the set that matches what\n// it does. Every tool that reaches the Runpod API sets openWorldHint; the\n// knowledge tools read the bundled plugin package and do not. destructiveHint here means \"can delete a resource or work in flight\",\n// not \"can lose state\": an additive update such as a PATCH is not destructive.\nimport type { ToolAnnotations } from '../types.js';\n\n/** A pure read: safe to call without asking anyone. */\nexport const readOnly: ToolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n};\n\n/** A read of the bundled plugin knowledge: no Runpod API call. */\nexport const bundledRead: ToolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n};\n\n/** A write that creates or submits: repeating it produces another thing. */\nexport const write: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n};\n\n/** A write that sets state: repeating it lands on the same state. */\nexport const idempotentWrite: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n};\n\n/** A write that destroys work in flight (cancel, purge, delete). */\nexport const destructive: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: true,\n};\n","// Curated get-capacity tool. The per-CUDA-version stock matrix, graded stock,\n// and per-version pricing live only in GraphQL (gpuTypes.lowestPrice with\n// gpuTypeCudaVersions / allowedCudaVersions input) — the REST catalog's only\n// CUDA dimension is a floor filter — so this cannot be generated from the v2\n// spec. Ported from the official MCP server (Apache-2.0, runpod/runpod-mcp).\n// Credential-free: served by the public GraphQL endpoint.\n\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\nconst CUDA_VERSION_REGEX = /^\\d{1,2}\\.\\d{1,2}$/;\nconst MAX_PROBE_VERSIONS = 12;\n\ninterface CapacityGpu {\n id: string;\n displayName: string;\n memoryInGb: number;\n secureCloud: boolean;\n communityCloud: boolean;\n lowestPrice?: {\n stockStatus: string | null;\n uninterruptablePrice: number | null;\n gpuTypeCudaVersions?: Array<{\n cudaVersion: string;\n availability: string;\n }> | null;\n } | null;\n}\n\ninterface CapacityResponse {\n gpuTypes: CapacityGpu[];\n}\n\nconst stockPriority: Record<string, number> = { High: 3, Medium: 2, Low: 1 };\n\n// The arguments both modes share, re-validated at runtime (the low-level\n// server never validates inputSchema): gpuCount coerced to an int in [1,8],\n// secureCloud a literal, blank filter entries dropped (a schema-bypassed [\"\"]\n// must not match the whole catalog).\ninterface CapacityQuery {\n gpuCount: number;\n secureArg: string;\n includeUnavailable: boolean;\n matchesFilter: (gpu: CapacityGpu) => boolean;\n pageOpts: { limit: number | undefined; cursor: string | undefined };\n}\n\nfunction parseCapacityArgs(args: Record<string, unknown>): CapacityQuery {\n const filterTerms = ((args.gpuTypeIds as string[] | undefined) ?? [])\n .filter((t) => typeof t === 'string' && t.trim().length > 0)\n .map((t) => t.toLowerCase());\n return {\n gpuCount: Math.min(8, Math.max(1, Math.floor(Number(args.gpuCount)) || 1)),\n secureArg: args.secureCloudOnly ? ', secureCloud: true' : '',\n includeUnavailable: args.includeUnavailable !== false,\n matchesFilter: (gpu) => {\n if (filterTerms.length === 0) return true;\n const id = gpu.id.toLowerCase();\n const name = gpu.displayName.toLowerCase();\n return filterTerms.some(\n (term) => id.includes(term) || name.includes(term)\n );\n },\n pageOpts: {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n },\n };\n}\n\n// The one ranking both modes share: most versions in stock first, then the\n// strongest stock grade, then memory; drop no-stock rows unless the caller\n// asked to keep them (they sort last either way).\nfunction rankByStock<T>(\n rows: T[],\n stats: (row: T) => {\n inStock: number;\n bestPriority: number;\n memoryGb: number;\n },\n includeUnavailable: boolean\n): T[] {\n const kept = includeUnavailable\n ? rows\n : rows.filter((row) => stats(row).inStock > 0);\n return kept.sort((a, b) => {\n const sa = stats(a);\n const sb = stats(b);\n return (\n sb.inStock - sa.inStock ||\n sb.bestPriority - sa.bestPriority ||\n sb.memoryGb - sa.memoryGb\n );\n });\n}\n\nexport const getCapacity: CuratedTool = {\n name: 'get-capacity',\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n cudaVersions: {\n type: 'array',\n items: { type: 'string', pattern: '^\\\\d{1,2}\\\\.\\\\d{1,2}$' },\n minItems: 1,\n maxItems: MAX_PROBE_VERSIONS,\n description:\n 'Deep-probe these host CUDA versions (e.g. [\"12.8\", \"13.0\"], max 12): one stock lookup per version returns graded stock and price. Omit for the single-call AVAILABLE/UNAVAILABLE matrix across all versions the fleet currently reports.',\n },\n includeUnavailable: {\n type: 'boolean',\n description:\n 'Out-of-stock GPUs are included by default (explicit \"Out\" cells / all-UNAVAILABLE rows, sorted last). Set false to hide GPUs with no stock on any listed version.',\n },\n gpuTypeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"Filter to GPU types matching any of these ids or display names (case-insensitive substring, e.g. ['NVIDIA GeForce RTX 4090'] or ['4090', 'H200']).\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n maximum: 8,\n description: 'GPUs per worker/pod to check stock for (default 1).',\n },\n secureCloudOnly: {\n type: 'boolean',\n description: 'Restrict the stock lookup to Secure Cloud hosts.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(() => {\n const query = parseCapacityArgs(args);\n const cudaVersions = args.cudaVersions as string[] | undefined;\n return cudaVersions?.length\n ? probeMode(ctx, query, cudaVersions)\n : matrixMode(ctx, query);\n }),\n};\n\n// Matrix mode: one query, per-version AVAILABLE/UNAVAILABLE from the fleet.\nasync function matrixMode(ctx: ToolContext, query: CapacityQuery) {\n // The public GraphQL path takes no variables, so arguments are inlined —\n // every inlined value was re-validated in parseCapacityArgs.\n const data = await ctx.graphql.public<CapacityResponse>(`\n query {\n gpuTypes {\n id\n displayName\n memoryInGb\n secureCloud\n communityCloud\n lowestPrice(input: { gpuCount: ${query.gpuCount}${query.secureArg} }) {\n stockStatus\n uninterruptablePrice\n gpuTypeCudaVersions {\n cudaVersion\n availability\n }\n }\n }\n }\n `);\n const rows = (data.gpuTypes ?? [])\n .filter((gpu) => gpu.id !== 'unknown' && query.matchesFilter(gpu))\n .map((gpu) => {\n const cuda: Record<string, string> = {};\n for (const c of gpu.lowestPrice?.gpuTypeCudaVersions ?? []) {\n cuda[c.cudaVersion] = c.availability;\n }\n return {\n id: gpu.id,\n displayName: gpu.displayName,\n memoryGb: gpu.memoryInGb,\n secureCloud: gpu.secureCloud,\n communityCloud: gpu.communityCloud,\n stockStatus: gpu.lowestPrice?.stockStatus || 'unavailable',\n pricePerHr: gpu.lowestPrice?.uninterruptablePrice ?? null,\n cudaVersions: cuda,\n };\n });\n const ranked = rankByStock(\n rows,\n (r) => ({\n inStock: Object.values(r.cudaVersions).filter((a) => a === 'AVAILABLE')\n .length,\n bestPriority: stockPriority[r.stockStatus] || 0,\n memoryGb: r.memoryGb,\n }),\n query.includeUnavailable\n );\n return ok(capList(ranked, query.pageOpts));\n}\n\ninterface ProbeRow {\n id: string;\n displayName: string;\n memoryGb: number;\n secureCloud: boolean;\n communityCloud: boolean;\n cudaVersions: Record<string, { stock: string; pricePerHr: number | null }>;\n}\n\n// Probe mode: one stock lookup per requested version, merged per GPU. The\n// schema caps at 12, but the cap is re-enforced here because direct handler\n// calls can bypass schema validation.\nasync function probeMode(\n ctx: ToolContext,\n query: CapacityQuery,\n cudaVersions: string[]\n) {\n const versions = [...new Set(cudaVersions)].slice(0, MAX_PROBE_VERSIONS);\n const invalid = versions.filter((v) => !CUDA_VERSION_REGEX.test(v));\n if (invalid.length > 0) {\n return badRequest(\n `Invalid CUDA version format: ${invalid.join(', ')}. Use \"major.minor\" strings like \"12.8\".`\n );\n }\n // allSettled, not all: a transient failure on one probe must not discard\n // the other versions' results — failures land in probeErrors instead.\n const perVersion = await Promise.allSettled(\n versions.map((v) =>\n ctx.graphql.public<CapacityResponse>(`\n query {\n gpuTypes {\n id\n displayName\n memoryInGb\n secureCloud\n communityCloud\n lowestPrice(input: { gpuCount: ${query.gpuCount}, allowedCudaVersions: [\"${v}\"]${query.secureArg} }) {\n stockStatus\n uninterruptablePrice\n }\n }\n }\n `)\n )\n );\n\n const probeErrors: Record<string, string> = {};\n const byId = new Map<string, ProbeRow>();\n versions.forEach((v, i) => {\n const settled = perVersion[i];\n if (settled.status === 'rejected') {\n probeErrors[v] =\n settled.reason instanceof Error\n ? settled.reason.message\n : String(settled.reason);\n return;\n }\n for (const gpu of settled.value.gpuTypes ?? []) {\n if (gpu.id === 'unknown' || !query.matchesFilter(gpu)) continue;\n let row = byId.get(gpu.id);\n if (!row) {\n row = {\n id: gpu.id,\n displayName: gpu.displayName,\n memoryGb: gpu.memoryInGb,\n secureCloud: gpu.secureCloud,\n communityCloud: gpu.communityCloud,\n cudaVersions: {},\n };\n byId.set(gpu.id, row);\n }\n const stock = gpu.lowestPrice?.stockStatus;\n // No stockStatus means no hosts match this version at all — record\n // an explicit \"Out\" cell so starvation is visible rather than an\n // absence the agent has to infer.\n row.cudaVersions[v] =\n !stock || stock === 'Out'\n ? { stock: 'Out', pricePerHr: null }\n : {\n stock,\n pricePerHr: gpu.lowestPrice?.uninterruptablePrice ?? null,\n };\n }\n });\n\n const ranked = rankByStock(\n [...byId.values()],\n (r) => ({\n inStock: Object.values(r.cudaVersions).filter((c) => c.stock !== 'Out')\n .length,\n bestPriority: Math.max(\n 0,\n ...Object.values(r.cudaVersions).map((c) => stockPriority[c.stock] || 0)\n ),\n memoryGb: r.memoryGb,\n }),\n query.includeUnavailable\n );\n return ok(\n capList(ranked, query.pageOpts, {\n probedCudaVersions: versions,\n ...(Object.keys(probeErrors).length > 0 ? { probeErrors } : {}),\n })\n );\n}\n","// GPU-selection convenience tool. REST v2 supports exclusions directly, so a\n// sparse PATCH replaces the legacy GraphQL read/echo/write operation.\nimport type { components } from '@runpod/typescript-api-sdk';\nimport type { CuratedTool } from '../types.js';\nimport { restError } from '../clients/rest-result.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { idempotentWrite } from './annotations.js';\n\ntype GpuSelection = { pools: string[]; excludedTypes: string[] };\nconst CUDA_VERSION = /^\\d+\\.\\d+$/;\n\nfunction nonemptyStrings(value: unknown): value is string[] {\n return (\n Array.isArray(value) &&\n value.every((item) => typeof item === 'string' && item.trim().length > 0)\n );\n}\n\nfunction gpuSelection(args: Record<string, unknown>): GpuSelection | string {\n if (args.gpuIds !== undefined) {\n if (typeof args.gpuIds !== 'string' || !args.gpuIds.trim())\n return 'gpuIds must be a non-empty string.';\n const selection: GpuSelection = { pools: [], excludedTypes: [] };\n for (const value of args.gpuIds.split(',').map((value) => value.trim())) {\n if (!value || value === '-')\n return 'gpuIds contains an empty pool or GPU exclusion.';\n if (value.startsWith('-'))\n selection.excludedTypes.push(value.slice(1).trim());\n else selection.pools.push(value);\n }\n return selection.pools.length\n ? selection\n : 'gpuIds must include at least one GPU pool.';\n }\n if (!nonemptyStrings(args.pools) || args.pools.length === 0)\n return 'Provide gpuIds or a non-empty pools array. See list-gpu-types for pool names.';\n if (\n args.excludeGpuTypeIds !== undefined &&\n !nonemptyStrings(args.excludeGpuTypeIds)\n )\n return 'excludeGpuTypeIds must be an array of non-empty strings.';\n return {\n pools: args.pools.map((value) => value.trim()),\n excludedTypes:\n (args.excludeGpuTypeIds as string[] | undefined)?.map((value) =>\n value.trim()\n ) ?? [],\n };\n}\n\nfunction formatGpuIds(gpu: {\n pools?: string[];\n excludedTypes?: string[];\n}): string {\n return [\n ...(gpu.pools ?? []),\n ...(gpu.excludedTypes ?? []).map((id) => `-${id}`),\n ].join(',');\n}\n\nexport const setEndpointGpus: CuratedTool = {\n name: 'set-endpoint-gpus',\n annotations: idempotentWrite,\n description:\n \"Set which GPUs a Serverless endpoint's workers run on — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n type: 'string',\n description: 'ID of the Serverless endpoint to update',\n },\n gpuIds: {\n type: 'string',\n description:\n \"Raw gpuIds string, e.g. 'ADA_24' or 'AMPERE_16,-NVIDIA RTX A4500'. Takes precedence over pools/excludeGpuTypeIds.\",\n },\n pools: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"GPU pool names workers may use (e.g. ['ADA_80_PRO','AMPERE_80']). The pool field from list-gpu-types.\",\n },\n excludeGpuTypeIds: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"GPU type ids to exclude from the allowed pools (e.g. ['NVIDIA H100 NVL']). Use with pools to pin specific SKUs.\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n description: 'GPUs per worker. Omit to keep the current value.',\n },\n minCudaVersion: {\n type: 'string',\n description:\n \"Minimum host CUDA version workers may run on (e.g. '12.4'). Omit to keep the current value; use an empty string to clear it.\",\n },\n allowedCudaVersions: {\n type: 'string',\n description:\n \"Comma-separated allowed host CUDA versions (e.g. '12.8,12.7,12.6'). Omit to keep the current value; use an empty string to clear the list. CUDA compatibility is part of GPU selection — a narrow list can leave an endpoint unable to schedule workers.\",\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const selection = gpuSelection(args);\n if (typeof selection === 'string') return badRequest(selection);\n if (typeof args.endpointId !== 'string' || !args.endpointId.trim())\n return badRequest('endpointId must be a non-empty string.');\n if (\n args.gpuCount !== undefined &&\n (!Number.isSafeInteger(args.gpuCount) || Number(args.gpuCount) < 1)\n )\n return badRequest('gpuCount must be a positive integer.');\n if (\n args.minCudaVersion !== undefined &&\n (typeof args.minCudaVersion !== 'string' ||\n (args.minCudaVersion !== '' &&\n !CUDA_VERSION.test(args.minCudaVersion)))\n )\n return badRequest(\n 'minCudaVersion must be major.minor, or an empty string to clear it.'\n );\n if (\n args.allowedCudaVersions !== undefined &&\n typeof args.allowedCudaVersions !== 'string'\n )\n return badRequest(\n 'allowedCudaVersions must be a comma-separated string.'\n );\n const allowed =\n typeof args.allowedCudaVersions === 'string'\n ? args.allowedCudaVersions\n .split(',')\n .map((value) => value.trim())\n .filter(Boolean)\n : undefined;\n if (allowed?.some((value) => !CUDA_VERSION.test(value)))\n return badRequest(\n 'allowedCudaVersions must contain major.minor versions.'\n );\n if (allowed?.length && args.minCudaVersion)\n return badRequest(\n 'Set either allowedCudaVersions or minCudaVersion, not both.'\n );\n\n const params = { path: { id: args.endpointId } };\n const current = await ctx.sdk.GET('/v2/serverless/{id}', { params });\n if (!current.response.ok)\n return restError(current.response, current.error);\n if (!current.data?.gpu)\n return badRequest('This endpoint does not have a GPU configuration.');\n const gpu: components['schemas']['UpdateEndpointGpuConfig'] = {\n ...selection,\n ...(args.gpuCount !== undefined\n ? { count: args.gpuCount as number }\n : {}),\n ...(args.minCudaVersion !== undefined\n ? { minCudaVersion: args.minCudaVersion as string }\n : {}),\n ...(allowed !== undefined ? { allowedCudaVersions: allowed } : {}),\n };\n const updated = await ctx.sdk.PATCH('/v2/serverless/{id}', {\n params,\n body: { gpu },\n });\n if (!updated.response.ok)\n return restError(updated.response, updated.error);\n const updatedGpu = updated.data?.gpu;\n if (!updated.data || !updatedGpu)\n return {\n ok: false,\n status: 502,\n payload: { error: 'The API returned no updated GPU endpoint.' },\n };\n const endpoint = updated.data;\n return ok({\n endpoint: {\n id: endpoint.id,\n name: endpoint.name,\n gpuIds: formatGpuIds(updatedGpu),\n gpuCount: updatedGpu.count,\n workersMin: endpoint.workers?.min,\n workersMax: endpoint.workers?.max,\n },\n previousGpuIds: formatGpuIds(current.data.gpu),\n });\n }),\n};\n","// Curated Hub tools. The Hub catalog and Hub deploys have no REST home: the\n// catalog is the public GraphQL `listings(input: {})` query, and a deploy is\n// the authenticated saveEndpoint mutation pinned to a hubReleaseId. Ported\n// from the official MCP server (Apache-2.0, runpod/runpod-mcp).\n\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport type { ToolResult } from '../dispatch.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { readOnly, write } from './annotations.js';\n\ninterface HubBuild {\n id: string;\n imageName: string;\n}\n\ninterface HubRelease {\n id: string;\n name: string;\n tagName: string;\n createdAt: string;\n config?: string | null;\n build?: HubBuild | null;\n}\n\ninterface HubListing {\n id: string;\n repoId: string;\n title: string;\n description: string | null;\n repoName: string;\n repoOwner: string;\n createdAt: string;\n updatedAt: string;\n views: number;\n stars: number;\n deploys: number;\n language: string | null;\n category: string | null;\n tags: string[] | null;\n type: string;\n listedRelease?: HubRelease | null;\n}\n\ninterface ListingsResponse {\n listings: HubListing[];\n}\n\n// The release `config` is the repo's .runpod/hub.json serialized as a JSON\n// string (hardware requirements + env-var input schema). Tens of KB per\n// listing, so it is only requested when needed.\nfunction parseReleaseConfig(config: string | null | undefined): unknown {\n if (!config) return undefined;\n try {\n return JSON.parse(config);\n } catch {\n return config;\n }\n}\n\ninterface HubReleaseConfig {\n runsOn?: string;\n containerDiskInGb?: number;\n gpuIds?: string;\n gpuCount?: number;\n allowedCudaVersions?: string[];\n env?: Array<{\n key: string;\n input?: {\n name?: string;\n type?: string;\n default?: unknown;\n required?: boolean;\n trueValue?: string;\n falseValue?: string;\n };\n }>;\n}\n\n// The one listings query both hub tools share. `withConfig` pulls in the\n// (large) release config only when the caller needs it.\nfunction listingsQuery(withConfig: boolean): string {\n return `\n query {\n listings(input: {}) {\n id\n repoId\n title\n description\n repoName\n repoOwner\n createdAt\n updatedAt\n views\n stars\n deploys\n language\n category\n tags\n type\n listedRelease {\n id\n name\n tagName\n createdAt${withConfig ? '\\n config' : ''}\n build {\n id\n imageName\n }\n }\n }\n }\n `;\n}\n\n// Serializes a boolean through the schema's trueValue/falseValue. Applied to\n// caller values too: an agent naturally passes 'true' where the schema\n// declares trueValue '1'. Only exact 'true'/'false' map; anything else is a\n// deliberate literal.\nfunction serializeBoolean(\n value: string,\n input: { type?: string; trueValue?: string; falseValue?: string }\n): string {\n if (value === 'true') return input.trueValue ?? 'true';\n if (value === 'false') return input.falseValue ?? 'false';\n return value;\n}\n\n// Builds the template env array a Hub deploy submits: every key from the\n// release's env schema with its default (booleans serialized through\n// trueValue/falseValue), overridden by caller values. Caller keys not in the\n// schema are appended verbatim. Returns the missing required keys so the tool\n// can fail with an actionable message instead of a broken endpoint.\nexport function buildHubEnv(\n config: HubReleaseConfig,\n overrides: Record<string, string>\n): { env: Array<{ key: string; value: string }>; missingRequired: string[] } {\n const env: Array<{ key: string; value: string }> = [];\n const missingRequired: string[] = [];\n const remaining = { ...overrides };\n\n for (const entry of config.env ?? []) {\n const input = entry.input ?? {};\n const override = entry.key in remaining ? remaining[entry.key] : undefined;\n delete remaining[entry.key];\n\n // Empty overrides retain the existing fallback to the release default.\n // Validate the final serialized value, including boolean mappings.\n let value: string | undefined;\n if (override !== undefined && override !== '') {\n value =\n input.type === 'boolean' ? serializeBoolean(override, input) : override;\n } else if (input.default !== undefined && input.default !== null) {\n value =\n typeof input.default === 'boolean'\n ? serializeBoolean(String(input.default), input)\n : String(input.default);\n }\n\n if (input.required && (value === undefined || value === '')) {\n missingRequired.push(entry.key);\n env.push({ key: entry.key, value: '' });\n continue;\n }\n if (value !== undefined) env.push({ key: entry.key, value });\n\n // Optional, no default, nothing supplied: OMIT the key rather than send ''\n // (os.environ.get('X', 'fallback') returns '' when X='', shadowing the\n // fallback).\n }\n\n for (const [key, value] of Object.entries(remaining)) {\n env.push({ key, value });\n }\n\n return { env, missingRequired };\n}\n\n// Lowest entry of the config's allowedCudaVersions (numeric-aware compare, so\n// '12.10' > '12.9'). The console submits this as minCudaVersion.\nexport function minCudaVersion(versions: string[] | undefined): string | null {\n if (!versions || versions.length === 0) return null;\n const compare = (a: string, b: string) => {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d;\n }\n return 0;\n };\n return [...versions].sort(compare)[0];\n}\n\nfunction randomSuffix(): string {\n return Math.random().toString(36).slice(2, 8);\n}\n\nexport const listHubRepos: CuratedTool = {\n name: 'list-hub-repos',\n annotations: readOnly,\n description:\n 'List repos published to the Runpod Hub (prebuilt Serverless workers and Pod templates, e.g. vLLM, ComfyUI). Public catalog — 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) — it is large, so prefer requesting it for a single repo via the repoOwner/searchTerm filters.',\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n searchTerm: {\n type: 'string',\n description:\n \"Case-insensitive search across title, description, repo name, owner, and tags (e.g. 'vllm', 'comfyui', 'fine-tuning')\",\n },\n category: {\n type: 'string',\n description:\n \"Filter by category (e.g. 'language', 'image', 'audio', 'video', 'embedding')\",\n },\n type: {\n type: 'string',\n enum: ['SERVERLESS', 'POD'],\n description:\n 'Filter by listing type: SERVERLESS (endpoint workers) or POD (pod templates)',\n },\n repoOwner: {\n type: 'string',\n description:\n \"Filter to listings from this GitHub owner/org (e.g. 'runpod-workers', 'axolotl-ai-cloud')\",\n },\n includeConfig: {\n type: 'boolean',\n description:\n 'Include the listed release config (hardware requirements + env-var input schema, parsed from .runpod/hub.json). Large — off by default.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const data = await ctx.graphql.public<ListingsResponse>(\n listingsQuery(args.includeConfig === true)\n );\n\n let listings = data.listings ?? [];\n\n if (args.type) {\n // Normalize the arg too: the server never validates inputSchema, so a\n // lowercase \"serverless\" must match, not return a silent empty page.\n const term = String(args.type).toUpperCase();\n listings = listings.filter(\n (l) => (l.type ?? '').toUpperCase() === term\n );\n }\n if (args.category) {\n const term = String(args.category).toLowerCase();\n listings = listings.filter(\n (l) => (l.category ?? '').toLowerCase() === term\n );\n }\n if (args.repoOwner) {\n const term = String(args.repoOwner).toLowerCase();\n listings = listings.filter(\n (l) => (l.repoOwner ?? '').toLowerCase() === term\n );\n }\n if (args.searchTerm) {\n const term = String(args.searchTerm).toLowerCase();\n listings = listings.filter((l) =>\n [\n l.title,\n l.description,\n l.repoName,\n l.repoOwner,\n ...(l.tags ?? []),\n ].some((field) => (field ?? '').toLowerCase().includes(term))\n );\n }\n\n // Most-deployed first, id as tiebreak. The tiebreak is load-bearing:\n // each page re-fetches the whole catalog and the query promises no\n // order, so ties would move between requests and paging would silently\n // skip and duplicate.\n listings = [...listings].sort(\n (a, b) =>\n (b.deploys ?? 0) - (a.deploys ?? 0) || a.id.localeCompare(b.id)\n );\n\n const result = listings.map((l) => ({\n id: l.id,\n repo: `${l.repoOwner}/${l.repoName}`,\n title: l.title,\n description: l.description,\n type: l.type,\n category: l.category,\n tags: l.tags,\n language: l.language,\n stars: l.stars,\n deploys: l.deploys,\n views: l.views,\n githubUrl: `https://github.com/${l.repoOwner}/${l.repoName}`,\n hubUrl: `https://console.runpod.io/hub/${l.repoOwner}/${l.repoName}`,\n createdAt: l.createdAt,\n updatedAt: l.updatedAt,\n listedRelease: l.listedRelease\n ? {\n hubReleaseId: l.listedRelease.id,\n name: l.listedRelease.name,\n tagName: l.listedRelease.tagName,\n createdAt: l.listedRelease.createdAt,\n imageName: l.listedRelease.build?.imageName,\n ...(args.includeConfig === true\n ? { config: parseReleaseConfig(l.listedRelease.config) }\n : {}),\n }\n : null,\n }));\n\n return ok(\n capList(result, {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n })\n );\n }),\n};\n\nexport const deployHubRepo: CuratedTool = {\n name: 'deploy-hub-repo',\n // Two sequential upstream calls: together they can outlast a client's request timeout.\n holdsResponse: true,\n annotations: write,\n description:\n \"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 — 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).\",\n inputSchema: {\n type: 'object',\n properties: {\n repo: {\n type: 'string',\n description:\n 'The Hub repo to deploy as \"owner/name\" (e.g. \\'runpod-workers/worker-comfyui\\'). Deploys its currently listed release. Provide this or hubReleaseId.',\n },\n hubReleaseId: {\n type: 'string',\n description:\n 'The Hub release ID to deploy (from list-hub-repos listedRelease.hubReleaseId). Provide this or repo.',\n },\n name: {\n type: 'string',\n description:\n \"Name for the new endpoint. Defaults to '<listing title> <release tag>'.\",\n },\n env: {\n type: 'object',\n additionalProperties: { type: 'string' },\n description:\n 'Environment variable overrides, merged over the release config defaults. Keys not in the release schema are passed through as-is.',\n },\n gpuIds: {\n type: 'string',\n description:\n \"Comma-separated GPU pool names for workers (e.g. 'ADA_24' or 'ADA_80_PRO,AMPERE_80'). To pin specific GPU SKUs within a pool, append exclusions prefixed with '-' using GPU type ids from list-gpu-types. Defaults to the release config's gpuIds; required when the config does not specify one.\",\n },\n gpuCount: {\n type: 'integer',\n minimum: 1,\n description: 'GPUs per worker. Defaults to the release config (or 1).',\n },\n containerDiskInGb: {\n type: 'integer',\n minimum: 1,\n description:\n 'Container disk size in GB. Defaults to the release config.',\n },\n workersMin: {\n type: 'integer',\n minimum: 0,\n description: 'Minimum workers (default 0 — scale to zero).',\n },\n workersMax: {\n type: 'integer',\n minimum: 1,\n description: 'Maximum workers (default: account default).',\n },\n idleTimeout: {\n type: 'integer',\n minimum: 1,\n description: 'Seconds a worker idles before scaling down (default 5).',\n },\n scalerType: {\n type: 'string',\n enum: ['QUEUE_DELAY', 'REQUEST_COUNT'],\n description: 'Autoscaler type (default QUEUE_DELAY).',\n },\n scalerValue: {\n type: 'number',\n description: 'Autoscaler target value (default 4).',\n },\n executionTimeoutMs: {\n type: 'integer',\n minimum: 1,\n description: 'Per-job execution timeout in ms (default 600000).',\n },\n flashboot: {\n type: 'string',\n enum: ['OFF', 'FLASHBOOT', 'PRIORITY_FLASHBOOT'],\n description: 'FlashBoot mode (default FLASHBOOT).',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n if (!args.repo && !args.hubReleaseId) {\n return badRequest(\n 'Provide either repo (\"owner/name\") or hubReleaseId. Use list-hub-repos to discover both.'\n );\n }\n const catalog = await ctx.graphql.public<ListingsResponse>(\n listingsQuery(true)\n );\n const listing = resolveListing(catalog, args);\n if ('payload' in listing) return listing;\n const release = checkDeployable(listing);\n if ('payload' in release) return release;\n const built = buildEndpointInput(listing, release, args);\n if ('payload' in built) return built;\n const data = await ctx.graphql.authed<SaveEndpointResponse>(\n SAVE_ENDPOINT_MUTATION,\n { input: built.input }\n );\n return ok({\n endpoint: data.saveEndpoint,\n deployed: {\n repo: `${listing.repoOwner}/${listing.repoName}`,\n release: release.tagName,\n hubReleaseId: release.id,\n imageName: release.build.imageName,\n },\n note: `Endpoint created. Submit jobs with run-endpoint/runsync-endpoint using endpointId \"${data.saveEndpoint.id}\".`,\n });\n }),\n};\n\n// ---- deploy-hub-repo helpers. Each returns its value or a ToolResult error\n// (discriminated by the `payload` key, which only ToolResult carries) so the\n// handler reads as the sequence of steps it is.\n\n// Narrowed by checkDeployable: a deployable release has a built image.\ntype DeployListedRelease = NonNullable<HubListing['listedRelease']> & {\n build: { imageName: string };\n};\n\n// Resolve the listing from the public catalog. The catalog only exposes each\n// repo's currently LISTED release, so a hubReleaseId must match one of those\n// (also the only state the console deploys).\nfunction resolveListing(\n catalog: ListingsResponse,\n args: Record<string, unknown>\n): HubListing | ToolResult {\n let listing: HubListing | undefined;\n if (args.hubReleaseId) {\n listing = (catalog.listings ?? []).find(\n (l) => l.listedRelease?.id === args.hubReleaseId\n );\n } else {\n const repoKey = String(args.repo).toLowerCase();\n listing = (catalog.listings ?? []).find(\n (l) => `${l.repoOwner}/${l.repoName}`.toLowerCase() === repoKey\n );\n }\n if (!listing) {\n return badRequest(\n `No Hub listing found for ${\n args.hubReleaseId\n ? `hubReleaseId \"${args.hubReleaseId}\" (only each repo's currently listed release is deployable)`\n : `repo \"${args.repo}\"`\n }. Use list-hub-repos to see the catalog.`\n );\n }\n return listing;\n}\n\nfunction checkDeployable(\n listing: HubListing\n): DeployListedRelease | ToolResult {\n const release = listing.listedRelease;\n if (!release?.build?.imageName) {\n return badRequest(\n `Hub repo ${listing.repoOwner}/${listing.repoName} has no listed release with a built image, so it cannot be deployed.`\n );\n }\n if ((listing.type ?? '').toUpperCase() !== 'SERVERLESS') {\n return badRequest(\n `Hub repo ${listing.repoOwner}/${listing.repoName} is a ${listing.type} listing — only SERVERLESS listings deploy as endpoints.`\n );\n }\n return release as DeployListedRelease;\n}\n\nfunction buildEndpointInput(\n listing: HubListing,\n release: DeployListedRelease,\n args: Record<string, unknown>\n): { input: Record<string, unknown> } | ToolResult {\n const config = (parseReleaseConfig(release.config) ?? {}) as HubReleaseConfig;\n\n const gpuIds = (args.gpuIds as string | undefined) ?? config.gpuIds;\n if (!gpuIds) {\n return badRequest(\n 'This release does not specify a GPU pool — pass gpuIds (comma-separated pool names, e.g. \"ADA_80_PRO,AMPERE_80\"; see the pool field on list-gpu-types).'\n );\n }\n\n const { env, missingRequired } = buildHubEnv(\n config,\n (args.env as Record<string, string> | undefined) ?? {}\n );\n if (missingRequired.length > 0) {\n return badRequest(\n `Missing required environment variables for this release: ${missingRequired.join(', ')}. Pass them via the env parameter.`\n );\n }\n\n const endpointName =\n (args.name as string | undefined) ?? `${listing.title} ${release.tagName}`;\n const minCuda = minCudaVersion(config.allowedCudaVersions);\n\n return {\n input: {\n name: endpointName,\n hubReleaseId: release.id,\n type: 'QB',\n gpuIds,\n gpuCount: (args.gpuCount as number | undefined) ?? config.gpuCount ?? 1,\n workersMin: (args.workersMin as number | undefined) ?? 0,\n workersMax: (args.workersMax as number | undefined) ?? null,\n idleTimeout: (args.idleTimeout as number | undefined) ?? 5,\n scalerType: (args.scalerType as string | undefined) ?? 'QUEUE_DELAY',\n scalerValue: (args.scalerValue as number | undefined) ?? 4,\n executionTimeoutMs:\n (args.executionTimeoutMs as number | undefined) ?? 600000,\n flashBootType: (args.flashboot as string | undefined) ?? 'FLASHBOOT',\n locations: null,\n networkVolumeIds: null,\n compliance: [],\n modelReferences: [],\n ...(minCuda\n ? {\n minCudaVersion: minCuda,\n allowedCudaVersions: config.allowedCudaVersions!.join(','),\n }\n : {}),\n template: {\n name: `${endpointName}__template__${randomSuffix()}`,\n imageName: release.build.imageName,\n containerDiskInGb:\n (args.containerDiskInGb as number | undefined) ??\n config.containerDiskInGb ??\n 20,\n containerRegistryAuthId: '',\n dockerArgs: '',\n startScript: '',\n ports: '',\n env,\n },\n },\n };\n}\n\ninterface SaveEndpointResponse {\n saveEndpoint: {\n id: string;\n name: string;\n gpuIds: string;\n gpuCount: number;\n workersMin: number;\n workersMax: number | null;\n idleTimeout: number;\n scalerType: string;\n scalerValue: number;\n flashBootType: string;\n templateId: string;\n };\n}\n\nconst SAVE_ENDPOINT_MUTATION = `\n mutation saveEndpoint($input: EndpointInput!) {\n saveEndpoint(input: $input) {\n id\n name\n gpuIds\n gpuCount\n workersMin\n workersMax\n idleTimeout\n scalerType\n scalerValue\n flashBootType\n templateId\n }\n }\n`;\n\nexport const hubTools: CuratedTool[] = [listHubRepos, deployHubRepo];\n","// Curated tools for the Serverless runtime plane (job submission and\n// lifecycle at api.runpod.ai/v2/{endpointId}/...). Runpod publishes no OpenAPI\n// document for this plane, so these cannot be generated from the v2 spec;\n// behavior is ported from the official MCP server (Apache-2.0,\n// runpod/runpod-mcp). Two transports serve these tools: local stdio\n// (5-minute wait budgets) and the hosted Vercel path, where the 60s gateway\n// reaper clamps every hold to HTTP_LONG_POLL_BUDGET_MS (see HOSTED below).\n\nimport { HttpError } from '../clients/http-error.js';\nimport type { CuratedTool } from '../types.js';\nimport type { ToolContext } from '../context.js';\nimport { badRequest, ok, runTool } from './util.js';\nimport { destructive, readOnly, write } from './annotations.js';\n\nconst ID_PATTERN = '^[a-zA-Z0-9_-]+$';\nconst ID_REGEX = new RegExp(ID_PATTERN);\n\n// Upstream default the server applies when no ?wait= is sent on /runsync.\nconst RUNSYNC_UPSTREAM_DEFAULT_WAIT_MS = 90_000;\n// Client deadline slack on top of the wait the server was asked to hold — a\n// deadline at the hold aborts the reply we are waiting for.\nconst UPSTREAM_HOLD_SLACK_MS = 5_000;\n\n// stream-job polling: total budget, what an empty /stream holds for when no\n// ?wait= is sent (the stdio path omits the query), per-poll floor, pause\n// between polls, and the consecutive-error cap that ends the run.\n// Hosted (Vercel) requests are reaped at 60s (vercel.json maxDuration), so\n// every server-side hold clamps to 45s there — the response must serialize\n// before the platform kills the invocation. stdio keeps the 5-minute budgets.\nexport const HOSTED = process.env.VERCEL === '1';\nexport const HTTP_LONG_POLL_BUDGET_MS = 45_000;\nexport const STREAM_BUDGET_MS = HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : 5 * 60 * 1000;\nconst STREAM_UPSTREAM_DEFAULT_WAIT_MS = 10_000;\nconst MIN_POLL_TIMEOUT_MS = 1;\nconst STREAM_JOB_POLL_INTERVAL_MS = 1_000;\nexport const MAX_CONSECUTIVE_STREAM_ERRORS = 5;\n\n// get-job-status server-side wait: the ceiling on a single blocking call and\n// the pause between /status polls inside it. /status returns instantly (it\n// does not hold like /stream), so blocking through a cold start means polling\n// it here rather than making the agent tight-loop the tool — a turn-burn that\n// never advances wall-clock. Ceiling matches runsync's 5-minute wait cap.\nexport const STATUS_WAIT_MAX_MS = HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : 5 * 60 * 1000;\nconst STATUS_POLL_INTERVAL_MS = 4_000;\n\nconst TERMINAL_STATUSES = new Set([\n 'COMPLETED',\n 'FAILED',\n 'CANCELLED',\n 'TIMED_OUT',\n]);\n\nconst RESUME_ADVICE =\n 'Call stream-job again to continue collecting output, get-job-status to check the job without streaming, or stream without a budget by calling the runtime API directly (GET https://api.runpod.ai/v2/{endpointId}/stream/{jobId} with a Bearer API key).';\n\nfunction formatBudget(ms: number): string {\n return ms < 120_000\n ? `${Math.round(ms / 1000)} seconds`\n : `${Math.round(ms / 60_000)} minutes`;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(() => resolve(), ms);\n });\n}\n\n// A poll can use only the time remaining in the caller's budget. The\n// upstream hold gets slack when available, never an extension of that budget.\nexport function streamPollTimeoutMs(\n remainingMs: number,\n holdMs: number\n): number {\n return Math.max(\n Math.min(remainingMs, holdMs + UPSTREAM_HOLD_SLACK_MS),\n MIN_POLL_TIMEOUT_MS\n );\n}\n\n// One polling driver for both wait loops (/stream and /status): poll until a\n// terminal status, the budget runs out, or the API fails\n// MAX_CONSECUTIVE_STREAM_ERRORS times IN A ROW. Only consecutive failures end\n// the run, and the error reported at the end is one still happening at the\n// end. The callers differ only in how each poll's deadline derives from the\n// remaining budget, the cadence, and the advice attached to a non-terminal\n// exit.\nasync function pollUntilTerminal(deps: {\n poll: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n // Deadline for ONE poll, derived from the budget's remaining ms.\n timeoutFor: (remainingMs: number) => number;\n pollIntervalMs: number;\n // Advice strings for the two non-terminal exits.\n abortedNote: string;\n timedOutNote: string;\n // Chunk collection seam (/stream); called on every successful reply.\n onReply?: (reply: Record<string, unknown>) => void;\n}): Promise<Record<string, unknown>> {\n const startedAt = Date.now();\n const elapsed = () => Date.now() - startedAt;\n let result: Record<string, unknown> = {};\n let consecutiveErrors = 0;\n let lastError: string | undefined;\n let lastErrorStatus = 502;\n\n while (elapsed() < deps.budgetMs) {\n try {\n const reply = await deps.poll(deps.timeoutFor(deps.budgetMs - elapsed()));\n consecutiveErrors = 0;\n lastError = undefined;\n deps.onReply?.(reply);\n result = reply;\n if (TERMINAL_STATUSES.has(reply.status as string)) return result;\n } catch (error) {\n // Retrying cannot repair client errors. Let runTool retain the status\n // and recovery hint (especially 401 re-auth and 429 Retry-After).\n // A request timeout is transient and can still use the polling budget.\n if (\n error instanceof HttpError &&\n error.status >= 400 &&\n error.status < 500 &&\n error.status !== 408\n ) {\n throw error;\n }\n consecutiveErrors++;\n lastError = error instanceof Error ? error.message : String(error);\n lastErrorStatus =\n error instanceof HttpError\n ? error.status\n : error instanceof Error &&\n ['TimeoutError', 'AbortError'].includes(error.name)\n ? 504\n : 502;\n if (consecutiveErrors >= MAX_CONSECUTIVE_STREAM_ERRORS) {\n throw new HttpError(\n `Polling aborted after ${MAX_CONSECUTIVE_STREAM_ERRORS} consecutive errors: ${lastError}`,\n lastErrorStatus,\n { ...result, note: deps.abortedNote }\n );\n }\n }\n\n const remainingMs = Math.max(0, deps.budgetMs - elapsed());\n await sleep(Math.min(deps.pollIntervalMs, remainingMs));\n // If the next poll cannot fit after its interval, this was the final wait.\n // Timers can wake slightly early; do not turn that into an extra request.\n if (remainingMs <= deps.pollIntervalMs) break;\n }\n\n if (lastError !== undefined) {\n throw new HttpError(\n `Polling budget expired after an upstream error: ${lastError}`,\n lastErrorStatus,\n {\n ...result,\n note: 'The latest job status could not be retrieved. Retry after addressing the upstream error.',\n }\n );\n }\n return { ...result, pollingTimedOut: true, note: deps.timedOutNote };\n}\n\n// Exported so a test can drive the loop through `poll` without a server.\nexport async function collectJobStream(deps: {\n poll: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n holdMs: number;\n pollIntervalMs?: number;\n}): Promise<{ result: Record<string, unknown>; chunks: unknown[] }> {\n const chunks: unknown[] = [];\n let result: Record<string, unknown>;\n try {\n result = await pollUntilTerminal({\n poll: deps.poll,\n budgetMs: deps.budgetMs,\n timeoutFor: (remainingMs) =>\n streamPollTimeoutMs(remainingMs, deps.holdMs),\n pollIntervalMs: deps.pollIntervalMs ?? STREAM_JOB_POLL_INTERVAL_MS,\n abortedNote: `Polling stopped after ${MAX_CONSECUTIVE_STREAM_ERRORS} consecutive errors with the job possibly still running. ${RESUME_ADVICE}`,\n timedOutNote: `Polling stopped after ${formatBudget(deps.budgetMs)} with the job possibly still running. ${RESUME_ADVICE}`,\n onReply: (reply) => {\n if (Array.isArray(reply.stream)) chunks.push(...reply.stream);\n },\n });\n } catch (error) {\n if (error instanceof HttpError) {\n throw new HttpError(error.message, error.status, {\n ...(error.payload && typeof error.payload === 'object'\n ? error.payload\n : { error: error.payload }),\n stream: chunks,\n });\n }\n throw error;\n }\n return { result, chunks };\n}\n\n// Block on a job by polling /status until it reaches a terminal status, the\n// wait budget runs out, or the API fails MAX_CONSECUTIVE_STREAM_ERRORS times in\n// a row. /status returns instantly, so the hold lives here, not on the server.\n// Exported so a test can drive the loop through `fetchStatus` without a server.\nexport async function pollJobStatus(deps: {\n fetchStatus: (timeoutMs: number) => Promise<Record<string, unknown>>;\n budgetMs: number;\n pollIntervalMs?: number;\n}): Promise<Record<string, unknown>> {\n return pollUntilTerminal({\n poll: deps.fetchStatus,\n budgetMs: deps.budgetMs,\n // One /status call may not outlive the budget: unbounded, a hung socket\n // holds the request past the hosted 60s reaper (the client default is\n // 30s, which a poll started at 44s of a 45s budget would exceed).\n timeoutFor: (remainingMs) => Math.max(remainingMs, MIN_POLL_TIMEOUT_MS),\n pollIntervalMs: deps.pollIntervalMs ?? STATUS_POLL_INTERVAL_MS,\n abortedNote:\n 'Polling stopped after repeated errors with the job possibly still running. Call get-job-status again to keep checking.',\n timedOutNote: `Still not terminal after waiting ${formatBudget(deps.budgetMs)} — a first-job cold start (image pull + model load) can take several minutes. Call get-job-status again (with wait) to keep blocking, or check back without waiting.`,\n });\n}\n\n// A job stuck IN_QUEUE has two very different causes its status alone cannot\n// distinguish: no host has the endpoint's GPU available (capacity), or a\n// worker DID spin up and is crash-looping. The platform SOMETIMES marks the\n// latter UNHEALTHY — but not always: a container that fails to start loops\n// while its worker keeps reporting RUNNING or THROTTLED (observed\n// 2026-09-08), so UNHEALTHY is a symptom to act on rather than a test to\n// trust, and every branch below ends by pointing at the logs. Agents read the endless IN_QUEUE as \"no\n// capacity\" and stop digging, so get-job-status best-effort attaches the\n// endpoint's worker summary and a hint. Never fails the status call itself.\ninterface WorkerSummary {\n idle?: number;\n initializing?: number;\n running?: number;\n throttled?: number;\n total?: number;\n unhealthy?: number;\n}\n\n// Cost controls ported from the official server (runpod/runpod-mcp): a stuck\n// job is polled repeatedly against the SAME endpoint, so a short TTL cache\n// makes the extra round trip effectively free across a poll loop, and a\n// dedicated timeout stops a slow /workers call from eating into the caller's\n// budget. Together these are what make diagnosing on every IN_QUEUE — v1's\n// behavior — affordable on the hosted path.\nconst DIAGNOSIS_TTL_MS = 15_000;\nconst MAX_DIAGNOSIS_ENTRIES = 500;\nexport const QUEUED_DIAGNOSIS_TIMEOUT_MS = 5_000;\n\ninterface CachedDiagnosis {\n value: { workerHealth: WorkerSummary; hint: string };\n expiresAt: number;\n}\n// A context belongs to one caller. Never reuse private worker diagnostics\n// across callers that happen to ask about the same endpoint ID.\nconst diagnosisCaches = new WeakMap<\n ToolContext,\n Map<string, CachedDiagnosis>\n>();\n\nasync function diagnoseQueuedJob(\n ctx: ToolContext,\n endpointId: string\n): Promise<{ workerHealth: WorkerSummary; hint: string } | null> {\n const diagnosisCache =\n diagnosisCaches.get(ctx) ?? new Map<string, CachedDiagnosis>();\n diagnosisCaches.set(ctx, diagnosisCache);\n const cached = diagnosisCache.get(endpointId);\n if (cached && cached.expiresAt > Date.now()) return cached.value;\n diagnosisCache.delete(endpointId);\n\n const remember = (value: { workerHealth: WorkerSummary; hint: string }) => {\n if (diagnosisCache.size >= MAX_DIAGNOSIS_ENTRIES) {\n const oldest = diagnosisCache.keys().next().value;\n if (oldest !== undefined) diagnosisCache.delete(oldest);\n }\n diagnosisCache.set(endpointId, {\n value,\n expiresAt: Date.now() + DIAGNOSIS_TTL_MS,\n });\n return value;\n };\n\n // Explicit controller + ref'd timer, not AbortSignal.timeout: that timer is\n // unref'd and never fires on an otherwise idle loop (see bounded-fetch.ts).\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n QUEUED_DIAGNOSIS_TIMEOUT_MS\n );\n try {\n const { data, error } = await ctx.sdk.GET('/v2/serverless/{id}/workers', {\n params: { path: { id: endpointId } },\n signal: controller.signal,\n });\n if (error !== undefined || !data) return null;\n const summary = (data as { summary?: WorkerSummary }).summary;\n const workers =\n (data as { workers?: Array<{ id: string; status?: string }> }).workers ??\n [];\n if (!summary) return null;\n\n if ((summary.unhealthy ?? 0) > 0) {\n const badIds = workers\n .filter((w) => w.status === 'UNHEALTHY')\n .map((w) => w.id)\n .join(', ');\n return remember({\n workerHealth: summary,\n hint: `${summary.unhealthy} of ${summary.total} worker(s) on this endpoint are UNHEALTHY — the container is likely crash-looping (repeated starts that exit before the handler runs). The job can stay IN_QUEUE indefinitely; this is a worker failure, NOT a capacity shortage. Inspect the logs with stream-worker-logs${badIds ? ` (workerId: ${badIds})` : ''}.`,\n });\n }\n if ((summary.total ?? 0) === 0) {\n return remember({\n workerHealth: summary,\n hint: 'No workers are scheduled for this endpoint yet — it may simply be scaling up from zero (normal for the first seconds of a cold start), or it is waiting for GPU capacity / its GPU-CUDA constraints exclude the currently-available hosts. If this persists, check availability with get-capacity or widen the GPU/CUDA settings.',\n });\n }\n if ((summary.initializing ?? 0) > 0) {\n return remember({\n workerHealth: summary,\n hint: 'A worker is initializing — likely a cold start (image pull / model load); the job should start soon.',\n });\n }\n // Workers exist, none UNHEALTHY, none initializing — and the job is still\n // queued. Do NOT read this as \"the workers are fine\": a container that\n // fails to start loops while its worker keeps reporting RUNNING or\n // THROTTLED and unhealthy stays 0. Observed 2026-09-08: twelve\n // `error starting container: no space left on device` cycles in 100\n // seconds, unhealthy 0 throughout. The logs are the only authority here,\n // so send the caller there rather than returning an empty hint.\n const running = summary.running ?? 0;\n const throttled = summary.throttled ?? 0;\n return remember({\n workerHealth: summary,\n hint: `${summary.total ?? 0} worker(s) exist and none report UNHEALTHY${\n throttled > 0 ? ` (${throttled} throttled)` : ''\n }, yet the job is still queued. UNHEALTHY is one symptom of a crash loop, not a test for it — a container failing to start loops while its worker still reports RUNNING. Read stream-worker-logs on ${\n running > 0 ? 'a RUNNING worker' : 'any worker'\n } (ids from list-endpoint-workers) before concluding this is only a slow cold start.`,\n });\n } catch {\n return null; // diagnosis is best-effort — never break the status call\n } finally {\n clearTimeout(timer);\n }\n}\n\nconst endpointIdProperty = {\n type: 'string',\n pattern: ID_PATTERN,\n description: 'ID of the Serverless endpoint',\n} as const;\n\nconst jobIdProperty = {\n type: 'string',\n pattern: ID_PATTERN,\n description: 'ID of the job',\n} as const;\n\nconst inputProperty = {\n type: 'object',\n additionalProperties: true,\n description:\n 'Input payload for the worker handler. The expected fields depend on the deployed model or worker.',\n} as const;\n\nconst webhookProperty = {\n type: 'string',\n description:\n 'Webhook URL to receive job completion notifications instead of polling',\n} as const;\n\nconst policyProperty = {\n type: 'object',\n description: 'Execution policy options',\n properties: {\n executionTimeout: {\n type: 'number',\n description: 'Maximum execution time in milliseconds',\n },\n lowPriority: {\n type: 'boolean',\n description: 'Submit as a low-priority job',\n },\n ttl: {\n type: 'number',\n description: 'Time-to-live for the job result in milliseconds',\n },\n },\n} as const;\n\nconst s3ConfigProperty = {\n type: 'object',\n description: 'S3-compatible storage config for large outputs',\n properties: {\n accessId: { type: 'string', description: 'S3 access key ID' },\n accessSecret: { type: 'string', description: 'S3 secret access key' },\n bucketName: { type: 'string', description: 'S3 bucket name' },\n endpointUrl: { type: 'string', description: 'S3 endpoint URL' },\n },\n required: ['accessId', 'accessSecret', 'bucketName', 'endpointUrl'],\n} as const;\n\nfunction requireIds(\n args: Record<string, unknown>,\n keys: string[]\n): string | null {\n for (const key of keys) {\n const value = args[key];\n if (typeof value !== 'string' || !ID_REGEX.test(value)) {\n return `${key} must be a string matching ${ID_PATTERN}`;\n }\n }\n return null;\n}\n\n// The low-level MCP server does not enforce the advertised input schema.\n// Reject malformed waits before they reach timeout arithmetic or the API.\nfunction validateWait(wait: unknown): string | null {\n if (wait === undefined) return null;\n return typeof wait === 'number' && Number.isFinite(wait) && wait >= 1000\n ? null\n : 'wait must be a finite number of at least 1000 milliseconds, or omitted.';\n}\n\nexport const runEndpoint: CuratedTool = {\n name: 'run-endpoint',\n annotations: write,\n description:\n 'Submit an asynchronous job to a Serverless endpoint. Returns a job ID immediately — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to run',\n },\n input: inputProperty,\n webhook: webhookProperty,\n policy: policyProperty,\n s3Config: s3ConfigProperty,\n },\n required: ['endpointId', 'input'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n const { endpointId, ...body } = args;\n return ok(\n await ctx.runtime(endpointId as string, '/run', {\n method: 'POST',\n body: body as Record<string, unknown>,\n })\n );\n }),\n};\n\nexport const runsyncEndpoint: CuratedTool = {\n name: 'runsync-endpoint',\n holdsResponse: true,\n annotations: write,\n description:\n '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' +\n (HOSTED\n ? ` — 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.`\n : ' to up to 5 minutes (300000 ms); it defaults to 90000 (90 seconds).'),\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to run synchronously',\n },\n input: inputProperty,\n wait: {\n type: 'number',\n minimum: 1000,\n maximum: HOSTED ? HTTP_LONG_POLL_BUDGET_MS : 300000,\n description: HOSTED\n ? `How long in milliseconds the server should wait for a result (1000–${HTTP_LONG_POLL_BUDGET_MS}; higher values clamp to ${HTTP_LONG_POLL_BUDGET_MS}, the gateway ceiling).`\n : 'How long in milliseconds the server should wait for a result before returning a job ID to poll (1000–300000). Defaults to 90000 (90 seconds).',\n },\n webhook: webhookProperty,\n policy: policyProperty,\n s3Config: s3ConfigProperty,\n },\n required: ['endpointId', 'input'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n const waitError = validateWait(args.wait);\n if (waitError) return badRequest(waitError);\n const { endpointId, wait, ...body } = args;\n // Hosted: an omitted wait inherits the upstream 90s hold, which outlives\n // the 60s platform reaper — send an explicit clamped wait instead.\n const requested = wait as number | undefined;\n const clamped =\n requested === undefined\n ? HOSTED\n ? HTTP_LONG_POLL_BUDGET_MS\n : undefined\n : Math.min(requested, STATUS_WAIT_MAX_MS);\n // Omitted local waits retain the upstream default; hosted always sends\n // an explicit wait that fits its gateway budget.\n const waitQuery = clamped === undefined ? '' : `?wait=${clamped}`;\n return ok(\n await ctx.runtime(endpointId as string, `/runsync${waitQuery}`, {\n method: 'POST',\n body: body as Record<string, unknown>,\n // The client deadline must outlast the wait the server was asked to\n // hold, or we abort the reply we are waiting for.\n timeoutMs:\n (clamped ?? RUNSYNC_UPSTREAM_DEFAULT_WAIT_MS) +\n UPSTREAM_HOLD_SLACK_MS,\n })\n );\n }),\n};\n\nexport const getJobStatus: CuratedTool = {\n name: 'get-job-status',\n holdsResponse: true,\n annotations: readOnly,\n description:\n '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 ' +\n STATUS_WAIT_MAX_MS +\n ') to BLOCK server-side, polling until the job reaches a terminal status or the budget expires — use it to ride out a cold start (a first job on a fresh worker pulls the image and loads the model, commonly 1–5+ 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 — call again (with `wait`) to keep blocking. IMPORTANT: a job stuck IN_QUEUE does not necessarily mean a capacity shortage — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to check' },\n wait: {\n type: 'number',\n minimum: 1000,\n maximum: STATUS_WAIT_MAX_MS,\n description: `How long in milliseconds to block server-side, polling the job until it reaches a terminal status (1000–${STATUS_WAIT_MAX_MS}). Omit for a single immediate check. Use this to wait through a cold start rather than tight-looping the tool.`,\n },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n const waitError = validateWait(args.wait);\n if (waitError) return badRequest(waitError);\n const endpointId = args.endpointId as string;\n const jobId = args.jobId as string;\n const fetchStatus = (timeoutMs?: number) =>\n ctx.runtime(endpointId, `/status/${jobId}`, {\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n }) as Promise<Record<string, unknown>>;\n const result =\n args.wait === undefined\n ? await fetchStatus()\n : await pollJobStatus({\n fetchStatus,\n budgetMs: Math.min(args.wait as number, STATUS_WAIT_MAX_MS),\n });\n if (\n result &&\n typeof result === 'object' &&\n (result as { status?: string }).status === 'IN_QUEUE'\n ) {\n const diagnosis = await diagnoseQueuedJob(ctx, endpointId);\n if (diagnosis) {\n return ok({\n ...(result as Record<string, unknown>),\n workerHealth: diagnosis.workerHealth,\n ...(diagnosis.hint ? { hint: diagnosis.hint } : {}),\n });\n }\n }\n return ok(result);\n }),\n};\n\nexport const streamJob: CuratedTool = {\n name: 'stream-job',\n holdsResponse: true,\n annotations: readOnly,\n 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 — call stream-job again to resume where it left off, or get-job-status to check without streaming.`,\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: {\n ...jobIdProperty,\n description: 'ID of the job to stream results from',\n },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n const { result, chunks } = await collectJobStream({\n budgetMs: STREAM_BUDGET_MS,\n holdMs: STREAM_UPSTREAM_DEFAULT_WAIT_MS,\n poll: (timeoutMs) =>\n ctx.runtime(args.endpointId as string, `/stream/${args.jobId}`, {\n timeoutMs,\n }) as Promise<Record<string, unknown>>,\n });\n return ok({ ...result, stream: chunks });\n }),\n};\n\nexport const cancelJob: CuratedTool = {\n name: 'cancel-job',\n annotations: destructive,\n description: 'Cancel a Serverless job that is queued or in progress.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to cancel' },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, `/cancel/${args.jobId}`, {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const retryJob: CuratedTool = {\n name: 'retry-job',\n annotations: write,\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint the job belongs to',\n },\n jobId: { ...jobIdProperty, description: 'ID of the job to retry' },\n },\n required: ['endpointId', 'jobId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId', 'jobId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, `/retry/${args.jobId}`, {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const endpointHealth: CuratedTool = {\n name: 'endpoint-health',\n annotations: readOnly,\n description:\n \"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 — when a job is stuck IN_QUEUE, prefer list-endpoint-workers over this rollup for per-worker state — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to check health for',\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n return ok(await ctx.runtime(args.endpointId as string, '/health'));\n }),\n};\n\nexport const purgeEndpointQueue: CuratedTool = {\n name: 'purge-endpoint-queue',\n annotations: destructive,\n description:\n 'Remove all pending jobs from a Serverless endpoint queue. Only affects queued jobs — in-progress jobs continue running. Use this for error recovery or clearing outdated requests.',\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n ...endpointIdProperty,\n description: 'ID of the Serverless endpoint to purge the queue for',\n },\n },\n required: ['endpointId'],\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const invalid = requireIds(args, ['endpointId']);\n if (invalid) return badRequest(invalid);\n return ok(\n await ctx.runtime(args.endpointId as string, '/purge-queue', {\n method: 'POST',\n })\n );\n }),\n};\n\nexport const jobTools: CuratedTool[] = [\n runEndpoint,\n runsyncEndpoint,\n getJobStatus,\n streamJob,\n cancelJob,\n retryJob,\n endpointHealth,\n purgeEndpointQueue,\n];\n","// Curated tool overriding the generated listEndpoints (excluded in\n// specgen/generator-config.yaml): full endpoint objects carry env maps and\n// requestUrls — six URLs per endpoint, all derivable from the id — which\n// measured 56% of a real account's payload (~32k tokens for 61 endpoints).\n// This returns the identifying fields, paginated; get-endpoint has the rest.\n\nimport { restError } from '../clients/rest-result.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport {\n listPaginationProperties,\n serverPageQuery,\n serverPagination,\n} from '../pagination.js';\nimport { readOnly } from './annotations.js';\n\nexport const listEndpoints: CuratedTool = {\n name: 'list-endpoints',\n annotations: readOnly,\n description:\n 'List serverless endpoints owned by the account (trimmed: id, name, image, ' +\n 'compute config, worker counts, scaling, data centers per endpoint — env ' +\n 'vars and request URLs are omitted; use get-endpoint for the full object). ' +\n 'Returns a page; pass cursor=nextCursor for more.',\n inputSchema: {\n type: 'object',\n properties: { ...listPaginationProperties },\n },\n async handler(ctx: ToolContext, args) {\n const { data, error, response } = await ctx.sdk.GET('/v2/serverless', {\n params: { query: serverPageQuery(args) },\n });\n if (!response.ok) return restError(response, error);\n if (!data || !Array.isArray(data.endpoints)) {\n return {\n ok: false,\n status: 502,\n payload: { error: 'The Runpod API returned no list data.' },\n };\n }\n const trimmed = data.endpoints.map((endpoint) => ({\n id: endpoint.id,\n name: endpoint.name,\n type: endpoint.type,\n image: endpoint.image,\n gpu: endpoint.gpu,\n cpu: endpoint.cpu,\n workers: endpoint.workers,\n scaling: endpoint.scaling,\n dataCenterIds: endpoint.dataCenterIds,\n flashboot: endpoint.flashboot,\n createdAt: endpoint.createdAt,\n }));\n return {\n ok: true,\n status: response.status,\n payload: {\n items: trimmed,\n pagination: serverPagination(data.pagination, trimmed.length),\n },\n };\n },\n};\n","// Curated tool overriding the generated listTemplates (excluded in\n// generator-config.yaml): full template objects carry env maps and readmes\n// that blow up LLM context, so this returns the identifying fields only.\n\nimport { restError } from '../clients/rest-result.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport {\n listPaginationProperties,\n serverPageQuery,\n serverPagination,\n} from '../pagination.js';\nimport { readOnly } from './annotations.js';\n\nexport const listTemplates: CuratedTool = {\n name: 'list-templates',\n annotations: readOnly,\n description:\n 'List templates visible to the account. Returns id, name, image, and ' +\n 'serverless flag per template; use get-template for full detail. ' +\n 'Returns 20 templates per page by default. To find a template, follow ' +\n '`pagination.nextCursor` until `hasNextPage` is false: a name missing ' +\n 'from one page may be on a later one.',\n inputSchema: {\n type: 'object',\n properties: { ...listPaginationProperties },\n },\n async handler(ctx: ToolContext, args) {\n const { data, error, response } = await ctx.sdk.GET('/v2/templates', {\n params: { query: serverPageQuery(args) },\n });\n if (!response.ok) return restError(response, error);\n if (!data || !Array.isArray(data.templates)) {\n return {\n ok: false,\n status: 502,\n payload: { error: 'The Runpod API returned no list data.' },\n };\n }\n return {\n ok: true,\n status: response.status,\n payload: {\n templates: data.templates.map((template) => ({\n id: template.id,\n name: template.name,\n image: template.image,\n serverless: template.serverless,\n })),\n pagination: serverPagination(data.pagination, data.templates.length),\n },\n };\n },\n};\n","// Curated log tools. Pod logs (GET /v2/pods/{id}/logs) and worker logs\n// (GET /v2/serverless/{id}/workers/{workerId}/logs) are the same feature on\n// two resources: an SSE stream of `data: {source,line,ts}` frames that stays\n// open to tail live output. The generated JSON dispatch cannot consume\n// text/event-stream, so both operations are excluded in generator-config.yaml\n// and served here as bounded snapshots instead.\n\nimport { sdkBase } from '../../_shared/hosts.js';\nimport type { CuratedTool } from '../types.js';\nimport { collectLogSnapshot, type LogSnapshotParams } from '../clients/sse.js';\nimport { ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\nconst logStreamProperties = {\n source: {\n type: 'string',\n enum: ['container', 'system', 'both'],\n description: 'Which log source to read (default: both)',\n },\n tail: {\n type: 'integer',\n minimum: 0,\n maximum: 5000,\n description:\n 'Historical lines to backfill before live output (API default 100, max 5000; 0 = live only). Ignored when `since` is set.',\n },\n since: {\n type: 'string',\n description:\n 'RFC3339 timestamp to resume from; when set, `tail` is ignored.',\n },\n maxWaitMs: {\n type: 'integer',\n minimum: 500,\n maximum: 30000,\n description: 'How long to read the stream, in ms (default 5000, max 30000)',\n },\n} as const;\n\nfunction baseUrl(): string {\n return sdkBase(process.env);\n}\n\n// The low-level MCP server never validates inputSchema, so the schema bounds\n// above are advisory. Re-derive the params here — otherwise a hostile\n// maxWaitMs holds the SSE socket open arbitrarily and a non-numeric tail goes\n// to the wire as ?tail=garbage.\nfunction clampInt(\n value: unknown,\n min: number,\n max: number,\n fallback: number | undefined\n): number | undefined {\n const n = typeof value === 'number' ? value : Number(value);\n if (value === undefined || value === null || !Number.isFinite(n))\n return fallback;\n return Math.min(max, Math.max(min, Math.trunc(n)));\n}\n\nconst LOG_SOURCES = logStreamProperties.source.enum;\n\nfunction logParams(args: Record<string, unknown>): LogSnapshotParams {\n return {\n source: LOG_SOURCES.includes(args.source as (typeof LOG_SOURCES)[number])\n ? (args.source as LogSnapshotParams['source'])\n : undefined,\n tail: clampInt(args.tail, 0, 5000, undefined),\n since: typeof args.since === 'string' ? args.since : undefined,\n maxWaitMs: clampInt(args.maxWaitMs, 500, 30_000, undefined),\n };\n}\n\nexport const streamPodLogs: CuratedTool = {\n name: 'stream-pod-logs',\n holdsResponse: true,\n annotations: readOnly,\n description:\n \"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.\",\n inputSchema: {\n type: 'object',\n properties: {\n podId: { type: 'string', description: 'ID of the Pod to read logs from' },\n ...logStreamProperties,\n },\n required: ['podId'],\n },\n handler: (ctx, args) =>\n runTool(async () =>\n ok(\n await collectLogSnapshot(\n ctx.sse,\n `${baseUrl()}/v2/pods/${encodeURIComponent(args.podId as string)}/logs`,\n logParams(args)\n )\n )\n ),\n};\n\nexport const streamWorkerLogs: CuratedTool = {\n name: 'stream-worker-logs',\n holdsResponse: true,\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object',\n properties: {\n endpointId: {\n type: 'string',\n description: 'ID of the Serverless endpoint the worker belongs to',\n },\n workerId: {\n type: 'string',\n description: 'ID of the worker to read logs from',\n },\n ...logStreamProperties,\n },\n required: ['endpointId', 'workerId'],\n },\n handler: (ctx, args) =>\n runTool(async () =>\n ok(\n await collectLogSnapshot(\n ctx.sse,\n `${baseUrl()}/v2/serverless/${encodeURIComponent(args.endpointId as string)}/workers/${encodeURIComponent(args.workerId as string)}/logs`,\n logParams(args)\n )\n )\n ),\n};\n\nexport const logTools: CuratedTool[] = [streamPodLogs, streamWorkerLogs];\n","// node_modules/.pnpm/openapi-fetch@0.17.0/node_modules/openapi-fetch/dist/index.mjs\nvar PATH_PARAM_RE = /\\{[^{}]+\\}/g;\nvar supportsRequestInitExt = () => {\n return typeof process === \"object\" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;\n};\nfunction randomID() {\n return Math.random().toString(36).slice(2, 11);\n}\nfunction createClient(clientOptions) {\n let {\n baseUrl = \"\",\n Request: CustomRequest = globalThis.Request,\n fetch: baseFetch = globalThis.fetch,\n querySerializer: globalQuerySerializer,\n bodySerializer: globalBodySerializer,\n pathSerializer: globalPathSerializer,\n headers: baseHeaders,\n requestInitExt = void 0,\n ...baseOptions\n } = { ...clientOptions };\n requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;\n baseUrl = removeTrailingSlash(baseUrl);\n const globalMiddlewares = [];\n async function coreFetch(schemaPath, fetchOptions) {\n const {\n baseUrl: localBaseUrl,\n fetch = baseFetch,\n Request: Request2 = CustomRequest,\n headers,\n params = {},\n parseAs = \"json\",\n querySerializer: requestQuerySerializer,\n bodySerializer = globalBodySerializer ?? defaultBodySerializer,\n pathSerializer: requestPathSerializer,\n body,\n middleware: requestMiddlewares = [],\n ...init\n } = fetchOptions || {};\n let finalBaseUrl = baseUrl;\n if (localBaseUrl) {\n finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;\n }\n let querySerializer = typeof globalQuerySerializer === \"function\" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);\n if (requestQuerySerializer) {\n querySerializer = typeof requestQuerySerializer === \"function\" ? requestQuerySerializer : createQuerySerializer({\n ...typeof globalQuerySerializer === \"object\" ? globalQuerySerializer : {},\n ...requestQuerySerializer\n });\n }\n const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;\n const serializedBody = body === void 0 ? void 0 : bodySerializer(\n body,\n // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:\n // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however,\n // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,\n // setting the content-type at the very beginning to be overwritten.\n // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers.\n mergeHeaders(baseHeaders, headers, params.header)\n );\n const finalHeaders = mergeHeaders(\n // with no body, we should not to set Content-Type\n serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression\n serializedBody instanceof FormData ? {} : {\n \"Content-Type\": \"application/json\"\n },\n baseHeaders,\n headers,\n params.header\n );\n const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];\n const requestInit = {\n redirect: \"follow\",\n ...baseOptions,\n ...init,\n body: serializedBody,\n headers: finalHeaders\n };\n let id;\n let options;\n let request = new Request2(\n createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer, pathSerializer }),\n requestInit\n );\n let response;\n for (const key in init) {\n if (!(key in request)) {\n request[key] = init[key];\n }\n }\n if (finalMiddlewares.length) {\n id = randomID();\n options = Object.freeze({\n baseUrl: finalBaseUrl,\n fetch,\n parseAs,\n querySerializer,\n bodySerializer,\n pathSerializer\n });\n for (const m of finalMiddlewares) {\n if (m && typeof m === \"object\" && typeof m.onRequest === \"function\") {\n const result = await m.onRequest({\n request,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (result instanceof Request2) {\n request = result;\n } else if (result instanceof Response) {\n response = result;\n break;\n } else {\n throw new Error(\"onRequest: must return new Request() or Response() when modifying the request\");\n }\n }\n }\n }\n }\n if (!response) {\n try {\n response = await fetch(request, requestInitExt);\n } catch (error2) {\n let errorAfterMiddleware = error2;\n if (finalMiddlewares.length) {\n for (let i = finalMiddlewares.length - 1; i >= 0; i--) {\n const m = finalMiddlewares[i];\n if (m && typeof m === \"object\" && typeof m.onError === \"function\") {\n const result = await m.onError({\n request,\n error: errorAfterMiddleware,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (result instanceof Response) {\n errorAfterMiddleware = void 0;\n response = result;\n break;\n }\n if (result instanceof Error) {\n errorAfterMiddleware = result;\n continue;\n }\n throw new Error(\"onError: must return new Response() or instance of Error\");\n }\n }\n }\n }\n if (errorAfterMiddleware) {\n throw errorAfterMiddleware;\n }\n }\n if (finalMiddlewares.length) {\n for (let i = finalMiddlewares.length - 1; i >= 0; i--) {\n const m = finalMiddlewares[i];\n if (m && typeof m === \"object\" && typeof m.onResponse === \"function\") {\n const result = await m.onResponse({\n request,\n response,\n schemaPath,\n params,\n options,\n id\n });\n if (result) {\n if (!(result instanceof Response)) {\n throw new Error(\"onResponse: must return new Response() when modifying the response\");\n }\n response = result;\n }\n }\n }\n }\n }\n const contentLength = response.headers.get(\"Content-Length\");\n if (response.status === 204 || request.method === \"HEAD\" || contentLength === \"0\" && !response.headers.get(\"Transfer-Encoding\")?.includes(\"chunked\")) {\n return response.ok ? { data: void 0, response } : { error: void 0, response };\n }\n if (response.ok) {\n const getResponseData = async () => {\n if (parseAs === \"stream\") {\n return response.body;\n }\n if (parseAs === \"json\" && !contentLength) {\n const raw = await response.text();\n return raw ? JSON.parse(raw) : void 0;\n }\n return await response[parseAs]();\n };\n return { data: await getResponseData(), response };\n }\n let error = await response.text();\n try {\n error = JSON.parse(error);\n } catch {\n }\n return { error, response };\n }\n return {\n request(method, url, init) {\n return coreFetch(url, { ...init, method: method.toUpperCase() });\n },\n /** Call a GET endpoint */\n GET(url, init) {\n return coreFetch(url, { ...init, method: \"GET\" });\n },\n /** Call a PUT endpoint */\n PUT(url, init) {\n return coreFetch(url, { ...init, method: \"PUT\" });\n },\n /** Call a POST endpoint */\n POST(url, init) {\n return coreFetch(url, { ...init, method: \"POST\" });\n },\n /** Call a DELETE endpoint */\n DELETE(url, init) {\n return coreFetch(url, { ...init, method: \"DELETE\" });\n },\n /** Call a OPTIONS endpoint */\n OPTIONS(url, init) {\n return coreFetch(url, { ...init, method: \"OPTIONS\" });\n },\n /** Call a HEAD endpoint */\n HEAD(url, init) {\n return coreFetch(url, { ...init, method: \"HEAD\" });\n },\n /** Call a PATCH endpoint */\n PATCH(url, init) {\n return coreFetch(url, { ...init, method: \"PATCH\" });\n },\n /** Call a TRACE endpoint */\n TRACE(url, init) {\n return coreFetch(url, { ...init, method: \"TRACE\" });\n },\n /** Register middleware */\n use(...middleware) {\n for (const m of middleware) {\n if (!m) {\n continue;\n }\n if (typeof m !== \"object\" || !(\"onRequest\" in m || \"onResponse\" in m || \"onError\" in m)) {\n throw new Error(\"Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`\");\n }\n globalMiddlewares.push(m);\n }\n },\n /** Unregister middleware */\n eject(...middleware) {\n for (const m of middleware) {\n const i = globalMiddlewares.indexOf(m);\n if (i !== -1) {\n globalMiddlewares.splice(i, 1);\n }\n }\n }\n };\n}\nfunction serializePrimitiveParam(name, value, options) {\n if (value === void 0 || value === null) {\n return \"\";\n }\n if (typeof value === \"object\") {\n throw new Error(\n \"Deeply-nested arrays/objects aren\\u2019t supported. Provide your own `querySerializer()` to handle these.\"\n );\n }\n return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;\n}\nfunction serializeObjectParam(name, value, options) {\n if (!value || typeof value !== \"object\") {\n return \"\";\n }\n const values = [];\n const joiner = {\n simple: \",\",\n label: \".\",\n matrix: \";\"\n }[options.style] || \"&\";\n if (options.style !== \"deepObject\" && options.explode === false) {\n for (const k in value) {\n values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));\n }\n const final2 = values.join(\",\");\n switch (options.style) {\n case \"form\": {\n return `${name}=${final2}`;\n }\n case \"label\": {\n return `.${final2}`;\n }\n case \"matrix\": {\n return `;${name}=${final2}`;\n }\n default: {\n return final2;\n }\n }\n }\n for (const k in value) {\n const finalName = options.style === \"deepObject\" ? `${name}[${k}]` : k;\n values.push(serializePrimitiveParam(finalName, value[k], options));\n }\n const final = values.join(joiner);\n return options.style === \"label\" || options.style === \"matrix\" ? `${joiner}${final}` : final;\n}\nfunction serializeArrayParam(name, value, options) {\n if (!Array.isArray(value)) {\n return \"\";\n }\n if (options.explode === false) {\n const joiner2 = { form: \",\", spaceDelimited: \"%20\", pipeDelimited: \"|\" }[options.style] || \",\";\n const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);\n switch (options.style) {\n case \"simple\": {\n return final;\n }\n case \"label\": {\n return `.${final}`;\n }\n case \"matrix\": {\n return `;${name}=${final}`;\n }\n // case \"spaceDelimited\":\n // case \"pipeDelimited\":\n default: {\n return `${name}=${final}`;\n }\n }\n }\n const joiner = { simple: \",\", label: \".\", matrix: \";\" }[options.style] || \"&\";\n const values = [];\n for (const v of value) {\n if (options.style === \"simple\" || options.style === \"label\") {\n values.push(options.allowReserved === true ? v : encodeURIComponent(v));\n } else {\n values.push(serializePrimitiveParam(name, v, options));\n }\n }\n return options.style === \"label\" || options.style === \"matrix\" ? `${joiner}${values.join(joiner)}` : values.join(joiner);\n}\nfunction createQuerySerializer(options) {\n return function querySerializer(queryParams) {\n const search = [];\n if (queryParams && typeof queryParams === \"object\") {\n for (const name in queryParams) {\n const value = queryParams[name];\n if (value === void 0 || value === null) {\n continue;\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n search.push(\n serializeArrayParam(name, value, {\n style: \"form\",\n explode: true,\n ...options?.array,\n allowReserved: options?.allowReserved || false\n })\n );\n continue;\n }\n if (typeof value === \"object\") {\n search.push(\n serializeObjectParam(name, value, {\n style: \"deepObject\",\n explode: true,\n ...options?.object,\n allowReserved: options?.allowReserved || false\n })\n );\n continue;\n }\n search.push(serializePrimitiveParam(name, value, options));\n }\n }\n return search.join(\"&\");\n };\n}\nfunction defaultPathSerializer(pathname, pathParams) {\n let nextURL = pathname;\n for (const match of pathname.match(PATH_PARAM_RE) ?? []) {\n let name = match.substring(1, match.length - 1);\n let explode = false;\n let style = \"simple\";\n if (name.endsWith(\"*\")) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n if (name.startsWith(\".\")) {\n style = \"label\";\n name = name.substring(1);\n } else if (name.startsWith(\";\")) {\n style = \"matrix\";\n name = name.substring(1);\n }\n if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {\n continue;\n }\n const value = pathParams[name];\n if (Array.isArray(value)) {\n nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));\n continue;\n }\n if (typeof value === \"object\") {\n nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));\n continue;\n }\n if (style === \"matrix\") {\n nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);\n continue;\n }\n nextURL = nextURL.replace(match, style === \"label\" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));\n }\n return nextURL;\n}\nfunction defaultBodySerializer(body, headers) {\n if (body instanceof FormData) {\n return body;\n }\n if (headers) {\n const contentType = headers.get instanceof Function ? headers.get(\"Content-Type\") ?? headers.get(\"content-type\") : headers[\"Content-Type\"] ?? headers[\"content-type\"];\n if (contentType === \"application/x-www-form-urlencoded\") {\n return new URLSearchParams(body).toString();\n }\n }\n return JSON.stringify(body);\n}\nfunction createFinalURL(pathname, options) {\n let finalURL = `${options.baseUrl}${pathname}`;\n if (options.params?.path) {\n finalURL = options.pathSerializer(finalURL, options.params.path);\n }\n let search = options.querySerializer(options.params.query ?? {});\n if (search.startsWith(\"?\")) {\n search = search.substring(1);\n }\n if (search) {\n finalURL += `?${search}`;\n }\n return finalURL;\n}\nfunction mergeHeaders(...allHeaders) {\n const finalHeaders = new Headers();\n for (const h of allHeaders) {\n if (!h || typeof h !== \"object\") {\n continue;\n }\n const iterator = h instanceof Headers ? h.entries() : Object.entries(h);\n for (const [k, v] of iterator) {\n if (v === null) {\n finalHeaders.delete(k);\n } else if (Array.isArray(v)) {\n for (const v2 of v) {\n finalHeaders.append(k, v2);\n }\n } else if (v !== void 0) {\n finalHeaders.set(k, v);\n }\n }\n }\n return finalHeaders;\n}\nfunction removeTrailingSlash(url) {\n if (url.endsWith(\"/\")) {\n return url.substring(0, url.length - 1);\n }\n return url;\n}\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/util.js\nvar asciiRe = /^[\\x20-\\x7E]*$/;\nvar tokenRe = /^[a-zA-Z*][:/!#$%&'*+\\-.^_`|~A-Za-z0-9]*$/;\nfunction isAscii(str) {\n return asciiRe.test(str);\n}\nfunction isValidTokenStr(str) {\n return tokenRe.test(str);\n}\nfunction base64ToArrayBuffer(b64) {\n const binaryString = atob(b64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/token.js\nvar Token = class {\n constructor(value) {\n if (!isValidTokenStr(value)) {\n throw new TypeError(\"Invalid character in Token string. Tokens must start with *, A-Z and the rest of the string may only contain a-z, A-Z, 0-9, :/!#$%&'*+-.^_`|~\");\n }\n this.value = value;\n }\n toString() {\n return this.value;\n }\n};\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/displaystring.js\nvar DisplayString = class {\n constructor(value) {\n this.value = value;\n }\n toString() {\n return this.value;\n }\n};\n\n// node_modules/.pnpm/structured-headers@2.1.0/node_modules/structured-headers/dist/parser.js\nfunction parseList(input) {\n const parser = new Parser(input);\n return parser.parseList();\n}\nvar ParseError = class extends Error {\n constructor(position, message) {\n super(`Parse error: ${message} at offset ${position}`);\n }\n};\nvar Parser = class {\n constructor(input) {\n this.input = input;\n this.pos = 0;\n }\n parseDictionary() {\n this.skipWS();\n const dictionary = /* @__PURE__ */ new Map();\n while (!this.eof()) {\n const thisKey = this.parseKey();\n let member;\n if (this.lookChar() === \"=\") {\n this.pos++;\n member = this.parseItemOrInnerList();\n } else {\n member = [true, this.parseParameters()];\n }\n dictionary.set(thisKey, member);\n this.skipOWS();\n if (this.eof()) {\n return dictionary;\n }\n this.expectChar(\",\");\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, \"Dictionary contained a trailing comma\");\n }\n }\n return dictionary;\n }\n parseList() {\n this.skipWS();\n const members = [];\n while (!this.eof()) {\n members.push(this.parseItemOrInnerList());\n this.skipOWS();\n if (this.eof()) {\n return members;\n }\n this.expectChar(\",\");\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, \"A list may not end with a trailing comma\");\n }\n }\n return members;\n }\n parseItem(standaloneItem = true) {\n if (standaloneItem)\n this.skipWS();\n const result = [\n this.parseBareItem(),\n this.parseParameters()\n ];\n if (standaloneItem)\n this.checkTrail();\n return result;\n }\n parseItemOrInnerList() {\n if (this.lookChar() === \"(\") {\n return this.parseInnerList();\n } else {\n return this.parseItem(false);\n }\n }\n parseInnerList() {\n this.expectChar(\"(\");\n this.pos++;\n const innerList = [];\n while (!this.eof()) {\n this.skipWS();\n if (this.lookChar() === \")\") {\n this.pos++;\n return [\n innerList,\n this.parseParameters()\n ];\n }\n innerList.push(this.parseItem(false));\n const nextChar = this.lookChar();\n if (nextChar !== \" \" && nextChar !== \")\") {\n throw new ParseError(this.pos, \"Expected a whitespace or ) after every item in an inner list\");\n }\n }\n throw new ParseError(this.pos, \"Could not find end of inner list\");\n }\n parseBareItem() {\n const char = this.lookChar();\n if (char === void 0) {\n throw new ParseError(this.pos, \"Unexpected end of string\");\n }\n if (char.match(/^[-0-9]/)) {\n return this.parseIntegerOrDecimal();\n }\n if (char === '\"') {\n return this.parseString();\n }\n if (char.match(/^[A-Za-z*]/)) {\n return this.parseToken();\n }\n if (char === \":\") {\n return this.parseByteSequence();\n }\n if (char === \"?\") {\n return this.parseBoolean();\n }\n if (char === \"@\") {\n return this.parseDate();\n }\n if (char === \"%\") {\n return this.parseDisplayString();\n }\n throw new ParseError(this.pos, \"Unexpected input\");\n }\n parseParameters() {\n const parameters = /* @__PURE__ */ new Map();\n while (!this.eof()) {\n const char = this.lookChar();\n if (char !== \";\") {\n break;\n }\n this.pos++;\n this.skipWS();\n const key = this.parseKey();\n let value = true;\n if (this.lookChar() === \"=\") {\n this.pos++;\n value = this.parseBareItem();\n }\n parameters.set(key, value);\n }\n return parameters;\n }\n parseIntegerOrDecimal() {\n let type = \"integer\";\n let sign = 1;\n let inputNumber = \"\";\n if (this.lookChar() === \"-\") {\n sign = -1;\n this.pos++;\n }\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, \"Expected a digit (0-9)\");\n }\n while (!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber += char;\n } else if (type === \"integer\" && char === \".\") {\n if (inputNumber.length > 12) {\n throw new ParseError(this.pos, \"Exceeded maximum decimal length\");\n }\n inputNumber += \".\";\n type = \"decimal\";\n } else {\n this.pos--;\n break;\n }\n if (type === \"integer\" && inputNumber.length > 15) {\n throw new ParseError(this.pos, \"Exceeded maximum integer length\");\n }\n if (type === \"decimal\" && inputNumber.length > 16) {\n throw new ParseError(this.pos, \"Exceeded maximum decimal length\");\n }\n }\n if (type === \"integer\") {\n return parseInt(inputNumber, 10) * sign;\n } else {\n if (inputNumber.endsWith(\".\")) {\n throw new ParseError(this.pos, \"Decimal cannot end on a period\");\n }\n if (inputNumber.split(\".\")[1].length > 3) {\n throw new ParseError(this.pos, \"Number of digits after the decimal point cannot exceed 3\");\n }\n return parseFloat(inputNumber) * sign;\n }\n }\n parseString() {\n let outputString = \"\";\n this.expectChar('\"');\n this.pos++;\n while (!this.eof()) {\n const char = this.getChar();\n if (char === \"\\\\\") {\n if (this.eof()) {\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n const nextChar = this.getChar();\n if (nextChar !== \"\\\\\" && nextChar !== '\"') {\n throw new ParseError(this.pos, \"A backslash must be followed by another backslash or double quote\");\n }\n outputString += nextChar;\n } else if (char === '\"') {\n return outputString;\n } else if (!isAscii(char)) {\n throw new ParseError(this.pos, \"Strings must be in the ASCII range\");\n } else {\n outputString += char;\n }\n }\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n parseDisplayString() {\n const chars = this.getChars(2);\n if (chars !== '%\"') {\n throw new ParseError(this.pos, \"Unexpected character. Display strings should start with %=\");\n }\n const result = [];\n while (!this.eof()) {\n const char = this.getChar();\n if (char.charCodeAt(0) <= 31 || char.charCodeAt(0) >= 127 && char.charCodeAt(0) <= 255) {\n throw new ParseError(this.pos, \"Invalid char found in DisplayString. Did you forget to escape?\");\n }\n if (char === \"%\") {\n const hexChars = this.getChars(2);\n if (/^[0-9a-f]{2}$/.test(hexChars)) {\n result.push(parseInt(hexChars, 16));\n } else {\n throw new ParseError(this.pos, `Unexpected sequence after % in DispalyString: \"${hexChars}\". Note that hexidecimals must be lowercase`);\n }\n continue;\n }\n if (char === '\"') {\n const textDecoder = new TextDecoder(\"utf-8\", {\n fatal: true\n });\n try {\n return new DisplayString(textDecoder.decode(new Uint8Array(result)));\n } catch {\n throw new ParseError(this.pos, \"Fatal error decoding UTF-8 sequence in Display String\");\n }\n }\n result.push(char.charCodeAt(0));\n }\n throw new ParseError(this.pos, \"Unexpected end of input\");\n }\n parseToken() {\n let outputString = \"\";\n while (!this.eof()) {\n const char = this.lookChar();\n if (char === void 0 || !/^[:/!#$%&'*+\\-.^_`|~A-Za-z0-9]$/.test(char)) {\n return new Token(outputString);\n }\n outputString += this.getChar();\n }\n return new Token(outputString);\n }\n parseByteSequence() {\n this.expectChar(\":\");\n this.pos++;\n const endPos = this.input.indexOf(\":\", this.pos);\n if (endPos === -1) {\n throw new ParseError(this.pos, 'Could not find a closing \":\" character to mark end of Byte Sequence');\n }\n const b64Content = this.input.substring(this.pos, endPos);\n this.pos += b64Content.length + 1;\n if (!/^[A-Za-z0-9+/=]*$/.test(b64Content)) {\n throw new ParseError(this.pos, \"ByteSequence does not contain a valid base64 string\");\n }\n try {\n return base64ToArrayBuffer(b64Content);\n } catch {\n throw new ParseError(this.pos, \"ByteSequence does not contain a valid base64 string\");\n }\n }\n parseBoolean() {\n this.expectChar(\"?\");\n this.pos++;\n const char = this.getChar();\n if (char === \"1\") {\n return true;\n }\n if (char === \"0\") {\n return false;\n }\n throw new ParseError(this.pos, 'Unexpected character. Expected a \"1\" or a \"0\"');\n }\n parseDate() {\n this.expectChar(\"@\");\n this.pos++;\n let sign = 1;\n let inputNumber = \"\";\n if (this.lookChar() === \"-\") {\n sign = -1;\n this.pos++;\n }\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, \"Expected a digit (0-9)\");\n }\n while (!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber += char;\n } else {\n throw new ParseError(this.pos, \"Expected a digit (0-9), whitespace or EOL\");\n }\n }\n if (inputNumber.length > 15) {\n throw new ParseError(this.pos, \"Exceeded max length for a date value\");\n }\n return new Date(parseInt(inputNumber, 10) * sign * 1e3);\n }\n parseKey() {\n if (!this.lookChar()?.match(/^[a-z*]/)) {\n throw new ParseError(this.pos, \"A key must begin with an asterisk or letter (a-z)\");\n }\n let outputString = \"\";\n while (!this.eof()) {\n const char = this.lookChar();\n if (char === void 0 || !/^[a-z0-9_\\-.*]$/.test(char)) {\n return outputString;\n }\n outputString += this.getChar();\n }\n return outputString;\n }\n /**\n * Looks at the next character without advancing the cursor.\n *\n * Returns undefined if we were at the end of the string.\n */\n lookChar() {\n return this.input[this.pos];\n }\n /**\n * Checks if the next character is 'char', and fail otherwise.\n */\n expectChar(char) {\n if (this.lookChar() !== char) {\n throw new ParseError(this.pos, `Expected ${char}`);\n }\n }\n getChar() {\n return this.input[this.pos++];\n }\n getChars(count) {\n const result = this.input.substr(this.pos, count);\n this.pos += count;\n return result;\n }\n eof() {\n return this.pos >= this.input.length;\n }\n // Advances the pointer to skip all whitespace.\n skipOWS() {\n while (true) {\n const c = this.input.substr(this.pos, 1);\n if (c === \" \" || c === \"\t\") {\n this.pos++;\n } else {\n break;\n }\n }\n }\n // Advances the pointer to skip all spaces\n skipWS() {\n while (this.lookChar() === \" \") {\n this.pos++;\n }\n }\n // At the end of parsing, we need to make sure there are no bytes after the\n // header except whitespace.\n checkTrail() {\n this.skipWS();\n if (!this.eof()) {\n throw new ParseError(this.pos, \"Unexpected characters at end of input\");\n }\n }\n};\nvar isDigitRegex = /^[0-9]$/;\nfunction isDigit(char) {\n if (char === void 0)\n return false;\n return isDigitRegex.test(char);\n}\n\n// src/rate-limit.ts\nfunction parseRetryAfter(header, now = Date.now()) {\n if (header === null) return void 0;\n const value = header.trim();\n if (/^\\d+$/.test(value)) {\n const ms = Number(value) * 1e3;\n return Number.isSafeInteger(ms) ? ms : void 0;\n }\n if (!/^[A-Za-z]{3},? /.test(value)) return void 0;\n const date = Date.parse(value);\n return Number.isFinite(date) ? Math.max(0, date - now) : void 0;\n}\nfunction secondsToMilliseconds(value) {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) return void 0;\n const milliseconds = value * 1e3;\n return Number.isSafeInteger(milliseconds) ? milliseconds : void 0;\n}\nfunction getRateLimitInfo(headers, now = Date.now()) {\n const retryAfter = headers.get(\"Retry-After\");\n const retryAfterMs = parseRetryAfter(retryAfter, now);\n const info = {\n windows: [],\n retryAfterMs,\n retryDelayMs: retryAfterMs,\n incomplete: retryAfter !== null && retryAfterMs === void 0\n };\n const raw = headers.get(\"RateLimit\");\n if (raw === null) return info;\n if (!raw.trim()) return { ...info, incomplete: true };\n try {\n for (const [value, params] of parseList(raw)) {\n const name = value instanceof Token ? value.toString() : value;\n const remaining = params.get(\"r\");\n if (typeof name !== \"string\" || typeof remaining !== \"number\" || !Number.isSafeInteger(remaining) || remaining < 0) {\n info.incomplete = true;\n continue;\n }\n const resetAfterMs = secondsToMilliseconds(params.get(\"t\"));\n info.windows.push({ name, remaining, resetAfterMs });\n if (remaining !== 0) continue;\n if (resetAfterMs === void 0) {\n info.incomplete = true;\n continue;\n }\n info.retryDelayMs = Math.max(info.retryDelayMs ?? 0, resetAfterMs);\n }\n } catch {\n info.incomplete = true;\n }\n return info;\n}\n\n// src/retry.ts\nvar DEFAULTS = {\n maxAttempts: 4,\n minBackoffMs: 1e3,\n maxBackoffMs: 3e4,\n maxRetryAfterMs: 6e4\n};\nvar IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([\"GET\", \"HEAD\", \"PUT\", \"DELETE\", \"OPTIONS\"]);\nvar RETRYABLE_STATUS = /* @__PURE__ */ new Set([500, 502, 503, 504]);\nfunction isAbortError(error) {\n const name = error?.name;\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\nfunction shouldRetry(method, response) {\n const idempotent = IDEMPOTENT_METHODS.has(method);\n if (response === void 0) return idempotent;\n if (response.status === 429) return true;\n return idempotent && RETRYABLE_STATUS.has(response.status);\n}\nfunction sleepWithSignal(ms, signal, custom) {\n return new Promise((resolve, reject) => {\n let timer;\n const cleanup = () => {\n if (timer !== void 0) clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n };\n const onAbort = () => {\n cleanup();\n reject(signal.reason);\n };\n if (signal.aborted) {\n reject(signal.reason);\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n const done = () => {\n cleanup();\n resolve();\n };\n if (custom) {\n Promise.resolve().then(() => {\n signal.throwIfAborted();\n return custom(ms);\n }).then(done, (error) => {\n cleanup();\n reject(error);\n });\n } else {\n timer = setTimeout(done, ms);\n }\n });\n}\nfunction createRetryFetch(options = {}) {\n const maxAttempts = options.maxAttempts ?? DEFAULTS.maxAttempts;\n const minBackoffMs = options.minBackoffMs ?? DEFAULTS.minBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetryAfterMs = options.maxRetryAfterMs ?? DEFAULTS.maxRetryAfterMs;\n const baseFetch = options.fetch ?? globalThis.fetch;\n const random = options.random ?? Math.random;\n if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1) {\n throw new RangeError(\"maxAttempts must be a positive safe integer\");\n }\n for (const [name, value] of Object.entries({ minBackoffMs, maxBackoffMs, maxRetryAfterMs })) {\n if (!Number.isFinite(value) || value < 0 || value > 2147483647) {\n throw new RangeError(`${name} must be finite and between 0 and 2147483647`);\n }\n }\n if (minBackoffMs > maxBackoffMs) {\n throw new RangeError(\"minBackoffMs must not exceed maxBackoffMs\");\n }\n return async (input, init) => {\n const original = new Request(input, init);\n for (let attempt = 1; ; attempt++) {\n original.signal.throwIfAborted();\n let response;\n let networkError;\n try {\n response = await baseFetch(original.clone());\n } catch (error) {\n original.signal.throwIfAborted();\n if (isAbortError(error)) throw error;\n networkError = error;\n }\n if (response !== void 0 && !shouldRetry(original.method, response)) return response;\n if (response === void 0 && !shouldRetry(original.method, void 0)) throw networkError;\n if (attempt >= maxAttempts) {\n if (response !== void 0) return response;\n throw networkError;\n }\n const rateLimit = response ? getRateLimitInfo(response.headers) : void 0;\n let delay = rateLimit?.retryDelayMs;\n if (response && (rateLimit?.incomplete || delay !== void 0 && delay > maxRetryAfterMs)) return response;\n if (delay === void 0) {\n const shift = Math.min(attempt - 1, 20);\n const backoff = Math.min(minBackoffMs * 2 ** shift, maxBackoffMs);\n delay = backoff / 2 + random() * (backoff / 2);\n }\n await response?.body?.cancel();\n await sleepWithSignal(delay, original.signal, options.sleep);\n }\n };\n}\n\n// src/abort.ts\nfunction abortable(operation, signal) {\n if (!signal) return operation;\n return new Promise((resolve, reject) => {\n const onAbort = () => reject(signal.reason);\n const cleanup = () => signal.removeEventListener(\"abort\", onAbort);\n if (signal.aborted) onAbort();\n else signal.addEventListener(\"abort\", onAbort, { once: true });\n operation.then(\n (value) => {\n cleanup();\n resolve(value);\n },\n (error) => {\n cleanup();\n reject(error);\n }\n );\n });\n}\n\n// src/deadline.ts\nfunction wrapResponse(response, signal, cleanup) {\n const reader = response.body.getReader();\n let finished = false;\n let bodyController;\n function finish() {\n finished = true;\n signal.removeEventListener(\"abort\", onAbort);\n cleanup();\n }\n function cancelReader(reason) {\n void reader.cancel(reason).catch(() => {\n });\n reader.releaseLock();\n }\n function onAbort() {\n if (finished) return;\n finish();\n bodyController.error(signal.reason);\n cancelReader(signal.reason);\n }\n const body = new ReadableStream({\n start(controller) {\n bodyController = controller;\n signal.addEventListener(\"abort\", onAbort, { once: true });\n if (signal.aborted) onAbort();\n },\n async pull(controller) {\n try {\n const chunk = await reader.read();\n if (finished) return;\n if (!chunk.done) {\n controller.enqueue(chunk.value);\n return;\n }\n finish();\n reader.releaseLock();\n controller.close();\n } catch (error) {\n if (finished) return;\n finish();\n reader.releaseLock();\n controller.error(error);\n }\n },\n cancel(reason) {\n finish();\n cancelReader(reason);\n }\n });\n const wrapped = new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers\n });\n for (const key of [\"url\", \"redirected\", \"type\"]) {\n Object.defineProperty(wrapped, key, { value: response[key] });\n }\n return wrapped;\n}\nfunction createDeadlineFetch(fetchImpl, timeoutMs) {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647) {\n throw new RangeError(\"timeoutMs must be positive and at most 2147483647\");\n }\n return async (input, init) => {\n const original = new Request(input, init);\n original.signal.throwIfAborted();\n const controller = new AbortController();\n const onCallerAbort = () => controller.abort(original.signal.reason);\n const timer = setTimeout(() => {\n controller.abort(new DOMException(`Runpod request exceeded ${timeoutMs}ms`, \"TimeoutError\"));\n }, timeoutMs);\n const cleanup = () => {\n clearTimeout(timer);\n original.signal.removeEventListener(\"abort\", onCallerAbort);\n };\n original.signal.addEventListener(\"abort\", onCallerAbort, { once: true });\n try {\n const operation = Promise.resolve().then(async () => {\n controller.signal.throwIfAborted();\n const response2 = await fetchImpl(new Request(original, { signal: controller.signal }));\n if (controller.signal.aborted) void response2.body?.cancel().catch(() => {\n });\n controller.signal.throwIfAborted();\n return response2;\n });\n const response = await abortable(operation, controller.signal);\n if (response.body) return wrapResponse(response, controller.signal, cleanup);\n cleanup();\n return response;\n } catch (error) {\n cleanup();\n throw error;\n }\n };\n}\n\n// src/logs.ts\nfunction parseLogEntry(raw) {\n try {\n const parsed = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return { raw };\n const entry = parsed;\n const valid = [\"source\", \"line\", \"ts\", \"raw\"].every(\n (key) => !(key in entry) || typeof entry[key] === \"string\"\n );\n return valid ? entry : { raw };\n } catch {\n return { raw };\n }\n}\nfunction utf8Size(character) {\n const codePoint = character.codePointAt(0);\n if (codePoint <= 127) return 1;\n if (codePoint <= 2047) return 2;\n return codePoint <= 65535 ? 3 : 4;\n}\nvar LogEventParser = class {\n constructor(maxEventBytes) {\n this.maxEventBytes = maxEventBytes;\n }\n maxEventBytes;\n line = \"\";\n dataLines = [];\n eventName = \"\";\n lastEventId;\n eventBytes = 0;\n afterCR = false;\n push(character) {\n if (this.afterCR && character === \"\\n\") {\n this.afterCR = false;\n return;\n }\n this.afterCR = character === \"\\r\";\n this.eventBytes += utf8Size(character);\n if (this.eventBytes > this.maxEventBytes) {\n throw new RangeError(\"SSE log event exceeds maxEventBytes\");\n }\n if (character === \"\\r\" || character === \"\\n\") return this.consumeLine();\n this.line += character;\n }\n consumeLine() {\n const line = this.line;\n this.line = \"\";\n if (line === \"\") return this.finishEvent();\n if (line.startsWith(\":\")) return;\n const colon = line.indexOf(\":\");\n const field = colon < 0 ? line : line.slice(0, colon);\n const value = colon < 0 ? \"\" : line.slice(colon + 1).replace(/^ /, \"\");\n switch (field) {\n case \"data\":\n this.dataLines.push(value);\n break;\n case \"event\":\n this.eventName = value;\n break;\n case \"id\":\n if (!value.includes(\"\\0\")) this.lastEventId = value;\n break;\n }\n }\n finishEvent() {\n const event = this.dataLines.length ? {\n event: this.eventName || \"message\",\n id: this.lastEventId,\n data: parseLogEntry(this.dataLines.join(\"\\n\"))\n } : void 0;\n this.dataLines = [];\n this.eventName = \"\";\n this.eventBytes = 0;\n return event;\n }\n};\nasync function* iterateLogEvents(stream, options = {}) {\n const maxEventBytes = options.maxEventBytes ?? 1048576;\n if (!Number.isSafeInteger(maxEventBytes) || maxEventBytes <= 0) {\n throw new RangeError(\"maxEventBytes must be a positive safe integer\");\n }\n const parser = new LogEventParser(maxEventBytes);\n const decoder = new TextDecoder();\n const reader = stream.getReader();\n const signal = options.signal;\n const onAbort = () => {\n void reader.cancel(signal?.reason).catch(() => {\n });\n };\n let finished = false;\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n try {\n while (true) {\n signal?.throwIfAborted();\n const chunk = await abortable(reader.read(), signal);\n signal?.throwIfAborted();\n if (chunk.done) {\n finished = true;\n return;\n }\n for (const character of decoder.decode(chunk.value, { stream: true })) {\n signal?.throwIfAborted();\n const event = parser.push(character);\n if (event) yield event;\n }\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n if (!finished) void reader.cancel().catch(() => {\n });\n reader.releaseLock();\n }\n}\n\n// src/index.ts\nvar DEFAULT_TIMEOUT_MS = 3e4;\nvar DEFAULT_BASE_URL = \"https://api.runpod.io\";\nfunction createRunpodClient(options = {}) {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n if (!apiKey) {\n throw new Error(\"runpod: API key required (set RUNPOD_API_KEY or pass apiKey)\");\n }\n const baseUrl = options.baseUrl?.trim() || process.env.RUNPOD_API_BASE_URL?.trim() || DEFAULT_BASE_URL;\n const baseFetch = options.fetch ?? globalThis.fetch;\n const retryFetch = options.retry === false ? baseFetch : createRetryFetch({ ...options.retry, fetch: baseFetch });\n const requestFetch = options.timeoutMs === false ? retryFetch : createDeadlineFetch(retryFetch, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n return createClient({\n baseUrl,\n fetch: requestFetch,\n // Generation rejects contracts with a different array query encoding.\n querySerializer: { array: { style: \"form\", explode: false } },\n headers: { Authorization: `Bearer ${apiKey}` }\n });\n}\nexport {\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n createDeadlineFetch,\n createRetryFetch,\n createRunpodClient,\n getRateLimitInfo,\n iterateLogEvents,\n parseRetryAfter\n};\n","import { iterateLogEvents, type LogEntry } from '@runpod/typescript-api-sdk';\nexport type { LogEntry } from '@runpod/typescript-api-sdk';\n\n// Bounded SSE reader for the v2 log endpoints (GET /v2/pods/{id}/logs and\n// GET /v2/serverless/{id}/workers/{workerId}/logs). Both serve\n// text/event-stream and hold the connection open to tail live output, so the\n// generated JSON dispatch cannot consume them; the curated log tools read a\n// time- and byte-bounded snapshot instead. Ported from the official MCP\n// server's reader (Apache-2.0, runpod/runpod-mcp).\n\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\nimport { HttpError, missingKeyError } from './http-error.js';\nimport { boundedFetch } from './bounded-fetch.js';\n\nexport const LOG_STREAM_DEFAULT_WAIT_MS = 5_000;\nexport const LOG_STREAM_MAX_BYTES = 256 * 1024;\n\nexport type SseReader = (\n url: string,\n opts: { maxWaitMs: number; maxBytes: number }\n) => Promise<{ raw: string; truncated: boolean }>;\n\n// Time-bounded by maxWaitMs (the stream stays open to tail live output) and\n// byte-bounded by maxBytes; whichever fires first aborts and returns what was\n// collected. A deadline ends an established stream normally; a timeout before\n// response headers arrive is a failed request. Bytes are concatenated and decoded\n// once at the end so a UTF-8 char split across chunks is never corrupted.\nexport function createSseReader(\n options: { apiKey?: string; fetchImpl?: typeof fetch } = {}\n): SseReader {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async (url, opts) => {\n if (!apiKey) throw missingKeyError();\n const chunks: Uint8Array[] = [];\n let bytes = 0;\n let truncated = false;\n let streamEstablished = false;\n try {\n const response = await boundedFetch(fetchImpl, opts.maxWaitMs)(url, {\n method: 'GET',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n },\n });\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new HttpError(\n `Runpod API error (${response.status})`,\n response.status,\n response.status === 429\n ? withRateLimitHint({ error: body }, response.headers)\n : body\n );\n }\n streamEstablished = true;\n if (response.body) {\n for await (const chunk of response.body as unknown as AsyncIterable<Uint8Array>) {\n const boundedChunk = chunk.subarray(0, opts.maxBytes - bytes);\n chunks.push(boundedChunk);\n bytes += boundedChunk.length;\n if (bytes >= opts.maxBytes) {\n truncated = true;\n break;\n }\n }\n }\n } catch (err) {\n // The request deadline ends an established stream normally.\n // Before headers, there is no successful log read to return; runTool\n // maps the timeout to a retryable 504 instead of an empty success.\n if (\n !(\n streamEstablished &&\n err instanceof Error &&\n err.name === 'TimeoutError'\n )\n ) {\n throw err;\n }\n }\n return { raw: Buffer.concat(chunks).toString('utf8'), truncated };\n };\n}\n\nexport interface LogSnapshotParams {\n source?: 'container' | 'system' | 'both';\n tail?: number;\n since?: string;\n maxWaitMs?: number;\n}\n\n// Read a bounded snapshot of a log endpoint and return the parsed frames.\n// `source: 'both'` (or omitted) sends no source param — the endpoint returns\n// both streams when it is absent (the wire enum is only container|system).\nexport async function collectLogSnapshot(\n reader: SseReader,\n logsUrl: string,\n params: LogSnapshotParams\n): Promise<{ items: LogEntry[]; count: number; truncated: boolean }> {\n const qs = new URLSearchParams();\n if (params.source && params.source !== 'both')\n qs.append('source', params.source);\n if (params.tail !== undefined) qs.append('tail', String(params.tail));\n if (params.since) qs.append('since', params.since);\n const query = qs.toString() ? `?${qs}` : '';\n const { raw, truncated } = await reader(`${logsUrl}${query}`, {\n maxWaitMs: params.maxWaitMs ?? LOG_STREAM_DEFAULT_WAIT_MS,\n maxBytes: LOG_STREAM_MAX_BYTES,\n });\n // The SDK handles SSE framing and discards an incomplete final event.\n // MCP keeps ownership of its time and total-byte snapshot limits above.\n const items: LogEntry[] = [];\n for await (const event of iterateLogEvents(new Response(raw).body!)) {\n items.push(event.data);\n }\n return { items, count: items.length, truncated };\n}\n","// Curated list-public-endpoints tool. Runpod Public Endpoints (managed\n// pay-per-use model APIs) have no REST home — the catalog is the public\n// GraphQL query allAiApiPublicConfigs, served unauthenticated. Ported from\n// the official MCP server (Apache-2.0, runpod/runpod-mcp).\n\nimport type { CuratedTool } from '../types.js';\nimport { listPaginationProperties, capList } from '../pagination.js';\nimport { ok, runTool } from './util.js';\nimport { readOnly } from './annotations.js';\n\ninterface PublicEndpointConfig {\n id: string;\n aiApiId: string;\n modelName: string;\n displayName: string;\n description: string | null;\n metadata: string | null;\n isLive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface PublicEndpointsResponse {\n allAiApiPublicConfigs: PublicEndpointConfig[];\n}\n\n// `metadata` is a JSON string carrying pricing and classification. Parsed\n// defensively — a malformed value falls back to undefined fields.\ninterface PublicEndpointMetadata {\n cost?: number;\n owner?: string;\n source?: string;\n tag?: string;\n priceString?: string;\n}\n\nfunction parseMetadata(\n metadata: string | null | undefined\n): PublicEndpointMetadata {\n if (!metadata) return {};\n try {\n const parsed = JSON.parse(metadata) as unknown;\n return parsed && typeof parsed === 'object'\n ? (parsed as PublicEndpointMetadata)\n : {};\n } catch {\n return {};\n }\n}\n\nexport const listPublicEndpoints: CuratedTool = {\n name: 'list-public-endpoints',\n annotations: readOnly,\n description:\n 'List Runpod Public Endpoints — 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.',\n inputSchema: {\n type: 'object',\n properties: {\n ...listPaginationProperties,\n searchTerm: {\n type: 'string',\n description:\n \"Case-insensitive search across display name, model name, endpoint id, description, owner, and tag (e.g. 'kimi', 'video', 'flux')\",\n },\n modality: {\n type: 'string',\n description:\n \"Filter by modality/category (the metadata source field, e.g. 'language', 'image', 'video', 'audio')\",\n },\n owner: {\n type: 'string',\n description:\n \"Filter by model owner (e.g. 'moonshot', 'minimax', 'google')\",\n },\n includeOffline: {\n type: 'boolean',\n description:\n 'Include endpoints that are not currently live (isLive:false). Default false — only live endpoints are listed.',\n },\n },\n },\n handler: (ctx, args) =>\n runTool(async () => {\n const data = await ctx.graphql.public<PublicEndpointsResponse>(`\n query {\n allAiApiPublicConfigs {\n id\n aiApiId\n modelName\n displayName\n description\n metadata\n isLive\n createdAt\n updatedAt\n }\n }\n `);\n\n let configs = data.allAiApiPublicConfigs.map((c) => ({\n config: c,\n meta: parseMetadata(c.metadata),\n }));\n\n if (!args.includeOffline) {\n configs = configs.filter(({ config }) => config.isLive);\n }\n if (args.modality) {\n const term = String(args.modality).toLowerCase();\n configs = configs.filter(\n ({ meta }) => (meta.source ?? '').toLowerCase() === term\n );\n }\n if (args.owner) {\n const term = String(args.owner).toLowerCase();\n configs = configs.filter(\n ({ meta }) => (meta.owner ?? '').toLowerCase() === term\n );\n }\n if (args.searchTerm) {\n const term = String(args.searchTerm).toLowerCase();\n configs = configs.filter(({ config, meta }) =>\n [\n config.displayName,\n config.modelName,\n config.aiApiId,\n config.description,\n meta.owner,\n meta.tag,\n meta.source,\n ].some((field) => (field ?? '').toLowerCase().includes(term))\n );\n }\n\n // Stable, scannable order for the catalog.\n configs = [...configs].sort((a, b) =>\n a.config.displayName.localeCompare(b.config.displayName)\n );\n\n const result = configs.map(({ config, meta }) => ({\n endpointId: config.aiApiId,\n displayName: config.displayName,\n modelName: config.modelName,\n description: config.description,\n modality: meta.source,\n tag: meta.tag,\n owner: meta.owner,\n pricing: meta.priceString,\n isLive: config.isLive,\n baseUrl: `https://api.runpod.ai/v2/${config.aiApiId}`,\n createdAt: config.createdAt,\n updatedAt: config.updatedAt,\n }));\n\n return ok(\n capList(result, {\n limit: args.limit as number | undefined,\n cursor: args.cursor as string | undefined,\n })\n );\n }),\n};\n","// Knowledge tools: the official Runpod plugin's skills, reference docs, golden\n// paths and concept graph, served from the @runpod/plugin-knowledge bundle so an\n// agent without the plugin installed can read them. Read-only and offline:\n// nothing here calls the Runpod API.\n\nimport {\n loadKnowledge,\n type Concept,\n type Guide,\n type Rule,\n} from '@runpod/plugin-knowledge';\nimport type { CuratedTool } from '../types.js';\nimport { bundledRead } from './annotations.js';\nimport { badRequest, ok } from './util.js';\n\nconst knowledge = loadKnowledge();\n\nconst GUIDE_KINDS = ['skill', 'reference', 'golden-path'] as const;\nconst STOPWORDS = new Set(\n 'a an and are as at be by can do does for from how i in is it my of on or the to what when why with you your'.split(\n ' '\n )\n);\n\n/** Drop a simple English plural, so \"pods\" matches \"pod\" and \"policies\" \"policy\". */\nconst singular = (word: string) => {\n if (word.length > 4 && word.endsWith('ies')) return `${word.slice(0, -3)}y`;\n if (word.length > 3 && word.endsWith('s') && !word.endsWith('ss'))\n return word.slice(0, -1);\n return word;\n};\n\nconst words = (text: string) =>\n text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((word) => word.length > 1 && !STOPWORDS.has(word))\n .map(singular);\n\n/** Levenshtein distance, giving up once it passes max. */\nfunction editDistance(a: string, b: string, max: number): number {\n if (Math.abs(a.length - b.length) > max) return max + 1;\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n previous[j] + 1,\n current[j - 1] + 1,\n previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)\n );\n }\n if (Math.min(...current) > max) return max + 1;\n previous = current;\n }\n return previous[b.length];\n}\n\n/** Typos tolerated in a word or name: none under 4 letters, two from 8. */\nconst typoBudget = (text: string) =>\n text.length >= 8 ? 2 : text.length >= 4 ? 1 : 0;\n\n/** A search term five letters or longer also matches a word one typo away. */\nconst oneTypo = (word: string, term: string) =>\n term.length >= 5 && editDistance(word, term, 1) <= 1;\n\n/** A search term matches a word it starts, or one typo away from it. */\nconst termMatches = (word: string, term: string) =>\n word.startsWith(term) || oneTypo(word, term);\n\n/** A search term matches a concept name word exactly, or one typo away. */\nconst nameMatches = (name: string, term: string) =>\n name === term || oneTypo(name, term);\n\nconst guideSummary = ({\n id,\n kind,\n title,\n description,\n lanes,\n mcp,\n needs_shell,\n concepts,\n}: Guide) => ({\n id,\n kind,\n title,\n description,\n lanes,\n mcp,\n needs_shell,\n concepts,\n});\n\n/** Guides linked to a concept, split into golden-path examples and docs. */\nfunction linkedGuides(conceptId: string) {\n const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));\n const seen = new Set<string>();\n const examples: { id: string; title: string; mcp: Guide['mcp'] }[] = [];\n const docs: { id: string; title: string; rules?: string[] }[] = [];\n for (const link of knowledge.links) {\n if (link.to !== conceptId || seen.has(link.from)) continue;\n seen.add(link.from);\n const guide = byId.get(link.from);\n if (!guide) continue;\n if (guide.kind === 'golden-path')\n examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });\n else\n docs.push({\n id: guide.id,\n title: guide.title,\n ...(link.rules ? { rules: link.rules } : {}),\n });\n }\n return { examples, docs };\n}\n\n/** Concept ids by lower-cased id, name and alias. */\nconst conceptIndex = new Map<string, Concept>();\nfor (const concept of knowledge.concepts) {\n for (const key of [concept.id, concept.name, ...concept.aliases]) {\n if (!conceptIndex.has(key.toLowerCase()))\n conceptIndex.set(key.toLowerCase(), concept);\n }\n}\n/** The same keys, lower-cased with plurals dropped: \"Instant Clusters\" -> \"instant cluster\". */\nconst conceptKey = (text: string) =>\n text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter(Boolean)\n .map(singular)\n .join(' ');\nconst conceptKeyIndex = new Map<string, Concept>();\nfor (const [key, concept] of conceptIndex) {\n if (!conceptKeyIndex.has(conceptKey(key)))\n conceptKeyIndex.set(conceptKey(key), concept);\n}\n\n/**\n * Resolve a concept reference: exact id, name or alias first, then with\n * plurals dropped, then the one key within typo range. `matchedAs` is set\n * when the match was not exact.\n */\nfunction resolveConcept(\n input: string\n): { concept: Concept; matchedAs?: string } | undefined {\n const exact = conceptIndex.get(input.trim().toLowerCase());\n if (exact) return { concept: exact };\n const key = conceptKey(input);\n const plural = conceptKeyIndex.get(key);\n if (plural) return { concept: plural, matchedAs: key };\n const budget = typoBudget(key);\n let best: { concept: Concept; key: string; distance: number } | undefined;\n let tied = false;\n for (const [candidate, concept] of conceptKeyIndex) {\n const distance = editDistance(key, candidate, budget);\n if (distance > budget) continue;\n if (!best || distance < best.distance) {\n best = { concept, key: candidate, distance };\n tied = false;\n } else if (distance === best.distance && concept.id !== best.concept.id) {\n tied = true;\n }\n }\n return best && !tied\n ? { concept: best.concept, matchedAs: best.key }\n : undefined;\n}\n\nconst ruleIndex = new Map<string, { rule: Rule; concept: Concept }>();\nfor (const concept of knowledge.concepts) {\n for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });\n}\n\nconst source = {\n plugin_version: knowledge.version,\n plugin_commit: knowledge.commit,\n};\n\nexport const listGuides: CuratedTool = {\n name: 'list-guides',\n annotations: bundledRead,\n recordedArguments: ['kind', 'query', 'concept'],\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n kind: {\n type: 'string',\n enum: [...GUIDE_KINDS],\n description: 'Only this kind of guide.',\n },\n query: {\n type: 'string',\n description: 'Words to match against the id, title and description.',\n },\n concept: {\n type: 'string',\n description:\n 'Only guides linked to this concept id, for example \"network-volume\".',\n },\n },\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const kind = args.kind as Guide['kind'] | undefined;\n const terms = words(String(args.query ?? ''));\n const concept = args.concept ? String(args.concept).trim() : undefined;\n const guides = knowledge.guides\n .filter((guide) => !kind || guide.kind === kind)\n .filter((guide) => !concept || guide.concepts.includes(concept))\n .filter((guide) => {\n if (!terms.length) return true;\n const haystack =\n `${guide.id} ${guide.title} ${guide.description}`.toLowerCase();\n return terms.some((term) => haystack.includes(term));\n })\n .map(guideSummary);\n return ok({ ...source, count: guides.length, guides });\n },\n};\n\nexport const readGuide: CuratedTool = {\n name: 'read-guide',\n annotations: bundledRead,\n recordedArguments: ['id'],\n recordedGuideKind: (args) =>\n knowledge.guides.find((guide) => guide.id === String(args.id).trim())?.kind,\n description:\n 'Read one official Runpod guide in full, by the id list-guides returns (for example \"runpod-usage/storage\" or \"golden-path/06-dev-pod\").',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'The guide id from list-guides.' },\n },\n required: ['id'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const id = String(args.id).trim();\n const guide = knowledge.guides.find((candidate) => candidate.id === id);\n if (!guide) {\n const close = knowledge.guides\n .filter(\n (candidate) => candidate.id.includes(id) || id.includes(candidate.id)\n )\n .map((candidate) => candidate.id);\n return {\n ok: false,\n status: 404,\n payload: {\n error: `No guide with id \"${id}\".`,\n hint: close.length\n ? `Did you mean: ${close.join(', ')}?`\n : 'Call list-guides for the ids.',\n },\n };\n }\n return ok({\n ...source,\n ...guideSummary(guide),\n parent: guide.parent,\n path: guide.path,\n body: guide.body,\n });\n },\n};\n\nexport const lookupConcept: CuratedTool = {\n name: 'lookup-concept',\n annotations: bundledRead,\n recordedArguments: ['concept'],\n description:\n 'Look up one Runpod concept (pod, network volume, machine, worker, template, …) 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\".',\n inputSchema: {\n type: 'object',\n properties: {\n concept: {\n type: 'string',\n description:\n 'An id, name or alias, such as \"pod\", \"Network volume\" or \"volume disk\".',\n },\n },\n required: ['concept'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const resolved = resolveConcept(String(args.concept));\n if (!resolved) {\n const ref = conceptKey(String(args.concept));\n const close = [...conceptKeyIndex.keys()]\n .filter(\n (key) =>\n key.includes(ref) ||\n editDistance(key, ref, typoBudget(ref) + 1) <= typoBudget(ref) + 1\n )\n .slice(0, 10);\n return {\n ok: false,\n status: 404,\n payload: {\n error: `No concept matches \"${args.concept}\".`,\n hint: close.length\n ? `Close matches: ${close.join(', ')}.`\n : 'Try search-concepts with a few words instead.',\n },\n };\n }\n const { concept, matchedAs } = resolved;\n const pointedAtBy = knowledge.concepts.flatMap((other) => [\n ...(other.is_a === concept.id\n ? [{ concept: other.id, type: 'is_a' }]\n : []),\n ...(other.part_of === concept.id\n ? [{ concept: other.id, type: 'part_of' }]\n : []),\n ...other.relations\n .filter((relation) => relation.target === concept.id)\n .map((relation) => ({ concept: other.id, type: relation.type })),\n ]);\n const linkedRules = [...new Set(concept.rules.flatMap((rule) => rule.see))]\n .map((id) => ruleIndex.get(id))\n .filter((entry) => entry !== undefined)\n .map(({ rule, concept: owner }) => ({\n concept: owner.id,\n id: rule.id,\n statement: rule.statement.trim(),\n }));\n return ok({\n ...source,\n ...(matchedAs ? { matched_as: matchedAs } : {}),\n ...concept,\n pointed_at_by: pointedAtBy,\n linked_rules: linkedRules,\n ...linkedGuides(concept.id),\n });\n },\n};\n\nexport const searchConcepts: CuratedTool = {\n name: 'search-concepts',\n annotations: bundledRead,\n recordedArguments: ['query', 'limit'],\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'A few words describing the question.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 25,\n description: 'Most rules to return. Default 8.',\n },\n },\n required: ['query'],\n additionalProperties: false,\n },\n handler: async (_ctx, args) => {\n const terms = words(String(args.query));\n if (!terms.length) return badRequest('query needs at least one word.');\n const limit = Math.min(Math.max(Number(args.limit) || 8, 1), 25);\n const hits = [...ruleIndex.values()]\n .map(({ rule, concept }) => {\n const statement = words(rule.statement);\n const names = words(\n [concept.id, concept.name, ...concept.aliases].join(' ')\n );\n const ruleId = words(rule.id);\n // Statement matches count once per occurrence; concept names weigh more,\n // since a question usually names the thing it is about.\n const score = terms.reduce(\n (total, term) =>\n total +\n statement.filter((word) => termMatches(word, term)).length +\n (names.some((name) => nameMatches(name, term)) ? 3 : 0) +\n (ruleId.includes(term) ? 1 : 0),\n 0\n );\n const matched = terms.filter(\n (term) =>\n statement.some((word) => termMatches(word, term)) ||\n names.some((name) => nameMatches(name, term))\n ).length;\n return { rule, concept, score: score * matched };\n })\n .filter((hit) => hit.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map(({ rule, concept }) => ({\n concept: concept.id,\n concept_name: concept.name,\n id: rule.id,\n statement: rule.statement.trim(),\n status: rule.status,\n conflict: rule.conflict,\n evidence: rule.evidence,\n }));\n return ok({ ...source, count: hits.length, rules: hits });\n },\n};\n\nexport const knowledgeTools: CuratedTool[] = [\n listGuides,\n readGuide,\n lookupConcept,\n searchConcepts,\n];\n\n/** The plugin guides as MCP resources, for clients that read resources. */\nexport const GUIDE_URI_PREFIX = 'runpod://guides/';\nexport const guideResources = knowledge.guides.map((guide) => ({\n uri: `${GUIDE_URI_PREFIX}${guide.id}`,\n name: guide.id,\n title: guide.title,\n description: guide.description,\n mimeType: 'text/markdown',\n text: guide.body,\n}));\n","// Sentence splitting shared by the generator's description compaction and the\n// served tool listing, so both cut at the same places.\n\nconst ABBREVIATIONS = ['e.g.', 'i.e.', 'etc.', 'vs.'];\nconst DOT = '\\u0000';\n\nexport function splitSentences(text: string): string[] {\n let guarded = text;\n for (const abbreviation of ABBREVIATIONS) {\n guarded = guarded.replaceAll(\n abbreviation,\n abbreviation.replaceAll('.', DOT)\n );\n }\n return guarded\n .split(/(?<=[.!?])\\s+(?=[A-Z`\"'([])/)\n .map((sentence) => sentence.replaceAll(DOT, '.').trim())\n .filter(Boolean);\n}\n\nexport function leadSentence(text: string): string {\n return splitSentences(text)[0] ?? text;\n}\n","// Every tool is listed by name, description and annotations, but a tool\n// flagged `schemaOnDemand` lists only its call shape: the top-level arguments\n// with their types and a lead sentence each, nested objects collapsed. The\n// full schema is served by describe-tool and still gates every call, so what\n// a tool accepts does not change — only what every handshake carries.\n\nimport type { ToolAnnotations } from './generated/tools.gen.js';\nimport { leadSentence } from './prose.js';\n\nexport const DESCRIBE_TOOL_NAME = 'describe-tool';\n\nconst ON_DEMAND_POINTER = ` Call ${DESCRIBE_TOOL_NAME} for the full argument schema before the first use.`;\n\ntype Schema = Record<string, unknown>;\n\nexport interface ListedTool {\n name: string;\n description: string;\n inputSchema: Schema;\n annotations: Partial<ToolAnnotations>;\n}\n\nexport interface ListableTool extends ListedTool {\n annotations: ToolAnnotations;\n schemaOnDemand?: boolean;\n}\n\n// Every tools/list carries the annotations of every tool, so idempotentHint is\n// left out when false, its MCP spec default; the client reads the same value\n// either way. The other three are always sent: hosts gate on readOnlyHint and\n// destructiveHint (which defaults to true), and some directory reviews look\n// for openWorldHint itself.\nexport function listedAnnotations(\n annotations: ToolAnnotations\n): Partial<ToolAnnotations> {\n const { idempotentHint, ...listed } = annotations;\n return idempotentHint ? annotations : listed;\n}\n\nexport function listTool(tool: ListableTool): ListedTool {\n const { name, description, inputSchema } = tool;\n const annotations = listedAnnotations(tool.annotations);\n if (!tool.schemaOnDemand)\n return { name, description, inputSchema, annotations };\n return {\n name,\n description: description + ON_DEMAND_POINTER,\n inputSchema: callShape(inputSchema),\n annotations,\n };\n}\n\nexport function callShape(schema: Schema): Schema {\n const defs = (schema.$defs ?? {}) as Record<string, Schema>;\n const resolve = (node: Schema): Schema => {\n if (typeof node.$ref !== 'string') return node;\n const name = node.$ref.split('/').pop() ?? '';\n return defs[name] ?? {};\n };\n const properties = Object.fromEntries(\n Object.entries((schema.properties ?? {}) as Record<string, Schema>).map(\n ([key, value]) => [key, shallowProperty(resolve(value), resolve)]\n )\n );\n return {\n type: 'object',\n properties,\n ...(schema.required ? { required: schema.required } : {}),\n };\n}\n\ntype Resolve = (node: Schema) => Schema;\n\nfunction shallowProperty(node: Schema, resolve: Resolve): Schema {\n const out: Schema = {};\n const type = schemaType(node, resolve);\n if (type !== undefined) out.type = type;\n if (type === 'array') {\n const items = resolve((node.items ?? {}) as Schema);\n const itemType = schemaType(items, resolve);\n if (itemType !== undefined) out.items = { type: itemType };\n }\n if (Array.isArray(node.enum)) out.enum = node.enum;\n if (typeof node.description === 'string')\n out.description = leadSentence(node.description);\n return out;\n}\n\nfunction schemaType(node: Schema, resolve: Resolve): unknown {\n if (node.type !== undefined) return node.type;\n if (node.properties || node.allOf) return 'object';\n const branches = (node.anyOf ?? node.oneOf) as Schema[] | undefined;\n const allObjects =\n branches?.every(\n (branch) => schemaType(resolve(branch), resolve) === 'object'\n ) ?? false;\n return allObjects ? 'object' : undefined;\n}\n","// Serves any tool's full definition. Tools flagged schemaOnDemand list only\n// their call shape (src/specgen/on-demand.ts); the rest is read from here.\n\nimport { DESCRIBE_TOOL_NAME, type ListableTool } from '../on-demand.js';\nimport type { CuratedTool } from '../types.js';\nimport { ok } from './util.js';\n\nexport function createDescribeTool(served: () => ListableTool[]): CuratedTool {\n return {\n name: DESCRIBE_TOOL_NAME,\n description:\n \"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.\",\n inputSchema: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description:\n \"A tool name exactly as this server's tool list spells it.\",\n },\n },\n required: ['name'],\n },\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n handler: async (_ctx, args) => {\n const name = String(args.name ?? '');\n const tools = served();\n const tool = tools.find((candidate) => candidate.name === name);\n if (!tool) {\n return {\n ok: false,\n status: 404,\n payload: {\n error: `No tool named ${name}.`,\n suggestions: similarNames(\n name,\n tools.map((candidate) => candidate.name)\n ),\n hint: 'Tool names are exactly as this server lists them; the suggestions share a word with the name you sent.',\n },\n };\n }\n const { description, inputSchema, annotations } = tool;\n return ok({ name: tool.name, description, inputSchema, annotations });\n },\n };\n}\n\nexport function similarNames(query: string, names: string[]): string[] {\n const wanted = new Set(words(query));\n return names\n .map((name) => {\n const own = new Set(words(name));\n const shared = [...own].filter((word) => wanted.has(word)).length;\n return { name, score: shared / new Set([...own, ...wanted]).size };\n })\n .filter((entry) => entry.score > 0)\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, 8)\n .map((entry) => entry.name);\n}\n\nfunction words(name: string): string[] {\n return name\n .toLowerCase()\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((word) => word.replace(/s$/, ''));\n}\n","// Anonymous product analytics (PostHog), hosted-path only.\n//\n// OFF BY DEFAULT: every capture is a no-op unless POSTHOG_API_KEY is set —\n// it never is locally or in CI, so only a deployment that deliberately sets\n// it (the Vercel project) sends anything. Users opt out per client with the\n// `X-Runpod-Analytics: off` header (see README), and the stdio transport\n// never captures at all.\n//\n// SECURITY: the event payload is the closed set of fields in ToolCallEvent,\n// ResourceEvent and LoopBlockedEvent — never the API key, the Authorization header, resource ids,\n// or response payloads. Tool arguments are dropped unless the tool names them\n// in CuratedTool.recordedArguments; only the bundled guide and concept tools\n// do, and their arguments are guide ids, concept names and search words. The caller identity is an HMAC of the key with a\n// server-side salt (MCP_ANALYTICS_SALT): stable across instances so per-user\n// frequency works in PostHog, irreversible without the salt, and never\n// joinable to the key itself. $process_person_profile stays false — no\n// person profiles, just anonymous distinct ids.\n\nimport { createHmac } from 'node:crypto';\n\nexport interface ToolCallEvent {\n tool: string;\n ok: boolean;\n status: number;\n durationMs: number;\n transport: 'stdio' | 'http';\n serverVersion: string;\n /** Sanitized client token from the User-Agent (never the raw header). */\n clientName?: string;\n /** Stable account id (the pre-flight's myself.id). Preferred identity:\n * keys rotate on every OAuth sign-in, the account does not. Hashed like\n * the key — the raw id never leaves the process. */\n accountId?: string;\n /** Argument values the tool allowlists (CuratedTool.recordedArguments),\n * already passed through recordedArgumentValues. Sent as arg_<name>. */\n args?: Record<string, string>;\n /** Kind of the guide read-guide resolved: skill, reference or golden-path. */\n guideKind?: string;\n /** Set when this server's own limiter denied the call (not an API 429). */\n blockedBy?: string;\n}\n\n/** The hosted 404 loop breaker started blocking one account + tool. */\nexport interface LoopBlockedEvent {\n tool: string;\n blockedForS: number;\n transport: 'stdio' | 'http';\n serverVersion: string;\n clientName?: string;\n accountId?: string;\n}\n\n/** A resources/read request. `uri` is the served guide URI, or 'unknown'\n * on a miss so arbitrary client strings never land in events. */\nexport interface ResourceEvent {\n method: 'resources/read';\n uri: string;\n ok: boolean;\n transport: 'stdio' | 'http';\n serverVersion: string;\n clientName?: string;\n accountId?: string;\n}\n\nconst CAPTURE_TIMEOUT_MS = 3_000;\n\n// Durable generation marker for v1-vs-v2 attribution, independent of the npm\n// package version: '2' is the spec-generated surface (v1 was the hand-written\n// tool set). Bump on surface generations ('3') or notable revisions ('2.1').\n// Keep in sync with the `surface=` User-Agent token in _shared/tracking.ts.\nexport const SURFACE_VERSION = '2';\n\nfunction posthogHost(): string {\n return process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n}\n\n// Stable anonymous caller id. Identity source, best first: the account id\n// (stable across key rotations and OAuth re-auths), then the API key (a\n// per-key identity is better than none when the pre-flight was skipped).\n// Without MCP_ANALYTICS_SALT the HMAC key falls back to the PostHog key —\n// still server-side and secret, so the id stays non-reversible; set the salt\n// to rotate identities independently of the PostHog project.\nexport function analyticsCallerId(\n apiKey: string | undefined,\n accountId?: string\n): string {\n const identity = accountId ?? apiKey;\n if (!identity) return 'anonymous';\n const salt =\n process.env.MCP_ANALYTICS_SALT || process.env.POSTHOG_API_KEY || '';\n const prefix = accountId ? 'a:' : 'k:';\n return (\n prefix +\n createHmac('sha256', salt).update(identity).digest('hex').slice(0, 16)\n );\n}\n\n// Longest recorded argument or URI. Guide ids and concept names are far\n// shorter; the cap bounds what a client can push into an event.\nconst MAX_RECORDED_VALUE_LENGTH = 200;\n\nfunction bounded(value: string): string {\n return value.slice(0, MAX_RECORDED_VALUE_LENGTH);\n}\n\n// Picks the allowlisted argument values off a tool call. Only strings and\n// numbers are kept, so an object-shaped argument can never be serialized in.\nexport function recordedArgumentValues(\n names: readonly string[] | undefined,\n args: Record<string, unknown>\n): Record<string, string> | undefined {\n if (!names?.length) return undefined;\n const values: Record<string, string> = {};\n for (const name of names) {\n const value = args[name];\n if (typeof value === 'string' || typeof value === 'number') {\n values[name] = bounded(String(value).trim());\n }\n }\n return Object.keys(values).length ? values : undefined;\n}\n\n// Fire-and-forget: never throws, never blocks the response. A lost event is\n// fine; a failed tool call because of analytics is not.\nfunction capture(\n event: string,\n distinctId: string,\n properties: Record<string, unknown>\n): void {\n const posthogKey = process.env.POSTHOG_API_KEY;\n if (!posthogKey) return;\n void fetch(`${posthogHost()}/capture/`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n api_key: posthogKey,\n event,\n distinct_id: distinctId,\n timestamp: new Date().toISOString(),\n properties: {\n ...properties,\n surface_version: SURFACE_VERSION,\n $process_person_profile: false,\n },\n }),\n signal: AbortSignal.timeout(CAPTURE_TIMEOUT_MS),\n }).catch(() => {\n // Dropped events are acceptable; noisy logs on every blip are not.\n });\n}\n\nexport function captureToolCall(\n apiKey: string | undefined,\n event: ToolCallEvent\n): void {\n const args = Object.fromEntries(\n Object.entries(event.args ?? {}).map(([name, value]) => [\n `arg_${name}`,\n value,\n ])\n );\n capture('runpod_mcp_tool_call', analyticsCallerId(apiKey, event.accountId), {\n tool: event.tool,\n ok: event.ok,\n status: event.status,\n duration_ms: event.durationMs,\n transport: event.transport,\n server_version: event.serverVersion,\n ...(event.clientName ? { client_name: event.clientName } : {}),\n ...(event.guideKind ? { guide_kind: event.guideKind } : {}),\n ...(event.blockedBy ? { blocked_by: event.blockedBy } : {}),\n ...args,\n });\n}\n\nexport function captureLoopBlocked(\n apiKey: string | undefined,\n event: LoopBlockedEvent\n): void {\n capture(\n 'runpod_mcp_loop_blocked',\n analyticsCallerId(apiKey, event.accountId),\n {\n tool: event.tool,\n blocked_for_s: event.blockedForS,\n transport: event.transport,\n server_version: event.serverVersion,\n ...(event.clientName ? { client_name: event.clientName } : {}),\n }\n );\n}\n\nexport function captureResourceCall(\n apiKey: string | undefined,\n event: ResourceEvent\n): void {\n capture(\n 'runpod_mcp_resource_call',\n analyticsCallerId(apiKey, event.accountId),\n {\n method: event.method,\n uri: bounded(event.uri),\n ok: event.ok,\n transport: event.transport,\n server_version: event.serverVersion,\n ...(event.clientName ? { client_name: event.clientName } : {}),\n }\n );\n}\n","import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport {\n CallToolRequestSchema,\n InitializeRequestSchema,\n JSONRPCMessageSchema,\n type JSONRPCMessage,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { createSpecgenServer, responseHoldingTools } from './specgen/server.js';\nimport { createToolContext as createSpecgenContext } from './specgen/context.js';\nimport { callerId } from './specgen/ops.js';\nimport { analyticsCallerId, captureLoopBlocked } from './specgen/analytics.js';\nimport {\n createNotFoundLimiter,\n notFoundSinkUrl,\n} from './specgen/not-found-limiter.js';\nimport { SERVER_VERSION } from './server.js';\nimport { searchConfigured, searchKnowledge } from './search/knowledge.js';\nimport { sanitizeUaToken } from './_shared/tracking.js';\nimport {\n createCredentialChecker,\n type CredentialCheckerHandle,\n} from './_shared/credential-check.js';\nimport type { HandleMcpRequestOptions, RpcSummary } from './types.js';\nimport {\n sdkBase,\n serverlessBase,\n authedGraphqlBase,\n type Env,\n} from './_shared/hosts.js';\nimport { IncomingMessage, ServerResponse } from 'node:http';\n\n/**\n * Extract the bearer token from an HTTP request's Authorization header.\n * Returns null if the header is missing or malformed.\n */\nexport function extractBearerToken(req: IncomingMessage): string | null {\n const authHeader = req.headers.authorization;\n if (!authHeader) return null;\n const parts = authHeader.split(' ');\n if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') return null;\n return parts[1];\n}\n\n// Per-request analytics opt-out: any client can send\n// `X-Runpod-Analytics: off` (or 0/false) and no usage event is captured for\n// its calls. Checked case-insensitively; absence means opted in (the capture\n// itself is still a no-op unless the deployment sets POSTHOG_API_KEY).\nfunction analyticsOptedOut(req: IncomingMessage): boolean {\n const value = header(req, 'x-runpod-analytics')?.trim().toLowerCase();\n return value === 'off' || value === '0' || value === 'false';\n}\n\n// Structural request type so the Vercel adapter (api/index.ts) can share this\n// proxy-header parsing instead of keeping a second copy.\nexport function getBaseUrl(req: {\n headers: { host?: string; 'x-forwarded-proto'?: string | string[] };\n}): string {\n const protoHeader = req.headers['x-forwarded-proto'];\n const proto =\n (Array.isArray(protoHeader) ? protoHeader[0] : protoHeader)?.split(\n ','\n )[0] ?? 'https';\n const host = req.headers.host;\n if (!host) {\n throw new Error('Missing Host header');\n }\n return `${proto}://${host}`;\n}\n\nfunction writeUnauthorized(\n req: IncomingMessage,\n res: ServerResponse,\n error: string,\n // A credential was supplied and rejected, as opposed to none being sent. RFC\n // 6750 §3.1 puts error=\"invalid_token\" on that case and requires it be omitted\n // otherwise, so a client can tell \"never authenticated\" from \"re-authenticate\".\n invalidToken = false\n): void {\n // Always advertise the protected-resource metadata so OAuth-capable clients\n // (e.g. Claude) know to start the \"Sign in with Runpod\" flow.\n const challenge = [\n 'Bearer realm=\"mcp\"',\n ...(invalidToken\n ? [\n 'error=\"invalid_token\"',\n 'error_description=\"The credential was rejected; re-authenticate.\"',\n ]\n : []),\n `resource_metadata=\"${getBaseUrl(\n req\n )}/.well-known/oauth-protected-resource\"`,\n ].join(', ');\n\n res.writeHead(401, {\n 'Content-Type': 'application/json',\n 'WWW-Authenticate': challenge,\n });\n res.end(JSON.stringify({ error }));\n}\n\n// The GraphQL host the pre-flight authenticates against. This call carries the\n// CALLER'S key, so it uses authedGraphqlBase (RUNPOD_AUTHED_GRAPHQL_URL) — the\n// variable backend.ts reserves for key-bearing GraphQL — NOT the freely\n// repointable OAuth flash-auth var (RUNPOD_GRAPHQL_URL): repointing that one\n// must never redirect every caller's key to an arbitrary host. One resolver so\n// the checker and the environment guard below cannot disagree about defaults.\n// Shared across requests so the verdict cache helps on a warm instance. Uses the\n// global fetch (Node >= 18) — this runs before any MCP/tool wiring exists.\nexport const defaultCredentialChecker: CredentialCheckerHandle =\n createCredentialChecker({\n fetch: (url, init) => fetch(url, init),\n url: () => authedGraphqlBase(process.env as Env),\n });\n\nconst sameHost = (a: string, b: string) => normalizeUrl(a) === normalizeUrl(b);\n\n// Hosts that are the same backend under a different name. `v2-rest.runpod.io`\n// served as the REST v2 default before `api.runpod.io` became canonical, and a\n// deployment that pinned it back then must not read as \"REST moved\" — that\n// disagreement with the (unmoved) GraphQL host would silently switch the\n// pre-flight off. Prod pair only: `v2-rest.runpod.dev` is genuinely a different\n// environment and must NOT normalize into prod.\nconst HOST_ALIASES: Record<string, string> = {\n 'v2-rest.runpod.io': 'api.runpod.io',\n};\n\n// Lowercased origin + path with any trailing slash removed, so cosmetic\n// differences in an env var do not read as a different environment.\nfunction normalizeUrl(raw: string): string {\n try {\n const u = new URL(raw);\n const host = u.host.toLowerCase();\n return `${u.protocol}//${HOST_ALIASES[host] ?? host}${u.pathname.replace(/\\/+$/, '')}`;\n } catch {\n return raw.trim().toLowerCase().replace(/\\/+$/, '');\n }\n}\n\n// The pre-flight checks the token against RUNPOD_AUTHED_GRAPHQL_URL; the tools\n// authenticate against the REST/Serverless hosts. Those are independent, so a\n// deployment pointing REST at a dev environment while GraphQL stays on prod\n// would validate a dev key against prod and reject EVERY request — though every\n// tool would have worked. Skipping on that ambiguity is the safer error: a wrong\n// 401 rejects everything, a missed one only restores the prior behaviour.\n//\n// UNVERIFIED: nobody has confirmed what the hosted deployment actually sets.\n// There is no .env in the repo, no `env` block in vercel.json, and CI sets no\n// RUNPOD_* vars — the values live only in the Vercel dashboard. If production\n// points any REST host somewhere non-default without also setting\n// RUNPOD_AUTHED_GRAPHQL_URL, this guard is silently disabling the gate in production\n// right now. Run `vercel env ls production` to settle it.\nfunction credentialCheckMayBeWrongEnvironment(env = process.env): boolean {\n // Compare normalized destinations so formatting differences do not disable\n // the credential preflight. Host resolvers treat blank overrides as unset.\n const envWithoutEmpties = Object.fromEntries(\n Object.entries(env).filter(([, v]) => v !== '')\n ) as Record<string, string | undefined>;\n const restMoved =\n !sameHost(sdkBase(envWithoutEmpties), sdkBase({})) ||\n !sameHost(serverlessBase(envWithoutEmpties), serverlessBase({}));\n const graphqlMoved = !sameHost(\n authedGraphqlBase(envWithoutEmpties as Env),\n authedGraphqlBase({})\n );\n // Skip whenever REST and the auth-GraphQL host DISAGREE about whether they are\n // on the default (prod) environment — in EITHER direction. Validating a key\n // against an auth backend from a different environment than the tools use\n // rejects every request while every tool would have worked, and OAuth clients\n // answer that 401 by re-authenticating in a loop. Only when both sides agree\n // (both default, or both moved) is the pre-flight validating against the same\n // environment the tools will call. An earlier version only caught REST-moved-\n // but-GraphQL-default, so moving only RUNPOD_GRAPHQL_URL (its documented dev\n // override) still 401'd every good credential.\n return restMoved !== graphqlMoved;\n}\n\n// The one place a request body is validated. The SDK parses each element with\n// this same schema and answers 400 when any fails, so an element dropped here\n// never reaches a tool; everything past this point works on typed messages. An\n// absent or host-unparsed body (undefined) yields no messages.\nexport function parseMcpMessages(body: unknown): JSONRPCMessage[] {\n const elements = Array.isArray(body) ? body : [body];\n return elements.flatMap((element) => {\n const parsed = JSONRPCMessageSchema.safeParse(element);\n return parsed.success ? [parsed.data] : [];\n });\n}\n\n// A response element ({jsonrpc, id, result}) invokes nothing, so it needs no\n// credential. `some`, not `every`: one response element in a batch must not opt\n// the tool call beside it out of the pre-flight.\nconst invokesMethod = (message: JSONRPCMessage): boolean => 'method' in message;\n\nexport function bodyIsCheckable(body: unknown): boolean {\n return parseMcpMessages(body).some(invokesMethod);\n}\n\n// The gate must be at least as permissive as the SDK's own content-type check,\n// or any type the SDK accepts but the gate rejects is a bypass window: the gate\n// skips, then the SDK parses and runs the tool with an unverified credential.\n// The SDK uses `ct.includes('application/json')` (streamableHttp.js), so\n// `application/json-patch+json` and `application/jsonx` reach a tool — an exact\n// match here missed them. Mirror the SDK's substring test (lowercased, so the\n// gate is a superset and stays safe even if the SDK never normalises case). A\n// type the SDK 415s that we happen to check only costs one needless probe.\nfunction isJsonContentType(req: IncomingMessage): boolean {\n const ct = req.headers['content-type'];\n if (!ct) return false;\n return ct.toLowerCase().includes('application/json');\n}\n\n// Match the SDK's own body limit (MAXIMUM_MESSAGE_SIZE, '4mb'). A body the SDK\n// would reject as too large is one we must not buffer either.\nconst MAX_BODY_BYTES = 4 * 1024 * 1024;\n// readJsonBody's distinct \"over the cap\" result, kept separate from undefined\n// (absent/unparseable) so the caller answers 413 rather than falling through to\n// the skip path and handing a partial stream back to the SDK.\nconst BODY_TOO_LARGE = Symbol('body_too_large');\n\n// Buffer and parse a JSON body when the host did not already. Without this the\n// gate cannot run on a plain node:http host — the published ./http export and\n// scripts/serve-http.local.ts — because there is nothing to inspect, which would\n// silently disable the pre-flight for those consumers. The parsed value is handed\n// to transport.handleRequest afterwards, so the SDK never needs the stream this\n// consumed. Returns undefined when the body is absent or not JSON (the caller\n// then skips), or BODY_TOO_LARGE past the cap (the caller answers 413).\n//\n// Capped, and only ever called after the cheap skip checks pass, so a non-JSON,\n// kill-switched or oversized request never buffers: on the un-pre-parsed\n// node:http path this replaces the SDK's own getRawBody, which enforced the same\n// 4mb limit — without the cap an unauthenticated caller could stream unbounded\n// bytes into memory, and reading before the content-type check let a slow\n// non-JSON upload hold the request slot open.\nasync function readJsonBody(\n req: IncomingMessage\n): Promise<unknown | typeof BODY_TOO_LARGE> {\n const existing = (req as { body?: unknown }).body;\n if (existing !== undefined) return existing;\n const declared = Number(req.headers['content-length']);\n if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {\n return BODY_TOO_LARGE;\n }\n try {\n const chunks: Buffer[] = [];\n let total = 0;\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n total += buf.length;\n // Covers a chunked upload or a lying Content-Length: stop the moment the\n // bytes on the wire exceed the cap, before growing the buffer further.\n if (total > MAX_BODY_BYTES) return BODY_TOO_LARGE;\n chunks.push(buf);\n }\n const raw = Buffer.concat(chunks).toString('utf8').trim();\n return raw ? JSON.parse(raw) : undefined;\n } catch {\n return undefined;\n }\n}\n\ntype SkipReason =\n | 'skip_env_var'\n | 'skip_env_mismatch'\n | 'skip_not_post'\n | 'skip_not_json'\n | 'skip_not_mcp_body';\n\n// Body-independent skip reasons, decided before the body is read (see\n// readJsonBody). Only well-formed MCP POSTs are ever checked. This does NOT close\n// the credential oracle — a caller who speaks the protocol still learns\n// 401-vs-otherwise from a well-formed tools/list — but it stops an\n// unauthenticated scanner probing stolen keys through us with arbitrary requests,\n// and avoids an upstream query per junk request. Closing it properly needs rate\n// limiting, which this does not add. GET and DELETE make no authenticated\n// upstream call, so a dead credential breaks nothing there. The cheap header\n// checks precede the env-mismatch scan (which parses several URLs) so the common\n// non-POST path stays cheap, and the kill switch comes first so it also prevents\n// the body read.\nfunction earlyCredentialCheckSkip(req: IncomingMessage): SkipReason | null {\n if (process.env.MCP_SKIP_CREDENTIAL_CHECK === 'true') return 'skip_env_var';\n if (req.method !== 'POST') return 'skip_not_post';\n if (!isJsonContentType(req)) return 'skip_not_json';\n if (credentialCheckMayBeWrongEnvironment()) return 'skip_env_mismatch';\n return null;\n}\n\nconst callsResponseHoldingTool = (message: JSONRPCMessage): boolean => {\n const call = CallToolRequestSchema.safeParse(message);\n return call.success && responseHoldingTools.has(call.data.params.name);\n};\n\n// The CDN compresses application/json but never text/event-stream, so every\n// request answers as JSON except a call to a tool that holds its response open\n// (CuratedTool.holdsResponse): clients read an SSE body under their long stream\n// timeout but a JSON body under the short request timeout (30s in the Python\n// SDK). No parsed messages keeps SSE, the SDK's default.\nexport function prefersJsonResponse(messages: JSONRPCMessage[]): boolean {\n return messages.length > 0 && !messages.some(callsResponseHoldingTool);\n}\n\nconst DEFAULT_REQUEST_LOG_SAMPLE_RATE = 0.1;\n\n// A line per request is more than the log pipeline needs, so it is sampled;\n// `sampleRate` rides along so counts can be scaled back up. MCP_VERBOSE_LOGS=true\n// logs every request.\nexport function requestLogSampleRate(\n env: NodeJS.ProcessEnv = process.env\n): number {\n if (env.MCP_VERBOSE_LOGS === 'true') return 1;\n const raw = env.MCP_REQUEST_LOG_SAMPLE_RATE;\n if (raw === undefined || raw === '') return DEFAULT_REQUEST_LOG_SAMPLE_RATE;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) return DEFAULT_REQUEST_LOG_SAMPLE_RATE;\n return Math.min(1, Math.max(0, parsed));\n}\n\n// `initialize`, `tools/list`, `tools/call:list-pods`, or a comma-joined list for\n// a batch. `initialize` also carries the client's self-reported name/version.\nexport function summarizeRpc(messages: JSONRPCMessage[]): RpcSummary {\n const rpc = messages.map((message) => {\n const call = CallToolRequestSchema.safeParse(message);\n if (call.success) return `tools/call:${call.data.params.name}`;\n return 'method' in message ? message.method : 'response';\n });\n const init = messages\n .map((message) => InitializeRequestSchema.safeParse(message))\n .find((result) => result.success);\n const client = init?.success\n ? `${init.data.params.clientInfo.name}/${init.data.params.clientInfo.version}`\n : undefined;\n return { rpc: rpc.length > 0 ? rpc.join(',') : undefined, client };\n}\n\nfunction header(req: IncomingMessage, name: string): string | undefined {\n const value = req.headers[name];\n return Array.isArray(value) ? value[0] : value;\n}\n\nfunction clientAddress(req: IncomingMessage): string | undefined {\n return (\n header(req, 'x-real-ip') ||\n header(req, 'x-forwarded-for')?.split(',')[0].trim() ||\n req.socket?.remoteAddress ||\n undefined\n );\n}\n\ninterface RequestLog {\n note(summary: RpcSummary): void;\n}\n\n// Emits once the response is done (or the client went away) so the line carries\n// the status and duration alongside what was asked and by whom. Key and address\n// go through callerId, the per-process salted hash tool_call lines use, so the\n// two lines join within an instance and neither id is replayable offline.\nfunction startRequestLog(\n req: IncomingMessage,\n res: ServerResponse,\n bearerToken: string | null\n): RequestLog {\n const sampleRate = requestLogSampleRate();\n if (Math.random() >= sampleRate) return { note() {} };\n const startedAt = Date.now();\n let summary: RpcSummary = {};\n const address = clientAddress(req);\n const userAgent = header(req, 'user-agent');\n let emitted = false;\n const emit = (): void => {\n if (emitted) return;\n emitted = true;\n console.log('mcp_request', {\n method: req.method,\n url: req.url,\n status: res.writableFinished ? res.statusCode : undefined,\n durationMs: Date.now() - startedAt,\n rpc: summary.rpc,\n client: summary.client,\n ua: userAgent?.slice(0, 160),\n caller: callerId(bearerToken ?? undefined),\n ip: address ? callerId(address) : undefined,\n sampleRate,\n });\n };\n res.on('finish', emit);\n res.on('close', emit);\n return {\n note(next) {\n summary = next;\n },\n };\n}\n\nfunction logCredentialCheck(\n outcome: SkipReason | 'pass' | 'reject' | 'fail_open'\n): void {\n // 'pass' is the bulk of traffic and is pure log spend; everything else —\n // rejections, fail-open guesses, every skip reason — always logs, because those\n // are the only way to notice the gate misbehaving or silently not running.\n if (outcome === 'pass' && process.env.MCP_VERBOSE_LOGS !== 'true') return;\n console.log('credential_check', { outcome });\n}\n\n/**\n * Handle an incoming HTTP request as a streamable MCP session.\n *\n * Each request gets its own McpServer + transport. The caller's Bearer token\n * is forwarded directly to the Runpod API as the credential — it may be a\n * Runpod API key (set manually by the caller) or a token obtained through the\n * OAuth \"Sign in with Runpod\" flow. The server holds no credential of its own\n * and never shares one across users.\n *\n * The token is pre-flight verified (cached) before the MCP request is\n * handled: a dead credential — e.g. an OAuth-minted key revoked mid-session —\n * must surface as an HTTP 401 + WWW-Authenticate so\n * OAuth-capable clients re-run their auth flow automatically. Without this,\n * the upstream 401 is wrapped into a 200 JSON-RPC tool error and the client\n * never re-authenticates. Set MCP_SKIP_CREDENTIAL_CHECK=true to disable.\n *\n * The gate also self-disables when the REST hosts are overridden without a\n * matching RUNPOD_AUTHED_GRAPHQL_URL — see credentialCheckMayBeWrongEnvironment.\n */\nexport async function handleMcpRequest(\n req: IncomingMessage,\n res: ServerResponse,\n opts: HandleMcpRequestOptions = {}\n): Promise<void> {\n const bearerToken = extractBearerToken(req);\n const requestLog = startRequestLog(req, res, bearerToken);\n // Stateless server: there are no server-initiated messages, so the standalone\n // GET SSE stream has nothing to carry. Per spec, answer 405 instead of letting\n // the SDK hold an idle stream open until the platform kills it.\n if (req.method === 'GET') {\n res.writeHead(405, {\n Allow: 'POST, DELETE',\n 'Content-Type': 'application/json',\n });\n res.end(\n JSON.stringify({\n jsonrpc: '2.0',\n error: {\n code: -32000,\n message:\n 'Method Not Allowed: this server does not offer a standalone SSE stream.',\n },\n id: null,\n })\n );\n return;\n }\n if (!bearerToken) {\n writeUnauthorized(\n req,\n res,\n 'Missing or invalid Authorization header. Provide a Bearer token.'\n );\n return;\n }\n\n // The body is read only when the pre-flight might actually run. The cheap,\n // body-independent skips are decided first (earlyCredentialCheckSkip) so a\n // non-JSON, kill-switched or wrong-environment request never buffers a body —\n // an earlier version read every body up front, which removed the SDK's 4mb cap\n // and let a slow or oversized non-JSON upload hold the request slot open. For a\n // skipped request `body` stays whatever the host pre-parsed (undefined on plain\n // node:http, where the SDK then reads the stream itself).\n let body: unknown = (req as { body?: unknown }).body;\n // Stable account identity from the pre-flight's `myself { id }` probe —\n // carried into anonymous analytics so a user keeps one identity across key\n // rotations. Absent when the check is skipped or fails open.\n let accountId: string | undefined;\n const early = earlyCredentialCheckSkip(req);\n if (!early) {\n const read = await readJsonBody(req);\n if (read === BODY_TOO_LARGE) {\n res.writeHead(413, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Request body too large.' }));\n return;\n }\n body = read;\n }\n const messages = parseMcpMessages(body);\n // Before the gate, so a rejected or skipped request still logs what it asked.\n requestLog.note(summarizeRpc(messages));\n if (early) {\n logCredentialCheck(early);\n } else if (!messages.some(invokesMethod)) {\n // Absent, unparseable, or not an MCP message — nothing to check, and\n // checking it anyway would reopen the credential oracle.\n logCredentialCheck('skip_not_mcp_body');\n } else {\n const verify = opts.verifyCredential ?? defaultCredentialChecker.verify;\n const verdict = await verify(bearerToken);\n if (verdict.status === 'valid') accountId = verdict.accountId;\n // 'unknown' is logged distinctly from 'pass': both let the request through,\n // but one is an answer and the other a guess made because the auth backend\n // could not be reached. Silently merging them hides an outage upstream.\n logCredentialCheck(\n verdict.status === 'invalid'\n ? 'reject'\n : verdict.status === 'valid'\n ? 'pass'\n : 'fail_open'\n );\n if (verdict.status === 'invalid') {\n writeUnauthorized(\n req,\n res,\n `${verdict.reason} Re-authenticate to continue.`,\n true\n );\n return;\n }\n }\n\n // Loop breaker for scripts polling deleted resources: hosted only, signed-in\n // callers only, and only where the Convex sink is configured.\n const notFoundUrl = process.env.ALP_SINK_URL\n ? notFoundSinkUrl(process.env.ALP_SINK_URL)\n : null;\n const notFoundLimiter =\n bearerToken && notFoundUrl && process.env.ALP_SINK_SECRET\n ? createNotFoundLimiter({\n key: analyticsCallerId(bearerToken, accountId),\n sinkUrl: notFoundUrl,\n secret: process.env.ALP_SINK_SECRET,\n // One usage event per block, unless this client opted out.\n onBlockStarted: analyticsOptedOut(req)\n ? undefined\n : (tool, blockedUntil) =>\n captureLoopBlocked(bearerToken, {\n tool,\n blockedForS: Math.round((blockedUntil - Date.now()) / 1000),\n transport: 'http',\n serverVersion: opts.serverVersion ?? SERVER_VERSION,\n clientName: sanitizeUaToken(\n String(req.headers['user-agent'] ?? 'unknown')\n ),\n accountId,\n }),\n })\n : null;\n\n // SPEC-GENERATED SURFACE (feat/specgen-server): the tool set generated from\n // the v2 OpenAPI spec plus its curated overlay, mounted behind this shell's\n // existing auth/transport. Per-request context from the caller's bearer\n // token — nothing credential-bearing lives at module scope.\n const server = createSpecgenServer(\n createSpecgenContext({\n apiKey: bearerToken,\n tracking: {\n // Stateless HTTP never sees the MCP clientInfo; the inbound\n // User-Agent is the best identity available.\n clientName: req.headers['user-agent'],\n transport: 'http',\n serverVersion: opts.serverVersion ?? SERVER_VERSION,\n },\n }),\n opts.serverVersion ?? SERVER_VERSION,\n {\n // Anonymous usage analytics: hosted-only, no-op unless POSTHOG_API_KEY\n // is set on the deployment, and any client can opt out per request\n // with the X-Runpod-Analytics: off header.\n ...(analyticsOptedOut(req)\n ? {}\n : {\n analytics: {\n transport: 'http' as const,\n serverVersion: opts.serverVersion ?? SERVER_VERSION,\n clientName: sanitizeUaToken(\n String(req.headers['user-agent'] ?? 'unknown')\n ),\n accountId,\n },\n }),\n // ALP write tools: advertised only when this deployment can actually\n // store submissions (the sink is configured). The ingest endpoint is\n // this deployment's own /api/alp/submit — one write path, both\n // transports (docs/agent-learning-protocol.md).\n ...(process.env.ALP_SINK_URL && process.env.ALP_SINK_SECRET\n ? {\n alp: {\n ingestUrl: `${getBaseUrl(req)}/api/alp/submit`,\n transport: 'http' as const,\n harness: sanitizeUaToken(\n String(req.headers['user-agent'] ?? 'unknown')\n ),\n harnessSource: 'user_agent' as const,\n },\n }\n : {}),\n // search-docs: listed only where the deployment holds the assistant's\n // service key; the search runs in-process with it.\n ...(searchConfigured()\n ? { search: (request) => searchKnowledge(request) }\n : {}),\n ...(notFoundLimiter\n ? {\n rateLimiter: notFoundLimiter.rateLimiter,\n onToolResult: notFoundLimiter.onToolResult,\n }\n : {}),\n // A tool call that 401s proves a cached \"valid\" verdict wrong before\n // its TTL — drop it so the next request re-checks and re-auths.\n onUnauthorized: () =>\n (opts.invalidateCredential ?? defaultCredentialChecker.invalidate)(\n bearerToken\n ),\n }\n );\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined, // stateless — no session persistence\n enableJsonResponse: prefersJsonResponse(messages),\n });\n\n // This per-request server/transport pair is single-use; dispose it when the\n // response closes so listeners don't accumulate on a warm serverless instance.\n res.on('close', () => {\n transport.close().catch(() => {});\n server.close().catch(() => {});\n });\n\n await server.connect(transport);\n // Pass the already-parsed body when the host provides one (e.g. Vercel's\n // VercelRequest exposes `req.body`); the SDK reads the raw stream otherwise.\n // Pass the body we already resolved: readJsonBody may have consumed the stream.\n await transport.handleRequest(req, res, body);\n}\n","// The shared context threaded into every curated tool handler: the generated\n// SDK client for the v2 management API, plus the clients for the two planes\n// the spec does not cover (Serverless runtime, GraphQL) and the bounded SSE\n// reader for the log endpoints.\n//\n// TENANCY: on the hosted (HTTP) path every request builds its own context\n// from the caller's bearer token — nothing here may be cached at module\n// scope. The stdio path builds one context per process from RUNPOD_API_KEY.\n\nimport { randomUUID } from 'node:crypto';\nimport {\n createRunpodClient,\n type RetryOptions,\n type RunpodClient,\n} from '@runpod/typescript-api-sdk';\nimport { sdkBase } from '../_shared/hosts.js';\nimport { buildTrackingHeaders } from '../_shared/tracking.js';\nimport { createGraphqlClient, type GraphqlClient } from './clients/graphql.js';\nimport { missingKeyError } from './clients/http-error.js';\nimport { createRuntimeClient, type RuntimeClient } from './clients/runtime.js';\nimport { createSseReader, type SseReader } from './clients/sse.js';\n\nexport interface ToolContext {\n sdk: RunpodClient;\n runtime: RuntimeClient;\n graphql: GraphqlClient;\n sse: SseReader;\n /** The key this context authenticates with (hosted: the caller's bearer token). */\n apiKey: string | undefined;\n /** Late-bind the calling client's identity into the tracking User-Agent.\n * The stdio transport only learns it from the MCP initialize handshake,\n * which happens after this context is built. No-op without tracking. */\n setClientInfo?: (name: string, version?: string) => void;\n}\n\nexport interface ToolContextOptions {\n /** Per-caller credential. Falls back to RUNPOD_API_KEY (stdio path). */\n apiKey?: string;\n /** Caller identity stamped on every outbound API call (User-Agent +\n * X-Runpod-Session-Id). Ported from the pre-specgen server. */\n tracking?: {\n clientName?: string;\n clientVersion?: string;\n transport: 'stdio' | 'http';\n serverVersion: string;\n };\n /** Test seam: deadline for one SDK (generated-tool) request. */\n sdkTimeoutMs?: number;\n /** Test seam: SDK retry tuning (false disables the retry layer). */\n sdkRetry?: RetryOptions | false;\n}\n\n// Deadline for one SDK request. The generated tools are plain CRUD calls —\n// nothing on that surface legitimately takes longer, and without a signal a\n// host that accepts the connection then goes silent parks the invocation\n// until the platform reaper (the leak PR #83 fixed on the old surface). The\n// long-hold paths (job waits, SSE streams) do NOT go through the SDK; their\n// clients carry their own bounded signals.\nconst SDK_TIMEOUT_MS = 30_000;\n\n// Bound the SDK's retry layer: its defaults honor Retry-After up to 60s per\n// sleep across 4 attempts, which alone can outlive the hosted invocation's\n// 45s budget. Retries here are for transient blips only — a real 429 must\n// come back to the agent quickly, carrying the header-derived wait hint, so\n// the AGENT decides how long to pause (dispatch enriches it; a server-side\n// sleep would just burn the budget silently).\nconst SDK_RETRY: RetryOptions = {\n maxAttempts: 3,\n maxBackoffMs: 2_000,\n maxRetryAfterMs: 5_000,\n};\n\nexport function createToolContext(\n options: ToolContextOptions = {}\n): ToolContext {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n\n // One wrapped fetch shared by all four clients: identifies the calling MCP\n // client on every outbound API request. The session id is per-context —\n // per-request on hosted, per-process on stdio.\n let fetchImpl: typeof fetch = fetch;\n let setClientInfo: ToolContext['setClientInfo'];\n if (options.tracking) {\n // Mutable so the stdio handshake can late-bind clientInfo; headers are\n // rebuilt only when it changes.\n const tracking = { ...options.tracking, sessionId: randomUUID() };\n let headers = buildTrackingHeaders(tracking);\n setClientInfo = (name, version) => {\n tracking.clientName = name;\n tracking.clientVersion = version;\n headers = buildTrackingHeaders(tracking);\n };\n fetchImpl = (input, init) => {\n // openapi-fetch calls fetch with a fully-built Request as `input`\n // (headers inside it, no init); other clients pass (url, init). Fold\n // both into one Request, then add the tracking headers only where\n // absent — passing a headers init alongside a Request would REPLACE\n // the request's own headers and drop Authorization.\n const request = new Request(input, init);\n for (const [name, value] of Object.entries(headers)) {\n if (!request.headers.has(name)) request.headers.set(name, value);\n }\n return fetch(request);\n };\n }\n\n let sdk: RunpodClient | undefined;\n\n return {\n apiKey,\n setClientInfo,\n // Built on first use, not at startup. The SDK client constructor throws\n // when no API key is present, and the MCP handshake plus tools/list are a\n // credential-free surface — a client must be able to start the server and\n // read its tool list without a key. A key-less call then fails as a 401\n // tool result instead of killing the process.\n get sdk(): RunpodClient {\n if (!sdk) {\n if (!apiKey) throw missingKeyError();\n sdk = createRunpodClient({\n apiKey,\n baseUrl: sdkBase(process.env),\n fetch: fetchImpl,\n timeoutMs: options.sdkTimeoutMs ?? SDK_TIMEOUT_MS,\n retry: options.sdkRetry ?? SDK_RETRY,\n });\n }\n return sdk;\n },\n runtime: createRuntimeClient({ apiKey, fetchImpl }),\n graphql: createGraphqlClient({ apiKey, fetchImpl }),\n sse: createSseReader({ apiKey, fetchImpl }),\n };\n}\n","// ============== CALLER TRACKING (pure header construction) ==============\n// The structured User-Agent + session id that identify the calling MCP client\n// on every outbound API call. Pure functions here so they're unit-testable\n// without the MCP SDK; the SDK-touching part (reading clientInfo off the\n// handshake) stays at the call site and is reduced to plain strings before\n// reaching `buildTrackingHeaders`.\n\n// Sanitizes a value for inclusion in a User-Agent token. RFC 7230 reserves\n// parens and a few other chars; strip them so the structured UA stays\n// parseable, and bound the length so a hostile client can't blow up a header.\nexport function sanitizeUaToken(value: string): string {\n return value.replace(/[()<>@,;:\\\\\"/[\\]?={}\\s]/g, '_').slice(0, 64);\n}\n\nexport interface TrackingInput {\n // Client identity resolved from the MCP `initialize` handshake's clientInfo,\n // or the inbound HTTP User-Agent as a fallback (stateless HTTP).\n clientName?: string;\n clientVersion?: string;\n transport: 'stdio' | 'http';\n serverVersion: string;\n sessionId: string;\n}\n\n// Builds the `User-Agent` + `X-Runpod-Session-Id` headers. The clientInfo →\n// fallback → 'unknown' resolution is the caller's job (it owns the SDK handle);\n// this function just sanitizes and formats whatever identity it's given.\nexport function buildTrackingHeaders(\n input: TrackingInput\n): Record<string, string> {\n const name = sanitizeUaToken(input.clientName || 'unknown');\n const version = sanitizeUaToken(input.clientVersion || 'unknown');\n // `surface=v2` is the durable generation marker for warehouse attribution\n // (the spec-generated surface; v1 was the hand-written tool set). Bump it\n // with the surface, independently of the npm package version. Keep in sync\n // with SURFACE_VERSION in src/specgen/analytics.ts.\n const userAgent = `runpod-mcp-server/${input.serverVersion} (caller=mcp; surface=v2; client=${name}; client_version=${version}; transport=${input.transport})`;\n return {\n 'User-Agent': userAgent,\n 'X-Runpod-Session-Id': input.sessionId,\n };\n}\n","// Client for the Runpod GraphQL API, used by the curated tools whose\n// capability has no REST v2 home yet (Hub, capacity matrix, public endpoints,\n// endpoint GPU pinning). Two deliberately separate seams, mirroring the\n// official MCP server:\n//\n// - public: credential-free discovery queries (the server answers them\n// unauthenticated). Host from RUNPOD_PUBLIC_GRAPHQL_URL.\n// - authed: the caller's API key as a Bearer token (the GraphQL gateway\n// accepts the same key REST uses). Host from RUNPOD_AUTHED_GRAPHQL_URL.\n//\n// Separate env vars despite the identical default, so the credential-free\n// path can be pointed at a stub without the key following it.\n\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\nimport { authedGraphqlBase, publicGraphqlBase } from '../../_shared/hosts.js';\nimport { boundedFetch } from './bounded-fetch.js';\nimport { HttpError, missingKeyError } from './http-error.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport interface GraphqlClient {\n public<T>(query: string): Promise<T>;\n authed<T>(query: string, variables?: Record<string, unknown>): Promise<T>;\n}\n\nexport interface GraphqlClientOptions {\n apiKey?: string;\n publicUrl?: string;\n authedUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function createGraphqlClient(\n options: GraphqlClientOptions = {}\n): GraphqlClient {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n // Resolved through _shared/hosts.ts so '' reads as unset here exactly like\n // it does in the hosted wrong-environment guard.\n const publicUrl = options.publicUrl ?? publicGraphqlBase(process.env);\n const authedUrl = options.authedUrl ?? authedGraphqlBase(process.env);\n const fetchImpl = options.fetchImpl ?? fetch;\n\n async function request<T>(\n url: string,\n query: string,\n variables?: Record<string, unknown>,\n bearer?: string\n ): Promise<T> {\n const response = await boundedFetch(fetchImpl, DEFAULT_TIMEOUT_MS)(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}),\n },\n body: JSON.stringify(variables ? { query, variables } : { query }),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new HttpError(\n `Runpod GraphQL HTTP error (${response.status})`,\n response.status,\n response.status === 429\n ? withRateLimitHint({ error: body }, response.headers)\n : body\n );\n }\n\n const result = (await response.json()) as {\n data?: T;\n errors?: Array<{ message: string }>;\n };\n if (result.errors && result.errors.length > 0) {\n throw new HttpError(\n `GraphQL error: ${result.errors.map((e) => e.message).join(', ')}`,\n response.status,\n result.errors\n );\n }\n if (result.data === undefined || result.data === null) {\n throw new HttpError('GraphQL response carried no data', response.status);\n }\n return result.data;\n }\n\n return {\n public: (query) => request(publicUrl, query),\n authed: async (query, variables) => {\n // A key-less authed call must 401 up front, not go out unauthenticated\n // and come back as an opaque gateway error that never trips\n // onUnauthorized. async so the 401 is a rejection, matching the\n // Promise-returning signature (a sync throw escapes Promise.race/\n // fire-then-await callers).\n if (!apiKey) throw missingKeyError();\n return request(authedUrl, query, variables, apiKey);\n },\n };\n}\n","// Client for the Serverless runtime plane (job submission and lifecycle at\n// api.runpod.ai/v2/{endpointId}/...). This is a separate API from the v2\n// management spec the generated tools cover — Runpod publishes no OpenAPI\n// document for it, so the tools that use it are curated (src/specgen/tools/jobs.ts).\n\nimport { serverlessBase } from '../../_shared/hosts.js';\nimport { boundedFetch } from './bounded-fetch.js';\nimport { HttpError, missingKeyError } from './http-error.js';\nimport { withRateLimitHint } from '../../_shared/rate-limit.js';\n\nexport const DEFAULT_SERVERLESS_BASE_URL = 'https://api.runpod.ai/v2';\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport interface RuntimeRequestOptions {\n method?: string;\n body?: Record<string, unknown>;\n timeoutMs?: number;\n}\n\nexport type RuntimeClient = (\n endpointId: string,\n path: string,\n options?: RuntimeRequestOptions\n) => Promise<unknown>;\n\nexport interface RuntimeClientOptions {\n apiKey?: string;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function createRuntimeClient(\n options: RuntimeClientOptions = {}\n): RuntimeClient {\n const apiKey = options.apiKey ?? process.env.RUNPOD_API_KEY;\n const baseUrl = options.baseUrl || serverlessBase(process.env);\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async (endpointId, path, opts = {}) => {\n if (!apiKey) throw missingKeyError();\n if (typeof endpointId !== 'string' || !/^[A-Za-z0-9_-]+$/.test(endpointId))\n throw new HttpError(\n 'endpointId must contain only letters, digits, underscores or hyphens.',\n 400,\n {}\n );\n const response = await boundedFetch(\n fetchImpl,\n opts.timeoutMs ?? DEFAULT_TIMEOUT_MS\n )(`${baseUrl}/${endpointId}${path}`, {\n method: opts.method ?? 'GET',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n ...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),\n });\n\n const text = await response.text();\n let payload: unknown = text;\n try {\n payload = text ? JSON.parse(text) : {};\n } catch {\n // non-JSON body stays verbatim\n }\n if (!response.ok) {\n // 429: turn the RateLimit/Retry-After headers into a wait instruction.\n const detail =\n response.status === 429\n ? withRateLimitHint(payload, response.headers)\n : payload;\n throw new HttpError(\n `Runpod runtime API error (${response.status})`,\n response.status,\n detail\n );\n }\n return payload;\n };\n}\n","// Operational seam for the hosted path: per-tool-call structured logging and\n// the rate-limit gate. The rate limiter is a deliberate STUB — it defines the\n// seat in the request path (keyed on a caller identity, consulted before any\n// tool work) so real enforcement (e.g. a KV-backed counter) can land without\n// touching the dispatch pipeline. Until then it always admits.\n//\n// SECURITY: nothing in this file may log the API key, the Authorization\n// header, or tool arguments (which can carry payload secrets). Callers are\n// identified by a short salted hash of the token — stable within one warm\n// instance for correlation, useless for recovering the credential.\n\nimport { createHash, randomBytes } from 'node:crypto';\n\n// Per-process salt: caller ids correlate within an instance's log window but\n// cannot be joined across instances or replayed offline against a key list.\nconst SALT = randomBytes(16).toString('hex');\n\nexport function callerId(token: string | undefined): string {\n if (!token) return 'anonymous';\n return createHash('sha256')\n .update(SALT)\n .update(token)\n .digest('hex')\n .slice(0, 12);\n}\n\n// ---- rate limiting (stub) ----\n\nexport interface RateLimitVerdict {\n allowed: boolean;\n /** Seconds the caller should wait; only set when denied. */\n retryAfterS?: number;\n /** Which limiter denied, recorded as blocked_by on the usage event. */\n reason?: string;\n}\n\nexport type RateLimiter = (\n caller: string,\n toolName: string\n) => Promise<RateLimitVerdict>;\n\n// Always admits. Replace with a KV/Upstash-backed counter to enforce; the\n// http handler already turns a denial into a JSON-RPC tool error with a\n// retry hint, so enforcement is a one-function change.\nexport const noopRateLimiter: RateLimiter = async () => ({ allowed: true });\n\n// ---- structured tool-call logging ----\n\nexport interface ToolCallLog {\n tool: string;\n caller: string;\n ok: boolean;\n status: number;\n durationMs: number;\n}\n\n// One line per tool call, visible in Vercel's logs and on local stderr.\n// stdout belongs exclusively to the MCP JSON-RPC transport on stdio.\nexport function logToolCall(entry: ToolCallLog): void {\n console.error('tool_call', JSON.stringify(entry));\n}\n","// Knowledge search for search-docs, backed by the runpod-assistant Convex\n// deployment's POST /v1/search (docs, curated support knowledge, blog,\n// runpod.io site; merged and ranked there).\n//\n// The assistant's service key (RUNPOD_ASSISTANT_API_KEY) stays on the hosted\n// server. The hosted search-docs tool calls searchKnowledge in-process; the\n// stdio package calls the hosted POST /api/search (route.ts) with the\n// caller's own Runpod API key, so the npm package never holds the service key.\n//\n// RETRIES: /v1/search admits a fixed number of concurrent searches (the\n// Convex plan caps concurrent actions) and rejects the rest at once with 503,\n// 429, or Convex's own \"Too many concurrent requests\". A slot frees in about\n// one search latency (~0.3s), so this client retries those with jittered\n// exponential backoff, the same contract as the assistant's own client\n// (runpod-assistant convex/rag/knowledge.ts, searchKnowledgeHttp). Every other\n// failure is returned at once. The whole call fits a deadline well under the\n// hosted function's 60s maxDuration.\n\nimport { knowledgeSearchBase, type Env } from '../_shared/hosts.js';\n\nexport const SEARCH_NAMESPACES = ['docs', 'knowledge', 'blog', 'site'] as const;\n/** /v1/search caps a query at 2000 characters and a page at 4 x 5 results. */\nexport const MAX_QUERY_CHARS = 2000;\nexport const MAX_SEARCH_LIMIT = 20;\n\nexport interface SearchRequest {\n query: string;\n namespaces?: string[];\n limit?: number;\n}\n\n/** The fields of the /v1/search response this server passes on. */\ninterface SearchResponse {\n text: string;\n totalResults: number;\n failedNamespaces: string[];\n}\n\n/** A search outcome as an HTTP status plus a JSON body, success or not. */\nexport interface SearchOutcome {\n status: number;\n body: SearchResponse | { error: string; hint?: string };\n}\n\n/** Backs search-docs. apiKey is the caller's Runpod key (stdio forwards it). */\nexport type SearchFn = (\n request: SearchRequest,\n apiKey: string | undefined\n) => Promise<SearchOutcome>;\n\nexport interface SearchKnowledgeOptions {\n /** Test seams. Production uses process.env, global fetch, and real timers. */\n env?: Env;\n fetch?: typeof fetch;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n}\n\nconst ATTEMPTS = 7;\nconst BASE_DELAY_MS = 250;\nconst ATTEMPT_TIMEOUT_MS = 10_000;\n/** No retry starts after this. Leaves room for one last attempt under 60s. */\nconst RETRY_DEADLINE_MS = 30_000;\n\nconst PLATFORM_LIMIT = /TooManyConcurrentRequests|Too many concurrent requests/;\n\nconst AT_CAPACITY: SearchOutcome = {\n status: 503,\n body: {\n error: 'Runpod knowledge search is at capacity.',\n hint: 'Retry the same call in a few seconds.',\n },\n};\n\nconst UNREACHABLE: SearchOutcome = {\n status: 504,\n body: {\n error: 'Runpod knowledge search did not respond.',\n hint: 'Retry the same call once.',\n },\n};\n\n/** Configured when this deployment can reach /v1/search with the service key. */\nexport function searchConfigured(env: Env = process.env): boolean {\n return Boolean(knowledgeSearchBase(env) && env.RUNPOD_ASSISTANT_API_KEY);\n}\n\n/** Validate tool or route input. Returns the request or a client-facing error. */\nexport function parseSearchRequest(\n raw: Record<string, unknown>\n): { request: SearchRequest } | { error: string } {\n if (typeof raw.query !== 'string' || !raw.query.trim()) {\n return { error: 'query must be a non-empty string.' };\n }\n if (raw.query.length > MAX_QUERY_CHARS) {\n return { error: `query exceeds ${MAX_QUERY_CHARS} characters.` };\n }\n const request: SearchRequest = { query: raw.query };\n if (raw.namespaces !== undefined) {\n if (\n !Array.isArray(raw.namespaces) ||\n raw.namespaces.length === 0 ||\n !raw.namespaces.every((ns) =>\n (SEARCH_NAMESPACES as readonly unknown[]).includes(ns)\n )\n ) {\n return {\n error: `namespaces must be a non-empty list of: ${SEARCH_NAMESPACES.join(', ')}.`,\n };\n }\n request.namespaces = raw.namespaces as string[];\n }\n if (raw.limit !== undefined) {\n if (\n typeof raw.limit !== 'number' ||\n !Number.isInteger(raw.limit) ||\n raw.limit < 1 ||\n raw.limit > MAX_SEARCH_LIMIT\n ) {\n return {\n error: `limit must be an integer from 1 to ${MAX_SEARCH_LIMIT}.`,\n };\n }\n request.limit = raw.limit;\n }\n return { request };\n}\n\n/** Call /v1/search with the service key, retrying capacity rejections. */\nexport async function searchKnowledge(\n request: SearchRequest,\n opts: SearchKnowledgeOptions = {}\n): Promise<SearchOutcome> {\n const env = opts.env ?? process.env;\n const doFetch = opts.fetch ?? fetch;\n const sleep =\n opts.sleep ??\n ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));\n const now = opts.now ?? Date.now;\n if (!searchConfigured(env)) {\n return {\n status: 503,\n body: { error: 'Knowledge search is not configured on this server.' },\n };\n }\n const url = `${knowledgeSearchBase(env)}/v1/search`;\n // Built once: every attempt sends the same request.\n const init = {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${env.RUNPOD_ASSISTANT_API_KEY}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ ...request, source: 'runpod-mcp' }),\n };\n const startedAt = now();\n for (let attempt = 1; ; attempt++) {\n try {\n const res = await doFetch(url, {\n ...init,\n signal: AbortSignal.timeout(ATTEMPT_TIMEOUT_MS),\n });\n if (res.ok) {\n // A non-JSON 200 (proxy page, truncated body) is an upstream fault,\n // not an unreachable one.\n const data = (await res\n .json()\n .catch(() => null)) as Partial<SearchResponse> | null;\n if (!data) {\n console.warn('knowledge_search_failed status=200 invalid_json');\n return {\n status: 502,\n body: { error: 'Runpod knowledge search failed.' },\n };\n }\n return {\n status: 200,\n body: {\n text: String(data.text ?? ''),\n totalResults: Number(data.totalResults ?? 0),\n failedNamespaces: Array.isArray(data.failedNamespaces)\n ? data.failedNamespaces\n : [],\n },\n };\n }\n const text = await res.text();\n const retryable =\n res.status === 503 || res.status === 429 || PLATFORM_LIMIT.test(text);\n if (!retryable) {\n // 400 is the caller's input; anything else is ours to fix, and the\n // caller cannot act on the upstream detail.\n console.warn(`knowledge_search_failed status=${res.status}`);\n return res.status === 400\n ? { status: 400, body: { error: errorField(text) } }\n : { status: 502, body: { error: 'Runpod knowledge search failed.' } };\n }\n } catch (error) {\n console.warn(\n `knowledge_search_unreachable ${error instanceof Error ? error.name : 'error'}`\n );\n return UNREACHABLE;\n }\n const delay = Math.random() * BASE_DELAY_MS * 2 ** (attempt - 1);\n if (attempt >= ATTEMPTS || now() - startedAt + delay > RETRY_DEADLINE_MS) {\n return AT_CAPACITY;\n }\n await sleep(delay);\n }\n}\n\nfunction errorField(text: string): string {\n try {\n const parsed = JSON.parse(text) as { error?: unknown };\n if (typeof parsed.error === 'string') return parsed.error;\n } catch {\n // Not JSON: fall through to the generic message.\n }\n return 'Invalid search request.';\n}\n\nconst HOSTED_CLIENT_TIMEOUT_MS = 55_000;\n\n/** stdio: search through the hosted server's POST /api/search (route.ts). */\nexport function hostedSearch(\n searchUrl: string,\n doFetch: typeof fetch = fetch\n): SearchFn {\n return async (request, apiKey) => {\n try {\n const res = await doFetch(searchUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(HOSTED_CLIENT_TIMEOUT_MS),\n });\n const body = (await res.json().catch(() => null)) as\n | SearchOutcome['body']\n | null;\n return body\n ? { status: res.status, body }\n : {\n status: 502,\n body: { error: `Runpod knowledge search returned ${res.status}.` },\n };\n } catch {\n return UNREACHABLE;\n }\n };\n}\n","// ============== HOSTED CREDENTIAL PRE-FLIGHT ==============\n// The hosted HTTP server forwards the caller's Bearer token straight to the\n// Runpod API. When that credential dies mid-session (the OAuth-minted key\n// is revoked), every tool call fails upstream with a 401 — but the\n// MCP SDK wraps thrown tool errors into a 200 JSON-RPC tool result, so the\n// client never sees an HTTP 401 and never re-runs its OAuth flow. The user is\n// stuck with bare \"Unauthorized\" tool errors until they manually reconnect.\n//\n// This module verifies the credential BEFORE the MCP request is handled, so\n// a dead credential turns into a proper HTTP 401 + WWW-Authenticate response\n// (src/http.ts writeUnauthorized) — the signal OAuth-capable MCP clients use\n// to re-authenticate automatically.\n//\n// Verification is one authenticated `myself { id }` GraphQL query. Observed live:\n// - never-valid key → HTTP 401\n// - anonymous (no ident) → HTTP 200 with `myself: null`\n// - valid key → HTTP 200 with `myself.id`\n//\n// NOT yet observed: what a once-valid, since-REVOKED key returns. The assumption\n// is HTTP 401, same as a key that never existed — but if it instead answers\n// `{data: null, errors: [...]}` that lands in the indeterminate branch below and\n// the gate fails open, silently never firing for the case it exists for. Probe a\n// genuinely revoked key to settle it.\n// Verdicts are cached in-memory by token hash (never the raw token) so a warm\n// instance adds no per-request latency: valid verdicts live for a few minutes,\n// invalid ones briefly (a just-reauthorized user shouldn't wait long). Network\n// failures and 5xx responses FAIL OPEN — the request proceeds and the tools\n// surface the real upstream error — so an auth-backend blip can't take down\n// the whole server.\n\nimport { createHash } from 'node:crypto';\n\n// `unknown` is the fail-open case: the request proceeds, but it is a GUESS and is\n// never cached — caching one lets a revoked credential skip the 401 for a full\n// TTL, which is the behaviour this module exists to remove.\nexport type CredentialVerdict =\n // accountId is the probe's `myself.id` — the stable account identity behind\n // the token. Carried so consumers (anonymous analytics) can identify a USER\n // across key rotations without any additional API call; may be absent when\n // the check was skipped or failed open.\n | { status: 'valid'; accountId?: string }\n | { status: 'invalid'; reason: string }\n | { status: 'unknown' };\n\nexport type CredentialChecker = (token: string) => Promise<CredentialVerdict>;\n\n// A checker plus the hook needed to correct a stale verdict (see invalidate).\nexport interface CredentialCheckerHandle {\n verify: CredentialChecker;\n // Drop a cached verdict. Called when a tool's own upstream call 401s, which\n // proves the cached \"valid\" wrong sooner than its TTL would.\n invalidate: (token: string) => void;\n}\n\n// Named AuthProbeFetch/AuthProbeResponse, not FetchLike: kept distinct from\n// the fetch-shaped types the specgen clients use, since this probe needs only\n// this narrow shape.\ninterface AuthProbeResponse {\n ok: boolean;\n status: number;\n json(): Promise<unknown>;\n}\n\ntype AuthProbeFetch = (\n url: string,\n init: {\n method: string;\n headers: Record<string, string>;\n body: string;\n signal?: AbortSignal;\n }\n) => Promise<AuthProbeResponse>;\n\n// A valid verdict is short-lived on purpose. It bounds how long a key revoked\n// mid-session keeps passing the gate and failing upstream instead — the exact\n// experience this module exists to remove — for the cost of one cheap query a\n// minute per active token.\nconst VALID_TTL_MS = 60_000;\nconst INVALID_TTL_MS = 30_000;\n// The pre-flight blocks the MCP request, so a slow auth backend must not be\n// able to hold it open. Without this the request hangs until the platform's own\n// limit (Vercel maxDuration 60s) turns it into a 504 — failing OPEN covers an\n// erroring backend but not a slow one. Mirrors the old backend resolver's probe deadline.\nconst REQUEST_TIMEOUT_MS = 4000;\n// Cap so a stream of one-off tokens cannot grow the map without bound: entries\n// expire lazily (only on a repeat lookup of the same token), and an unauthed\n// caller can mint arbitrarily many distinct tokens.\nconst MAX_CACHE_ENTRIES = 1000;\n\nfunction hashToken(token: string): string {\n return createHash('sha256').update(token).digest('hex');\n}\n\nexport function createCredentialChecker(deps: {\n fetch: AuthProbeFetch;\n // Resolved per call so an env change takes effect without a module reload\n // (matches how the tool runtime resolves its base URLs).\n url: () => string;\n now?: () => number;\n validTtlMs?: number;\n invalidTtlMs?: number;\n timeoutMs?: number;\n maxEntries?: number;\n}): CredentialCheckerHandle {\n // Monotonic by default, not Date.now: TTLs are elapsed-time bounds, and a\n // wall-clock step backwards (NTP/VM correction) against an absolute Date.now\n // stamp would silently extend a cached verdict well past its TTL — turning the\n // documented ~60s revocation bound into minutes. Tests inject their own `now`.\n const now = deps.now ?? (() => performance.now());\n const validTtl = deps.validTtlMs ?? VALID_TTL_MS;\n const invalidTtl = deps.invalidTtlMs ?? INVALID_TTL_MS;\n const timeoutMs = deps.timeoutMs ?? REQUEST_TIMEOUT_MS;\n // Clamped so the two call sites below need no degenerate-case guards.\n const maxEntries = Math.max(1, deps.maxEntries ?? MAX_CACHE_ENTRIES);\n // ONE entry per token: either a check in flight or a settled verdict. A\n // settling check writes its result only if the entry it started with is still\n // the one in the map, and invalidate() removes the entry — so a check already\n // running when a credential is rejected cannot resurrect its stale verdict.\n //\n // Insertion-ordered, so this doubles as the LRU: a hit re-inserts to move the\n // key to the back (see verify), and eviction takes the front.\n interface Entry {\n // Set while a check is running; cleared once it settles.\n promise?: Promise<CredentialVerdict>;\n // Set once a DEFINITIVE answer arrives. An indeterminate fail-open is never\n // stored — it is a guess, and caching a guess for a full TTL lets a dead\n // credential skip the 401 for that window, the bug this module exists to fix.\n verdict?: CredentialVerdict;\n expiresAt: number;\n }\n const entries = new Map<string, Entry>();\n\n async function fetchVerdict(token: string): Promise<CredentialVerdict> {\n try {\n const response = await deps.fetch(deps.url(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ query: 'query { myself { id } }' }),\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (response.status === 401) {\n return {\n status: 'invalid',\n reason:\n 'The Runpod API rejected the credential (it may have been revoked).',\n };\n }\n // 403 is NOT a dead credential. This host sits behind Cloudflare, so a\n // WAF/bot block answers 403 with no relation to the token, and a\n // permission-scoped key can 403 while still working for other calls.\n // Treating it as dead sent a 401 back, the client re-ran OAuth, and that\n // MINTS A NEW API KEY on every attempt — a loop that never recovers and\n // fills the user's dashboard with keys. Fail open and let the tool\n // surface the real error.\n if (!response.ok) return { status: 'unknown' };\n\n const result = (await response.json()) as {\n data?: { myself?: { id?: string } | null };\n errors?: unknown[];\n };\n if (result?.data?.myself?.id)\n return { status: 'valid', accountId: result.data.myself.id };\n // A GraphQL response that carries errors is NOT authoritative about the\n // credential. Per the GraphQL spec a resolver failure on the nullable\n // `myself` field answers HTTP 200 with `myself: null` AND an `errors`\n // array — that null reflects a server-side fault, not a dead token. The\n // shape is identical for every caller during a backend blip, so treating\n // it as `invalid` would 401 EVERY valid credential at once and drive every\n // OAuth client into the re-auth key-minting loop the 403 branch above\n // exists to prevent — and it fails closed, which is worse than 403's\n // fail-open. So fail open on any errors; a genuine anonymous token returns\n // a clean `myself: null` with no errors (verified live).\n if (Array.isArray(result?.errors) && result.errors.length > 0) {\n return { status: 'unknown' };\n }\n if (result?.data && result.data.myself === null) {\n // The backend treated the request as anonymous — the token carries no\n // identity, so every downstream call would 401.\n return {\n status: 'invalid',\n reason: 'The credential does not resolve to a Runpod account.',\n };\n }\n // Unrecognized shape (including a bare {data: null}) — fail open.\n return { status: 'unknown' };\n } catch {\n // Network error, or the timeout above aborting — fail open.\n return { status: 'unknown' };\n }\n }\n\n function evictIfFull(): void {\n // Never evict an entry whose check is still in flight. Doing so disowns a\n // registered check — its settle handler then fails the `entries.get(key) ===\n // entry` identity test and drops its verdict — which breaks the one-in-flight-\n // check-per-token invariant that makes last-writer-wins safe. Without this a\n // flood of distinct tokens (each cached as a definitive `invalid`, so they\n // hold the map full) could evict a legitimate user's in-flight check and let\n // a since-revoked key cache as `valid` for a full TTL, and duplicate the\n // upstream call. Only settled entries are evicted, oldest first (insertion\n // order = LRU). If every entry is in flight we allow a brief, bounded\n // overshoot: in-flight count is capped by request concurrency and each check\n // self-clears within the request timeout.\n while (entries.size >= maxEntries) {\n let victim: string | undefined;\n for (const [k, e] of entries) {\n if (!e.promise) {\n victim = k;\n break;\n }\n }\n if (victim === undefined) return;\n entries.delete(victim);\n }\n }\n\n async function verify(token: string): Promise<CredentialVerdict> {\n const key = hashToken(token);\n const existing = entries.get(key);\n\n if (existing?.verdict) {\n if (existing.expiresAt > now()) {\n // Refresh recency so a hot token is not evicted ahead of a cold one.\n entries.delete(key);\n entries.set(key, existing);\n return existing.verdict;\n }\n entries.delete(key);\n } else if (existing?.promise) {\n // Join the check already running for this token rather than duplicating it.\n return existing.promise;\n }\n\n const entry: Entry = { expiresAt: 0 };\n entry.promise = fetchVerdict(token).then((verdict) => {\n // Only RECORD the result if this entry is still the one registered. A\n // different entry means invalidate() removed ours, or a newer check\n // replaced it, so this answer must not be stored — and must not delete the\n // newer entry either. The caller that started this check is still served\n // its own result; only the shared state is protected.\n if (entries.get(key) === entry) {\n if (verdict.status !== 'unknown') {\n entry.verdict = verdict;\n entry.expiresAt =\n now() + (verdict.status === 'valid' ? validTtl : invalidTtl);\n entry.promise = undefined;\n } else {\n entries.delete(key);\n }\n }\n return verdict;\n });\n\n evictIfFull();\n entries.set(key, entry);\n return entry.promise;\n }\n\n return {\n verify,\n invalidate: (token: string) => {\n // Removing the entry is the whole mechanism: a check already in flight can\n // no longer match it on settle, so it cannot resurrect the verdict this\n // call just rejected. Nothing to prune afterwards, so nothing can leak.\n entries.delete(hashToken(token));\n },\n };\n}\n","// ALP journal read-back: POST /api/alp/journal (see docs/agent-learning-protocol.md,\n// \"The tool pair\"). The one read path, for the one route that is readable.\n//\n// SCOPE IS THE TOKEN, NOT THE REQUEST. Identity is resolved from the caller's\n// Bearer key exactly as ingest does, and that resolved id is the ONLY filter\n// sent to the sink. The request body is read for `limit` and nothing else — an\n// `identity` field in it is ignored, so no caller can name whose journal to\n// read. Holding a valid key for an account is the only way to see its journal,\n// and a key holder already has that account's pods and billing.\n//\n// FAIL-CLOSED, CALMLY. Anything that prevents a scoped read (no token verdict,\n// no sink, sink down, unrecognized reply) returns a non-error result with zero\n// entries and a note. It never guesses an identity and never falls back to a\n// wider query. Only a missing or invalid credential is a real 401.\n\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { defaultCredentialChecker } from '../http.js';\nimport { isSinkUrl } from './ingest.js';\n\nexport const DEFAULT_JOURNAL_LIMIT = 20;\nexport const MAX_JOURNAL_LIMIT = 50;\nconst SINK_TIMEOUT_MS = 5_000;\n\nexport interface JournalEntry {\n content: string;\n intention?: string;\n trigger?: string;\n tool?: string;\n receivedAt: string;\n}\n\ninterface VerifyResult {\n status: 'valid' | 'invalid' | 'unknown';\n accountId?: string;\n}\n\nexport interface AlpReadOptions {\n /** Test seams. Production uses the shared checker + global fetch + env. */\n verify?: (token: string) => Promise<VerifyResult>;\n sinkFetch?: typeof fetch;\n env?: Record<string, string | undefined>;\n}\n\n/** The read door sits beside the write door on the same Convex deployment. */\nexport function journalSinkUrl(submitUrl: string): string | null {\n if (!isSinkUrl(submitUrl)) return null;\n const url = new URL(submitUrl);\n url.pathname = '/alp/journal';\n return url.toString();\n}\n\n/** Clamp a caller-supplied limit; anything unusable becomes the default. */\nexport function clampLimit(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) return DEFAULT_JOURNAL_LIMIT;\n return Math.min(Math.max(Math.trunc(n), 1), MAX_JOURNAL_LIMIT);\n}\n\nfunction unavailable(reason: string): Record<string, unknown> {\n return {\n available: false,\n entries: [],\n note: `Journal unavailable (${reason}). Do not retry — continue your task.`,\n };\n}\n\nexport async function handleAlpJournalRead(\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n opts: AlpReadOptions = {}\n): Promise<void> {\n const env = opts.env ?? process.env;\n const send = (code: number, body: unknown) => {\n res.writeHead(code, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(body));\n };\n\n const auth = req.headers.authorization;\n const token = auth?.startsWith('Bearer ') ? auth.slice(7).trim() : undefined;\n if (!token) {\n send(401, {\n available: false,\n entries: [],\n error: 'Authenticate with your Runpod API key as a Bearer token.',\n });\n return;\n }\n\n const body = (req.body && typeof req.body === 'object' ? req.body : {}) as {\n limit?: unknown;\n };\n const limit = clampLimit(body.limit);\n\n const verify = opts.verify ?? defaultCredentialChecker.verify;\n const verdict = await verify(token);\n if (verdict.status === 'invalid') {\n send(401, {\n available: false,\n entries: [],\n error:\n 'This Runpod API key is not valid. Re-authenticate and retry once.',\n });\n return;\n }\n if (verdict.status !== 'valid' || !verdict.accountId) {\n send(200, unavailable('identity could not be resolved right now'));\n return;\n }\n\n const submitUrl = env.ALP_SINK_URL;\n const sinkSecret = env.ALP_SINK_SECRET;\n const readUrl = submitUrl ? journalSinkUrl(submitUrl) : null;\n if (!submitUrl || !sinkSecret) {\n send(200, unavailable('the journal is not configured on this deployment'));\n return;\n }\n if (!readUrl) {\n console.warn('alp_sink_misconfigured');\n send(200, unavailable('the journal is misconfigured on this deployment'));\n return;\n }\n\n try {\n const sinkFetch = opts.sinkFetch ?? fetch;\n const response = await sinkFetch(readUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-ALP-Secret': sinkSecret,\n },\n // The resolved account id, never anything from the request body.\n body: JSON.stringify({ identity: verdict.accountId, limit }),\n signal: AbortSignal.timeout(SINK_TIMEOUT_MS),\n });\n if (!response.ok) {\n console.warn('alp_journal_sink_error', { status: response.status });\n send(200, unavailable('the store did not answer the read'));\n return;\n }\n const sinkBody = (await response.json().catch(() => null)) as {\n ok?: boolean;\n entries?: unknown;\n } | null;\n if (sinkBody?.ok !== true || !Array.isArray(sinkBody.entries)) {\n console.warn('alp_journal_sink_unrecognized', {\n status: response.status,\n });\n send(200, unavailable('the store did not confirm the read'));\n return;\n }\n // Same privacy rule as alp_submit: count, never content.\n console.log(\n 'alp_journal_read',\n JSON.stringify({ entries: sinkBody.entries.length, limit })\n );\n send(200, { available: true, entries: sinkBody.entries as JournalEntry[] });\n } catch {\n console.warn('alp_journal_sink_unreachable');\n send(200, unavailable('the store is unreachable right now'));\n }\n}\n","// ALP tools (Agent Learning Protocol): report_feedback, save_to_journal,\n// ask_question write; read_journal reads back the caller's own journal. See\n// docs/agent-learning-protocol.md, \"The tool pair\".\n//\n// All four are thin clients of the hosted endpoints (POST /api/alp/submit and\n// POST /api/alp/journal) — the npm package holds no storage credentials, so\n// both transports go there with the caller's own key. The journal is the ONE\n// route that is served back, and only to the identity that wrote it; feedback\n// and questions return nothing, and every description and response says so\n// honestly — an ambiguous ack is a false affordance the model may plan around\n// (waiting, polling, re-asking).\n//\n// FAIL-SOFT: these tools are side quests. Whatever goes wrong, the result is\n// a calm non-error saying the entry was not recorded and not to retry —\n// never a tool failure that derails the agent's actual task.\n\nimport type { AlpRoute } from '../../alp/ingest.js';\nimport {\n clampLimit,\n DEFAULT_JOURNAL_LIMIT,\n MAX_JOURNAL_LIMIT,\n type JournalEntry,\n} from '../../alp/read.js';\nimport type { ToolContext } from '../context.js';\nimport type { CuratedTool } from '../types.js';\nimport { ok } from './util.js';\nimport { readOnly, write } from './annotations.js';\n\n// HOSTED-ONLY by decision (2026-09-03): src/http.ts registers these tools\n// whenever the deployment configures its sink (ALP_SINK_URL + ALP_SINK_SECRET);\n// the stdio entrypoint never does, so local users cannot enable them. Absent\n// from tools/list is the disabled state — absent is unambiguous and free,\n// present-but-failing costs context and invites retries.\n\nconst NOT_RECORDED =\n 'The entry was NOT recorded. Do not retry — continue your task.';\n\nasync function submit(\n ctx: ToolContext,\n ingestUrl: string,\n route: AlpRoute,\n args: Record<string, unknown>,\n extra: {\n transport: 'stdio' | 'http';\n harness?: string;\n harnessSource?: string;\n }\n): Promise<{ recorded: boolean }> {\n try {\n const response = await fetch(ingestUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(ctx.apiKey ? { Authorization: `Bearer ${ctx.apiKey}` } : {}),\n },\n body: JSON.stringify({\n route,\n content: args.content,\n intention: args.intention,\n modelType: args.modelType,\n severity: args.severity,\n tool: args.tool,\n workaround: args.workaround,\n trigger: args.trigger,\n ...extra,\n }),\n signal: AbortSignal.timeout(10_000),\n });\n const body = (await response.json().catch(() => ({}))) as {\n recorded?: boolean;\n };\n return { recorded: response.ok && body.recorded === true };\n } catch {\n return { recorded: false };\n }\n}\n\n// The read endpoint sits beside the write endpoint on the same deployment.\n// Derived, not configured, so the two can never point at different servers.\nexport function journalReadUrl(ingestUrl: string): string {\n return ingestUrl.replace(/\\/submit$/, '/journal');\n}\n\nasync function readJournal(\n ctx: ToolContext,\n readUrl: string,\n limit: number\n): Promise<{ available: boolean; entries: JournalEntry[] }> {\n try {\n const response = await fetch(readUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(ctx.apiKey ? { Authorization: `Bearer ${ctx.apiKey}` } : {}),\n },\n // Only the page size crosses the wire. Whose journal this is comes from\n // the Bearer token, resolved server-side — there is no argument for it.\n body: JSON.stringify({ limit }),\n signal: AbortSignal.timeout(10_000),\n });\n const body = (await response.json().catch(() => ({}))) as {\n available?: boolean;\n entries?: unknown;\n };\n if (\n !response.ok ||\n body.available !== true ||\n !Array.isArray(body.entries)\n ) {\n return { available: false, entries: [] };\n }\n return { available: true, entries: body.entries as JournalEntry[] };\n } catch {\n return { available: false, entries: [] };\n }\n}\n\n// Shared input schema. `content` stays the only required field — fewer required\n// args means a higher call-through rate (design doc, Fields) — and everything\n// added since is optional and mechanical, answerable from what the agent\n// already did rather than from fresh reasoning.\n//\n// The first 21 production submissions showed prose was never the shortfall:\n// 233-1794 characters each, `intention` filled on 20 of 21, several tracing a\n// contradiction across five paired reads. What was missing was any dimension to\n// sort or route them by, so a total blocker sat beside a docs nit and telling\n// them apart meant opening both. Hence structure, not longer prose.\nconst SEVERITY = ['blocked', 'degraded', 'cosmetic'] as const;\n\nconst TOOL_FIELD = {\n type: 'string' as const,\n description:\n '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.',\n};\n\nconst alpInputSchema = (\n contentDescription: string,\n extra: Record<string, unknown> = {}\n) => ({\n type: 'object' as const,\n properties: {\n content: {\n type: 'string' as const,\n description: contentDescription,\n },\n intention: {\n type: 'string' as const,\n description:\n 'One short sentence: what you were trying to accomplish when this came up.',\n },\n ...extra,\n modelType: {\n type: 'string' as const,\n description:\n 'Your best identification of the model you are running as, and the product running it if you know that too — 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.',\n },\n },\n required: ['content'],\n});\n\nexport interface AlpToolsOptions {\n ingestUrl: string;\n transport: 'stdio' | 'http';\n harness?: string;\n harnessSource?: 'client_info' | 'user_agent';\n}\n\nexport function createAlpTools(opts: AlpToolsOptions): CuratedTool[] {\n // Read from `opts` at CALL time, not creation time: on stdio the harness\n // (MCP clientInfo) only arrives with the initialize handshake, after these\n // tools are built — the server updates opts.harness then.\n const extra = () => ({\n transport: opts.transport,\n harness: opts.harness,\n harnessSource: opts.harnessSource,\n });\n\n const reportFeedback: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'report_feedback',\n annotations: write,\n description:\n '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 — 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 — 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.',\n inputSchema: alpInputSchema(\n 'The observation: what happened, what you expected, and the exact error or response text if you have it.',\n {\n severity: {\n type: 'string' as const,\n enum: [...SEVERITY],\n description:\n 'How much this cost you: blocked (you could not complete the task at all), degraded (you completed it the slow or awkward way), cosmetic (correct but confusing or badly worded). Report the effect on your task, not how bad the underlying bug looks.',\n },\n tool: TOOL_FIELD,\n workaround: {\n type: 'string' as const,\n description:\n 'What you did instead, if anything worked. Leave this out when nothing did — an absent workaround is read as fully blocked.',\n },\n }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'feedback',\n args,\n extra()\n );\n return ok({\n recorded,\n note: recorded\n ? 'Recorded for internal review. No reply will arrive in this session — continue your task.'\n : NOT_RECORDED,\n });\n },\n };\n\n const saveToJournal: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'save_to_journal',\n annotations: write,\n description:\n \"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 — an entry with no stated trigger cannot be surfaced to the session that needs it. Never include API keys or secrets.\",\n inputSchema: alpInputSchema(\n 'The learning, stated so a future agent can act on it: the situation, what turned out to be true, and how you verified it.',\n {\n trigger: {\n type: 'string' as const,\n description:\n 'The situation in which a future agent should recall this — the circumstances that make it relevant, not a restatement of the lesson. This is what makes the entry findable later, so write it as the condition you would want matched.',\n },\n tool: TOOL_FIELD,\n }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'journal',\n args,\n extra()\n );\n return ok({\n recorded,\n note: recorded\n ? \"Saved to this account's private journal. A future session on this account can read it back with read_journal. Continue your task.\"\n : NOT_RECORDED,\n });\n },\n };\n\n const askQuestion: CuratedTool = {\n // FAIL-SOFT applies to the argument gate too: a misnamed optional field\n // is ignored, never a 400 that derails the task the agent is actually on.\n lenientArguments: true,\n name: 'ask_question',\n annotations: write,\n description:\n 'Record a question about Runpod that you could not answer with the available tools, skills, and docs. NO ANSWER WILL COME BACK — 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 — if you have no Runpod question, do not call it.',\n inputSchema: alpInputSchema(\n 'The question, with enough context that someone reading it later understands what you were blocked on.',\n { tool: TOOL_FIELD }\n ),\n handler: async (ctx, args) => {\n const { recorded } = await submit(\n ctx,\n opts.ingestUrl,\n 'question',\n args,\n extra()\n );\n return ok({\n recorded,\n answer: null,\n note: recorded\n ? 'Recorded. No answer is coming — not now, not later in this session. Do not wait, poll, or retry. Check list-guides and read-guide for existing guidance and continue with your best judgment.'\n : NOT_RECORDED,\n });\n },\n };\n\n const readUrl = journalReadUrl(opts.ingestUrl);\n const readJournalTool: CuratedTool = {\n lenientArguments: true,\n name: 'read_journal',\n annotations: readOnly,\n description:\n \"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 — 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.\",\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'integer' as const,\n minimum: 1,\n maximum: MAX_JOURNAL_LIMIT,\n description: `How many of the newest entries to return. Default ${DEFAULT_JOURNAL_LIMIT}, maximum ${MAX_JOURNAL_LIMIT}.`,\n },\n },\n },\n handler: async (ctx, args) => {\n const { available, entries } = await readJournal(\n ctx,\n readUrl,\n clampLimit(args.limit)\n );\n return ok({\n available,\n count: entries.length,\n entries,\n note: !available\n ? 'The journal could not be read right now. Do not retry — continue your task.'\n : entries.length === 0\n ? 'This account has no journal entries yet. Continue your task; save what you learn with save_to_journal.'\n : \"These are earlier sessions' own notes, not verified documentation: confirm anything time-sensitive (stock, prices, versions) with a live read before acting on it.\",\n });\n },\n };\n\n return [reportFeedback, saveToJournal, askQuestion, readJournalTool];\n}\n","// search-docs: semantic search over Runpod's documentation, curated support\n// knowledge, blog and runpod.io site, through the runpod-assistant knowledge\n// index (src/search/knowledge.ts).\n//\n// The tool takes its search function from the transport: the hosted server\n// searches in-process with its service key (searchKnowledge); stdio calls the\n// hosted POST /api/search with the caller's own key (hostedSearch). Registered\n// only when a search function is configured, so a deployment without one does\n// not list it.\n\nimport {\n MAX_QUERY_CHARS,\n MAX_SEARCH_LIMIT,\n parseSearchRequest,\n SEARCH_NAMESPACES,\n type SearchFn,\n} from '../../search/knowledge.js';\nimport type { CuratedTool } from '../types.js';\nimport { readOnly } from './annotations.js';\nimport { badRequest } from './util.js';\n\nexport function createSearchDocsTool(search: SearchFn): CuratedTool {\n return {\n name: 'search-docs',\n annotations: readOnly,\n recordedArguments: ['limit'],\n description:\n '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.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n maxLength: MAX_QUERY_CHARS,\n description: 'The question, in natural language.',\n },\n namespaces: {\n type: 'array',\n items: { type: 'string', enum: [...SEARCH_NAMESPACES] },\n minItems: 1,\n description:\n 'Sources to search: docs (docs.runpod.io), knowledge (curated support answers), blog, site (runpod.io pages). Default: docs, knowledge, blog.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: MAX_SEARCH_LIMIT,\n description: 'Most passages to return. Default 8.',\n },\n },\n required: ['query'],\n additionalProperties: false,\n },\n handler: async (ctx, args) => {\n const parsed = parseSearchRequest(args);\n if ('error' in parsed) return badRequest(parsed.error);\n const outcome = await search(parsed.request, ctx.apiKey);\n return {\n ok: outcome.status === 200,\n status: outcome.status,\n payload: outcome.body,\n };\n },\n };\n}\n"],"mappings":"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","names":["SERVER_NAME","p","homedir","home","spinner","subcommand","failed","import_child_process","import_server","import_types","value","resolve","baseUrl","fetch","resolve","resolve","branches","words","import_node_crypto","DEFAULT_TIMEOUT_MS","DEFAULT_TIMEOUT_MS","baseUrl","path","import_node_crypto","import_node_crypto","runWizard"]}
|