UNPKG

@postman/postman-mcp-server

Version:

Postman MCP Server — connect AI agents (Claude Code, Cursor, VS Code Copilot, Gemini CLI) to your Postman collections, specifications, and environments via Model Context Protocol (MCP)

216 lines (215 loc) • 8.97 kB
import { z } from 'zod'; import { ContentType } from '../clients/postman.js'; import { asMcpError, McpError } from './utils/toolHelpers.js'; export const method = 'createSdk'; export const title = 'Generate an SDK'; export const description = 'Starts an SDK generation job for one language from a collection or a specification.\nReturns 202 with a job record — the SDK does not exist yet. Poll getSdk and wait for\n\\`buildStatus\\` to reach \\`succeeded\\` before trying to download it. The request body\ndepends on the \\`language\\` you pick, so send only the properties that language accepts.\nOne call generates one language; call it once per language rather than expecting a\nbundle. Requires a Postman Team or Enterprise plan.\n'; export const parameters = z.object({ source: z .object({ type: z.enum(['collection', 'spec']).describe('The type of Postman element.'), id: z.string().describe('The ID of the Postman Collection or specification in Postman.'), }) .describe('The collection or specification that the SDK is generated from.'), language: z .enum(['typescript', 'python', 'go', 'java', 'csharp', 'ruby', 'php', 'kotlin', 'rust', 'cli']) .describe('The target output language for the generated SDK.'), sdkVersion: z .string() .describe("An optional override for the SDK version. If this isn't provided, the next version is resolved from the latest auto-pull request.") .optional(), authors: z .array(z .object({ name: z.string().describe("The author's name."), email: z.string().email().describe("The author's email address.").optional(), }) .describe('Information about the author of the generated SDK.')) .describe('A list of package authors written into the generated manifest.') .optional(), retry: z .object({ enabled: z .boolean() .describe('If true, the generated SDK includes retry behavior.') .default(true), maxAttempts: z .number() .int() .describe('The maximum number of attempts to try before giving up.') .default(3), retryDelay: z .number() .int() .describe('The base wait between attempts, in milliseconds.') .default(150), maxDelay: z .number() .int() .gte(0) .describe('The maximum wait between attempts, in milliseconds.') .optional(), backOffFactor: z .number() .gt(0) .describe('The exponent base used to compute exponential backoff between attempts.') .optional(), retryDelayJitter: z .number() .int() .gte(0) .describe('The maximum random jitter added to wait times, in milliseconds.') .optional(), httpCodesToRetry: z .array(z.number().int().gte(200).lte(599).describe('An HTTP status code.')) .describe('A list of HTTP status codes that the SDK attempts its retries on.') .optional(), httpMethodsToRetry: z .array(z.preprocess((v) => (typeof v === 'string' ? v.toUpperCase() : v), z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE']))) .describe('A list of the HTTP methods that the SDK attempts its retries on.') .optional(), }) .describe("Retry behavior baked into the generated SDK's HTTP client. A power-user option; sensible defaults apply for any field left unset.") .optional(), typescriptOptions: z .object({ npmOrg: z .string() .describe("An npm organization's scope. Don't include a trailing slash.") .optional(), npmName: z.string().describe("The unscoped npm package's name.").optional(), }) .describe('TypeScript-specific SDK generation options.') .optional(), pythonOptions: z .object({ pypiPackageName: z.string().describe("The PyPI package's name.").optional() }) .describe('Python-specific SDK generation options.') .optional(), goOptions: z .object({ goModuleName: z .string() .describe('The Go module path written into the `go.mod` definition file.') .optional(), }) .describe('Go-specific SDK generation options.') .optional(), javaOptions: z .object({ groupId: z .string() .describe('The Maven group ID written into the `pom.xml` dependencies file.') .optional(), artifactId: z .string() .describe('The Maven artifact ID written into the `pom.xml` dependencies file.') .optional(), }) .describe('Java-specific SDK generation options.') .optional(), csharpOptions: z .object({ packageId: z.string().describe("The NuGet package's ID.").optional() }) .describe('C#-specific SDK generation options.') .optional(), rubyOptions: z .object({ gemName: z.string().describe("The RubyGems gem's name.").optional() }) .describe('Ruby-specific generation options.') .optional(), phpOptions: z .object({ packageName: z .string() .describe('The composer package name, in `vendor/package` format.') .optional(), }) .describe('PHP-specific SDK generation options.') .optional(), kotlinOptions: z .object({ groupId: z .string() .describe('The Maven group ID written into the `pom.xml` dependencies file.') .optional(), artifactId: z .string() .describe('The Maven artifact ID written into the `pom.xml` dependencies file.') .optional(), }) .describe('Kotlin-specific SDK generation options.') .optional(), rustOptions: z .object({ packageName: z.string().describe("The crates.io package's name.").optional() }) .describe('Rust-specific SDK generation options.') .optional(), cliOptions: z .object({ goModuleName: z.string().describe("The Go module's path for the generated CLI.").optional(), }) .describe('CLI-specific SDK generation options.') .optional(), }); export const annotations = { title: 'Generate an SDK', readOnlyHint: false, openWorldHint: true, destructiveHint: false, idempotentHint: false, }; export async function handler(args, extra) { try { const endpoint = `/sdks`; const query = new URLSearchParams(); const url = query.toString() ? `${endpoint}?${query.toString()}` : endpoint; const bodyPayload = {}; if (args.source !== undefined) bodyPayload.source = args.source; if (args.language !== undefined) bodyPayload.language = args.language; if (args.sdkVersion !== undefined) bodyPayload.sdkVersion = args.sdkVersion; if (args.authors !== undefined) bodyPayload.authors = args.authors; if (args.retry !== undefined) bodyPayload.retry = args.retry; if (args.typescriptOptions !== undefined) bodyPayload.typescriptOptions = args.typescriptOptions; if (args.pythonOptions !== undefined) bodyPayload.pythonOptions = args.pythonOptions; if (args.goOptions !== undefined) bodyPayload.goOptions = args.goOptions; if (args.javaOptions !== undefined) bodyPayload.javaOptions = args.javaOptions; if (args.csharpOptions !== undefined) bodyPayload.csharpOptions = args.csharpOptions; if (args.rubyOptions !== undefined) bodyPayload.rubyOptions = args.rubyOptions; if (args.phpOptions !== undefined) bodyPayload.phpOptions = args.phpOptions; if (args.kotlinOptions !== undefined) bodyPayload.kotlinOptions = args.kotlinOptions; if (args.rustOptions !== undefined) bodyPayload.rustOptions = args.rustOptions; if (args.cliOptions !== undefined) bodyPayload.cliOptions = args.cliOptions; const options = { body: JSON.stringify(bodyPayload), contentType: ContentType.Json, headers: extra.headers, }; const result = await extra.client.post(url, options); return { content: [ { type: 'text', text: `${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}`, }, ], }; } catch (e) { if (e instanceof McpError) { throw e; } throw asMcpError(e); } }