Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postman",
"version": "1.3.0",
"version": "1.4.0",
"description": "Full API lifecycle management for Claude Code. Sync collections, generate client code, discover APIs, run tests, create mocks, publish docs, and audit security. Powered by the Postman MCP Server.",
"author": {
"name": "Postman",
Expand Down
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,23 @@ is cut by tagging the matching `vX.Y.Z` (see [Releasing](#releasing)).

## [Unreleased]

## [1.4.0] - 2026-08-02

### Added

- `/postman:use-local` and `/postman:use-remote` commands — toggle which Postman
MCP Server this plugin talks to by rewriting the bundled `.mcp.json` in place.
`use-remote` points it at the hosted server (`https://mcp.postman.com/mcp`, Full
mode, OAuth); `use-local` points it at the local stdio package
(`npx @postman/postman-mcp-server@latest`, which requires `POSTMAN_API_KEY`).
Added for cross-plugin command parity with the Cursor and Antigravity plugins.
- `/postman:generate-client` command — generates typed client code from a
Postman collection. This is the inverse of `/postman:generate-spec` (which
authors an OpenAPI spec from code). Reads the collection through the MCP
codegen tools and writes a production-ready client matching the project's
language and conventions. Requires Full or Code MCP mode (this plugin
defaults to Full).

## [1.3.0] - 2026-07-20

### Added
Expand Down Expand Up @@ -72,7 +89,8 @@ Releases are automated by `.github/workflows/release.yml`. To cut a release:
The workflow verifies the tag matches `plugin.json`, extracts the matching
CHANGELOG section, and publishes a GitHub Release with those notes.

[Unreleased]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.3.0...HEAD
[Unreleased]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.4.0...HEAD
[1.4.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.0.0...v1.1.0
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ That's it. The plugin auto-configures the Postman MCP Server, verifies your conn
| `/postman:docs` | Generate, improve, and publish API documentation |
| `/postman:security` | Security audit against OWASP API Top 10 |
| `/postman:learn` | Search the Postman Learning Center for how-to guidance and suggested workflows (Full mode) |
| `/postman:generate-client` | Generate typed client code from a Postman collection (Full or Code mode) |
| `/postman:use-remote` | Switch the plugin to the hosted MCP Server (`mcp.postman.com`, Full mode, OAuth) |
| `/postman:use-local` | Switch the plugin to the local stdio MCP Server (`npx @postman/postman-mcp-server`, needs `POSTMAN_API_KEY`) |

## What You Can Do

Expand Down
117 changes: 117 additions & 0 deletions commands/generate-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
description: Generate typed client code from a Postman collection. Reads your private APIs and writes production-ready client code that matches your project conventions.
allowed-tools: Bash, Read, Write, Glob, Grep, mcp__postman__searchPostmanElements, mcp__postman__getWorkspaces, mcp__postman__getCollections, mcp__postman__getCollection, mcp__postman__getCollectionFolder, mcp__postman__getCollectionRequest, mcp__postman__getCollectionResponse, mcp__postman__getEnvironment, mcp__postman__getSpecDefinition, mcp__postman__getCodeGenerationInstructions
---

# Generate Client Code

Generate typed client code from a Postman collection. Reads your private APIs and writes production-ready client code that matches your project's language and conventions.

This is the inverse of `/postman:generate-spec` (which authors an OpenAPI spec *from* your code): here the collection is the source of truth and code is the output.

## Prerequisites

The Postman MCP Server must be connected. If MCP tools aren't available, tell the user: "Run `/postman:setup` to configure the Postman MCP Server."

This command's codegen tools (`getCodeGenerationInstructions`, the collection readers) require **Full** or **Code** MCP mode. This plugin defaults to Full mode, so it works out of the box; if the tools are missing, run `/postman:use-remote` (or unset `POSTMAN_MCP_MODE`) and restart Claude Code.

## Workflow

### Step 1: Find the API

1. Call `searchPostmanElements` with the API name and `entityType: collections`. Set `ownership` based on the user's intent:
- `ownership: organization` (default) for the user's org resources. To restrict to the trusted Private API Network, add `filters: {"$and":[{"privateNetwork":{"$eq":true}}]}`.
- `ownership: external` for third-party public APIs.
- `ownership: all` to search everywhere.
2. If results are sparse, broaden the search (widen `ownership`, relax filters) or fall back to `getWorkspaces` + `getCollections` with the `workspace` parameter and `name` filter.
3. Match by name or ask the user which collection to generate code from.
4. Call `getCollection` (full model) to get the complete collection with all requests, bodies, and params.
5. Call `getSpecDefinition` if a linked spec exists (richer type information).
6. Call `getCodeGenerationInstructions` for the MCP server's recommended codegen workflow.

### Step 2: Understand the API Shape

For the target collection:
1. Call `getCollectionFolder` for each folder to understand resource grouping.
2. Call `getCollectionRequest` for each relevant endpoint to get:
- HTTP method and URL
- Request headers and auth requirements
- Request body schema
- Path and query parameters
3. Call `getCollectionResponse` for each request to get:
- Response status codes
- Response body shapes (for typing)
- Error response formats
4. Call `getEnvironment` to understand base URLs and variables.

### Step 3: Detect Project Language

If the user doesn't specify a language, detect it from the project:

| File | Language |
|------|----------|
| `package.json` + `tsconfig.json` | TypeScript |
| `package.json` (no tsconfig) | JavaScript |
| `requirements.txt` or `pyproject.toml` | Python |
| `go.mod` | Go |
| `Cargo.toml` | Rust |
| `pom.xml` or `build.gradle` | Java |
| `*.csproj` | C# |
| `Gemfile` | Ruby |

### Step 4: Generate Code

Generate a client that includes:

- **Typed client class or module** with one method per endpoint
- **Request/response types** from the collection schemas and examples
- **Authentication handling** based on collection auth config (Bearer, API key, OAuth2)
- **Error handling** with typed error responses from documented error schemas
- **Environment-based configuration** (base URL from env vars)
- **Pagination support** if the API uses cursor or offset pagination

The generated code should:
- Match the project's existing conventions (imports, formatting, naming style)
- Include JSDoc, docstrings, or doc comments from collection descriptions
- Use the project's existing HTTP library if one is present (axios, fetch, requests, reqwest, etc.)
- Use proper camelCase/snake_case matching the target language conventions
- Handle query parameters, path parameters, headers, and request bodies correctly

### Step 5: Write and Present

Write the generated code to an appropriate location in the project:
- TypeScript/JavaScript: `src/clients/<api-name>.ts` or `src/lib/<api-name>.ts`
- Python: `src/clients/<api_name>.py` or `<package>/clients/<api_name>.py`
- Go: `pkg/clients/<apiname>.go` or `internal/clients/<apiname>.go`

Present a summary:

```
Generated: src/clients/users-api.ts

Endpoints covered:
GET /users -> getUsers(filters)
GET /users/{id} -> getUser(id)
POST /users -> createUser(data)
PUT /users/{id} -> updateUser(id, data)
DELETE /users/{id} -> deleteUser(id)

Types generated:
User, CreateUserRequest, UpdateUserRequest,
UserListResponse, ApiError

Auth: Bearer token (from USERS_API_TOKEN env var)
Base URL: from USERS_API_BASE_URL env var
```

## Error Handling

| Error | Response |
|-------|----------|
| MCP not configured | "Run `/postman:setup` to configure the Postman MCP Server." |
| Codegen tools missing (wrong mode) | "Client generation requires Full or Code MCP mode. Run `/postman:use-remote` (or unset `POSTMAN_MCP_MODE`) and restart Claude Code." |
| Collection not found | "I didn't find a collection matching that name. Run `/postman:search` to see what's available." |
| No requests in collection | "This collection is empty. Add requests in Postman first, or use `/postman:sync` to create from a spec." |
| Can't detect language | "I can't detect the project language. What language should I generate the client in?" |
| Missing auth config | "This collection doesn't specify an auth method. I'll generate the client without auth. You can add it later." |
| Spec not available | "No linked spec found. I'll generate types from the collection's saved examples and request bodies." |
66 changes: 66 additions & 0 deletions commands/use-local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
description: Switch this plugin's Postman MCP Server to the LOCAL stdio package (npx @postman/postman-mcp-server@latest). Requires POSTMAN_API_KEY.
allowed-tools: Bash, Read, Write
---

# Use Local MCP Server

Point this plugin at the **local** Postman MCP Server — the stdio package run via `npx @postman/postman-mcp-server@latest` — instead of Postman's hosted remote server. This rewrites the plugin's own `.mcp.json` in place, changing only the transport (remote → local). The local server authenticates with a `POSTMAN_API_KEY` read from your environment (there is no OAuth for the local package).

Switch back to the hosted server at any time with `/postman:use-remote`.

## Workflow

### Step 1: Locate this plugin's `.mcp.json`

The file to rewrite is the `.mcp.json` bundled with this plugin (it lives at the plugin's root, next to `.claude-plugin/`). Find it and show the current content:

```bash
for f in "$CLAUDE_PLUGIN_ROOT/.mcp.json" "$HOME"/.claude/plugins/*/.mcp.json "$HOME"/.claude/plugins/*/*/.mcp.json; do
[ -f "$f" ] || continue
if grep -q '"postman"' "$f"; then echo "FOUND: $f"; echo "--- current content ---"; cat "$f"; echo; fi
done
```

Use the `FOUND:` path as the target file to edit. If nothing is found, stop and ask the user for the path to the installed plugin's `.mcp.json`.

### Step 2: Verify the API key

The local server reads a Postman API key from the environment. Check it:

```bash
if [ -n "$POSTMAN_API_KEY" ]; then echo "POSTMAN_API_KEY is set"; else echo "POSTMAN_API_KEY is NOT set"; fi
```

If it is **not** set, tell the user to run `export POSTMAN_API_KEY=PMAK-your-key-here` and add that line to `~/.zshrc` or `~/.bashrc` so it persists, then restart the shell before continuing. They can generate a key at https://go.postman.co/settings/me/api-keys. Never hardcode the key into the file — it is read from the environment.

### Step 3: Overwrite the target `.mcp.json`

Write exactly this content to the `FOUND:` path:

```json
{
"mcpServers": {
"postman": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@postman/postman-mcp-server@latest"],
"env": {
"POSTMAN_API_KEY": "${POSTMAN_API_KEY}"
}
}
}
}
```

The `${POSTMAN_API_KEY}` reference is expanded by Claude Code from your environment (the same expansion the remote config uses for `${POSTMAN_MCP_MODE}`), and the spawned stdio process also inherits your shell environment. To preserve a specific toolset, add the matching mode flag to `args` (e.g. `--full`, `--code`, `--minimal`); with no mode flag the package runs its default toolset.

### Step 4: Confirm and restart

Print the new file content back to the user, confirm the switch (remote → local stdio), and tell them to **restart Claude Code** for the change to take effect. Remind them they can switch back to the hosted server at any time with `/postman:use-remote`.

## Error Handling

- **`.mcp.json` not found:** Ask the user for the path to the installed plugin's `.mcp.json`, or tell them to reinstall the plugin.
- **`POSTMAN_API_KEY` not set:** Walk through Step 2 — the local server cannot authenticate without it.
- **`npx` unavailable:** The local package needs Node.js. Tell the user to install Node, or switch back with `/postman:use-remote` (the hosted server needs no local runtime).
57 changes: 57 additions & 0 deletions commands/use-remote.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
description: Switch this plugin's Postman MCP Server to the REMOTE hosted server (https://mcp.postman.com/mcp, full mode). Authenticates via OAuth.
allowed-tools: Bash, Read, Write
---

# Use Remote MCP Server

Point this plugin back at Postman's **remote** hosted MCP Server (`https://mcp.postman.com`, Full mode) instead of the local stdio package. This rewrites the plugin's own `.mcp.json` in place, changing only the transport (local → remote). The hosted server authenticates via OAuth — no API key required.

This is the plugin's default configuration. Switch to the local package at any time with `/postman:use-local`.

## Workflow

### Step 1: Locate this plugin's `.mcp.json`

The file to rewrite is the `.mcp.json` bundled with this plugin (it lives at the plugin's root, next to `.claude-plugin/`). Find it and show the current content:

```bash
for f in "$CLAUDE_PLUGIN_ROOT/.mcp.json" "$HOME"/.claude/plugins/*/.mcp.json "$HOME"/.claude/plugins/*/*/.mcp.json; do
[ -f "$f" ] || continue
if grep -q '"postman"' "$f"; then echo "FOUND: $f"; echo "--- current content ---"; cat "$f"; echo; fi
done
```

Use the `FOUND:` path as the target file to edit. If nothing is found, stop and ask the user for the path to the installed plugin's `.mcp.json`.

### Step 2: Overwrite the target `.mcp.json`

Write exactly this content to the `FOUND:` path. This is the plugin's canonical remote form — Full mode (`https://mcp.postman.com/mcp`) with `X-Source` attribution headers:

```json
{
"mcpServers": {
"postman": {
"type": "http",
"url": "https://mcp.postman.com/${POSTMAN_MCP_MODE:-mcp}",
"headers": {
"X-Source": "claude-code-plugin",
"X-Plugin-Version": "1.2.0",
"User-Agent": "postman-claude-code-plugin/1.2.0"
}
}
}
}
```

The `${POSTMAN_MCP_MODE:-mcp}` expansion defaults to `/mcp` (Full mode, 100+ tools) and honors a `POSTMAN_MCP_MODE` environment variable if the user wants a lighter toolset (`minimal`, `code`). Full mode is required by commands like `/postman:learn` (its `searchLearningCenter` tool is absent in `minimal` and `code` modes). Keep the `X-Source` / version headers intact so remote traffic stays attributed to this plugin.

### Step 3: Confirm and restart

Print the new file content back to the user, confirm the switch (local → remote hosted server), and tell them to **restart Claude Code** for the change to take effect. On first use, run `/postman:setup` to complete the Postman OAuth login (no API key needed). Remind them they can switch to the local package at any time with `/postman:use-local`.

## Error Handling

- **`.mcp.json` not found:** Ask the user for the path to the installed plugin's `.mcp.json`, or tell them to reinstall the plugin.
- **Connection fails after switching:** Run `/postman:setup` to (re)authenticate via OAuth against the hosted server.
- **401 Unauthorized:** "Your Postman session was rejected. Run `/postman:setup` to re-authenticate via OAuth."
Loading