#
tokens: 48326/50000 51/68 files (page 1/6)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 6. Use http://codebase.md/delano/postman-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── Dockerfile
├── docs
│   ├── api
│   │   ├── references
│   │   │   ├── postman-api-examples.yaml
│   │   │   ├── postman-api-index.yaml
│   │   │   ├── postman-api-parameters.yaml
│   │   │   ├── postman-api-pathsonly.yaml
│   │   │   ├── postman-api-requestBodies.yaml
│   │   │   ├── postman-api-responsessonly.yaml
│   │   │   ├── postman-api-schemassonly.yaml
│   │   │   └── README.md
│   │   └── summaries
│   │       ├── additional-features.md
│   │       ├── apis.md
│   │       ├── auth.md
│   │       ├── collections.md
│   │       ├── common-features.md
│   │       ├── environments.md
│   │       ├── mocks.md
│   │       ├── monitors.md
│   │       ├── notes.md
│   │       ├── README.md
│   │       ├── security-features.md
│   │       └── workspaces.md
│   ├── cli
│   │   └── README.md
│   └── dev
│       ├── postman-cli-design-doc.md
│       └── updating-request-bodies.md
├── LICENSE
├── package.json
├── pnpm-lock.yaml
├── README.md
├── smithery.yaml
├── src
│   ├── handlers
│   │   ├── index.ts
│   │   ├── prompt-handler.ts
│   │   ├── README.md
│   │   ├── resource-handler.ts
│   │   ├── resource-template-handler.ts
│   │   └── tool-handler.ts
│   ├── index.ts
│   ├── server.ts
│   ├── tools
│   │   ├── api
│   │   │   ├── additional-features
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── apis
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── auth
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── base.ts
│   │   │   ├── collections
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── environments
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── mocks
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── monitors
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   ├── users
│   │   │   │   ├── definitions.ts
│   │   │   │   └── index.ts
│   │   │   └── workspaces
│   │   │       ├── definitions.ts
│   │   │       └── index.ts
│   │   └── index.ts
│   └── types
│       ├── apis.ts
│       ├── auth.ts
│       ├── collection.ts
│       ├── common.ts
│       ├── environment.ts
│       ├── index.ts
│       ├── resource.ts
│       ├── tool.ts
│       ├── validation.ts
│       └── workspaces.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
.DS_Store

node_modules/
build/
*.log
.env*

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

```

--------------------------------------------------------------------------------
/docs/cli/README.md:
--------------------------------------------------------------------------------

```markdown


## Prompts

For each of the CLI pages:

```
@https://learning.postman.com/docs/postman-cli/postman-cli-reporters/

Analyze this plan "Postman API & CLI MCP Server Design Document" to incorporate Postman CLI into this MCP Server tools. Having a better idea of what we're hoping to acheive, revise the design if necessary or update the documented plan for clarity and completeness.

NOTE: See the attached URL for the most current info about "Postman CLI". We are referring to the official command-line only tool and not the opensource Newman command-line tool and library.

IMPORTANT: Do not over engineer a solution. The goal is to provide a simple and easy to use interface to the Postman CLI tool.

@/docs/dev/postman-cli-design-doc.md

@/src/server.ts
```


```
Proofread this plan "Postman API & CLI MCP Server Design Document". Having a better idea of what we're hoping to acheive, revise the design if necessary or update the documented plan for clarity and completeness.

IMPORTANT: Do not over engineer a solution. The goal is to provide a simple and easy to use interface to the Postman CLI tool.

@/docs/dev/postman-cli-design-doc.md

@/src/server.ts
```

```

--------------------------------------------------------------------------------
/src/handlers/README.md:
--------------------------------------------------------------------------------

```markdown
# Building MCP Servers with Claude

This readme documents key requirements and patterns for the Postman API MCP server handlers.

## Official Tutorial

Visit [modelcontextprotocol.io/tutorials/building-mcp-with-llms](https://modelcontextprotocol.io/tutorials/building-mcp-with-llms) for a comprehensive guide covering:

- Documentation preparation
- Server development workflow
- Implementation best practices
- Testing and deployment steps


## Handler Requirements

### Prompt Handler
- Prompt IDs must be used in snake_case format (e.g., 'create_collection', not 'Create Collection')
- Input validation is performed using TypeScript type guards
- Each prompt has a defined input schema and generates appropriate messages

### Resource Handler
- Handles direct resource URIs in the format: `postman://{resource-type}`
- Resource types are fixed strings without parameters (e.g., 'workspaces', 'collections')
- Direct resources provide top-level API data (e.g., list of all workspaces)

### Resource Template Handler
- Handles parameterized URIs in the format: `postman://{resource-type}/{id}/[sub-resource]`
- Supports nested resources (e.g., workspace collections, API versions)
- Template parameters are validated before making API requests

## URI Formats

### Direct Resources (ResourceHandler)
```
postman://workspaces          # List all workspaces
postman://collections         # List all collections
postman://environments        # List all environments
```

### Templated Resources (ResourceTemplateHandler)
```
postman://workspaces/{id}/collections     # Collections in a workspace
postman://apis/{id}/versions              # Versions of an API
postman://collections/{id}/requests       # Requests in a collection
```

## Essential Resources

- [MCP Specification](https://modelcontextprotocol.io)
- [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
- [Python SDK](https://github.com/modelcontextprotocol/python-sdk)

For implementation examples and detailed guidance, refer to the [official tutorial](https://modelcontextprotocol.io/tutorials/building-mcp-with-llms).

```

--------------------------------------------------------------------------------
/docs/api/references/README.md:
--------------------------------------------------------------------------------

```markdown
# Postman Reference

* [Overview](#overview)
  * [Collection SDK vs API](#collection-sdk-vs-api)
  * [YAML Files](#yaml-files)
* [Getting Started](#getting-started)
  * [Prerequisites](#prerequisites)
  * [Quick Start](#quick-start)
* [Authentication](#authentication)
  * [API Keys](#api-keys)
  * [Collection Access Keys](#collection-access-keys)
  * [Rate Limits](#rate-limits)
* [API Sections](#api-sections)
  * [Workspaces](#workspaces)
  * [Collections](#collections)
  * [Environments and Variables](#environments-and-variables)
  * [APIs](#apis)
  * [Mock Servers](#mock-servers)
  * [Monitors](#monitors)
  * [Comments](#comments)
  * [Forks](#forks)
  * [Pull Requests](#pull-requests)
  * [User and Usage Data](#user-and-usage-data)
  * [Users and User Groups](#users-and-user-groups)
  * [Roles](#roles)
  * [Billing](#billing)

## Overview

### Collection SDK vs API
The Postman platform offers two distinct tools for programmatic interaction:

#### Collection SDK
- Node.js module for programmatic collection manipulation
- Works locally without requiring API calls
- Focused on collection creation and modification
- [SDK Documentation](https://www.postmanlabs.com/postman-collection/)
- [GitHub Repository](https://github.com/postmanlabs/postman-collection)
- [Integration Guide](https://learning.postman.com/docs/developer/collection-sdk/)

#### Postman API
- REST API service for Postman's cloud platform
- Requires authentication and internet connectivity
- Full access to platform features (workspaces, environments, monitors etc)
- [API Documentation](https://learning.postman.com/docs/developer/postman-api/intro-api/)
- [API Reference](https://www.postman.com/postman/postman-public-workspace/documentation/i2uqzpp/postman-api)

While both follow the Postman Collection Schema, they serve different purposes:
- Use the SDK for local collection manipulation in development pipelines
- Use the API for cloud platform integration and team collaboration features

Example workflow: Generate collections with the SDK locally, then use the API to deploy to team workspaces and configure monitoring.

For detailed comparisons and use cases, see the [Developer Tools Overview](https://learning.postman.com/docs/developer/resources-intro/).

### YAML Files
The YAML files in this directory are derived from the Postman API OpenAPI 3 specification. Files are organized by major section and named accordingly to facilitate work with Claude and AI tools.

Note: The `#/` references can be found in the corresponding reference files. For example:
- `collectionId` is in `docs/reference/postman-api-parameters`
- Request/response objects for `mergeEnvironmentFork` are in `postman-api-requestBodies.yaml` and `postman-api-responsesonly.yaml`
- Schemas are in `postman-api-schemasonly.yaml`

## Getting Started

### Prerequisites
1. Access the [Postman API collection](https://www.postman.com/postman/postman-public-workspace/collection/i2uqzpp/postman-api?ctx=documentation)
2. Generate an API key in [Postman account settings](https://go.postman.co/settings/me/api-keys)
3. Store your API key securely:
   - Use [Postman Vault](https://learning.postman.com/docs/sending-requests/postman-vault/postman-vault-secrets/) for personal use
   - Use [environment variables](https://learning.postman.com/docs/sending-requests/variables/environment-variables/) (secret type) for team sharing

### Quick Start
1. Fork the Postman API collection to your workspace
2. Navigate to the User folder and locate the `/me` endpoint
3. Set your stored API key in the request headers
4. Send the request to verify authentication

For detailed instructions, see [Making your first Postman API call](https://learning.postman.com/docs/developer/postman-api/make-postman-api-call/).

## Authentication

### API Keys
- Generate API keys in your [Postman account settings](https://go.postman.co/settings/me/api-keys)
- Include the API key in the `X-API-Key` header for all requests
- API keys provide access to all Postman resources you have permissions for
- Store API keys as `postman-api-key` variables to use with the [Postman API collection](https://www.postman.com/postman/postman-public-workspace/documentation/i2uqzpp/postman-api)

### Collection Access Keys
- Generate collection-specific read-only access keys for API sharing
- Manage keys in the [API keys page](https://go.postman.co/settings/me/api-keys) under "Collection access keys"
- Each key grants access to a single collection
- Keys can be revoked at any time

For detailed authentication documentation, see [Postman API Authentication](https://learning.postman.com/docs/developer/postman-api/authentication/).

### Rate Limits
Per-user rate limits: 300 requests per minute. Monitor usage through response headers and monthly allowances.

Rate limit information is available through response headers:
- Current window limits via `RateLimit` and `X-RateLimit-*` headers
- Monthly usage via `RateLimit-Limit-Month` and `RateLimit-Remaining-Month`
- Retry timing via `RetryAfter` when limits are exceeded

Resources:
- [API Reference](https://www.postman.com/postman/postman-public-workspace/collection/i2uqzpp/postman-api)
- [Documentation](https://learning.postman.com/docs/developer/postman-api/postman-api-rate-limits/)
- [Usage monitoring](https://go.postman.co/billing/add-ons/overview)
- [Plan comparison](https://www.postman.com/pricing/)
- [Resource usage docs](https://learning.postman.com/docs/billing/resource-usage/#postman-api-usage)

## API Sections

### Workspaces
Manage Postman workspaces, including creating temporary test workspaces and backing up workspace resources.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/wppke9j/workspaces)
- [Documentation](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/create-workspaces/)

### Collections
Manage Postman Collections with operations for adding, deleting, and updating collections and their contents. Includes fork/PR management and OpenAPI import/export.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/b7pojjp/collections)
- [Documentation](https://learning.postman.com/docs/collections/collections-overview/)

### Environments and Variables
Manage Postman environments and variables (global and collection-level) for different deployment contexts.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/t1fblas/environments)
- [Documentation](https://learning.postman.com/docs/sending-requests/variables/managing-environments/)

### APIs
Manage APIs and integrate with CI/CD systems. Features include API definition updates, version management, and collection synchronization.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/j34rt1l/api)
- [Documentation](https://learning.postman.com/docs/designing-and-developing-your-api/creating-an-api/)

### Mock Servers
Create and manage mock servers with public/private settings, call logging, and error response management.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/zueaxnn/mocks)
- [Documentation](https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/)

### Monitors
Run collections programmatically based on CI/CD events and manage webhooks for collection execution.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/uu45lzt/monitors)
- [Documentation](https://learning.postman.com/docs/monitoring-your-api/intro-monitors/)

### Comments
Manage comments across APIs, collections, folders, requests, and responses.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/kyjatxe/comments)
- [Documentation](https://learning.postman.com/docs/collaborating-in-postman/comments/)

### Forks
Create and manage forks of collections and environments.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/yrtfwkg/forks)
- [Documentation](https://learning.postman.com/docs/collaborating-in-postman/using-version-control/forking-elements/)

### Pull Requests
Handle pull requests for collections, including creation, updates, and status management.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/request/9wzo1v1/create-a-pull-request)
- [Documentation](https://learning.postman.com/docs/collaborating-in-postman/using-version-control/creating-pull-requests/)

### User and Usage Data
Access authenticated user information and account usage details.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/request/ay0ymqy/get-authenticated-user)

### Users and User Groups
Manage team users and groups with capabilities to retrieve team member and group details.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/gpu5rwc/users)
- [Documentation](https://learning.postman.com/docs/administration/managing-your-team/managing-your-team/)

### Roles
Define and manage user permissions for workspaces, collections, and other Postman elements.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/c5hrwtj/roles)
- [Documentation](https://learning.postman.com/docs/collaborating-in-postman/roles-and-permissions/)

### Billing
Access billing account information and integrate with internal systems.
- [API Reference](https://www.postman.com/postman/postman-public-workspace/folder/7iix2ud/billing)

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Postman MCP Server
[![smithery badge](https://smithery.ai/badge/postman-api-server)](https://smithery.ai/server/postman-api-server)
**Version:** v0.2.0

An MCP server that provides access to the [Postman](https://www.postman.com/) API. Functionality is based on the [official OpenAPI specification](https://www.postman.com/postman/postman-public-workspace/documentation/i2uqzpp/postman-api). For more information, see the [Postman API documentation](https://www.postman.com/postman-public-workspace/).

This project is part of the Model Context Protocol (MCP) initiative from Anthropic. For more information, visit the [MCP GitHub repository](https://github.com/modelcontextprotocol) and the announcement on the [Anthropic blog](https://www.anthropic.com/news/model-context-protocol).

**[Skip ahead to install instructions](#installation)**


![postman-mcp-server - Cover Image](https://github.com/user-attachments/assets/e19d712f-ad97-4456-a414-d69b159a9ed2)


> [!WARNING]
> This project is currently under active development. Please use with caution and expect breaking changes.

> [!NOTE]
> AI Generated Code. I used Cline v2.2.2 with Claude 3.5 Sonnet (2024-10-22). See docs/README.md for prompts and details about how this code was generated.

<a href="https://glama.ai/mcp/servers/zoig549xfd"><img width="380" height="200" src="https://glama.ai/mcp/servers/zoig549xfd/badge" alt="postman-mcp-server MCP server" /></a>

---

* [Overview](#overview)
* [Features](#features)
  * [Collections](#collections)
  * [Environments](#environments)
  * [APIs](#apis)
  * [Authentication \& Authorization](#authentication--authorization)
  * [Additional Features](#additional-features)
* [Installation](#installation)
  * [Prerequisites](#prerequisites)
  * [Steps](#steps)
* [Usage](#usage)
  * [Setting up API Keys](#setting-up-api-keys)
  * [Using Claude Desktop](#using-claude-desktop)
  * [Using Cline](#using-cline)
  * [Using Zed](#using-zed)
* [Documentation](#documentation)
  * [Project Overview](#project-overview)
* [Rationale](#rationale)
* [Development](#development)
* [Debugging](#debugging)
* [Other MCP Servers](#other-mcp-servers)
* [License](#license)

## Overview

Postman MCP Server is a TypeScript-based MCP server that integrates with the Postman API, providing comprehensive management of Postman collections, environments, and APIs.

## Features

### Collections
- **CRUD Operations**: Create, retrieve, update, and delete Postman collections.
- **Folder Management**: Organize requests into folders within collections.
- **Request Management**: Add, update, and delete requests within collections.
- **Response Management**: Manage responses associated with requests.
- **Version Control**: Fork, merge, and pull changes for collections.
- **Comments**: Add and manage comments on collections.

### Environments
- **Manage Environments**: Create and retrieve environments for different setups.
- **CRUD Operations**: Full support for creating, updating, and deleting environments.

### APIs
- **API Management**: Create, retrieve, update, and delete APIs.
- **Schema Support**: Manage API schemas with multi-file support.
- **Tagging**: Add and manage tags for APIs.
- **Comments**: Add and manage comments on APIs.

### Authentication & Authorization
- **API Key Authentication**: Secure access using API keys.
- **Role-Based Access Control**: Manage permissions at workspace and collection levels.
- **Workspace Permissions**: Define permissions specific to workspaces.

### Additional Features
- **Private API Network**: Manage elements and folders within a private API network.
- **Webhooks**: Create webhooks to trigger collections with custom payloads.
- **Enterprise Features**: Advanced role controls and SCIM support for enterprise environments.

## Installation

### Installing via Smithery

To install Postman MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/postman-api-server):

```bash
npx -y @smithery/cli install postman-api-server --client claude
```

### Prerequisites
- [Node.js](https://nodejs.org/) installed.

### Steps

1. **Clone the repository:**
    ```bash
    git clone https://github.com/delano/postman-api-server.git
    cd postman-api-server
    ```

2. **Install dependencies:**
    ```bash
    pnpm install
    ```

3. **Build the server:**
    ```bash
    pnpm run build
    ```

4. **Run in development mode with auto-rebuild:**
    ```bash
    pnpm run watch
    ```

## Usage

### Setting up API Keys

1. **Generate your API Key**
   - Visit [Postman Account Settings](https://go.postman.co/settings/me/api-keys)
   - Click "Generate API Key"
   - Save the key securely - it won't be shown again

2. **Configure the API Key**
   - Add the key to your environment as `POSTMAN_API_KEY`
   - For Claude Desktop or Cline, include it in your config file (see configuration examples below)
   - Never commit API keys to version control

3. **Verify Access**
   - The API key provides access to all Postman resources you have permissions for
   - Test access by running a simple query (e.g., list workspaces)

> [!NOTE]
> If you're using the [Postman API collection](https://www.postman.com/postman/postman-public-workspace/documentation/i2uqzpp/postman-api) directly, store your API key as a `postman-api-key` collection variable.

### Using Claude Desktop

To use with Claude Desktop, add the server config:

- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%/Claude/claude_desktop_config.json`

> [!IMPORTANT]
> If you're updating this provider, Claude must be restarted to pick up API changes from the input schema (i.e. When the MCP server's ToolDefinition elements have changed). This is because Claude caches the tool definitions when it starts up.

<img width="480" alt="claude-desktop-settings" src="https://github.com/user-attachments/assets/7ea7cba2-e27e-413a-a50a-590054d51344" />

#### Example configuration

```json
{
  "mcpServers": {
    "postman": {
      "command": "node",
      "args": [
        "/path/to/postman-api-server/build/index.js"
      ],
      "env": {
        "POSTMAN_API_KEY": "CHANGEME"
      }
    }
  }
}
```

### Using Cline

Using the same example configuration, add the server config to your Cline MCP Servers configuration:

<img width="480" alt="cline-settings" src="https://github.com/user-attachments/assets/651ec517-9aa2-4314-84f5-bee716aa8889" />


#### Example configuration

_Same as Claude above._

### Using Zed

I'm still trying to get this to work. From the [Zed docs](https://zed.dev/docs/assistant/model-context-protocol) it looks like it needs to be an extension ([also this issue #21455](https://github.com/zed-industries/zed/discussions/21455)).

---

## Documentation

The official [Postman API documentation](https://learning.postman.com/docs/developer/postman-api/intro-api/) is available in the [Postman Public Workspace](https://www.postman.com/postman/postman-public-workspace/).

### Project Overview

#### Postman API References & Summaries

This project leverages the Claude model and Cline extension to convert the OpenAPI specification into TypeScript code, enhancing type safety and integration within the MCP server.

This GitHub project includes [API References documentation](docs/api/references/README.md) that provides detailed guidance on utilizing the Postman platform programmatically. It covers both the Collection SDK for local development and the Postman API for cloud platform integration. Key topics include authentication mechanisms, rate limits, and in-depth documentation of all API endpoints, including workspaces, collections, environments, mock servers, monitors, and more. Additionally, the guide offers prerequisites and quick-start instructions to facilitate seamless API interactions.

The `docs/api/summaries` directory contains comprehensive Markdown summaries of the Postman API. These documents outline API endpoints, request/response formats, and implementation details essential for validating and ensuring the functionality of the MCP server. Refer to the [API Summaries README](docs/api/summaries/README.md) for an overview of the documentation structure and implementation strategies.

#### Converting OpenAPI Spec to TypeScript Code with Claude



#### Building the MCP Server

Refer to the [Handlers Documentation](src/handlers/README.md) for detailed specifications on implementing MCP server handlers. This includes URI formats, prompt requirements, and resource handling patterns. This guide is crucial for developers working on integrating and enhancing the Postman API functionalities within the MCP server.


---

## Rationale

The MCP wrapper for Postman tools makes sense primarily as an AI interaction layer for complex, multi-step operations where structure and safety are paramount. However, it may be overengineered for simple operations where direct CLI or API usage would suffice. The MCP wrapper provides most value when:

1. **Complex Operations**
- Managing multiple collections
- Coordinating environments
- Generating comprehensive reports

2. **AI-Driven Automation**
- Automated testing workflows
- API documentation maintenance
- Environment management

3. **Error-Sensitive Operations**
- Critical API testing
- Production deployments
- Compliance checking

It provides less value for:

1. **Simple Operations**
- Basic collection runs
- Single API calls
- Quick environment checks
2. **Direct CLI Usage**
- Developer-driven operations
- Local testing
- Quick iterations


## Development

Install dependencies:
```bash
pnpm install
```

Build the server:
```bash
pnpm run build
```

For development with auto-rebuild:
```bash
pnpm run watch
```

## Debugging

Since MCP servers communicate over stdio, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), available as a package script:

```bash
pnpm run inspector
```

[Docs](https://modelcontextprotocol.io/docs/tools/inspector)

The Inspector will provide a URL to access debugging tools in your browser: http://localhost:5173. You will need to add the POSTMAN_API_KEY before connecting. Navigate to "Tools" to get started.

## Other MCP Servers

- [Awesome MCP Servers by AppCypher](https://github.com/appcypher/awesome-mcp-servers)
- [Awesome MCP Servers by PunkPeye](https://github.com/punkpeye/awesome-mcp-servers)

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

```

--------------------------------------------------------------------------------
/docs/api/summaries/README.md:
--------------------------------------------------------------------------------

```markdown
# Postman API Implementation Summary

This document outlines the prompts and processes used to implement the Postman API functionality within the MCP server tools.

## Summary documents

Each of the following documents contains a summary of the Postman API functionality that is used to cross-check against the MCP server tools implementation.

1. [Workspaces](workspaces.md)
2. [Collections](collections.md)
3. [Environments](environments.md)
4. [APIs](apis.md)
5. [Mocks](mocks.md)
6. [Monitors](monitors.md)
7. [Security Features](security-features.md)
8. [Additional Features](additional-features.md)
9. [Authentication & Authorization](auth.md)
10. [Common Features](common-features.md)
11. [Notes](notes.md)

## Prompts

**Using Cline 2.2.2 and Continue 0.9.246**

Building out the Postman API functionality within the MCP server tools follows this general order of operations:

1. Split Postman API OpenAPI 3 definition into individual yaml files.
2. Peruse the individual yaml files to produce summary markdown documents.
3. Use the summary markdown documents to first implement the MCP server tools and later to cross-check against the implementation.
4. Using MCP documentation, ensure the MCP server tools are correctly implemented.

The OoO is not strictly linear and the processes involved are iterative. The goal is to continually add and correct details each time we review. The process is more additive and augmentative early on; later on it becomes more about cross-checking, correcting, and reducing. The goal is to keep files concise and focused.

Some version of this process can be repeated to implement changes to the Postman API spec. The same can be done for the MCP server tools implementation.


### Utilizing MCP Server Tools

#### List Workspaces

```prompt
Use Postman tools to list our workspaces.
```

```
Use postman tools to list environments in a workspace: 0ddc8458-12e6-48bf-8ff0-490ca0a8f775


```

### Improving MCP Server Tools

#### General Improvements
```prompt
@/docs/api/summaries/workspaces.md

Review the postman MCP tools workspace API access against the Postman API summary. Make corrections in our implementation.

```

#### Specific Improvements

##### Workspaces
```prompt
@/docs/api/summaries/environments.md

Review the postman MCP tools workspace API access against the Postman API summary. Make corrections in our implementation, paying particular attention to the request parameter naming and values.
```

##### Environments
```prompt
@/docs/api/summaries/wokspaces.md
@/docs/api/summaries/environments.md

Review the postman workspaces and environment docs. Understand the details and nuance around contstructuing environment identifier and using it appropriately when querying. Modify out MCP tools implementation accordingly.

@src/index.ts
@src/tools/api/workspaces.ts
@src/tools/api/environments.ts
```

```prompt
@/docs/api/summaries/environments.md
@/docs/api/references/postman-api-requestBodies.yaml

Review the postman environment md docs and yaml definitions. Understand the details and nuance of request bodies for POST/PUT requests. Modify out MCP tools implementation accordingly, including inline jsdocs.


@src/tools/api/environments.ts
@src/types.ts


We may also need to update the MCP protocol endpoints to reflect the changes. IOW, updating our code that communicates with the Postman API is one part but we also may need to update the MCP protocol code that communicates with the MCP clients.

```

```prompt
@/docs/api/summaries/collections.md
@/docs/api/references/postman-api-parameters.yaml
@/docs/api/references/postman-api-responsesonly.yaml
@/docs/api/references/postman-api-requestBodies.yaml

Review the postman collection md docs and yaml definitions. Understand the details and nuance of request bodies for POST/PUT/PATCH requests. Modify out MCP tools implementation accordingly, including inline jsdocs.


@src/tools/api/collections.ts
@src/types.ts


Refer to @/docs/dev/updating-request-bodies.md for what areas of the code need to be updated.
```

```prompt
@/docs/api/summaries/collections.md
@/docs/api/references/postman-api-parameters.yaml
@/docs/api/references/postman-api-responsesonly.yaml
@/docs/api/references/postman-api-requestBodies.yaml

Review the postman collection md docs and yaml definitions. Understand the details and nuance of requests and responses for GET/HEAD/OPTION/DELETE requests. Modify out MCP tools implementation accordingly, including inline jsdocs.


@src/tools/api/collections.ts
@src/types.ts


Refer to @/docs/dev/updating-request-bodies.md for what areas of the code need to be updated.
```
##### APIs

```prompt
@/docs/api/summaries/apis.md
@/docs/api/references/postman-api-parameters.yaml
@/docs/api/references/postman-api-requestBodies.yaml

Review the postman apis md docs and yaml definitions to implement `src/tools/api/apis.ts`. Understand the details and nuance of parameters and request bodies for POST/PUT/PATCH/GET/HEAD/OPTION/DELETE  requests. Modify out MCP tools implementation accordingly, including inline jsdocs.

@src/types/index.ts


We may also need to update the MCP protocol endpoints to reflect the changes. IOW, updating our code that communicates with the Postman API is one part but we also may need to update the MCP protocol code that communicates with the MCP clients.
```

##### MCP Protocol

```prompt

Revise the MCP protocol implementation to ensure the "List Resources", "List Prompts" endpoints are functionality fully and correctly.

@src/index.ts

```

### Improving codebase

#### Reduce duplication and emphasize concise files

More concise and focused files are easier to work with the models.

```prompt
@/src/index.ts

Review the main code entrypoint src/index.ts to devise a strategy to reduce duplication and manage complexity as functionality is added.


For example:
1)  `setupToolHandlers` currently defines the superset of all tool handlers which means it's length is unmitigated. Each tool should be responsible for defining its own handlers.

2) PostmanAPIServer should be defined in its own file and imported into the main index.ts file.

3) setupHandlers should be refactored similarly to setupToolHandlers.

4) Repetative function definitions should be refactored into at most one additional layer of abstraction.

```

```prompt
@/src/server.ts

Review the main server src/server.ts to continue reducing duplication and managing complexity as functionality is added.

`this.server.setRequestHandler(CallToolRequestSchema, async (request) => {...` can be update to implement like `ListToolsRequestSchema`.
```

#### Adding tool implementation

```prompt
@/docs/api/summaries/additional-features.md

@/docs/api/summaries/common-features.md

@/docs/api/references/postman-api-parameters.yaml

@/docs/api/references/postman-api-requestBodies.yaml

Review the postman md docs and yaml definitions to implement our MCP tool wrapper `src/tools/api/additional-features/index.ts`. Understand the details and nuance of parameters and request bodies for POST/PUT/PATCH/GET/HEAD/OPTION/DELETE  requests. Modify out MCP tools implementation accordingly, including inline jsdocs. Use `src/tools/api/environments/index.ts` as a reference for how to implement the wrapper. (When implementing ToolDefinition, the required field is required).

NOTE: this MCP server is a wrapper around existing API functionality that will be doing the actual validation so simplify the validation to just required fields. Keep the basic types and enums for type safety and documentation.

@src/types/index.ts

```

#### Reviewing tool implementations

```prompt
@/docs/api/summaries/apis.md

@/docs/api/summaries/common-features.md

@/docs/api/references/postman-api-parameters.yaml

@/docs/api/references/postman-api-requestBodies.yaml

Review the postman md docs and yaml definitions to cross check our MCP tools implementation `src/tools/api/apis/index.ts`. Understand the details and nuance of parameters and request bodies for POST/PUT/PATCH/GET/HEAD/OPTION/DELETE  requests. Modify out MCP tools implementation accordingly, including inline jsdocs. Use `src/tools/api/environments/index.ts` as a reference for how to implement the wrapper.

NOTE: this MCP server is a wrapper around existing API functionality that will be doing the actual validation so simplify the validation to just required fields. Keep the basic types and enums for type safety and documentation.

NOTE2: The best code is code that doesn't need to be written. If we analyse the imnplementation determine we do not need to write any code, that's a win. The goal is to be as minimal as possible.

@src/types/index.ts
@src/tools/api/base.ts

```

#### Reviewing MCP Server details

```prompt
@https://modelcontextprotocol.io/docs/concepts/resources

Peruse the Model Context Protocol documentation. In order to expose data to models automatically, server authors should use a model-controlled primitive such as Tools.

Review the MCP server details to ensure the "List Resources"  endpoint is functionality fully and correctly. It should return a list of all resources that are available for the user to interact with.

```


```prompt
@https://modelcontextprotocol.io/docs/concepts/prompts


Peruse the Model Context Protocol documentation. In order to expose data to models automatically, server authors should use a model-controlled primitive such as Tools.

Review the MCP server details to ensure the "List Prompts"  endpoint is functionality fully and correctly. It should return a list of all resources that are available for the user to interact with.

```

```prompt

@https://modelcontextprotocol.io/docs/concepts/tools

Peruse the Model Context Protocol documentation. In order to expose data to models automatically, server authors should use a model-controlled primitive such as Tools.

Review the MCP server details to ensure the "List Tools"  endpoint is functionality fully and correctly. It should return a list of all resources that are available for the user to interact with.

NOTE: We may need to add a new handler interface called ToolResourceHandler. The existing ToolHandler is used for the tool itself, not the resources that the tool can interact with. See @src/types/index.ts for the existing ToolHandler, ResourceHandler interfaces.

```

```prompt

@https://modelcontextprotocol.io/docs/concepts/transports

Peruse the Model Context Protocol transports documentation. Transports in the Model Context Protocol (MCP) provide the foundation for communication between clients and servers. A transport handles the underlying mechanics of how messages are sent and received.

While the TypeScript MCP SDK handles all of the server <=> client communication including implementing the transport layer, the server still needs to implement the SDK correctly.

Review @src/server.ts to ensure the MCP server is correctly implementing the TypeScript SDK following best practices and security recommendations.

```



### Improving Documentation

#### Linking to Postman API References
```prompt

Update this docs/references README.md file with a summary and links for each of:

Workspaces
Collections
Environments and variables
APIs
Mock servers
Monitors
Comments
Forks
Pull requests
User and usage data
Users and user groups
Roles
Billing

Add both the relevant `https://www.postman.com/postman/postman-public-workspace/` and  `https://learning.postman.com/docs` links to each of the above sections.
```

#### Adding Authentication Details

```prompt
@URL:https://learning.postman.com/docs/developer/postman-api/authentication/

Based on the content of the postman doc linked, add a new section with concise but complete details including relevant links (`learning.postman.com`, `go.postman.com`, `www.postman.com` pages) to this readme.md
```

#### Reviewing and Updating Documentation

```prompt
Proofread and tidy this markdown readme to a professional standard. Do not make up new content to add; and do not omit existing content, except where redundant and or unclear.
```


### Expanding Postman API Summaries

#### Working on Individual Files

##### Add Responses
```prompt
@/docs/api/references/postman-api-pathsonly.yaml

Peruse the postman OpenAPI 3 paths definition (note this is a very abrridged version of the full document, containing just the paths objects), this time to add the expected response references and associated http status (e.g. 200 '#/components/responses/getAccounts').

Continue updating the individual summary markdown document that we can use later on to cross-check against our tool implementations:
@/docs/api/summaries/collections.md

Workthrough the markdown summary document, operating one endpoint at a time, updating its documentation based on the contents of the pathsonly file. Each request endpoint in the pathsonly OpenAPI 3 definition document should have a list of `responses:`. Those are the details we want to add to the summary markdown doc.

Also continue to add missing endpoints that you come across. The goal is to be "additive" and "augmentative" so that we continually add and correct details each time we review. Do not remove details or re-summarize existing content.

When completed this file, request the next summary document to continue with. Keep doing this until I say stop or you get bored.
```

##### Add Parameters
```prompt
@/docs/api/references/postman-api-pathsonly.yaml

Peruse the postman OpenAPI 3 paths definition (note this is a very abrridged version of the full document, containing just the paths objects), this time to add the expected parameters references and associated http status (e.g. '#/components/parameters/workspaceQuery').

Continue updating the individual summary markdown document that we can use later on to cross-check against our tool implementations:
@/docs/api/summaries/environments.md
@/docs/api/summaries/workspaces.md
@/docs/api/summaries/collections.md
@/docs/api/summaries/apis.md
@/docs/api/summaries/mocks.md
@/docs/api/summaries/monitors.md
@/docs/api/summaries/security-features.md
@/docs/api/summaries/additional-features.md
@/docs/api/summaries/auth.md
@/docs/api/summaries/common-features.md
@/docs/api/summaries/notes.md

Workthrough the markdown summary document, operating one endpoint at a time, updating its documentation based on the contents of the definition file. Each request endpoint in the pathsonly OpenAPI 3 definition document should have a list of `parameters:`. Those are the details we want to add to the summary markdown doc.

Also continue to add missing endpoints that you come across. The goal is to be "additive" and "augmentative" so that we continually add and correct details each time we review. Do not remove details or re-summarize existing content.

When completed this file, request the next summary document to continue with. Keep doing this until I say stop or you get bored.
```

##### Add Parameter Details
```prompt
@/docs/api/references/postman-api-parameters.yaml

Peruse the postman OpenAPI 3 definition (note this is a very abrridged version of the full document, containing just the parameters objects), this time to add parameter details by matching the parameter name (e.g. The workspaceQuery in '#/components/parameters/workspaceQuery').

Continue updating the individual summary markdown document that we can use later on to cross-check against our tool implementations:
@/docs/api/summaries/environments.md
@/docs/api/summaries/workspaces.md
@/docs/api/summaries/collections.md
@/docs/api/summaries/apis.md
@/docs/api/summaries/mocks.md
@/docs/api/summaries/monitors.md
@/docs/api/summaries/security-features.md
@/docs/api/summaries/additional-features.md
@/docs/api/summaries/auth.md
@/docs/api/summaries/common-features.md
@/docs/api/summaries/notes.md

Workthrough the markdown summary document, operating one endpoint at a time, updating its documentation based on the contents of the definition file.

NOTE: The goal is to be "additive" and "augmentative" so that we continually add and correct details each time we review. Do not remove details or re-summarize existing content.

When completed this file, request the next summary document to continue with. Keep doing this until I say stop or you get bored.
```

##### Add Request Bodies (Paths Only)
```prompt
@/docs/api/references/postman-api-pathsonly.yaml

Peruse the postman OpenAPI 3 definition (note this is a very abrridged version of the full document, containing just the paths objects), this time to augment the POST/PUT requests with body content add parameter details by matching the parameter name (e.g. The updateEnvironment in '#/components/requestBodies/updateEnvironment').

Continue updating the individual summary markdown document that we can use later on to cross-check against our tool implementations:
@/docs/api/summaries/environments.md
@/docs/api/summaries/workspaces.md
@/docs/api/summaries/collections.md
@/docs/api/summaries/apis.md
@/docs/api/summaries/mocks.md
@/docs/api/summaries/monitors.md
@/docs/api/summaries/security-features.md
@/docs/api/summaries/additional-features.md
@/docs/api/summaries/auth.md
@/docs/api/summaries/common-features.md
@/docs/api/summaries/notes.md

Workthrough the markdown summary document, operating one endpoint at a time, updating its documentation based on the contents of the definition file. Each POST/PUT/etc request endpoint in the pathsonly OpenAPI 3 definition document should have at least one `requestBody:`. Those are the details we want to add to the summary markdown doc.

Also continue to add missing endpoints that you come across. The goal is to be "additive" and "augmentative" so that we continually add and correct details each time we review. Do not remove details or re-summarize existing content.

When completed this file, request the next summary document to continue with. Keep doing this until I say stop or you get bored.
```

##### Review for missing endpoints

```prompt
@/docs/api/references/postman-api-pathsonly.yaml

Peruse the postman OpenAPI 3 paths definition (note this is a very abrridged version of the full document, containing just the paths objects). Compare to @/docs/api/summaries/ .md files for missing endpoints. Add missing endpoints to the summary markdown files.
```

##### Add Request Bodies
```prompt
@/docs/api/references/postman-api-requestbodies.yaml

Review the abridged Postman OpenAPI 3 definition (containing only the requestBody objects) to augment POST/PUT requests with body content by matching request body names (e.g., `updateEnvironment` in '#/components/requestBodies/updateEnvironment').

Update the corresponding summary markdown documents:
- @/docs/api/summaries/environments.md
- @/docs/api/summaries/workspaces.md
- @/docs/api/summaries/collections.md
- @/docs/api/summaries/apis.md
- @/docs/api/summaries/mocks.md
- @/docs/api/summaries/monitors.md
- @/docs/api/summaries/security-features.md
- @/docs/api/summaries/additional-features.md
- @/docs/api/summaries/auth.md
- @/docs/api/summaries/common-features.md
- @/docs/api/summaries/notes.md

For each POST/PUT request endpoint, add `requestBody:` details to the summary markdown based on the definition file.

Continue adding missing endpoints to ensure comprehensive documentation. Maintain an additive and augmentative approach without removing existing content.

Upon completion, request the next summary document to continue. Repeat until instructed to stop.
```

### Splitting a Single Summary File into Multiple Files
```prompt
@docs/postman-api-summary.md

Let's split the single summary doc into multiple docs to help keep the size manageable. Create a new directory under docs/ and split the content at the `##` header level (e.g. "## Workspaces" is one document)
```

### Creating a Summary Document
```prompt
@/docs/api/references/postman-api-index.yaml

Review the postman environment, collection API from the OpenAPI 3 definition. Make a summary document that we can use to cross-check against our tool implementations (This implementation covers the basic Postman API functionality in MCP)
```

```

--------------------------------------------------------------------------------
/src/tools/index.ts:
--------------------------------------------------------------------------------

```typescript
export * from './api/index.js';

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { PostmanAPIServer } from './server.js';

const server = new PostmanAPIServer();
server.run().catch(console.error);

```

--------------------------------------------------------------------------------
/src/handlers/index.ts:
--------------------------------------------------------------------------------

```typescript
export * from './resource-handler.js';
export * from './resource-template-handler.js';
export * from './prompt-handler.js';
export * from './tool-handler.js';

```

--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------

```typescript
// Re-export all types from their respective modules
export * from './tool.js';
export * from './common.js';
export * from './collection.js';
export * from './environment.js';
export * from './validation.js';
export * from './apis.js';
export * from './workspaces.js';
export * from './auth.js';

```

--------------------------------------------------------------------------------
/src/tools/api/users/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  {
    name: 'get_user_info',
    description: 'Get information about the authenticated user',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [],
    },
  },
];

```

--------------------------------------------------------------------------------
/src/types/common.ts:
--------------------------------------------------------------------------------

```typescript
export interface WorkspaceArg {
  workspace: string;
}

export interface EnvironmentIdArg {
  environmentId: string;
}

export interface CollectionIdArg {
  collection_id: string;
}

export interface EnvironmentValue {
  key: string;
  value: string;
  type?: 'default' | 'secret';
  enabled?: boolean;
}

```

--------------------------------------------------------------------------------
/src/types/validation.ts:
--------------------------------------------------------------------------------

```typescript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

// Validation helper
export function validateArgs<T>(
  obj: unknown,
  validator: (obj: unknown) => obj is T,
  errorMessage: string
): T {
  if (!validator(obj)) {
    throw new McpError(ErrorCode.InvalidParams, errorMessage);
  }
  return obj;
}

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/src/tools/api/index.ts:
--------------------------------------------------------------------------------

```typescript
export * from './auth/index.js';
export * from './base.js';
export * from './mocks/index.js';
export * from './workspaces/index.js';
export * from './environments/index.js';
export * from './collections/index.js';
export * from './users/index.js';
export * from './apis/index.js';
export * from './monitors/index.js';
export * from './additional-features/index.js';

```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml

startCommand:
  type: stdio
  configSchema:
    # JSON Schema defining the configuration options for the MCP.
    type: object
    required:
      - postmanApiKey
    properties:
      postmanApiKey:
        type: string
        description: The API key for authenticating with the Postman API.
  commandFunction:
    # A function that produces the CLI command to start the MCP on stdio.
    |-
    (config) => ({ command: 'node', args: ['build/index.js'], env: { POSTMAN_API_KEY: config.postmanApiKey } })
    

```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
# Use a Node.js image with pnpm pre-installed
FROM node:18-alpine

# Create app directory
WORKDIR /app

# Copy package.json and pnpm-lock.yaml first for better caching
COPY package.json pnpm-lock.yaml ./

# Install app dependencies
RUN npm install -g pnpm && pnpm install

# Bundle app source
COPY . .

# Build the TypeScript application
RUN pnpm run build

# Expose the port the app runs on
EXPOSE 3000

# The POSTMAN_API_KEY will be provided via environment variables
ENV POSTMAN_API_KEY=${POSTMAN_API_KEY}

# Run the application
CMD ["node", "build/index.js"]
```

--------------------------------------------------------------------------------
/src/types/workspaces.ts:
--------------------------------------------------------------------------------

```typescript
export type WorkspaceType = 'personal' | 'team' | 'private' | 'public' | 'partner';
export type WorkspaceRole = 'Viewer' | 'Editor' | 'Admin';

export interface ListWorkspacesParams {
  type?: WorkspaceType;
  createdBy?: string;
  include?: string;
}

export interface WorkspaceBase {
  name: string;
  description?: string;
  type: WorkspaceType;
}

export type CreateWorkspaceRequest = WorkspaceBase;
export type UpdateWorkspaceRequest = Partial<WorkspaceBase>;

export interface GlobalVariable {
  key: string;
  value: string;
  type?: 'default' | 'secret';
  enabled?: boolean;
}

export interface RoleUpdate {
  op: 'add' | 'remove';
  path: string;
  value: WorkspaceRole;
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "postman-api-server",
  "version": "0.2.0",
  "description": "an MCP server for Postman API",
  "private": true,
  "type": "module",
  "bin": {
    "postman-api-server": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
    "prepare": "pnpm run build",
    "watch": "tsc --watch",
    "inspector": "pnpx @modelcontextprotocol/inspector build/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "@types/axios": "^0.14.4",
    "axios": "^1.7.9",
    "zod": "^3.24.1"
  },
  "devDependencies": {
    "@types/node": "^20.11.24",
    "typescript": "^5.3.3"
  }
}

```

--------------------------------------------------------------------------------
/src/types/environment.ts:
--------------------------------------------------------------------------------

```typescript
import { EnvironmentValue } from './common.js';

// Core interfaces for environment operations
export interface CreateEnvironmentArgs {
  environment: {
    name: string;
    values: EnvironmentValue[];
  };
  workspace?: string;
}

export interface UpdateEnvironmentArgs {
  environmentId: string;
  environment: {
    name?: string;
    values?: EnvironmentValue[];
  };
}

export interface ForkEnvironmentArgs {
  environmentId: string;
  label: string;
  workspace: string;
}

export interface GetEnvironmentForksArgs {
  environmentId: string;
  cursor?: string;
  direction?: 'asc' | 'desc';
  limit?: number;
  sort?: 'createdAt';
}

export interface MergeEnvironmentForkArgs {
  environmentId: string;
  source: string;
  destination: string;
  strategy?: {
    deleteSource?: boolean;
  };
}

export interface PullEnvironmentArgs {
  environmentId: string;
  source: string;
  destination: string;
}

```

--------------------------------------------------------------------------------
/src/types/auth.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Collection access key information
 */
export interface CollectionAccessKey {
  id: string;
  name: string;
  createdAt: string;
  updatedAt: string;
  collection: {
    id: string;
    name: string;
  };
}

/**
 * Detailed workspace role information including SCIM data
 */
export interface WorkspaceRoleInfo {
  id: string;
  name: string;
  description?: string;
  type: 'user' | 'group' | 'team';
  roleId: 'VIEWER' | 'EDITOR';
  entityId: number;
  entityType: string;
  scimId?: string;
}

/**
 * Collection role information
 */
export interface CollectionRole {
  id: string;
  name: string;
  description?: string;
  type: 'user' | 'group' | 'team';
  roleId: 'VIEWER' | 'EDITOR';
  entityId: number;
  entityType: string;
}

/**
 * Authenticated user information
 */
export interface AuthenticatedUser {
  id: string;
  username: string;
  email?: string;
  fullName?: string;
  avatar?: string;
  isPublic: boolean;
  verified: boolean;
  teams?: Array<{
    id: string;
    name: string;
    role?: string;
  }>;
  flow_count?: number; // Only returned for Free plan users
}

```

--------------------------------------------------------------------------------
/src/tools/api/workspaces/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] =  [
  {
    name: 'list_workspaces',
    description: 'List all workspaces',
    inputSchema: {
      type: 'object',
      properties: {
        type: {
          type: 'string',
          enum: ['personal', 'team', 'private', 'public', 'partner'],
          description: 'Filter workspaces by type',
        },
        createdBy: {
          type: 'string',
          description: 'Filter workspaces by creator',
        },
        include: {
          type: 'string',
          description: 'Additional data to include in response',
        },
      },
      required: [],
    },
  },
  {
    name: 'get_workspace',
    description: 'Get details of a specific workspace',
    inputSchema: {
      type: 'object',
      properties: {
        workspace: {
          type: 'string',
          description: 'Workspace ID',
        },
        include: {
          type: 'string',
          description: 'Additional data to include in response',
        },
      },
      required: ['workspace'],
    },
  },
];

```

--------------------------------------------------------------------------------
/src/tools/api/users/index.ts:
--------------------------------------------------------------------------------

```typescript
import { AxiosInstance } from 'axios';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { ToolHandler, ToolDefinition, ToolCallResponse } from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

export class UserTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: unknown): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'get_user_info':
          return await this.getUserInfo();
        default:
          throw new McpError(
            ErrorCode.MethodNotFound,
            `Unknown tool: ${name}`
          );
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  async getUserInfo(): Promise<ToolCallResponse> {
    const response = await this.client.get('/me');
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/src/types/tool.ts:
--------------------------------------------------------------------------------

```typescript
import { AxiosInstance } from 'axios';
import { Resource, ResourceContent } from './resource.js';

export interface ToolCallContent {
  type: 'text';  // Simplified since we only use 'text' type
  text: string;
}

export interface ToolCallResponse {
  content: ToolCallContent[];
  isError?: boolean;
}

export interface ToolDefinition {
  name: string;
  description: string;
  inputSchema: {
    type: 'object';
    properties: Record<string, unknown>;
    required: string[];
  };
}

/**
 * Represents a resource that a tool can interact with
 */
export interface ToolResource extends Resource {
  toolName: string;      // Name of the tool that can interact with this resource
  operations: string[];  // List of operations the tool can perform (e.g., ['read', 'write', 'delete'])
}

/**
 * Interface for handling tool-specific resources
 */
export interface ToolResourceHandler {
  /**
   * List all resources that this tool can interact with
   * @returns Promise<ToolResource[]>
   */
  listToolResources(): Promise<ToolResource[]>;

  /**
   * Get details about how a tool can interact with a specific resource
   * @param resourceUri The URI of the resource
   * @returns Promise<ToolResource>
   */
  getToolResourceDetails(resourceUri: string): Promise<ToolResource>;

  /**
   * Validate if a tool can interact with a given resource
   * @param resourceUri The URI of the resource
   * @returns Promise<boolean>
   */
  canHandleResource(resourceUri: string): Promise<boolean>;
}

/**
 * Interface for handling tool operations
 * Note: The HTTP client implementation is considered an implementation detail
 * and should not be exposed through the interface
 */
export interface ToolHandler extends ToolResourceHandler {
  getToolDefinitions(): ToolDefinition[];
  handleToolCall(name: string, args: unknown): Promise<ToolCallResponse>;
}

```

--------------------------------------------------------------------------------
/docs/dev/updating-request-bodies.md:
--------------------------------------------------------------------------------

```markdown
# Request Body Update Locations

When updating the request body JSON schemas that are sent to the Postman API, the following files need to be updated:

## Files to Update
1. types.ts

 - Type definitions and validation
2. src/tools/{resource}.ts

 - Tool implementation and schemas
3. src/api/{resource}.ts

 - API client implementation

## Implementation Details

### 1. Type Definitions
```typescript
interface UpdateEnvironmentArgs {
  environmentId: string;
  environment: {
    name?: string;
    values?: EnvironmentValue[];
  };
}

function isUpdateEnvironmentArgs(obj: unknown): obj is UpdateEnvironmentArgs {
  if (typeof obj !== 'object' || obj === null) return false;
  const args = obj as UpdateEnvironmentArgs;
  return (
    typeof args.environmentId === 'string' &&
    isValidUid(args.environmentId) &&
    typeof args.environment === 'object' &&
    args.environment !== null &&
    (args.environment.name === undefined || typeof args.environment.name === 'string') &&
    (args.environment.values === undefined ||
      (Array.isArray(args.environment.values) &&
       args.environment.values.every(isEnvironmentValue)))
  );
}
```

### 2. Tool Implementation
```typescript
inputSchema: {
  type: 'object',
  properties: {
    environmentId: {
      type: 'string',
      description: '...',
    },
    environment: {
      type: 'object',
      description: 'Environment details to update',
      properties: {
        name: {
          type: 'string',
          description: '...',
        },
        values: {
          type: 'array',
          items: { ... }
        }
      }
    }
  },
  required: ['environmentId', 'environment']
}

// Implementation
const { environmentId, environment } = args;
requestBody.environment = environment;
```

### 3. API Implementation
```typescript
// Update request construction
async function updateEnvironment(args: UpdateEnvironmentArgs) {
  const response = await client.put(`/environments/${args.environmentId}`, {
    body: args.environment
  });
  // ...existing code...
}

// Update tests
describe('updateEnvironment', () => {
  it('should construct valid request', async () => {
    // ...existing code...
    expect(mockClient.put).toHaveBeenCalledWith(
      '/environments/123',
      expect.objectContaining({
        body: {
          name: 'test',
          values: []
        }
      })
    );
  });
});
```

```

--------------------------------------------------------------------------------
/src/tools/api/monitors/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler,
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

/**
 * Implements Postman Monitor API endpoints
 */
export class MonitorTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'list_monitors':
          return await this.listMonitors(args.workspace);
        case 'get_monitor':
          return await this.getMonitor(args.monitorId);
        case 'create_monitor':
          return await this.createMonitor(args);
        case 'update_monitor':
          return await this.updateMonitor(args);
        case 'delete_monitor':
          return await this.deleteMonitor(args.monitorId);
        case 'run_monitor':
          return await this.runMonitor(args);
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  async listMonitors(workspace?: string): Promise<ToolCallResponse> {
    const response = await this.client.get('/monitors', {
      params: workspace ? { workspace } : undefined
    });
    return this.createResponse(response.data);
  }

  async getMonitor(monitorId: string): Promise<ToolCallResponse> {
    const response = await this.client.get(`/monitors/${monitorId}`);
    return this.createResponse(response.data);
  }

  async createMonitor(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post('/monitors', {
      monitor: args.monitor,
      workspace: args.workspace ? { id: args.workspace, type: 'workspace' } : undefined
    });
    return this.createResponse(response.data);
  }

  async updateMonitor(args: any): Promise<ToolCallResponse> {
    const response = await this.client.put(
      `/monitors/${args.monitorId}`,
      { monitor: args.monitor }
    );
    return this.createResponse(response.data);
  }

  async deleteMonitor(monitorId: string): Promise<ToolCallResponse> {
    const response = await this.client.delete(`/monitors/${monitorId}`);
    return this.createResponse(response.data);
  }

  async runMonitor(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post(
      `/monitors/${args.monitorId}/run`,
      undefined,
      {
        params: args.async !== undefined ? { async: args.async } : undefined
      }
    );
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/src/types/collection.ts:
--------------------------------------------------------------------------------

```typescript
import { WorkspaceArg, CollectionIdArg } from './common.js';

/**
 * Basic collection interfaces for type safety and documentation
 */
export interface GetCollectionsArgs extends Partial<WorkspaceArg> {
  name?: string;
  limit?: number;
  offset?: number;
}

export interface GetCollectionArgs extends CollectionIdArg {
  access_key?: string;
  model?: 'minimal';
}

export interface GetCollectionFolderArgs extends CollectionIdArg {
  folder_id: string;
  ids?: boolean;
  uid?: boolean;
  populate?: boolean;
}

export interface DeleteCollectionFolderArgs extends CollectionIdArg {
  folder_id: string;
}

export interface GetCollectionRequestArgs extends CollectionIdArg {
  request_id: string;
  ids?: boolean;
  uid?: boolean;
  populate?: boolean;
}

export interface DeleteCollectionRequestArgs extends CollectionIdArg {
  request_id: string;
}

export interface GetCollectionResponseArgs extends CollectionIdArg {
  response_id: string;
  ids?: boolean;
  uid?: boolean;
  populate?: boolean;
}

export interface DeleteCollectionResponseArgs extends CollectionIdArg {
  response_id: string;
}

/**
 * Core collection data structures
 */
export interface CollectionInfo {
  name: string;
  description?: string;
  schema: string;
}

export interface CollectionItem {
  id?: string;
  name?: string;
  description?: string;
  request?: CollectionRequest;
  response?: CollectionResponse[];
  item?: CollectionItem[];
  auth?: CollectionAuth;
  event?: CollectionEvent[];
  variable?: CollectionVariable[];
  protocolProfileBehavior?: Record<string, any>;
}

export interface CollectionRequest {
  method?: string;
  header?: Array<{key: string; value: string; description?: string}>;
  url?: string | {
    raw?: string;
    protocol?: string;
    host?: string[];
    path?: string[];
    variable?: Array<{
      key: string;
      value?: string;
      description?: string;
    }>;
  };
  description?: string;
  body?: any;
}

export interface CollectionResponse {
  id?: string;
  name?: string;
  originalRequest?: CollectionRequest;
  status?: string;
  code?: number;
  header?: Array<{key: string; value: string}>;
  body?: string;
  cookie?: any[];
}

export interface CollectionAuth {
  type: string;
  [key: string]: any;
}

export interface CollectionEvent {
  listen: string;
  script?: {
    id?: string;
    type?: string;
    exec?: string[];
  };
}

export interface CollectionVariable {
  key: string;
  value?: string;
  type?: string;
  enabled?: boolean;
}

/**
 * Operation interfaces
 */
export interface CreateCollectionArgs extends WorkspaceArg {
  collection: {
    info: CollectionInfo;
    item?: CollectionItem[];
    auth?: CollectionAuth;
    event?: CollectionEvent[];
    variable?: CollectionVariable[];
  };
}

export interface UpdateCollectionArgs extends CollectionIdArg {
  collection: {
    info: CollectionInfo;
    item: CollectionItem[];
    auth?: CollectionAuth;
    event?: CollectionEvent[];
    variable?: CollectionVariable[];
  };
}

export interface ForkCollectionArgs extends CollectionIdArg, WorkspaceArg {
  label: string;
}

```

--------------------------------------------------------------------------------
/src/types/resource.ts:
--------------------------------------------------------------------------------

```typescript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

/**
 * Represents a resource that can be exposed through the MCP server
 */
export interface Resource {
  uri: string;           // Unique identifier for the resource
  name: string;          // Human-readable name
  description?: string;  // Optional description
  mimeType?: string;    // Optional MIME type
}

/**
 * Represents a resource template for dynamic resources
 */
export interface ResourceTemplate {
  uriTemplate: string;   // URI template following RFC 6570
  name: string;          // Human-readable name for this type
  description?: string;  // Optional description
  mimeType?: string;    // Optional MIME type for all matching resources
}

/**
 * Represents the content of a resource
 */
export interface ResourceContent {
  uri: string;          // The URI of the resource
  mimeType?: string;    // Optional MIME type
  text?: string;        // For text resources
  blob?: string;        // For binary resources (base64 encoded)
}

/**
 * Interface for handling MCP resources
 */
export interface ResourceHandler {
  /**
   * List all available direct resources
   * @returns Promise<Resource[]>
   * @throws McpError if resources cannot be listed
   */
  listResources(): Promise<Resource[]>;

  /**
   * List all available resource templates
   * @returns Promise<ResourceTemplate[]>
   * @throws McpError if templates cannot be listed
   */
  listResourceTemplates(): Promise<ResourceTemplate[]>;

  /**
   * Read a resource's contents
   * @param uri The URI of the resource to read
   * @returns Promise<ResourceContent[]>
   * @throws McpError if resource cannot be read or URI is invalid
   */
  readResource(uri: string): Promise<ResourceContent[]>;

  /**
   * Validate a resource URI
   * @param uri The URI to validate
   * @returns boolean indicating if URI is valid
   */
  validateUri(uri: string): boolean;

  /**
   * Parse a resource URI into its components
   * @param uri The URI to parse
   * @returns Object containing parsed URI components
   * @throws McpError if URI format is invalid
   */
  parseUri(uri: string): {
    protocol: string;
    resourceType: string;
    params: Record<string, string>;
  };
}

/**
 * Base class for implementing resource handlers
 */
export abstract class BaseResourceHandler implements ResourceHandler {
  abstract listResources(): Promise<Resource[]>;
  abstract listResourceTemplates(): Promise<ResourceTemplate[]>;
  abstract readResource(uri: string): Promise<ResourceContent[]>;

  validateUri(uri: string): boolean {
    try {
      this.parseUri(uri);
      return true;
    } catch {
      return false;
    }
  }

  parseUri(uri: string): {
    protocol: string;
    resourceType: string;
    params: Record<string, string>;
  } {
    const match = uri.match(/^([a-zA-Z]+):\/\/([^/]+)(?:\/(.+))?$/);
    if (!match) {
      throw new McpError(
        ErrorCode.InvalidRequest,
        `Invalid URI format: ${uri}`
      );
    }

    const [, protocol, resourceType, path] = match;
    const params: Record<string, string> = {};

    if (path) {
      const segments = path.split('/');
      segments.forEach((segment, index) => {
        if (segment.startsWith('{') && segment.endsWith('}')) {
          const paramName = segment.slice(1, -1);
          const nextSegment = segments[index + 1];
          if (nextSegment && !nextSegment.startsWith('{')) {
            params[paramName] = nextSegment;
          }
        }
      });
    }

    return { protocol, resourceType, params };
  }
}

```

--------------------------------------------------------------------------------
/docs/api/summaries/notes.md:
--------------------------------------------------------------------------------

```markdown
## Notes

### API Overview
This implementation provides comprehensive coverage of the Postman API, including:

1. Core Resource Management
   - Workspaces (personal, team, private, public, partner)
   - Collections with Postman Collection Format v2.1.0 support
   - Environments with variable management
   - APIs with schema version control
   - Mock servers with response simulation
   - Monitors with scheduled runs

2. Version Control Features
   - Forking capabilities for collections and environments
   - Merge and pull operations
   - Git repository integration for APIs
   - Version history tracking
   - Pull request workflows

3. Enterprise Features
   - Private API Network management
   - Secret scanning and management
   - Audit logging
   - Advanced role-based access control
   - Team-level controls
   - Tag management across resources

4. Security Features
   - API security validation with OWASP rules
   - Secret detection and resolution
   - Role-based access control
   - Workspace visibility controls
   - Authentication options (API key, SCIM)

5. Collaboration Features
   - Comments system across resources
   - Thread-based discussions
   - Role and permission management
   - Team workspaces
   - Resource sharing controls

### Implementation Patterns

1. Consistent Resource Management
   - CRUD operations follow standard patterns
   - Workspace-scoped resources
   - Standardized metadata handling
   - Common error patterns
   - Versioning support

2. Flexible Pagination
   - Cursor-based pagination for large datasets
   - Limit/offset pagination where appropriate
   - Consistent parameter naming
   - Clear pagination metadata

3. Error Handling
   - Standard HTTP status codes
   - Detailed error messages
   - Domain-specific error types
   - Clear error resolution guidance

4. Asynchronous Operations
   - Task-based tracking
   - Status polling endpoints
   - Clear completion indicators
   - Timeout handling

5. API Versioning
   - Version headers required
   - Clear version dependencies
   - Backward compatibility notes
   - Version-specific features

### Best Practices

1. Resource Organization
   - Logical endpoint grouping
   - Clear resource relationships
   - Consistent naming conventions
   - Proper resource scoping

2. Security Implementation
   - Role-based access control
   - Resource-level permissions
   - Enterprise security features
   - Audit trail maintenance

3. Performance Considerations
   - Pagination for large datasets
   - Async operations for long-running tasks
   - Resource size limits
   - Rate limiting support

4. Documentation
   - Clear endpoint descriptions
   - Request/response examples
   - Error documentation
   - Feature availability notes

### Key Considerations

1. Enterprise vs Standard Features
   - Clear feature availability marking
   - Plan-specific endpoint behavior
   - Enterprise-only capabilities
   - Feature access control

2. Resource Limitations
   - Collection size limits (20MB)
   - Comment length limits (10,000 chars)
   - Rate limiting considerations
   - Plan-based restrictions

3. Version Control
   - Git integration capabilities
   - Fork and merge workflows
   - Version history management
   - Change tracking

4. Authentication & Authorization
   - Multiple auth methods
   - Role-based access
   - Resource permissions
   - Team-level controls

This implementation provides a robust and feature-rich API that supports both basic usage patterns and advanced workflows through version control, security features, and team collaboration tools. The API is designed to be scalable, maintainable, and secure, with clear documentation and consistent patterns throughout.

```

--------------------------------------------------------------------------------
/docs/api/summaries/monitors.md:
--------------------------------------------------------------------------------

```markdown
## Monitors

### Implemented Operations
- Get all monitors (`GET /monitors`)
  - Parameters:
    - `#/components/parameters/workspaceResultsQuery`
  - Responses:
    - 200: `#/components/responses/getMonitors`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Create monitor (`POST /monitors`)
  - Parameters:
    - `#/components/parameters/workspaceQuery`
  - Note: Cannot create monitors for collections added to an API definition
  - Request Body: `#/components/requestBodies/createMonitor`
    - Required fields:
      - name: Monitor name
      - collection: Collection ID to monitor
      - schedule: Schedule configuration
        - cron: Cron expression for timing
        - timezone: Timezone for schedule
    - Optional fields:
      - environment: Environment ID to use
      - options: Monitor options
        - strictSSL: SSL verification setting
        - followRedirects: Redirect handling
        - requestTimeout: Request timeout in ms
      - notifications: Notification settings
  - Responses:
    - 200: `#/components/responses/createMonitor`
    - 400: `#/components/responses/monitors400CreateErrors`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/common403ErrorAndFeatureUnavailable`
    - 500: `#/components/responses/common500ErrorServerError`

- Get specific monitor (`GET /monitors/{monitorId}`)
  - Parameters:
    - `#/components/parameters/monitorId` (required)
  - Responses:
    - 200: `#/components/responses/getMonitor`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 404: `#/components/responses/instanceNotFoundMonitor`
    - 500: `#/components/responses/common500ErrorServerError`

- Update monitor (`PUT /monitors/{monitorId}`)
  - Parameters:
    - `#/components/parameters/monitorId` (required)
  - Request Body: `#/components/requestBodies/updateMonitor`
    - Optional fields:
      - name: Updated monitor name
      - collection: New collection ID
      - environment: New environment ID
      - schedule: Updated schedule configuration
        - cron: New cron expression
        - timezone: New timezone
      - options: Updated monitor options
        - strictSSL: SSL verification setting
        - followRedirects: Redirect handling
        - requestTimeout: Request timeout in ms
      - notifications: Updated notification settings
  - Responses:
    - 200: `#/components/responses/updateMonitor`
    - 400: `#/components/responses/monitors400ErrorInvalidCronPattern`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 404: `#/components/responses/instanceNotFoundMonitor`
    - 500: `#/components/responses/common500ErrorServerError`

- Delete monitor (`DELETE /monitors/{monitorId}`)
  - Parameters:
    - `#/components/parameters/monitorId` (required)
  - Responses:
    - 200: `#/components/responses/deleteMonitor`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Run monitor (`POST /monitors/{monitorId}/run`)
  - Parameters:
    - `#/components/parameters/monitorId` (required)
    - `#/components/parameters/async`
  - Note: For async=true, response won't include stats, executions, and failures
  - Note: Use GET /monitors/{id} to get this information for async runs
  - Responses:
    - 200: `#/components/responses/runMonitor`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 500: `#/components/responses/common500ErrorServerError`

### Key Features
- Monitor CRUD operations
- Scheduled runs
- Manual run capability
- Run results and statistics
- Workspace integration
- Async/sync run modes
- Feature availability control

```

--------------------------------------------------------------------------------
/src/types/apis.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * API Types for Postman API Operations
 */
import { CollectionInfo } from './collection.js';

// Schema type enums
export enum ApiSchemaType {
  PROTO2 = 'proto:2',
  PROTO3 = 'proto:3',
  GRAPHQL = 'graphql',
  OPENAPI_3_1 = 'openapi:3_1',
  OPENAPI_3 = 'openapi:3',
  OPENAPI_2 = 'openapi:2',
  OPENAPI_1 = 'openapi:1',
  RAML_1 = 'raml:1',
  RAML_0_8 = 'raml:0_8',
  WSDL_2 = 'wsdl:2',
  WSDL_1 = 'wsdl:1',
  ASYNCAPI_2 = 'asyncapi:2'
}

// Collection operation types
export enum ApiCollectionOperationType {
  COPY = 'COPY_COLLECTION',
  CREATE = 'CREATE_NEW',
  GENERATE = 'GENERATE_FROM_SCHEMA'
}

// Basic API types
export interface ApiBase {
  name: string;
  summary?: string;
  description?: string;
}

// Essential request types
export interface CreateApiRequest {
  name: string;
  workspaceId: string;
  summary?: string;
  description?: string;
}

export interface UpdateApiRequest {
  name?: string;
  summary?: string;
  description?: string;
  versionTag?: string;
}

// Parameters for list/query operations
export interface ListApisParams {
  workspaceId: string;
  cursor?: string;
  limit?: number;
  createdBy?: number;
  description?: string;
}

export interface GetApiParams {
  apiId: string;
  include?: Array<'collections' | 'versions' | 'schemas' | 'gitInfo'>;
}

// Schema related types
export interface SchemaFile {
  path: string;
  content: string;
  root?: {
    enabled: boolean;
  };
}

export interface CreateApiSchemaRequest {
  type: ApiSchemaType;
  files: SchemaFile[];
}

// Version related types
export interface SchemaReference {
  id?: string;
  filePath?: string;
  directoryPath?: string;
}

export interface CollectionReference {
  id?: string;
  filePath?: string;
}

export interface CreateApiVersionRequest {
  name: string;
  schemas: SchemaReference[];
  collections: CollectionReference[];
  branch?: string;
  releaseNotes?: string;
}

export interface UpdateApiVersionRequest {
  name: string;
  releaseNotes?: string;
}

// Collection related types
export interface AddApiCollectionRequest {
  operationType: ApiCollectionOperationType;
  name?: string;
  data?: {
    collectionId?: string;
    info?: CollectionInfo;
    item?: any[];
  };
  options?: Record<string, any>;
}

// Comment related types
export interface CommentRequest {
  content: string;
  threadId?: number;
}

export interface UpdateCommentRequest {
  content: string;
}

// Tag related types
export interface ApiTag {
  slug: string;
  name?: string;
}

export interface UpdateApiTagsRequest {
  tags: ApiTag[];
}

// Query parameters
export interface QueryParams {
  cursor?: string;
  limit?: number;
}

export interface GetSchemaFilesParams extends QueryParams {
  apiId: string;
  schemaId: string;
  versionId?: string;
}

export interface GetCommentsParams extends QueryParams {
  apiId: string;
}

// Response types
export interface ApiResponse {
  id: string;
  name: string;
  summary?: string;
  description?: string;
  createdAt: string;
  updatedAt: string;
  createdBy: number;
  updatedBy: number;
  versions?: ApiVersionResponse[];
  collections?: ApiCollectionResponse[];
  schemas?: ApiSchemaResponse[];
  gitInfo?: ApiGitInfo;
}

export interface ApiVersionResponse {
  id: string;
  name: string;
  releaseNotes?: string;
  createdAt: string;
  updatedAt: string;
}

export interface ApiCollectionResponse {
  id: string;
  name: string;
  uid: string;
}

export interface ApiSchemaResponse {
  id: string;
  type: ApiSchemaType;
  files: SchemaFile[];
}

export interface ApiGitInfo {
  repository: string;
  branch: string;
  folder?: string;
}

export interface ApiCommentResponse {
  id: number;
  content: string;
  threadId?: number;
  createdAt: string;
  updatedAt: string;
  createdBy: number;
}

export interface ApiTagResponse {
  slug: string;
  name: string;
  createdAt: string;
  updatedAt: string;
}

// Task status types
export interface AsyncTaskResponse {
  id: string;
  status: 'pending' | 'completed' | 'failed';
  result?: any;
  error?: string;
}

```

--------------------------------------------------------------------------------
/src/handlers/tool-handler.ts:
--------------------------------------------------------------------------------

```typescript
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  McpError,
  ErrorCode
} from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import {
  ToolDefinition,
  ToolHandler as IToolHandler,
  ToolResource
} from '../types/index.js';
import axios from 'axios';

// Schema for listing tool resources
const ListToolResourcesRequestSchema = z.object({
  method: z.literal('tools/resources/list')
});

// Detect if we're running in Bun
const isBunRuntime = typeof (globalThis as any).Bun !== 'undefined';

/**
 * Handles tool-related requests and connects them to tool implementations
 */
export class ToolHandler {
  constructor(
    private server: Server,
    private toolDefinitions: ToolDefinition[],
    private toolHandlers: Map<string, IToolHandler>
  ) {
    this.setupHandlers();
  }

  private setupHandlers() {
    this.setupListTools();
    this.setupCallTool();
    // Only setup tool resources handler if not running in Bun (due to type compatibility issues)
    if (!isBunRuntime) {
      this.setupListToolResources();
    }
  }

  private setupListTools() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: this.toolDefinitions,
    }));
  }

  private setupListToolResources() {
    this.server.setRequestHandler(ListToolResourcesRequestSchema as any, async () => {
      try {
        const allResources: ToolResource[] = [];

        // Gather resources from all tool handlers
        for (const [toolName, handler] of this.toolHandlers.entries()) {
          if ('listToolResources' in handler) {
            const resources = await handler.listToolResources();
            allResources.push(...resources);
          }
        }

        return {
          resources: allResources
        };
      } catch (error) {
        if (error instanceof McpError) {
          throw error;
        }
        throw new McpError(
          ErrorCode.InternalError,
          error instanceof Error ? error.message : 'Failed to list tool resources'
        );
      }
    });
  }

  private async validateToolResource(toolName: string, resourceUri: string): Promise<boolean> {
    const handler = this.toolHandlers.get(toolName);
    if (!handler || !('canHandleResource' in handler)) {
      return false;
    }
    return handler.canHandleResource(resourceUri);
  }

  private setupCallTool() {
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      try {
        const { name, arguments: args = {} } = request.params;

        // Find the tool definition
        const toolDef = this.toolDefinitions.find(t => t.name === name);
        if (!toolDef) {
          throw new McpError(
            ErrorCode.MethodNotFound,
            `Unknown tool: ${name}`
          );
        }

        // Get the appropriate handler
        const handler = this.toolHandlers.get(name);
        if (!handler) {
          throw new McpError(
            ErrorCode.MethodNotFound,
            `No handler found for tool: ${name}`
          );
        }

        // If the tool is operating on a resource, validate access
        if ('resourceUri' in args && typeof args.resourceUri === 'string') {
          const canHandle = await this.validateToolResource(name, args.resourceUri);
          if (!canHandle) {
            throw new McpError(
              ErrorCode.InvalidRequest,
              `Tool ${name} cannot operate on resource: ${args.resourceUri}`
            );
          }
        }

        // Execute the tool call
        const response = await handler.handleToolCall(name, args);

        // Transform the response to match the SDK's expected format
        return {
          _meta: {},
          tools: [toolDef],
          content: response.content,
          isError: response.isError,
        };
      } catch (error) {
        if (error instanceof McpError) {
          throw error;
        }
        if (axios.isAxiosError(error)) {
          return {
            _meta: {},
            tools: [],
            content: [
              {
                type: 'text',
                text: `Postman API error: ${error.response?.data?.error?.message || error.message}`,
              },
            ],
            isError: true,
          };
        }
        throw new McpError(
          ErrorCode.InternalError,
          error instanceof Error ? error.message : 'An unknown error occurred'
        );
      }
    });
  }
}

```

--------------------------------------------------------------------------------
/src/tools/api/monitors/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  {
    name: 'list_monitors',
    description: 'Get all monitors',
    inputSchema: {
      type: 'object',
      properties: {
        workspace: {
          type: 'string',
          description: 'Return only monitors found in the given workspace'
        }
      },
      required: [] // Empty array since workspace is optional
    }
  },
  {
    name: 'get_monitor',
    description: 'Get details of a specific monitor',
    inputSchema: {
      type: 'object',
      properties: {
        monitorId: {
          type: 'string',
          description: 'Monitor ID'
        }
      },
      required: ['monitorId']
    }
  },
  {
    name: 'create_monitor',
    description: 'Create a new monitor. Cannot create monitors for collections added to an API definition.',
    inputSchema: {
      type: 'object',
      properties: {
        monitor: {
          type: 'object',
          description: 'Monitor details',
          properties: {
            name: { type: 'string', description: 'Monitor name' },
            collection: { type: 'string', description: 'Collection ID to monitor' },
            environment: { type: 'string', description: 'Environment ID to use' },
            schedule: {
              type: 'object',
              description: 'Schedule configuration',
              properties: {
                cron: { type: 'string', description: 'Cron expression for timing' },
                timezone: { type: 'string', description: 'Timezone for schedule' }
              },
              required: ['cron', 'timezone']
            },
            options: {
              type: 'object',
              description: 'Monitor options',
              properties: {
                strictSSL: { type: 'boolean', description: 'SSL verification setting' },
                followRedirects: { type: 'boolean', description: 'Redirect handling' },
                requestTimeout: { type: 'number', description: 'Request timeout in ms' }
              }
            }
          },
          required: ['name', 'collection', 'schedule']
        },
        workspace: { type: 'string', description: 'Workspace ID' }
      },
      required: ['monitor']
    }
  },
  {
    name: 'update_monitor',
    description: 'Update an existing monitor',
    inputSchema: {
      type: 'object',
      properties: {
        monitorId: {
          type: 'string',
          description: 'Monitor ID'
        },
        monitor: {
          type: 'object',
          description: 'Monitor details to update',
          properties: {
            name: { type: 'string', description: 'Updated monitor name' },
            collection: { type: 'string', description: 'New collection ID' },
            environment: { type: 'string', description: 'New environment ID' },
            schedule: {
              type: 'object',
              description: 'Updated schedule configuration',
              properties: {
                cron: { type: 'string', description: 'New cron expression' },
                timezone: { type: 'string', description: 'New timezone' }
              }
            },
            options: {
              type: 'object',
              description: 'Updated monitor options',
              properties: {
                strictSSL: { type: 'boolean', description: 'SSL verification setting' },
                followRedirects: { type: 'boolean', description: 'Redirect handling' },
                requestTimeout: { type: 'number', description: 'Request timeout in ms' }
              }
            }
          }
        }
      },
      required: ['monitorId', 'monitor']
    }
  },
  {
    name: 'delete_monitor',
    description: 'Delete a monitor',
    inputSchema: {
      type: 'object',
      properties: {
        monitorId: {
          type: 'string',
          description: 'Monitor ID'
        }
      },
      required: ['monitorId']
    }
  },
  {
    name: 'run_monitor',
    description: 'Run a monitor. For async=true, response won\'t include stats, executions, and failures. Use GET /monitors/{id} to get this information for async runs.',
    inputSchema: {
      type: 'object',
      properties: {
        monitorId: {
          type: 'string',
          description: 'Monitor ID'
        },
        async: {
          type: 'boolean',
          description: 'If true, runs the monitor asynchronously from the created monitor run task',
          default: false
        }
      },
      required: ['monitorId']
    }
  }
];

```

--------------------------------------------------------------------------------
/docs/api/summaries/security-features.md:
--------------------------------------------------------------------------------

```markdown
## Security Features

### API Security Validation
- API definition security validation (`POST /security/api-validation`)
  - Description: Analyzes API definition against predefined rulesets
  - Note: Maximum definition size: 10 MB
  - Note: Requires imported and enabled OWASP security rules
  - Request Body: `#/components/requestBodies/schemaSecurityValidation`
    - Required fields:
      - type: Schema type (e.g., "openapi3")
      - definition: API definition content
      - rulesets: Array of ruleset IDs to validate against
  - Responses:
    - 200: `#/components/responses/schemaSecurityValidation`
    - 400: `#/components/responses/schemaSecurityValidation400Error`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/featureUnavailable403Error`
    - 500: `#/components/responses/common500ErrorServerError`

### Secret Scanner (Enterprise)
- Get secret types (`GET /secret-types`)
  - Description: Gets metadata of supported secret types
  - Responses:
    - 200: `#/components/responses/getSecretTypes`
    - 401: `#/components/responses/secretScanner401Error`
    - 403: `#/components/responses/secretScanner403ErrorAndFeatureUnavailable`
    - 500: `#/components/responses/secretScanner500Error`

- Search detected secrets (`POST /detected-secrets-queries`)
  - Description: Returns secrets detected by Secret Scanner, grouped by workspace/resource
  - Parameters:
    - `#/components/parameters/limit`
    - `#/components/parameters/cursor`
    - `#/components/parameters/include`
    - `#/components/parameters/since`
    - `#/components/parameters/until`
  - Note: Empty request body returns all results
  - Request Body: `#/components/requestBodies/detectedSecretsQueries`
    - Optional fields:
      - workspaces: Array of workspace IDs to search
      - secretTypes: Array of secret type IDs
      - resolutions: Array of resolution statuses
      - resources: Array of resource types
  - Responses:
    - 200: `#/components/responses/detectedSecretsQueries`
    - 400: `#/components/responses/detectedSecretsQuery400Errors`
    - 401: `#/components/responses/secretScanner401Error`
    - 403: `#/components/responses/secretScanner403ErrorAndFeatureUnavailable`
    - 500: `#/components/responses/secretScanner500Error`

- Update secret resolution status (`PUT /detected-secrets/{secretId}`)
  - Parameters:
    - `#/components/parameters/secretId` (required)
  - Request Body: `#/components/requestBodies/updateSecretResolutions`
    - Required fields:
      - resolution: New resolution status
      - comment: Optional resolution comment
  - Responses:
    - 200: `#/components/responses/updateSecretResolutions`
    - 400: `#/components/responses/secretScanner400InvalidResolutionError`
    - 401: `#/components/responses/secretScanner401Error`
    - 403: `#/components/responses/secretScanner403ErrorAndFeatureUnavailable`
    - 500: `#/components/responses/secretScanner500Error`

- Get detected secrets locations (`GET /detected-secrets/{secretId}/locations`)
  - Parameters:
    - `#/components/parameters/secretId` (required)
    - `#/components/parameters/limit`
    - `#/components/parameters/cursor`
    - `#/components/parameters/workspaceIdQueryTrue`
    - `#/components/parameters/since`
    - `#/components/parameters/until`
    - `#/components/parameters/resourceType`
  - Responses:
    - 200: `#/components/responses/getSecretsLocations`
    - 400: `#/components/responses/secretScanner400Error`
    - 401: `#/components/responses/secretScanner401Error`
    - 403: `#/components/responses/secretScanner403ErrorAndFeatureUnavailable`
    - 500: `#/components/responses/secretScanner500Error`

### Audit Logs (Enterprise)
- Get team audit logs (`GET /audit/logs`)
  - Parameters:
    - `#/components/parameters/auditLogsSinceQuery`
    - `#/components/parameters/auditLogsUntilQuery`
    - `#/components/parameters/auditLogsLimitQuery`
    - `#/components/parameters/cursor`
    - `#/components/parameters/auditLogsOrderBy`
  - Responses:
    - 200: `#/components/responses/getAuditLogs`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

### Key Features
- API security validation
  - OWASP security rules integration
  - Schema validation
  - CI/CD process integration
  - Rule violation tracking
  - Solution suggestions

- Secret scanning
  - Multiple secret type support
  - Workspace/resource grouping
  - Location tracking
  - Resolution management
  - Enterprise-level control

- Audit logging
  - Team activity tracking
  - Event filtering
  - Pagination support
  - Enterprise plan feature

```

--------------------------------------------------------------------------------
/docs/api/summaries/common-features.md:
--------------------------------------------------------------------------------

```markdown
## Common Features

### Pagination
- Cursor-based pagination
  - Used in endpoints like:
    - `/apis` with `#/components/parameters/cursor`
    - `/collection-access-keys` with `#/components/parameters/cursor`
    - `/detected-secrets/{secretId}/locations` with `#/components/parameters/cursor`
  - Often paired with `limit` parameter to control page size
  - Provides consistent forward pagination
  - Returns next cursor in response for subsequent requests

- Limit/offset pagination
  - Used in endpoints like:
    - `/collections` with `#/components/parameters/limitNoDefault` and `#/components/parameters/offsetNoDefault`
    - `/network/private` with `#/components/parameters/limitDefault1000` and `#/components/parameters/offset`
  - Different default limits per endpoint (e.g., 1000 for Private API Network)
  - Allows random access to result pages
  - Supports both forward and backward pagination

### Error Handling
- Standard HTTP status codes
  - 200: Successful operation
  - 201: Resource created
  - 202: Accepted (async operations)
  - 204: No content (successful deletion)
  - 400: Bad request/Invalid parameters
  - 401: Unauthorized
  - 403: Forbidden/Feature unavailable
  - 404: Resource not found
  - 422: Unprocessable entity
  - 500: Internal server error

- Detailed error messages
  - Consistent error response format
  - Specific error types for different scenarios
  - Error categorization by domain (e.g., API errors, collection errors)
  - Clear error descriptions and potential solutions

### Resource Management
- Workspace scoping
  - Most resources belong to a workspace
  - Workspace ID required for creation operations
  - Workspace-level permissions and visibility
  - Support for different workspace types:
    - Personal
    - Team
    - Private
    - Public
    - Partner

- Resource metadata
  - Creation and modification timestamps
  - Owner/creator information
  - Version information where applicable
  - Resource relationships and dependencies

- Version control
  - Forking support
  - Merge capabilities
  - Version history tracking
  - Git repository integration
  - Pull/merge request workflows

- Commenting system
  - Comments on various resources (APIs, collections, etc.)
  - Thread-based discussions
  - Maximum 10,000 characters per comment
  - Comment management (CRUD operations)
  - Thread deletion rules (deleting first comment deletes thread)

- Tags and categorization
  - Enterprise feature
  - Supported on:
    - Workspaces
    - APIs
    - Collections
  - Consistent tag operations across resources:
    - GET to retrieve tags
    - PUT to update tags (replaces all existing tags)
  - Common response schemas:
    - Success: `#/components/responses/tagGetPut`
    - Errors:
      - 400: `#/components/responses/tag400Error`
      - 401: `#/components/responses/tag401Error`
      - 403: `#/components/responses/tag403Error`
      - 404: `#/components/responses/tag404Error`
      - 500: `#/components/responses/tag500Error`

### Common Parameters
- Workspace identification
  - `#/components/parameters/workspaceId`
  - `#/components/parameters/workspaceQuery`
  - `#/components/parameters/workspaceIdQuery`
  - Used for resource scoping and access control

- Pagination control
  - `#/components/parameters/cursor`
  - `#/components/parameters/limit`
  - `#/components/parameters/offset`
  - Consistent across paginated endpoints

- Date range filtering
  - `#/components/parameters/since`
  - `#/components/parameters/until`
  - ISO 8601 timestamp format
  - Used for filtering time-based data

- Sorting and ordering
  - `#/components/parameters/direction`
  - Various sort parameters specific to resources
  - Consistent sort parameter naming

- API versioning
  - `#/components/parameters/v10Accept` header required for many endpoints
  - Version-specific error responses (e.g., `#/components/responses/v9Unsupported`)
  - Clear version requirements in documentation

### Common Response Patterns
- Success responses
  - Consistent data structure
  - Resource metadata included
  - Pagination information when applicable
  - Clear success indicators

- Error responses
  - Standard error format
  - Detailed error messages
  - Error codes for programmatic handling
  - Suggested solutions when applicable

- Asynchronous operations
  - 202 Accepted response
  - Task ID for status tracking
  - Polling endpoints for status updates
  - Clear completion indicators

### Key Features
- Consistent resource management
- Standardized error handling
- Flexible pagination options
- Comprehensive metadata
- Version control capabilities
- Enterprise feature support
- Clear API versioning

```

--------------------------------------------------------------------------------
/src/tools/api/base.ts:
--------------------------------------------------------------------------------

```typescript
import axios, { AxiosInstance } from 'axios';
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { ToolDefinition, ToolResource } from '../../types/index.js';

interface PostmanToolOptions {
  baseURL?: string;
  acceptHeader?: string;
}

type ToolMapping = { [key: string]: any };

/**
 * Base class for Postman API tools
 * Provides common functionality and HTTP client setup
 */
export class BasePostmanTool {
  /**
   * Protected HTTP client for making API requests
   * All derived classes should use this for Postman API calls
   */
  protected readonly client: AxiosInstance;

  constructor(
    apiKey: string | null,
    options: PostmanToolOptions = {},
    existingClient?: AxiosInstance
  ) {
    const baseURL = options.baseURL || 'https://api.getpostman.com';

    if (existingClient) {
      this.client = existingClient;
    } else {
      // Create new client with API key
      if (!apiKey) {
        throw new Error('API key is required when not providing an existing client');
      }

      this.client = axios.create({
        baseURL,
        headers: {
          'X-Api-Key': apiKey,
          'Content-Type': 'application/json'
        }
      });
    }

    // Add custom Accept header if provided
    if (options.acceptHeader) {
      this.client.interceptors.request.use(config => {
        config.headers['Accept'] = options.acceptHeader;
        return config;
      });
    }

    // Add response interceptor for error handling
    this.client.interceptors.response.use(
      response => response,
      error => {
        if (error.response) {
          // Map HTTP status codes to appropriate MCP error codes
          switch (error.response.status) {
            case 400:
              throw new McpError(
                ErrorCode.InvalidRequest,
                error.response.data?.error?.message || 'Invalid request parameters'
              );
            case 401:
              throw new McpError(
                ErrorCode.InvalidRequest,
                'Unauthorized: Invalid or missing API key'
              );
            case 403:
              throw new McpError(
                ErrorCode.InvalidRequest,
                'Forbidden: Insufficient permissions or feature unavailable'
              );
            case 404:
              throw new McpError(
                ErrorCode.InvalidRequest,
                'Resource not found'
              );
            case 422:
              throw new McpError(
                ErrorCode.InvalidRequest,
                error.response.data?.error?.message || 'Invalid request parameters'
              );
            case 429:
              throw new McpError(
                ErrorCode.InvalidRequest,
                'Rate limit exceeded'
              );
            default:
              throw new McpError(
                ErrorCode.InternalError,
                error.response.data?.error?.message || 'Internal server error'
              );
          }
        } else if (error.request) {
          throw new McpError(
            ErrorCode.InternalError,
            'No response received from Postman API'
          );
        } else {
          throw new McpError(
            ErrorCode.InternalError,
            `Error making request: ${error.message}`
          );
        }
      }
    );
  }

  /**
   * Generate tool mappings from tool definitions
   * Each derived class should implement getToolDefinitions() to provide its specific tools
   * @returns Object mapping tool names to the tool handler instance
   */
  public getToolMappings(): ToolMapping {
    const toolDefinitions = this.getToolDefinitions();
    const mappings: ToolMapping = {};

    toolDefinitions.forEach(tool => {
      mappings[tool.name] = this;
    });

    return mappings;
  }

  /**
   * Get tool definitions for this tool class
   * Must be implemented by derived classes
   */
  public getToolDefinitions(): ToolDefinition[] {
    throw new Error('getToolDefinitions() must be implemented by derived class');
  }

  /**
   * List resources that this tool can interact with
   * Should be implemented by derived classes that handle resources
   */
  public async listToolResources(): Promise<ToolResource[]> {
    return [];
  }

  /**
   * Get details about how this tool can interact with a specific resource
   * Should be implemented by derived classes that handle resources
   * @throws {McpError} If the resource cannot be handled by this tool
   */
  public async getToolResourceDetails(resourceUri: string): Promise<ToolResource> {
    throw new McpError(
      ErrorCode.InvalidRequest,
      `Resource ${resourceUri} cannot be handled by this tool`
    );
  }

  /**
   * Check if this tool can handle a specific resource
   */
  public async canHandleResource(resourceUri: string): Promise<boolean> {
    try {
      await this.getToolResourceDetails(resourceUri);
      return true;
    } catch (error) {
      return false;
    }
  }
}

```

--------------------------------------------------------------------------------
/src/tools/api/auth/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  {
    name: 'list_collection_access_keys',
    description: 'List collection access keys with optional filtering by collection ID',
    inputSchema: {
      type: 'object',
      properties: {
        collectionId: {
          type: 'string',
          description: 'Filter results by collection ID'
        },
        cursor: {
          type: 'string',
          description: 'Pagination cursor'
        }
      },
      required: [] // No required fields
    }
  },
  {
    name: 'delete_collection_access_key',
    description: 'Delete a collection access key',
    inputSchema: {
      type: 'object',
      required: ['keyId'],
      properties: {
        keyId: {
          type: 'string',
          description: 'The collection access key ID to delete'
        }
      }
    }
  },
  {
    name: 'list_workspace_roles',
    description: 'Get all available workspace roles based on team\'s plan',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [] // No required fields
    }
  },
  {
    name: 'get_workspace_roles',
    description: 'Get roles for a specific workspace',
    inputSchema: {
      type: 'object',
      required: ['workspaceId'],
      properties: {
        workspaceId: {
          type: 'string',
          description: 'The workspace ID'
        },
        includeScim: {
          type: 'boolean',
          description: 'Include SCIM info in response'
        }
      }
    }
  },
  {
    name: 'update_workspace_roles',
    description: 'Update workspace roles for users and groups (limited to 50 operations per call)',
    inputSchema: {
      type: 'object',
      required: ['workspaceId', 'operations'],
      properties: {
        workspaceId: {
          type: 'string',
          description: 'The workspace ID'
        },
        operations: {
          type: 'array',
          maxItems: 50,
          items: {
            type: 'object',
            required: ['op', 'path', 'value'],
            properties: {
              op: {
                type: 'string',
                enum: ['update'],
                description: 'Operation type'
              },
              path: {
                type: 'string',
                enum: ['/user', '/group', '/team'],
                description: 'Resource path'
              },
              value: {
                type: 'array',
                items: {
                  type: 'object',
                  required: ['id', 'role'],
                  properties: {
                    id: {
                      type: 'number',
                      description: 'User/group/team ID'
                    },
                    role: {
                      type: 'string',
                      enum: ['VIEWER', 'EDITOR'],
                      description: 'Role to assign'
                    }
                  }
                }
              }
            }
          }
        },
        identifierType: {
          type: 'string',
          enum: ['scim'],
          description: 'Optional SCIM identifier type'
        }
      }
    }
  },
  {
    name: 'get_collection_roles',
    description: 'Get roles for a collection',
    inputSchema: {
      type: 'object',
      required: ['collectionId'],
      properties: {
        collectionId: {
          type: 'string',
          description: 'The collection ID'
        }
      }
    }
  },
  {
    name: 'update_collection_roles',
    description: 'Update collection roles (requires EDITOR role)',
    inputSchema: {
      type: 'object',
      required: ['collectionId', 'operations'],
      properties: {
        collectionId: {
          type: 'string',
          description: 'The collection ID'
        },
        operations: {
          type: 'array',
          items: {
            type: 'object',
            required: ['op', 'path', 'value'],
            properties: {
              op: {
                type: 'string',
                enum: ['update'],
                description: 'Operation type'
              },
              path: {
                type: 'string',
                enum: ['/user', '/group', '/team'],
                description: 'Resource path'
              },
              value: {
                type: 'array',
                items: {
                  type: 'object',
                  required: ['id', 'role'],
                  properties: {
                    id: {
                      type: 'number',
                      description: 'User/group/team ID'
                    },
                    role: {
                      type: 'string',
                      enum: ['VIEWER', 'EDITOR'],
                      description: 'Role to assign'
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    name: 'get_authenticated_user',
    description: 'Get authenticated user information',
    inputSchema: {
      type: 'object',
      properties: {},
      required: [] // No required fields
    }
  }
];

```

--------------------------------------------------------------------------------
/docs/api/summaries/auth.md:
--------------------------------------------------------------------------------

```markdown
## Authentication & Authorization

### Authentication
- API Key authentication via `x-api-key` header
- Support for SCIM API key authentication
- Collection access key support

### Authorization
- Role-based access control
- Workspace-level permissions
- Team-level permissions
- Enterprise features access control

### Response References

#### Collection Access Keys
- GET `/collection-access-keys`
  - Parameters:
    - `#/components/parameters/collectionUidQuery`
    - `#/components/parameters/cursor`
  - Responses:
    - 200: `#/components/responses/getCollectionAccessKeys`
    - 400: `#/components/responses/common400ErrorInvalidCursor`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/common403ErrorForbidden`
    - 500: `#/components/responses/common500ErrorSomethingWrong`

- DELETE `/collection-access-keys/{keyId}`
  - Parameters:
    - `#/components/parameters/collectionAccessKeyId` (required)
  - Responses:
    - 204: No Content (successful deletion)
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/common403ErrorForbidden`
    - 404: `#/components/responses/collectionAccessKeyNotFound404Error`
    - 500: `#/components/responses/common500ErrorSomethingWrong`

#### Roles & Permissions

##### Workspace Roles
- GET `/workspaces-roles`
  - Description: Gets all available roles based on team's plan
  - Responses:
    - 200: `#/components/responses/getAllWorkspaceRoles`
    - 401: `#/components/responses/api401ErrorUnauthorized`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 500: `#/components/responses/common500ErrorInternalServer`

- GET `/workspaces/{workspaceId}/roles`
  - Parameters:
    - `#/components/parameters/workspaceId` (required)
    - `#/components/parameters/workspaceIncludeScimQuery`
  - Responses:
    - 200: `#/components/responses/getWorkspaceRoles`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/resourceNotFound404Error`
    - 500: `#/components/responses/common500ErrorInternalServer`

- PATCH `/workspaces/{workspaceId}/roles`
  - Parameters:
    - `#/components/parameters/workspaceId` (required)
    - `#/components/parameters/identifierType`
  - Notes:
    - Groups available on Enterprise plans
    - Include `identifierType=scim` header for SCIM IDs
    - Cannot set roles for personal and partner workspaces
    - Does not support Partner or Guest external roles
    - Limited to 50 operations per call
    - Request body must contain one unique action per user/group
  - Request Body: `#/components/requestBodies/updateWorkspaceRoles`
  - Responses:
    - 200: `#/components/responses/updateWorkspaceRoles`
    - 400: `#/components/responses/workspaceRoles400Error`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/resourceNotFound404Error`
    - 422: `#/components/responses/workspaceRoles422UnsupportRoleError`
    - 500: `#/components/responses/common500ErrorInternalServer`

##### Collection Roles
- GET `/collections/{collectionId}/roles`
  - Parameters:
    - `#/components/parameters/collectionId` (required)
  - Responses:
    - 200: `#/components/responses/getCollectionRoles`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/collection404ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorInternalServer`

- PATCH `/collections/{collectionId}/roles`
  - Parameters:
    - `#/components/parameters/collectionId` (required)
  - Notes:
    - Only users with EDITOR role can use this endpoint
    - Does not support Partner or Guest external roles
  - Request Body: `#/components/requestBodies/updateCollectionRoles`
  - Responses:
    - 204: No Content (successful update)
    - 400: `#/components/responses/collectionRoles400ErrorMissingProperty`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/collection404ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorInternalServer`

### User Information
- GET `/me` (Get authenticated user)
  - Note: Different response for Guest and Partner roles
  - Note: `flow_count` only returns for Free plan users
  - Responses:
    - 200: `#/components/responses/getAuthenticatedUser`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

### Key Features
- Multiple authentication methods
  - API key
  - SCIM API key
  - Collection access keys
- Role-based access control
  - Workspace roles
  - Collection roles
  - Team roles
- Permission management
  - User permissions
  - Group permissions (Enterprise)
  - Role assignment limits
- Enterprise features
  - SCIM support
  - Group management
  - Advanced role controls

### Notes
- Role operations support both user and user group management
- SCIM ID support available with `identifierType=scim` header
- Role operations are limited to 50 operations per call
- Partner and Guest external roles are not supported via the API
- Personal and partner workspace roles cannot be modified

```

--------------------------------------------------------------------------------
/src/tools/api/environments/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler,
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

/**
 * Implements Postman Environment API endpoints
 * All environment IDs must be in the format: {ownerId}-{environmentId}
 */
export class EnvironmentTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'list_environments':
          return await this.listEnvironments(args.workspace);
        case 'get_environment':
          return await this.getEnvironment(args.environmentId);
        case 'create_environment':
          return await this.createEnvironment(args);
        case 'update_environment':
          return await this.updateEnvironment(args);
        case 'delete_environment':
          return await this.deleteEnvironment(args.environmentId);
        case 'fork_environment':
          return await this.createEnvironmentFork(args);
        case 'get_environment_forks':
          return await this.getEnvironmentForks(args);
        case 'merge_environment_fork':
          return await this.mergeEnvironmentFork(args);
        case 'pull_environment':
          return await this.pullEnvironment(args);
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error: any) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  /**
   * List all environments in a workspace
   * If workspace not specified, lists environments in "My Workspace"
   */
  async listEnvironments(workspace?: string): Promise<ToolCallResponse> {
    const response = await this.client.get('/environments', {
      params: workspace ? { workspace } : undefined
    });
    return this.createResponse(response.data);
  }

  /**
   * Get details of a specific environment
   * @param environmentId Environment ID in format: {ownerId}-{environmentId}
   */
  async getEnvironment(environmentId: string): Promise<ToolCallResponse> {
    const response = await this.client.get(`/environments/${environmentId}`);
    return this.createResponse(response.data);
  }

  /**
   * Create a new environment in a workspace
   * Creates in "My Workspace" if workspace not specified
   */
  async createEnvironment(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post('/environments', {
      environment: args.environment,
      workspace: args.workspace ? { id: args.workspace, type: 'workspace' } : undefined
    });
    return this.createResponse(response.data);
  }

  /**
   * Update an existing environment
   * @param args.environmentId Environment ID in format: {ownerId}-{environmentId}
   */
  async updateEnvironment(args: any): Promise<ToolCallResponse> {
    const response = await this.client.put(
      `/environments/${args.environmentId}`,
      { environment: args.environment }
    );
    return this.createResponse(response.data);
  }

  /**
   * Delete an environment
   * @param environmentId Environment ID in format: {ownerId}-{environmentId}
   */
  async deleteEnvironment(environmentId: string): Promise<ToolCallResponse> {
    const response = await this.client.delete(`/environments/${environmentId}`);
    return this.createResponse(response.data);
  }

  /**
   * Create a fork of an environment in a workspace
   * @param args.environmentId Environment ID in format: {ownerId}-{environmentId}
   */
  async createEnvironmentFork(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post(`/environments/${args.environmentId}/forks`, {
      forkName: args.label,
      workspace: { id: args.workspace, type: 'workspace' }
    });
    return this.createResponse(response.data);
  }

  /**
   * Get a list of environment forks
   * @param args.environmentId Environment ID in format: {ownerId}-{environmentId}
   */
  async getEnvironmentForks(args: any): Promise<ToolCallResponse> {
    const response = await this.client.get(`/environments/${args.environmentId}/forks`, {
      params: {
        cursor: args.cursor,
        direction: args.direction,
        limit: args.limit,
        sort: args.sort
      }
    });
    return this.createResponse(response.data);
  }

  /**
   * Merge a forked environment back into its parent
   * @param args.environmentId Environment ID in format: {ownerId}-{environmentId}
   * @param args.source Source environment ID in format: {ownerId}-{environmentId}
   * @param args.destination Destination environment ID in format: {ownerId}-{environmentId}
   */
  async mergeEnvironmentFork(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post(`/environments/${args.environmentId}/merges`, {
      source: args.source,
      destination: args.destination,
      deleteSource: args.strategy?.deleteSource
    });
    return this.createResponse(response.data);
  }

  /**
   * Pull changes from parent environment into forked environment
   * @param args.environmentId Environment ID in format: {ownerId}-{environmentId}
   * @param args.source Source environment ID in format: {ownerId}-{environmentId}
   * @param args.destination Destination environment ID in format: {ownerId}-{environmentId}
   */
  async pullEnvironment(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post(`/environments/${args.environmentId}/pulls`, {
      source: args.source,
      destination: args.destination
    });
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/src/tools/api/additional-features/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler,
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

export class AdditionalFeatureTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        // Billing
        case 'get_accounts':
          return await this.getAccounts();
        case 'list_account_invoices':
          return await this.listAccountInvoices(args);

        // Comment Resolution
        case 'resolve_comment_thread':
          return await this.resolveCommentThread(args.threadId);

        // Private API Network
        case 'list_pan_elements':
          return await this.listPanElements(args);
        case 'add_pan_element':
          return await this.addPanElement(args);
        case 'update_pan_element':
          return await this.updatePanElement(args);
        case 'remove_pan_element':
          return await this.removePanElement(args);

        // Webhooks
        case 'create_webhook':
          return await this.createWebhook(args);

        // Tags
        case 'get_tagged_elements':
          return await this.getTaggedElements(args);
        case 'get_workspace_tags':
          return await this.getWorkspaceTags(args.workspaceId);
        case 'update_workspace_tags':
          return await this.updateWorkspaceTags(args);

        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  // Billing Methods
  async getAccounts(): Promise<ToolCallResponse> {
    const response = await this.client.get('/accounts');
    return this.createResponse(response.data);
  }

  async listAccountInvoices(args: any): Promise<ToolCallResponse> {
    const response = await this.client.get(`/accounts/${args.accountId}/invoices`, {
      params: { status: args.status }
    });
    return this.createResponse(response.data);
  }

  // Comment Resolution Methods
  async resolveCommentThread(threadId: string): Promise<ToolCallResponse> {
    const response = await this.client.post(`/comments-resolutions/${threadId}`);
    return this.createResponse(response.data);
  }

  // Private API Network Methods
  async listPanElements(args: any): Promise<ToolCallResponse> {
    const response = await this.client.get('/network/private', {
      params: {
        since: args.since,
        until: args.until,
        addedBy: args.addedBy,
        name: args.name,
        summary: args.summary,
        description: args.description,
        sort: args.sort,
        direction: args.direction,
        offset: args.offset,
        limit: args.limit,
        parentFolderId: args.parentFolderId,
        type: args.type
      }
    });
    return this.createResponse(response.data);
  }

  async addPanElement(args: any): Promise<ToolCallResponse> {
    const payload: any = {};

    switch (args.type) {
      case 'api':
        payload.api = { id: args.elementId };
        break;
      case 'collection':
        payload.collection = { id: args.elementId };
        break;
      case 'workspace':
        payload.workspace = { id: args.elementId };
        break;
      case 'folder':
        payload.folder = {
          name: args.name,
          description: args.description,
          parentFolderId: args.parentFolderId
        };
        break;
    }

    const response = await this.client.post('/network/private', payload);
    return this.createResponse(response.data);
  }

  async updatePanElement(args: any): Promise<ToolCallResponse> {
    const payload: any = {};
    const path = `/network/private/${args.elementType}/${args.elementId}`;

    switch (args.elementType) {
      case 'folder':
        payload.folder = {
          name: args.name,
          description: args.description,
          parentFolderId: args.parentFolderId
        };
        break;
      default:
        payload[args.elementType] = {
          name: args.name,
          description: args.description,
          summary: args.summary,
          parentFolderId: args.parentFolderId
        };
    }

    const response = await this.client.put(path, payload);
    return this.createResponse(response.data);
  }

  async removePanElement(args: any): Promise<ToolCallResponse> {
    const response = await this.client.delete(
      `/network/private/${args.elementType}/${args.elementId}`
    );
    return this.createResponse(response.data);
  }

  // Webhook Methods
  async createWebhook(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post('/webhooks', {
      webhook: args.webhook
    }, {
      params: { workspace: args.workspace }
    });
    return this.createResponse(response.data);
  }

  // Tag Methods
  async getTaggedElements(args: any): Promise<ToolCallResponse> {
    const response = await this.client.get(`/tags/${args.slug}/entities`, {
      params: {
        limit: args.limit,
        direction: args.direction,
        cursor: args.cursor,
        entityType: args.entityType
      }
    });
    return this.createResponse(response.data);
  }

  async getWorkspaceTags(workspaceId: string): Promise<ToolCallResponse> {
    const response = await this.client.get(`/workspaces/${workspaceId}/tags`);
    return this.createResponse(response.data);
  }

  async updateWorkspaceTags(args: any): Promise<ToolCallResponse> {
    const response = await this.client.put(`/workspaces/${args.workspaceId}/tags`, {
      tags: args.tags
    });
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/src/tools/api/workspaces/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler,
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

export class WorkspaceTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'list_workspaces':
          return await this.listWorkspaces(args);
        case 'get_workspace':
          return await this.getWorkspace(args.workspace, args.include);
        case 'create_workspace':
          return await this.createWorkspace(args);
        case 'update_workspace':
          return await this.updateWorkspace(args.workspace_id, args);
        case 'delete_workspace':
          return await this.deleteWorkspace(args.workspace_id);
        case 'get_global_variables':
          return await this.getGlobalVariables(args.workspace_id);
        case 'update_global_variables':
          return await this.updateGlobalVariables(args.workspace_id, args.variables);
        case 'get_workspace_roles':
          return await this.getWorkspaceRoles(args.workspace_id, args.includeScimQuery);
        case 'update_workspace_roles':
          return await this.updateWorkspaceRoles(args.workspace_id, args.operations, args.identifierType);
        case 'get_all_workspace_roles':
          return await this.getAllWorkspaceRoles();
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  async listWorkspaces(params?: {
    type?: 'personal' | 'team' | 'private' | 'public' | 'partner';
    createdBy?: string;
    include?: string;
  }): Promise<ToolCallResponse> {
    const response = await this.client.get('/workspaces', { params });
    return this.createResponse(response.data);
  }

  async getWorkspace(workspace_id: string, include?: string): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    const response = await this.client.get(`/workspaces/${workspace_id}`, {
      params: { include }
    });
    return this.createResponse(response.data);
  }

  async createWorkspace(data: {
    name: string;
    description?: string;
    type?: 'personal' | 'team';
  }): Promise<ToolCallResponse> {
    if (!data.name) {
      throw new McpError(ErrorCode.InvalidParams, 'name is required');
    }
    const response = await this.client.post('/workspaces', data);
    return this.createResponse(response.data);
  }

  async updateWorkspace(workspace_id: string, data: {
    name?: string;
    description?: string;
    type?: 'personal' | 'team';
  }): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    const response = await this.client.put(`/workspaces/${workspace_id}`, data);
    return this.createResponse(response.data);
  }

  async deleteWorkspace(workspace_id: string): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    const response = await this.client.delete(`/workspaces/${workspace_id}`);
    return this.createResponse(response.data);
  }

  async getGlobalVariables(workspace_id: string): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    const response = await this.client.get(`/workspaces/${workspace_id}/global-variables`);
    return this.createResponse(response.data);
  }

  async updateGlobalVariables(workspace_id: string, variables: Array<{
    key: string;
    value: string;
    type?: 'default' | 'secret';
    enabled?: boolean;
  }>): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    if (!Array.isArray(variables)) {
      throw new McpError(ErrorCode.InvalidParams, 'variables must be an array');
    }
    const response = await this.client.put(
      `/workspaces/${workspace_id}/global-variables`,
      { variables }
    );
    return this.createResponse(response.data);
  }

  async getWorkspaceRoles(workspace_id: string, includeScimQuery?: boolean): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    const response = await this.client.get(`/workspaces/${workspace_id}/roles`, {
      params: { includeScimQuery }
    });
    return this.createResponse(response.data);
  }

  async updateWorkspaceRoles(
    workspace_id: string,
    operations: Array<{
      op: 'update';
      path: '/user' | '/group' | '/team';
      value: Array<{
        id: number;
        role: 'VIEWER' | 'EDITOR';
      }>;
    }>,
    identifierType?: string
  ): Promise<ToolCallResponse> {
    if (!workspace_id) {
      throw new McpError(ErrorCode.InvalidParams, 'workspace_id is required');
    }
    if (!Array.isArray(operations)) {
      throw new McpError(ErrorCode.InvalidParams, 'operations must be an array');
    }
    if (operations.length > 50) {
      throw new McpError(ErrorCode.InvalidParams, 'Maximum 50 role operations allowed per request');
    }

    const response = await this.client.patch(
      `/workspaces/${workspace_id}/roles`,
      { operations },
      { params: { identifierType } }
    );
    return this.createResponse(response.data);
  }

  async getAllWorkspaceRoles(): Promise<ToolCallResponse> {
    const response = await this.client.get('/workspaces-roles');
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/docs/api/summaries/environments.md:
--------------------------------------------------------------------------------

```markdown
## Environments

**Note:** Environment endpoints require the full `uid` format: `{ownerId}-{environmentId}`. Using only the `environmentId` will result in "Invalid environment ID format" errors.

Example `uid` construction from environment response:
```json
{
  "owner": "31912785",
  "id": "b8cdb26a-0c58-4f35-9775-4945c39d7ee2",
  "uid": "31912785-b8cdb26a-0c58-4f35-9775-4945c39d7ee2"
}
```
Use the full `uid` as follows:
```bash
environmentId: 31912785-b8cdb26a-0c58-4f35-9775-4945c39d7ee2
```
*Reason:* The Postman API requires the complete `uid` to ensure that users can only access environments they own, enhancing security.


### Implemented Operations
- Get all environments (`GET /environments`)
  - Query Parameters:
    - workspace (`#/components/parameters/workspaceQuery`)
  - Responses:
    - 200: `#/components/responses/getEnvironments`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/instanceNotFoundEnvironment`
    - 500: `#/components/responses/common500ErrorServerError`

- Get a specific environment (`GET /environments/{environmentId}`)
  - Parameters:
    - environmentId (`#/components/parameters/environmentId`)
  - Responses:
    - 200: `#/components/responses/getEnvironment`
    - 400: `#/components/responses/instanceNotFoundEnvironment`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Create environment (`POST /environments`)
  - Note: Creates in "My Workspace" if workspace not specified
  - Parameters:
    - workspaceQuery (`#/components/parameters/workspaceQuery`)
  - Request Body: `#/components/requestBodies/createEnvironment`
    - Required fields:
      - name: Environment name
    - Optional fields:
      - values: Array of environment variables
        - key: Variable name
        - value: Variable value
        - type: Variable type (default/secret)
        - enabled: Variable enabled status
  - Responses:
    - 200: `#/components/responses/createEnvironment`
    - 400: `#/components/responses/environments400ErrorMalformedRequest`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/common403Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Update environment (`PUT /environments/{environmentId}`)
  - Parameters:
    - environmentId (`#/components/parameters/environmentId`)
  - Request Body: `#/components/requestBodies/updateEnvironment`
    - Optional fields:
      - name: New environment name
      - values: Updated array of environment variables
        - key: Variable name
        - value: Variable value
        - type: Variable type (default/secret)
        - enabled: Variable enabled status
  - Responses:
    - 200: `#/components/responses/updateEnvironment`
    - 400: `#/components/responses/environments400ErrorMalformedRequest`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Delete environment (`DELETE /environments/{environmentId}`)
  - Parameters:
    - environmentId (`#/components/parameters/environmentId`)
  - Responses:
    - 200: `#/components/responses/deleteEnvironment`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/instanceNotFoundEnvironment`
    - 500: `#/components/responses/common500ErrorServerError`

#### Environment Version Control
- Create environment fork (`POST /environments/{environmentId}/forks`)
  - Parameters:
    - environmentUid (`#/components/parameters/environmentUid`)
    - workspaceIdQueryTrue (`#/components/parameters/workspaceIdQueryTrue`)
  - Request Body: `#/components/requestBodies/forkEnvironment`
    - Required fields:
      - label: Fork label/name
      - workspace: Target workspace ID
  - Responses:
    - 200: `#/components/responses/forkEnvironment`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/environmentForks404Error`
    - 500: `#/components/responses/common500Error`

- Get environment forks (`GET /environments/{environmentId}/forks`)
  - Parameters:
    - environmentUid (`#/components/parameters/environmentUid`)
    - cursor (`#/components/parameters/cursor`)
    - directionQuery (`#/components/parameters/directionQuery`)
    - limit (`#/components/parameters/limit`)
    - sortByCreatedAt (`#/components/parameters/sortByCreatedAt`)
  - Responses:
    - 200: `#/components/responses/getEnvironmentForks`
    - 400: `#/components/responses/environmentForks400Error`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/environmentForks404Error`
    - 500: `#/components/responses/common500Error`

- Merge environment fork (`POST /environments/{environmentId}/merges`)
  - Description: Merges a forked environment back into its parent environment
  - Parameters:
    - environmentUid (`#/components/parameters/environmentUid`)
  - Request Body: `#/components/requestBodies/mergeEnvironmentFork`
    - Required fields:
      - source: Source environment ID
      - destination: Destination environment ID
      - strategy: Merge strategy details
  - Responses:
    - 200: `#/components/responses/mergeEnvironmentFork`
    - 400: `#/components/responses/environmentForks400Error`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/environmentForks404Error`
    - 500: `#/components/responses/common500Error`

- Pull environment changes (`POST /environments/{environmentId}/pulls`)
  - Description: Pulls changes from parent (source) environment into forked environment
  - Parameters:
    - environmentUid (`#/components/parameters/environmentUid`)
  - Request Body: `#/components/requestBodies/pullEnvironment`
    - Required fields:
      - source: Source environment ID
      - destination: Destination environment ID
      - strategy: Pull strategy details
  - Responses:
    - 200: `#/components/responses/pullEnvironment`
    - 400: `#/components/responses/environmentForks400Error`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/environmentForks404Error`
    - 500: `#/components/responses/common500Error`

### Key Features
- Environment CRUD operations
- Environment variable management
- Support for secret and default variable types
- Basic environment metadata management
- Version control features (fork, merge, pull)
- Workspace scoping

```

--------------------------------------------------------------------------------
/src/tools/api/environments/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  {
    name: 'list_environments',
    description: 'List all environments in a workspace. If workspace not specified, lists environments in "My Workspace".',
    inputSchema: {
      type: 'object',
      properties: {
        workspace: {
          type: 'string',
          description: 'Workspace ID (optional)',
        },
      },
      required: [], // Empty array since workspace is optional
    },
  },
  {
    name: 'get_environment',
    description: 'Get details of a specific environment',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId} (e.g., "31912785-b8cdb26a-0c58-4f35-9775-4945c39d7ee2")',
        },
      },
      required: ['environmentId'],
    },
  },
  {
    name: 'create_environment',
    description: 'Create a new environment in a workspace. Creates in "My Workspace" if workspace not specified.',
    inputSchema: {
      type: 'object',
      properties: {
        environment: {
          type: 'object',
          description: 'Environment details',
          properties: {
            name: { type: 'string', description: 'Environment name' },
            values: {
              type: 'array',
              description: 'Environment variables',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string', description: 'Variable name' },
                  value: { type: 'string', description: 'Variable value' },
                  type: { type: 'string', enum: ['default', 'secret'], description: 'Variable type' },
                  enabled: { type: 'boolean', description: 'Variable enabled status' }
                },
                required: ['key', 'value']
              }
            }
          },
          required: ['name']
        },
        workspace: { type: 'string', description: 'Workspace ID (optional)' }
      },
      required: ['environment']
    }
  },
  {
    name: 'update_environment',
    description: 'Update an existing environment. Only include variables that need to be modified.',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        },
        environment: {
          type: 'object',
          description: 'Environment details to update',
          properties: {
            name: { type: 'string', description: 'New environment name (optional)' },
            values: {
              type: 'array',
              description: 'Environment variables to update (optional)',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string' },
                  value: { type: 'string' },
                  type: { type: 'string', enum: ['default', 'secret'] },
                  enabled: { type: 'boolean' }
                },
                required: ['key', 'value']
              }
            }
          }
        }
      },
      required: ['environmentId', 'environment']
    }
  },
  {
    name: 'delete_environment',
    description: 'Delete an environment',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        }
      },
      required: ['environmentId']
    }
  },
  {
    name: 'fork_environment',
    description: 'Create a fork of an environment in a workspace',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        },
        label: { type: 'string', description: 'Label/name for the forked environment' },
        workspace: { type: 'string', description: 'Target workspace ID' }
      },
      required: ['environmentId', 'label', 'workspace']
    }
  },
  {
    name: 'get_environment_forks',
    description: 'Get a list of environment forks',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        },
        cursor: { type: 'string', description: 'Pagination cursor' },
        direction: { type: 'string', enum: ['asc', 'desc'], description: 'Sort direction' },
        limit: { type: 'number', description: 'Number of results per page' },
        sort: { type: 'string', enum: ['createdAt'], description: 'Sort field' }
      },
      required: ['environmentId']
    }
  },
  {
    name: 'merge_environment_fork',
    description: 'Merge a forked environment back into its parent',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        },
        source: {
          type: 'string',
          description: 'Source environment ID in format: {ownerId}-{environmentId}'
        },
        destination: {
          type: 'string',
          description: 'Destination environment ID in format: {ownerId}-{environmentId}'
        },
        strategy: {
          type: 'object',
          description: 'Merge strategy options',
          properties: {
            deleteSource: { type: 'boolean', description: 'Whether to delete the source environment after merging' }
          }
        }
      },
      required: ['environmentId', 'source', 'destination']
    }
  },
  {
    name: 'pull_environment',
    description: 'Pull changes from parent environment into forked environment',
    inputSchema: {
      type: 'object',
      properties: {
        environmentId: {
          type: 'string',
          description: 'Environment ID in format: {ownerId}-{environmentId}'
        },
        source: {
          type: 'string',
          description: 'Source (parent) environment ID in format: {ownerId}-{environmentId}'
        },
        destination: {
          type: 'string',
          description: 'Destination (fork) environment ID in format: {ownerId}-{environmentId}'
        }
      },
      required: ['environmentId', 'source', 'destination']
    }
  }
];

```

--------------------------------------------------------------------------------
/src/tools/api/auth/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

/**
 * Handles Postman authentication and authorization operations including:
 * - Collection access key management
 * - Workspace and collection role management
 * - User authentication information
 */
export class AuthTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'list_collection_access_keys':
          return await this.listCollectionAccessKeys(args);
        case 'delete_collection_access_key':
          return await this.deleteCollectionAccessKey(args.keyId);
        case 'list_workspace_roles':
          return await this.listWorkspaceRoles();
        case 'get_workspace_roles':
          return await this.getWorkspaceRoles(args);
        case 'update_workspace_roles':
          return await this.updateWorkspaceRoles(args);
        case 'get_collection_roles':
          return await this.getCollectionRoles(args.collectionId);
        case 'update_collection_roles':
          return await this.updateCollectionRoles(args);
        case 'get_authenticated_user':
          return await this.getAuthenticatedUser();
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  /**
   * List collection access keys with optional filtering
   */
  async listCollectionAccessKeys(args: {
    collectionId?: string;
    cursor?: string;
  }): Promise<ToolCallResponse> {
    const params = new URLSearchParams();
    if (args.collectionId) {
      params.append('collectionId', args.collectionId);
    }
    if (args.cursor) {
      params.append('cursor', args.cursor);
    }

    const response = await this.client.get('/collection-access-keys', {
      params: params.toString() ? params : undefined
    });
    return this.createResponse(response.data);
  }

  /**
   * Delete a collection access key
   */
  async deleteCollectionAccessKey(keyId: string): Promise<ToolCallResponse> {
    if (!keyId) {
      throw new McpError(ErrorCode.InvalidParams, 'keyId is required');
    }
    const response = await this.client.delete(`/collection-access-keys/${keyId}`);
    return this.createResponse(response.data);
  }

  /**
   * Get all available workspace roles based on team's plan
   */
  async listWorkspaceRoles(): Promise<ToolCallResponse> {
    const response = await this.client.get('/workspaces-roles');
    return this.createResponse(response.data);
  }

  /**
   * Get roles for a specific workspace
   */
  async getWorkspaceRoles(args: {
    workspaceId: string;
    includeScim?: boolean;
  }): Promise<ToolCallResponse> {
    if (!args.workspaceId) {
      throw new McpError(ErrorCode.InvalidParams, 'workspaceId is required');
    }

    const params = new URLSearchParams();
    if (args.includeScim) {
      params.append('include', 'scim');
    }

    const response = await this.client.get(
      `/workspaces/${args.workspaceId}/roles`,
      { params: params.toString() ? params : undefined }
    );
    return this.createResponse(response.data);
  }

  /**
   * Update workspace roles for users and groups
   * Limited to 50 operations per call
   */
  async updateWorkspaceRoles(args: {
    workspaceId: string;
    operations: Array<{
      op: 'update';
      path: '/user' | '/group' | '/team';
      value: Array<{
        id: number;
        role: 'VIEWER' | 'EDITOR';
      }>;
    }>;
    identifierType?: 'scim';
  }): Promise<ToolCallResponse> {
    if (!args.workspaceId) {
      throw new McpError(ErrorCode.InvalidParams, 'workspaceId is required');
    }
    if (!args.operations || !Array.isArray(args.operations)) {
      throw new McpError(ErrorCode.InvalidParams, 'operations array is required');
    }
    if (args.operations.length > 50) {
      throw new McpError(ErrorCode.InvalidParams, 'Maximum 50 role operations allowed per request');
    }

    const headers: Record<string, string> = {};
    if (args.identifierType) {
      headers['identifierType'] = args.identifierType;
    }

    const response = await this.client.patch(
      `/workspaces/${args.workspaceId}/roles`,
      { roles: args.operations },
      { headers }
    );
    return this.createResponse(response.data);
  }

  /**
   * Get roles for a collection
   */
  async getCollectionRoles(collectionId: string): Promise<ToolCallResponse> {
    if (!collectionId) {
      throw new McpError(ErrorCode.InvalidParams, 'collectionId is required');
    }
    const response = await this.client.get(`/collections/${collectionId}/roles`);
    return this.createResponse(response.data);
  }

  /**
   * Update collection roles
   * Only users with EDITOR role can use this endpoint
   * Does not support Partner or Guest external roles
   */
  async updateCollectionRoles(args: {
    collectionId: string;
    operations: Array<{
      op: 'update';
      path: '/user' | '/group' | '/team';
      value: Array<{
        id: number;
        role: 'VIEWER' | 'EDITOR';
      }>;
    }>;
  }): Promise<ToolCallResponse> {
    if (!args.collectionId) {
      throw new McpError(ErrorCode.InvalidParams, 'collectionId is required');
    }
    if (!args.operations || !Array.isArray(args.operations)) {
      throw new McpError(ErrorCode.InvalidParams, 'operations array is required');
    }

    const response = await this.client.patch(
      `/collections/${args.collectionId}/roles`,
      { roles: args.operations }
    );
    return this.createResponse(response.data);
  }

  /**
   * Get authenticated user information
   * Returns different response for Guest and Partner roles
   * Returns flow_count only for Free plan users
   */
  async getAuthenticatedUser(): Promise<ToolCallResponse> {
    const response = await this.client.get('/me');
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/docs/api/summaries/workspaces.md:
--------------------------------------------------------------------------------

```markdown
## Workspaces

**Important:**
When working with workspaces, keep track of the `createdBy` (owner ID) from the workspace response. This ID is essential for constructing valid resource identifiers when accessing related workspace resources.

For example, a workspace response includes:
```json
{
  "id": "5ead536b-e095-403c-89f9-f9f03872537a",
  "name": "My Workspace",
  "type": "personal",
  "visibility": "personal",
  "createdBy": "31912785"
}
```

### Implemented Operations
- Get all workspaces (`GET /workspaces`)
  - Parameters:
    - workspaceTypeQuery (`#/components/parameters/workspaceTypeQuery`)
    - workspaceCreatedBy (`#/components/parameters/workspaceCreatedBy`)
    - workspaceIncludeQuery (`#/components/parameters/workspaceIncludeQuery`)
  - Supports filtering by workspace type and creator
  - Responses:
    - 200: `#/components/responses/getWorkspaces`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`
- Get a specific workspace (`GET /workspaces/{workspaceId}`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
    - workspaceIncludeQuery (`#/components/parameters/workspaceIncludeQuery`)
  - Responses:
    - 200: `#/components/responses/getWorkspace`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/workspace404ErrorNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Create workspace (`POST /workspaces`)
  - Supports setting name, description, type, and visibility
  - Note: Returns 403 if user lacks permission to create workspaces
  - Important: Linking collections/environments between workspaces is deprecated
  - Request Body: `#/components/requestBodies/createWorkspace`
  - Responses:
    - 200: `#/components/responses/createWorkspace`
    - 400: `#/components/responses/workspace400ErrorMalformedRequest`
    - 401: `#/components/responses/common401Error`
    - 403: `#/components/responses/workspace403ErrorUnauthorized`
    - 500: `#/components/responses/common500ErrorServerError`

- Update workspace (`PUT /workspaces/{workspaceId}`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Can modify workspace properties and linked resources
  - Important: Linking collections/environments between workspaces is deprecated
  - Request Body: `#/components/requestBodies/updateWorkspace`
  - Responses:
    - 200: `#/components/responses/updateWorkspace`
    - 400: `#/components/responses/workspace400ErrorMalformedRequest`
    - 403: `#/components/responses/workspace403Error`
    - 404: `#/components/responses/instanceNotFoundWorkspace`
    - 500: `#/components/responses/common500ErrorServerError`

- Delete workspace (`DELETE /workspaces/{workspaceId}`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Important: Deleting a workspace with linked collections/environments affects all workspaces
  - Responses:
    - 200: `#/components/responses/deleteWorkspace`
    - 400: `#/components/responses/workspace400Error`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Get workspace global variables (`GET /workspaces/{workspaceId}/global-variables`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Responses:
    - 200: `#/components/responses/getWorkspaceGlobalVariables`
    - 500: `#/components/responses/globalVariables500Error`

- Update workspace global variables (`PUT /workspaces/{workspaceId}/global-variables`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Note: Replaces all existing global variables
  - Request Body: `#/components/requestBodies/updateWorkspaceGlobalVariables`
  - Responses:
    - 200: `#/components/responses/updateWorkspaceGlobalVariables`
    - 500: `#/components/responses/globalVariables500Error`

- Get workspace roles (`GET /workspaces/{workspaceId}/roles`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
    - workspaceIncludeScimQuery (`#/components/parameters/workspaceIncludeScimQuery`)
  - Responses:
    - 200: `#/components/responses/getWorkspaceRoles`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/resourceNotFound404Error`
    - 500: `#/components/responses/common500ErrorInternalServer`

- Update workspace roles (`PATCH /workspaces/{workspaceId}/roles`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
    - identifierType (`#/components/parameters/identifierType`)
  - Supports updating roles for users and user groups
  - Available roles: Viewer, Editor, Admin
  - Note: Cannot set roles for personal/partner workspaces
  - Limited to 50 operations per call
  - Request Body: `#/components/requestBodies/updateWorkspaceRoles`
  - Responses:
    - 200: `#/components/responses/updateWorkspaceRoles`
    - 400: `#/components/responses/workspaceRoles400Error`
    - 401: `#/components/responses/unauthorizedError`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 404: `#/components/responses/resourceNotFound404Error`
    - 422: `#/components/responses/workspaceRoles422UnsupportRoleError`
    - 500: `#/components/responses/common500ErrorInternalServer`

- Get all roles (`GET /workspaces-roles`)
  - Lists available roles based on team's plan
  - Responses:
    - 200: `#/components/responses/getAllWorkspaceRoles`
    - 401: `#/components/responses/api401ErrorUnauthorized`
    - 403: `#/components/responses/common403ErrorPermissions`
    - 500: `#/components/responses/common500ErrorInternalServer`

- Get workspace tags (`GET /workspaces/{workspaceId}/tags`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Responses:
    - 200: `#/components/responses/tagGetPut`
    - 401: `#/components/responses/tag401Error`
    - 403: `#/components/responses/tag403Error`
    - 404: `#/components/responses/tag404Error`
    - 500: `#/components/responses/tag500Error`

- Update workspace tags (`PUT /workspaces/{workspaceId}/tags`)
  - Parameters:
    - workspaceId (`#/components/parameters/workspaceId`)
  - Description: Updates a workspace's associated tags. Replaces all existing tags.
  - Request Body: `#/components/requestBodies/tagUpdateTags`
  - Responses:
    - 200: `#/components/responses/tagGetPut`
    - 400: `#/components/responses/tag400Error`
    - 401: `#/components/responses/tag401Error`
    - 403: `#/components/responses/tag403Error`
    - 404: `#/components/responses/tag404Error`
    - 500: `#/components/responses/tag500Error`

### Key Features
- Support for workspace types: personal, team, private, public, partner
- Workspace visibility control
- Basic workspace metadata (name, description)
- Workspace resource listings (collections, environments, mocks, monitors, APIs)
- Global variables management
- Role-based access control
- Tags management (Enterprise plans)

```

--------------------------------------------------------------------------------
/src/tools/api/mocks/index.ts:
--------------------------------------------------------------------------------

```typescript
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { AxiosInstance } from 'axios';
import {
  ToolCallResponse,
  ToolDefinition,
  ToolHandler,
} from '../../../types/index.js';
import { BasePostmanTool } from '../base.js';
import { TOOL_DEFINITIONS } from './definitions.js';

/**
 * Handles Postman Mock Server API operations
 */
export class MockTools extends BasePostmanTool implements ToolHandler {
  constructor(existingClient: AxiosInstance) {
    super(null, {}, existingClient);
  }

  getToolDefinitions(): ToolDefinition[] {
    return TOOL_DEFINITIONS;
  }

  private createResponse(data: any): ToolCallResponse {
    return {
      content: [{ type: 'text', text: JSON.stringify(data, null, 2) }]
    };
  }

  async handleToolCall(name: string, args: any): Promise<ToolCallResponse> {
    try {
      switch (name) {
        case 'list_mocks':
          return await this.listMocks(args);
        case 'create_mock':
          return await this.createMock(args);
        case 'get_mock':
          return await this.getMock(args.mockId);
        case 'update_mock':
          return await this.updateMock(args);
        case 'delete_mock':
          return await this.deleteMock(args.mockId);
        case 'get_mock_call_logs':
          return await this.getMockCallLogs(args);
        case 'publish_mock':
          return await this.publishMock(args.mockId);
        case 'unpublish_mock':
          return await this.unpublishMock(args.mockId);
        case 'list_server_responses':
          return await this.listServerResponses(args.mockId);
        case 'create_server_response':
          return await this.createServerResponse(args);
        case 'get_server_response':
          return await this.getServerResponse(args);
        case 'update_server_response':
          return await this.updateServerResponse(args);
        case 'delete_server_response':
          return await this.deleteServerResponse(args);
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    } catch (error) {
      // Let base class interceptor handle API errors
      throw error;
    }
  }

  /**
   * List all mock servers
   * @param args Optional filters: teamId, workspace
   */
  async listMocks(args: any): Promise<ToolCallResponse> {
    const params: any = {};
    if (args.teamId) params.teamId = args.teamId;
    if (args.workspace) params.workspace = args.workspace;

    const response = await this.client.get('/mocks', { params });
    return this.createResponse(response.data);
  }

  /**
   * Create a new mock server
   * @param args.workspace Optional workspace ID
   * @param args.mock Mock server configuration
   */
  async createMock(args: any): Promise<ToolCallResponse> {
    const params: any = {};
    if (args.workspace) params.workspaceId = args.workspace;

    const response = await this.client.post('/mocks', { mock: args.mock }, { params });
    return this.createResponse(response.data);
  }

  /**
   * Get details of a specific mock server
   * @param mockId Mock server ID
   */
  async getMock(mockId: string): Promise<ToolCallResponse> {
    const response = await this.client.get(`/mocks/${mockId}`);
    return this.createResponse(response.data);
  }

  /**
   * Update an existing mock server
   * @param args.mockId Mock server ID
   * @param args.mock Updated mock server configuration
   */
  async updateMock(args: any): Promise<ToolCallResponse> {
    const response = await this.client.put(
      `/mocks/${args.mockId}`,
      { mock: args.mock }
    );
    return this.createResponse(response.data);
  }

  /**
   * Delete a mock server
   * @param mockId Mock server ID
   */
  async deleteMock(mockId: string): Promise<ToolCallResponse> {
    const response = await this.client.delete(`/mocks/${mockId}`);
    return this.createResponse(response.data);
  }

  /**
   * Get mock server call logs
   * @param args.mockId Mock server ID
   * @param args Optional filters and pagination
   */
  async getMockCallLogs(args: any): Promise<ToolCallResponse> {
    const params: any = {};
    const optionalParams = [
      'limit', 'cursor', 'until', 'since', 'responseStatusCode',
      'responseType', 'requestMethod', 'requestPath', 'sort',
      'direction', 'include'
    ];

    optionalParams.forEach(param => {
      if (args[param] !== undefined) params[param] = args[param];
    });

    const response = await this.client.get(
      `/mocks/${args.mockId}/call-logs`,
      { params }
    );
    return this.createResponse(response.data);
  }

  /**
   * Publish a mock server (set to public)
   * @param mockId Mock server ID
   */
  async publishMock(mockId: string): Promise<ToolCallResponse> {
    const response = await this.client.post(`/mocks/${mockId}/publish`);
    return this.createResponse(response.data);
  }

  /**
   * Unpublish a mock server (set to private)
   * @param mockId Mock server ID
   */
  async unpublishMock(mockId: string): Promise<ToolCallResponse> {
    const response = await this.client.delete(`/mocks/${mockId}/unpublish`);
    return this.createResponse(response.data);
  }

  /**
   * List all server responses for a mock
   * @param mockId Mock server ID
   */
  async listServerResponses(mockId: string): Promise<ToolCallResponse> {
    const response = await this.client.get(`/mocks/${mockId}/server-responses`);
    return this.createResponse(response.data);
  }

  /**
   * Create a new server response
   * @param args.mockId Mock server ID
   * @param args.serverResponse Server response configuration
   */
  async createServerResponse(args: any): Promise<ToolCallResponse> {
    const response = await this.client.post(
      `/mocks/${args.mockId}/server-responses`,
      { serverResponse: args.serverResponse }
    );
    return this.createResponse(response.data);
  }

  /**
   * Get a specific server response
   * @param args.mockId Mock server ID
   * @param args.serverResponseId Server response ID
   */
  async getServerResponse(args: any): Promise<ToolCallResponse> {
    const response = await this.client.get(
      `/mocks/${args.mockId}/server-responses/${args.serverResponseId}`
    );
    return this.createResponse(response.data);
  }

  /**
   * Update a server response
   * @param args.mockId Mock server ID
   * @param args.serverResponseId Server response ID
   * @param args.serverResponse Updated server response configuration
   */
  async updateServerResponse(args: any): Promise<ToolCallResponse> {
    const response = await this.client.put(
      `/mocks/${args.mockId}/server-responses/${args.serverResponseId}`,
      { serverResponse: args.serverResponse }
    );
    return this.createResponse(response.data);
  }

  /**
   * Delete a server response
   * @param args.mockId Mock server ID
   * @param args.serverResponseId Server response ID
   */
  async deleteServerResponse(args: any): Promise<ToolCallResponse> {
    const response = await this.client.delete(
      `/mocks/${args.mockId}/server-responses/${args.serverResponseId}`
    );
    return this.createResponse(response.data);
  }
}

```

--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import axios, { AxiosError } from 'axios';
import {
  WorkspaceTools,
  EnvironmentTools,
  CollectionTools,
  UserTools,
  ApiTools,
  AuthTools,
  MockTools,
  MonitorTools,
  AdditionalFeatureTools
} from './tools/index.js';
import { ToolDefinition, ToolHandler } from './types/index.js';
import {
  McpResourceHandler,
  ResourceTemplateHandler,
  PromptHandler,
  ToolHandler as ToolRequestHandler
} from './handlers/index.js';

const API_KEY = process.env.POSTMAN_API_KEY;
if (!API_KEY) {
  throw new Error('POSTMAN_API_KEY environment variable is required');
}

// Constants for configuration
const CONFIG = {
  SERVER_NAME: 'postman-api-server',
  VERSION: '0.2.0',
  API_BASE_URL: 'https://api.getpostman.com',
  REQUEST_TIMEOUT: 30000, // 30 seconds
  MAX_RETRIES: 3,
} as const;

export class PostmanAPIServer {
  private server: Server;
  private axiosInstance;
  private workspaceTools: WorkspaceTools;
  private environmentTools: EnvironmentTools;
  private collectionTools: CollectionTools;
  private userTools: UserTools;
  private apiTools: ApiTools;
  private authTools: AuthTools;
  private mockTools: MockTools;
  private monitorTools: MonitorTools;
  private additionalFeatureTools: AdditionalFeatureTools;
  private toolDefinitions: ToolDefinition[];
  private toolHandlers: Map<string, ToolHandler>;
  private isShuttingDown: boolean;

  constructor() {
    this.isShuttingDown = false;

    this.server = new Server(
      {
        name: CONFIG.SERVER_NAME,
        version: CONFIG.VERSION,
      },
      {
        capabilities: {
          tools: {
            resources: true  // Enable tool resources capability
          },
          resources: {},
          prompts: {},
        },
      }
    );

    this.axiosInstance = axios.create({
      baseURL: CONFIG.API_BASE_URL,
      headers: {
        'X-Api-Key': API_KEY,
        'User-Agent': `${CONFIG.SERVER_NAME}/${CONFIG.VERSION}`,
      },
      timeout: CONFIG.REQUEST_TIMEOUT,
      validateStatus: (status) => status >= 200 && status < 300,
    });

    // Add response interceptor for error handling
    this.axiosInstance.interceptors.response.use(
      (response) => response,
      async (error: AxiosError) => {
        if (error.response) {
          // API responded with error status
          throw new McpError(
            ErrorCode.InternalError,
            `Postman API error: ${error.response.status} - ${JSON.stringify(error.response.data)}`
          );
        } else if (error.request) {
          // Request made but no response received
          throw new McpError(
            ErrorCode.InternalError,
            'No response received from Postman API'
          );
        } else {
          // Error in request setup
          throw new McpError(
            ErrorCode.InternalError,
            `Request setup error: ${error.message}`
          );
        }
      }
    );

    // Initialize all properties explicitly
    this.workspaceTools = new WorkspaceTools(this.axiosInstance);
    this.environmentTools = new EnvironmentTools(this.axiosInstance);
    this.collectionTools = new CollectionTools(this.axiosInstance);
    this.userTools = new UserTools(this.axiosInstance);
    this.apiTools = new ApiTools(this.axiosInstance);
    this.authTools = new AuthTools(this.axiosInstance);
    this.mockTools = new MockTools(this.axiosInstance);
    this.monitorTools = new MonitorTools(this.axiosInstance);
    this.additionalFeatureTools = new AdditionalFeatureTools(this.axiosInstance);

    // Initialize tool definitions
    this.toolDefinitions = [
      ...this.workspaceTools.getToolDefinitions(),
      ...this.environmentTools.getToolDefinitions(),
      ...this.collectionTools.getToolDefinitions(),
      ...this.userTools.getToolDefinitions(),
      ...this.apiTools.getToolDefinitions(),
      ...this.authTools.getToolDefinitions(),
      ...this.mockTools.getToolDefinitions(),
      ...this.monitorTools.getToolDefinitions(),
      ...this.additionalFeatureTools.getToolDefinitions(),
    ];

    // Initialize tool handlers map
    const toolMapping = {
      ...this.workspaceTools.getToolMappings(),
      ...this.environmentTools.getToolMappings(),
      ...this.collectionTools.getToolMappings(),
      ...this.userTools.getToolMappings(),
      ...this.apiTools.getToolMappings(),
      ...this.authTools.getToolMappings(),
      ...this.mockTools.getToolMappings(),
      ...this.monitorTools.getToolMappings(),
      ...this.additionalFeatureTools.getToolMappings(),
    };
    this.toolHandlers = new Map(Object.entries(toolMapping));

    // Initialize request handlers
    new McpResourceHandler(this.server);
    new ResourceTemplateHandler(this.server);
    new PromptHandler(this.server);
    new ToolRequestHandler(this.server, this.toolDefinitions, this.toolHandlers);

    // Setup error handling
    this.setupErrorHandling();
  }

  private setupErrorHandling(): void {
    // Handle MCP server errors
    this.server.onerror = (error) => {
      console.error('[MCP Error]', error);
      // Log additional error details if available
      if (error instanceof McpError) {
        console.error(`Error Code: ${error.code}`);
        if (error.data) {
          console.error('Additional Data:', error.data);
        }
      }
    };

    // Handle process signals
    process.on('SIGINT', () => this.shutdown('SIGINT'));
    process.on('SIGTERM', () => this.shutdown('SIGTERM'));

    // Handle uncaught errors
    process.on('uncaughtException', (error) => {
      console.error('[Uncaught Exception]', error);
      this.shutdown('uncaughtException');
    });

    // Handle unhandled promise rejections
    process.on('unhandledRejection', (reason, promise) => {
      console.error('[Unhandled Rejection]', reason);
      this.shutdown('unhandledRejection');
    });
  }

  private async shutdown(signal: string): Promise<void> {
    if (this.isShuttingDown) return;

    this.isShuttingDown = true;
    console.error(`\n[${signal}] Shutting down gracefully...`);

    try {
      // Close MCP server connection
      await this.server.close();

      // Cancel any pending axios requests
      if (this.axiosInstance) {
        // @ts-ignore - Cancel token source exists on axios instance
        this.axiosInstance.CancelToken.source().cancel('Server shutting down');
      }

      console.error('Cleanup completed successfully');
      process.exit(0);
    } catch (error) {
      console.error('Error during shutdown:', error);
      process.exit(1);
    }
  }

  async run(): Promise<void> {
    try {
      const transport = new StdioServerTransport();

      // Add transport error handling
      transport.onerror = (error) => {
        console.error('[Transport Error]', error);
        if (!this.isShuttingDown) {
          this.shutdown('transport_error');
        }
      };

      await this.server.connect(transport);
      console.error(`${CONFIG.SERVER_NAME} v${CONFIG.VERSION} running on stdio`);
    } catch (error) {
      console.error('Failed to start server:', error);
      process.exit(1);
    }
  }
}

```

--------------------------------------------------------------------------------
/docs/api/summaries/mocks.md:
--------------------------------------------------------------------------------

```markdown
## Mocks

### Implemented Operations
- Get all mock servers (`GET /mocks`)
  - Parameters:
    - `#/components/parameters/teamIdResultsQuery`
    - `#/components/parameters/workspaceResultsQuery`
  - Note: If both teamId and workspace provided, only workspace is used
  - Responses:
    - 200: `#/components/responses/getMocks`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Create mock server (`POST /mocks`)
  - Parameters:
    - `#/components/parameters/workspaceIdQuery`
  - Note: Creates in Personal workspace if workspace not specified
  - Note: Cannot create mocks for collections added to an API definition
  - Request Body: `#/components/requestBodies/createMock`
    - Required fields:
      - collection: Collection ID to mock
      - name: Mock server name
    - Optional fields:
      - description: Mock server description
      - environment: Environment ID to use
      - private: Access control setting
      - versionTag: Collection version tag
  - Responses:
    - 200: `#/components/responses/mockCreateUpdate`
    - 400: `#/components/responses/paramMissing400Error`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Get specific mock server (`GET /mocks/{mockId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Responses:
    - 200: `#/components/responses/getMock`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Update mock server (`PUT /mocks/{mockId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Request Body: `#/components/requestBodies/updateMock`
    - Optional fields:
      - name: New mock server name
      - description: Updated description
      - environment: New environment ID
      - private: Updated access control setting
      - versionTag: Updated collection version tag
  - Responses:
    - 200: `#/components/responses/mockCreateUpdate`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Delete mock server (`DELETE /mocks/{mockId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Responses:
    - 200: `#/components/responses/deleteMock`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Get mock call logs (`GET /mocks/{mockId}/call-logs`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
    - `#/components/parameters/limitDefault100`
    - `#/components/parameters/cursor`
    - `#/components/parameters/until`
    - `#/components/parameters/since`
    - `#/components/parameters/mockResponseStatusCode`
    - `#/components/parameters/mockResponseType`
    - `#/components/parameters/mockRequestMethod`
    - `#/components/parameters/mockRequestPath`
    - `#/components/parameters/mockSortServedAt`
    - `#/components/parameters/direction`
    - `#/components/parameters/mockInclude`
  - Note: Maximum 6.5MB or 100 call logs per API call
  - Note: Retention period based on Postman plan
  - Responses:
    - 200: `#/components/responses/getMockCallLogs`
    - 400: `#/components/responses/mock400ErrorLogRetentionPeriodExceeded`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Publish mock server (`POST /mocks/{mockId}/publish`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Description: Sets Access Control to public
  - Responses:
    - 200: `#/components/responses/publishMock`
    - 400: `#/components/responses/mock400ErrorAlreadyPublished`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Unpublish mock server (`DELETE /mocks/{mockId}/unpublish`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Description: Sets Access Control to private
  - Responses:
    - 200: `#/components/responses/unpublishMock`
    - 400: `#/components/responses/mock400ErrorAlreadyUnpublished`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

#### Server Responses
- Get all server responses (`GET /mocks/{mockId}/server-responses`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Responses:
    - 200: `#/components/responses/getMockServerResponses`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Create server response (`POST /mocks/{mockId}/server-responses`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
  - Description: Simulates server-level responses (e.g., 5xx errors)
  - Note: Server responses are agnostic to application-level logic
  - Note: Only one server response can be active at a time
  - Request Body: `#/components/requestBodies/createMockServerResponse`
    - Required fields:
      - name: Response name
      - code: HTTP status code
      - headers: Response headers
      - body: Response body content
    - Optional fields:
      - active: Set as active response
      - delay: Response delay in milliseconds
  - Responses:
    - 200: `#/components/responses/mockServerResponse`
    - 400: `#/components/responses/paramMissing400Error`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Get server response (`GET /mocks/{mockId}/server-responses/{serverResponseId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
    - `#/components/parameters/serverResponseId` (required)
  - Responses:
    - 200: `#/components/responses/mockServerResponse`
    - 400: `#/components/responses/serverResponseNotFound400Error`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

- Update server response (`PUT /mocks/{mockId}/server-responses/{serverResponseId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
    - `#/components/parameters/serverResponseId` (required)
  - Request Body: `#/components/requestBodies/updateMockServerResponse`
    - Optional fields:
      - name: Updated response name
      - code: Updated HTTP status code
      - headers: Updated response headers
      - body: Updated response body
      - active: Change active status
      - delay: Updated response delay
  - Responses:
    - 200: `#/components/responses/mockServerResponse`
    - 400: `#/components/responses/paramMissing400Error`
    - 401: `#/components/responses/common401Error`
    - 500: `#/components/responses/common500ErrorServerError`

- Delete server response (`DELETE /mocks/{mockId}/server-responses/{serverResponseId}`)
  - Parameters:
    - `#/components/parameters/mockId` (required)
    - `#/components/parameters/serverResponseId` (required)
  - Responses:
    - 200: `#/components/responses/deleteMockServerResponse`
    - 400: `#/components/responses/serverResponseNotFound400Error`
    - 401: `#/components/responses/common401Error`
    - 404: `#/components/responses/mock400ErrorInstanceNotFound`
    - 500: `#/components/responses/common500ErrorServerError`

### Key Features
- Mock server management
- Call logging and history
- Custom server responses
- Public/private visibility control
- Response simulation (5xx errors)
- Workspace integration
- Call log retention based on plan

```

--------------------------------------------------------------------------------
/src/tools/api/additional-features/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  // Billing
  {
    name: 'get_accounts',
    description: 'Gets Postman billing account details for the given team',
    inputSchema: {
      type: 'object',
      properties: {},
      required: []
    }
  },
  {
    name: 'list_account_invoices',
    description: 'Gets all invoices for a Postman billing account filtered by status',
    inputSchema: {
      type: 'object',
      properties: {
        accountId: {
          type: 'string',
          description: "The account's ID"
        },
        status: {
          type: 'string',
          enum: ['PAID'],
          description: "The account's status"
        }
      },
      required: ['accountId', 'status']
    }
  },

  // Comment Resolution
  {
    name: 'resolve_comment_thread',
    description: 'Resolves a comment and any associated replies',
    inputSchema: {
      type: 'object',
      properties: {
        threadId: {
          type: 'string',
          description: 'The comment thread ID'
        }
      },
      required: ['threadId']
    }
  },

  // Private API Network
  {
    name: 'list_pan_elements',
    description: 'Get all elements and folders in Private API Network',
    inputSchema: {
      type: 'object',
      properties: {
        since: {
          type: 'string',
          description: 'Return only results created since the given time (ISO 8601)'
        },
        until: {
          type: 'string',
          description: 'Return only results created until this given time (ISO 8601)'
        },
        addedBy: {
          type: 'integer',
          description: 'Return only elements published by the given user ID'
        },
        name: {
          type: 'string',
          description: 'Return only elements whose name includes the given value'
        },
        summary: {
          type: 'string',
          description: 'Return only elements whose summary includes the given value'
        },
        description: {
          type: 'string',
          description: 'Return only elements whose description includes the given value'
        },
        sort: {
          type: 'string',
          enum: ['createdAt', 'updatedAt'],
          description: 'Sort field'
        },
        direction: {
          type: 'string',
          enum: ['asc', 'desc'],
          description: 'Sort direction'
        },
        offset: {
          type: 'integer',
          description: 'Number of results to skip'
        },
        limit: {
          type: 'integer',
          description: 'Maximum number of results to return'
        },
        parentFolderId: {
          type: 'integer',
          description: 'Return elements in specific folder. Use 0 for root folder.'
        },
        type: {
          type: 'string',
          enum: ['api', 'folder', 'collection', 'workspace'],
          description: 'Filter by element type'
        }
      },
      required: []
    }
  },
  {
    name: 'add_pan_element',
    description: 'Add element or folder to Private API Network',
    inputSchema: {
      type: 'object',
      properties: {
        type: {
          type: 'string',
          enum: ['api', 'collection', 'workspace', 'folder'],
          description: 'Element type'
        },
        name: {
          type: 'string',
          description: 'Element/folder name'
        },
        description: {
          type: 'string',
          description: 'Element/folder description'
        },
        summary: {
          type: 'string',
          description: 'Element summary'
        },
        parentFolderId: {
          type: 'integer',
          description: 'Parent folder ID'
        },
        elementId: {
          type: 'string',
          description: 'ID of API/collection/workspace to add'
        }
      },
      required: ['type', 'name']
    }
  },
  {
    name: 'update_pan_element',
    description: 'Update element or folder in Private API Network',
    inputSchema: {
      type: 'object',
      properties: {
        elementId: {
          type: 'string',
          description: 'Element ID'
        },
        elementType: {
          type: 'string',
          enum: ['api', 'collection', 'workspace', 'folder'],
          description: 'Element type'
        },
        name: {
          type: 'string',
          description: 'Updated name'
        },
        description: {
          type: 'string',
          description: 'Updated description'
        },
        summary: {
          type: 'string',
          description: 'Updated summary'
        },
        parentFolderId: {
          type: 'integer',
          description: 'New parent folder ID'
        }
      },
      required: ['elementId', 'elementType']
    }
  },
  {
    name: 'remove_pan_element',
    description: 'Remove element or folder from Private API Network',
    inputSchema: {
      type: 'object',
      properties: {
        elementId: {
          type: 'string',
          description: 'Element ID'
        },
        elementType: {
          type: 'string',
          enum: ['api', 'collection', 'workspace', 'folder'],
          description: 'Element type'
        }
      },
      required: ['elementId', 'elementType']
    }
  },

  // Webhooks
  {
    name: 'create_webhook',
    description: 'Creates webhook that triggers collection with custom payload',
    inputSchema: {
      type: 'object',
      properties: {
        workspace: {
          type: 'string',
          description: 'Workspace ID'
        },
        webhook: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'Webhook name'
            },
            collection: {
              type: 'string',
              description: 'Collection ID to trigger'
            },
            description: {
              type: 'string',
              description: 'Webhook description'
            },
            events: {
              type: 'array',
              description: 'Array of events to trigger on',
              items: {
                type: 'string'
              }
            }
          },
          required: ['name', 'collection']
        }
      },
      required: ['workspace', 'webhook']
    }
  },

  // Tags
  {
    name: 'get_tagged_elements',
    description: 'Get elements by tag',
    inputSchema: {
      type: 'object',
      properties: {
        slug: {
          type: 'string',
          description: 'Tag slug'
        },
        limit: {
          type: 'integer',
          description: 'Maximum number of results to return'
        },
        direction: {
          type: 'string',
          enum: ['asc', 'desc'],
          description: 'Sort direction'
        },
        cursor: {
          type: 'string',
          description: 'Pagination cursor'
        },
        entityType: {
          type: 'string',
          enum: ['api', 'collection', 'workspace'],
          description: 'Filter by entity type'
        }
      },
      required: ['slug']
    }
  },
  {
    name: 'get_workspace_tags',
    description: 'Get workspace tags',
    inputSchema: {
      type: 'object',
      properties: {
        workspaceId: {
          type: 'string',
          description: 'Workspace ID'
        }
      },
      required: ['workspaceId']
    }
  },
  {
    name: 'update_workspace_tags',
    description: 'Update workspace tags',
    inputSchema: {
      type: 'object',
      properties: {
        workspaceId: {
          type: 'string',
          description: 'Workspace ID'
        },
        tags: {
          type: 'array',
          description: 'Array of tag objects',
          items: {
            type: 'object',
            properties: {
              slug: {
                type: 'string',
                description: 'Tag slug'
              },
              name: {
                type: 'string',
                description: 'Tag name'
              }
            },
            required: ['slug', 'name']
          }
        }
      },
      required: ['workspaceId', 'tags']
    }
  }
];

```

--------------------------------------------------------------------------------
/src/tools/api/mocks/definitions.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition } from '../../../types/index.js';

export const TOOL_DEFINITIONS: ToolDefinition[] = [
  {
    name: 'list_mocks',
    description: 'List all mock servers',
    inputSchema: {
      type: 'object',
      properties: {
        teamId: {
          type: 'string',
          description: 'Return only results that belong to the given team ID'
        },
        workspace: {
          type: 'string',
          description: 'Return only results found in the given workspace. If both teamId and workspace provided, only workspace is used.'
        }
      },
      required: [] // No required fields for list operation
    }
  },
  {
    name: 'create_mock',
    description: 'Create a new mock server. Creates in Personal workspace if workspace not specified.',
    inputSchema: {
      type: 'object',
      properties: {
        workspace: {
          type: 'string',
          description: 'Workspace ID to create the mock in'
        },
        mock: {
          type: 'object',
          required: ['collection', 'name'],
          properties: {
            collection: {
              type: 'string',
              description: 'Collection ID to mock'
            },
            name: {
              type: 'string',
              description: 'Mock server name'
            },
            description: {
              type: 'string',
              description: 'Mock server description'
            },
            environment: {
              type: 'string',
              description: 'Environment ID to use'
            },
            private: {
              type: 'boolean',
              description: 'Access control setting'
            },
            versionTag: {
              type: 'string',
              description: 'Collection version tag'
            }
          }
        }
      },
      required: ['mock'] // mock object is required for creation
    }
  },
  {
    name: 'get_mock',
    description: 'Get details of a specific mock server',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        }
      }
    }
  },
  {
    name: 'update_mock',
    description: 'Update an existing mock server',
    inputSchema: {
      type: 'object',
      required: ['mockId', 'mock'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        mock: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'New mock server name'
            },
            description: {
              type: 'string',
              description: 'Updated description'
            },
            environment: {
              type: 'string',
              description: 'New environment ID'
            },
            private: {
              type: 'boolean',
              description: 'Updated access control setting'
            },
            versionTag: {
              type: 'string',
              description: 'Updated collection version tag'
            }
          }
        }
      }
    }
  },
  {
    name: 'delete_mock',
    description: 'Delete a mock server',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        }
      }
    }
  },
  {
    name: 'get_mock_call_logs',
    description: 'Get mock call logs. Maximum 6.5MB or 100 call logs per API call. Retention period based on Postman plan.',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        limit: {
          type: 'number',
          description: 'Maximum number of logs to return (default: 100)'
        },
        cursor: {
          type: 'string',
          description: 'Pagination cursor'
        },
        until: {
          type: 'string',
          description: 'Return logs until this timestamp'
        },
        since: {
          type: 'string',
          description: 'Return logs since this timestamp'
        },
        responseStatusCode: {
          type: 'number',
          description: 'Filter by response status code'
        },
        responseType: {
          type: 'string',
          description: 'Filter by response type'
        },
        requestMethod: {
          type: 'string',
          description: 'Filter by request method'
        },
        requestPath: {
          type: 'string',
          description: 'Filter by request path'
        },
        sort: {
          type: 'string',
          enum: ['servedAt'],
          description: 'Sort field'
        },
        direction: {
          type: 'string',
          enum: ['asc', 'desc'],
          description: 'Sort direction'
        },
        include: {
          type: 'string',
          description: 'Include additional data (request.headers, request.body, response.headers, response.body)'
        }
      }
    }
  },
  {
    name: 'publish_mock',
    description: 'Publish mock server (sets Access Control to public)',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        }
      }
    }
  },
  {
    name: 'unpublish_mock',
    description: 'Unpublish mock server (sets Access Control to private)',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        }
      }
    }
  },
  {
    name: 'list_server_responses',
    description: 'Get all server responses for a mock',
    inputSchema: {
      type: 'object',
      required: ['mockId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        }
      }
    }
  },
  {
    name: 'create_server_response',
    description: 'Create a server response. Only one server response can be active at a time.',
    inputSchema: {
      type: 'object',
      required: ['mockId', 'serverResponse'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        serverResponse: {
          type: 'object',
          required: ['name', 'code', 'headers', 'body'],
          properties: {
            name: {
              type: 'string',
              description: 'Response name'
            },
            code: {
              type: 'number',
              description: 'HTTP status code'
            },
            headers: {
              type: 'array',
              description: 'Response headers',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string' },
                  value: { type: 'string' }
                }
              }
            },
            body: {
              type: 'string',
              description: 'Response body content'
            },
            active: {
              type: 'boolean',
              description: 'Set as active response'
            },
            delay: {
              type: 'number',
              description: 'Response delay in milliseconds'
            }
          }
        }
      }
    }
  },
  {
    name: 'get_server_response',
    description: 'Get a specific server response',
    inputSchema: {
      type: 'object',
      required: ['mockId', 'serverResponseId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        serverResponseId: {
          type: 'string',
          description: 'The server response ID'
        }
      }
    }
  },
  {
    name: 'update_server_response',
    description: 'Update a server response',
    inputSchema: {
      type: 'object',
      required: ['mockId', 'serverResponseId', 'serverResponse'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        serverResponseId: {
          type: 'string',
          description: 'The server response ID'
        },
        serverResponse: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'Updated response name'
            },
            code: {
              type: 'number',
              description: 'Updated HTTP status code'
            },
            headers: {
              type: 'array',
              description: 'Updated response headers',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string' },
                  value: { type: 'string' }
                }
              }
            },
            body: {
              type: 'string',
              description: 'Updated response body'
            },
            active: {
              type: 'boolean',
              description: 'Change active status'
            },
            delay: {
              type: 'number',
              description: 'Updated response delay'
            }
          }
        }
      }
    }
  },
  {
    name: 'delete_server_response',
    description: 'Delete a server response',
    inputSchema: {
      type: 'object',
      required: ['mockId', 'serverResponseId'],
      properties: {
        mockId: {
          type: 'string',
          description: 'The mock server ID'
        },
        serverResponseId: {
          type: 'string',
          description: 'The server response ID'
        }
      }
    }
  }
];

```

--------------------------------------------------------------------------------
/src/handlers/resource-template-handler.ts:
--------------------------------------------------------------------------------

```typescript
import { ListResourceTemplatesRequestSchema, ReadResourceRequestSchema, McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import axios from 'axios';

/**
 * Handles resource template requests for dynamic Postman API resources
 */
export class ResourceTemplateHandler {
  constructor(private server: Server) {
    this.setupHandlers();
  }

  private setupHandlers() {
    this.setupListTemplates();
    this.setupReadResource();
  }

  private setupListTemplates() {
    this.server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
      resourceTemplates: [
        // Workspace Resources
        {
          uriTemplate: 'postman://workspaces/{workspaceId}/collections',
          name: 'Workspace Collections',
          description: 'List of collections in a specific workspace',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://workspaces/{workspaceId}/environments',
          name: 'Workspace Environments',
          description: 'List of environments in a specific workspace',
          mimeType: 'application/json',
        },

        // API Resources
        {
          uriTemplate: 'postman://apis/{apiId}',
          name: 'API Details',
          description: 'Details of a specific API',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/versions',
          name: 'API Versions',
          description: 'List of versions for a specific API',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/versions/{versionId}',
          name: 'API Version Details',
          description: 'Details of a specific API version',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/schemas',
          name: 'API Schemas',
          description: 'List of schemas for a specific API',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/schemas/{schemaId}/files',
          name: 'API Schema Files',
          description: 'List of files in an API schema',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/comments',
          name: 'API Comments',
          description: 'List of comments on a specific API',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://apis/{apiId}/tags',
          name: 'API Tags',
          description: 'Tags associated with a specific API',
          mimeType: 'application/json',
        },

        // Collection Resources
        {
          uriTemplate: 'postman://collections/{collectionId}',
          name: 'Collection Details',
          description: 'Details of a specific collection',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://collections/{collectionId}/requests',
          name: 'Collection Requests',
          description: 'List of requests in a specific collection',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://collections/{collectionId}/folders',
          name: 'Collection Folders',
          description: 'List of folders in a specific collection',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://collections/{collectionId}/responses',
          name: 'Collection Responses',
          description: 'List of saved responses in a specific collection',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://collections/{collectionId}/forks',
          name: 'Collection Forks',
          description: 'List of forks of a specific collection',
          mimeType: 'application/json',
        },

        // Environment Resources
        {
          uriTemplate: 'postman://environments/{environmentId}',
          name: 'Environment Details',
          description: 'Details of a specific environment',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://environments/{environmentId}/forks',
          name: 'Environment Forks',
          description: 'List of forks of a specific environment',
          mimeType: 'application/json',
        },

        // Mock Server Resources
        {
          uriTemplate: 'postman://mocks/{mockId}',
          name: 'Mock Server Details',
          description: 'Details of a specific mock server',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://mocks/{mockId}/serverResponses',
          name: 'Mock Server Responses',
          description: 'List of server responses for a specific mock',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://mocks/{mockId}/callLogs',
          name: 'Mock Call Logs',
          description: 'Call logs for a specific mock server',
          mimeType: 'application/json',
        },

        // Monitor Resources
        {
          uriTemplate: 'postman://monitors/{monitorId}',
          name: 'Monitor Details',
          description: 'Details of a specific monitor',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://monitors/{monitorId}/runs',
          name: 'Monitor Runs',
          description: 'List of runs for a specific monitor',
          mimeType: 'application/json',
        },

        // Security & Access Control Resources
        {
          uriTemplate: 'postman://collections/{collectionId}/roles',
          name: 'Collection Roles',
          description: 'List of roles for a specific collection',
          mimeType: 'application/json',
        },
        {
          uriTemplate: 'postman://workspaces/{workspaceId}/roles',
          name: 'Workspace Roles',
          description: 'List of roles for a specific workspace',
          mimeType: 'application/json',
        },

        // PAN Resources
        {
          uriTemplate: 'postman://pan/folders/{folderId}/elements',
          name: 'PAN Folder Elements',
          description: 'List of elements in a specific Private API Network folder',
          mimeType: 'application/json',
        }
      ],
    }));
  }

  private setupReadResource() {
    this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
      const { uri } = request.params;

      try {
        // Parse the URI to extract resource type and IDs
        const match = uri.match(/^postman:\/\/([^/]+)\/([^/]+)(?:\/([^/]+))?(?:\/([^/]+))?(?:\/([^/]+))?/);
        if (!match) {
          throw new McpError(ErrorCode.InvalidRequest, `Invalid URI format: ${uri}`);
        }

        const [, resourceType, id, subResource, subId, finalResource] = match;
        let endpoint = '';

        // Map URI patterns to Postman API endpoints
        switch (resourceType) {
          case 'workspaces':
            endpoint = `/workspaces/${id}`;
            if (subResource === 'collections') endpoint += '/collections';
            if (subResource === 'environments') endpoint += '/environments';
            break;

          case 'apis':
            endpoint = `/apis/${id}`;
            if (subResource === 'versions') {
              endpoint += '/versions';
              if (subId) endpoint += `/${subId}`;
            }
            if (subResource === 'schemas') {
              endpoint += '/schemas';
              if (subId) {
                endpoint += `/${subId}`;
                if (finalResource === 'files') endpoint += '/files';
              }
            }
            if (subResource === 'comments') endpoint += '/comments';
            if (subResource === 'tags') endpoint += '/tags';
            break;

          case 'collections':
            endpoint = `/collections/${id}`;
            if (subResource === 'requests') endpoint += '/requests';
            if (subResource === 'folders') endpoint += '/folders';
            if (subResource === 'responses') endpoint += '/responses';
            if (subResource === 'forks') endpoint += '/forks';
            if (subResource === 'roles') endpoint += '/roles';
            break;

          case 'environments':
            endpoint = `/environments/${id}`;
            if (subResource === 'forks') endpoint += '/forks';
            break;

          case 'mocks':
            endpoint = `/mocks/${id}`;
            if (subResource === 'serverResponses') endpoint += '/serverResponses';
            if (subResource === 'callLogs') endpoint += '/callLogs';
            break;

          case 'monitors':
            endpoint = `/monitors/${id}`;
            if (subResource === 'runs') endpoint += '/runs';
            break;

          case 'pan':
            if (subResource === 'folders') {
              endpoint = `/pan/folders/${id}/elements`;
            }
            break;

          default:
            throw new McpError(ErrorCode.InvalidRequest, `Unknown resource type: ${resourceType}`);
        }

        // Make request to Postman API
        const response = await axios.get(`https://api.getpostman.com${endpoint}`, {
          headers: {
            'X-Api-Key': process.env.POSTMAN_API_KEY!,
          },
        });

        return {
          contents: [
            {
              uri,
              mimeType: 'application/json',
              text: JSON.stringify(response.data, null, 2),
            },
          ],
        };
      } catch (error) {
        if (axios.isAxiosError(error)) {
          throw new McpError(
            ErrorCode.InternalError,
            `Postman API error: ${error.response?.data?.error?.message || error.message}`
          );
        }
        throw error;
      }
    });
  }
}

```
Page 1/6FirstPrevNextLast