@postman/postman-mcp-server 2.5.4 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +232 -1
- package/dist/package.json +1 -1
- package/dist/src/clients/postman.js +3 -2
- package/dist/src/enabledResources.js +1 -0
- package/dist/src/env.js +12 -0
- package/dist/src/index.js +14 -14
- package/dist/src/tools/createCollectionRequest.js +192 -3
- package/dist/src/tools/createSpec.js +5 -3
- package/dist/src/tools/getMonitors.js +1 -0
- package/dist/src/tools/getWorkspace.js +2 -2
- package/dist/src/tools/runner/telemetry.js +2 -1
- package/dist/src/tools/updateCollectionRequest.js +174 -3
- package/dist/src/tools/updateMock.js +3 -3
- package/package.json +1 -1
- package/dist/src/tools/getCollectionMap.js +0 -101
package/README.md
CHANGED
|
@@ -39,11 +39,18 @@ The Postman MCP Server supports the EU region for remote and local servers:
|
|
|
39
39
|
* [**VS Code**](#install-in-visual-studio-code)
|
|
40
40
|
* [**Cursor**](#install-in-cursor)
|
|
41
41
|
* [**Claude Code**](#install-in-claude-code)
|
|
42
|
+
* [**Codex**](#install-in-codex)
|
|
43
|
+
* [**Windsurf**](#install-in-windsurf)
|
|
44
|
+
* [**Antigravity**](#install-in-antigravity)
|
|
45
|
+
* [**GitHub Copilot CLI**](#install-in-github-copilot-cli)
|
|
42
46
|
* [**Local server**](#local-server)
|
|
43
47
|
* [**VS Code**](#install-in-visual-studio-code-1)
|
|
44
48
|
* [**Cursor**](#install-in-cursor-1)
|
|
45
49
|
* [**Claude**](#claude-integration)
|
|
46
50
|
* [**Claude Code**](#install-in-claude-code-1)
|
|
51
|
+
* [**Windsurf**](#install-in-windsurf-1)
|
|
52
|
+
* [**Antigravity**](#install-in-antigravity-1)
|
|
53
|
+
* [**GitHub Copilot CLI**](#install-in-github-copilot-cli-1)
|
|
47
54
|
* [**Gemini CLI**](#use-as-a-gemini-cli-extension)
|
|
48
55
|
* [**Docker**](#install-in-docker)
|
|
49
56
|
* [**Questions and support**](#questions-and-support)
|
|
@@ -129,6 +136,150 @@ For **Full** mode:
|
|
|
129
136
|
claude mcp add --transport http postman https://mcp.postman.com/mcp --header "Authorization: Bearer <POSTMAN_API_KEY>"
|
|
130
137
|
```
|
|
131
138
|
|
|
139
|
+
### Install in Codex
|
|
140
|
+
|
|
141
|
+
To install the MCP server in Codex, run the following command in your terminal:
|
|
142
|
+
|
|
143
|
+
For **Minimal** mode:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
codex mcp add postman --env POSTMAN_API_KEY=<POSTMAN_API_KEY> -- npx @postman/postman-mcp-server --minimal
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For **Code** mode:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
codex mcp add postman --env POSTMAN_API_KEY=<POSTMAN_API_KEY> -- npx @postman/postman-mcp-server --code
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
For **Full** mode:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
codex mcp add postman --env POSTMAN_API_KEY=<POSTMAN_API_KEY> -- npx @postman/postman-mcp-server --full
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Install in Windsurf
|
|
162
|
+
|
|
163
|
+
To install the MCP server in Windsurf, copy the following JSON config into the `.codeium/windsurf/mcp_config.json` file:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"mcpServers": {
|
|
168
|
+
"postman-api": {
|
|
169
|
+
"args": [
|
|
170
|
+
"mcp-remote",
|
|
171
|
+
"https://mcp.postman.com/mcp",
|
|
172
|
+
"--header",
|
|
173
|
+
"Authorization: Bearer XXX"
|
|
174
|
+
],
|
|
175
|
+
"command": "npx",
|
|
176
|
+
"disabled": false,
|
|
177
|
+
"disabledTools": [],
|
|
178
|
+
"env": {}
|
|
179
|
+
},
|
|
180
|
+
"postman-api-code": {
|
|
181
|
+
"args": [
|
|
182
|
+
"mcp-remote",
|
|
183
|
+
"https://mcp.postman.com/code",
|
|
184
|
+
"--header",
|
|
185
|
+
"Authorization: Bearer XXX"
|
|
186
|
+
],
|
|
187
|
+
"command": "npx",
|
|
188
|
+
"disabled": false,
|
|
189
|
+
"disabledTools": [],
|
|
190
|
+
"env": {}
|
|
191
|
+
},
|
|
192
|
+
"postman-api-minimal": {
|
|
193
|
+
"args": [
|
|
194
|
+
"mcp-remote",
|
|
195
|
+
"https://mcp.postman.com/minimal",
|
|
196
|
+
"--header",
|
|
197
|
+
"Authorization: Bearer XXX"
|
|
198
|
+
],
|
|
199
|
+
"command": "npx",
|
|
200
|
+
"disabled": false,
|
|
201
|
+
"disabledTools": [],
|
|
202
|
+
"env": {}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Install in Antigravity
|
|
209
|
+
|
|
210
|
+
To install the MCP server in Antigravity, click **Manage MCP servers > View raw config**. Then, copy the following JSON config into the `.codeium/windsurf/mcp_config.json` file:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"mcpServers": {
|
|
215
|
+
"postman-api": {
|
|
216
|
+
"args": [
|
|
217
|
+
"mcp-remote",
|
|
218
|
+
"https://mcp.postman.com/mcp",
|
|
219
|
+
"--header",
|
|
220
|
+
"Authorization: Bearer XXX"
|
|
221
|
+
],
|
|
222
|
+
"command": "npx",
|
|
223
|
+
"disabled": false,
|
|
224
|
+
"disabledTools": [],
|
|
225
|
+
"env": {}
|
|
226
|
+
},
|
|
227
|
+
"postman-api-code": {
|
|
228
|
+
"args": [
|
|
229
|
+
"mcp-remote",
|
|
230
|
+
"https://mcp.postman.com/code",
|
|
231
|
+
"--header",
|
|
232
|
+
"Authorization: Bearer XXX"
|
|
233
|
+
],
|
|
234
|
+
"command": "npx",
|
|
235
|
+
"disabled": false,
|
|
236
|
+
"disabledTools": [],
|
|
237
|
+
"env": {}
|
|
238
|
+
},
|
|
239
|
+
"postman-api-minimal": {
|
|
240
|
+
"args": [
|
|
241
|
+
"mcp-remote",
|
|
242
|
+
"https://mcp.postman.com/minimal",
|
|
243
|
+
"--header",
|
|
244
|
+
"Authorization: Bearer XXX"
|
|
245
|
+
],
|
|
246
|
+
"command": "npx",
|
|
247
|
+
"disabled": false,
|
|
248
|
+
"disabledTools": [],
|
|
249
|
+
"env": {}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Install in GitHub Copilot CLI
|
|
256
|
+
|
|
257
|
+
Use the Copilot CLI to interactively add the MCP server:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
/mcp add
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Alternatively, create or edit the configuration file `~/.copilot/mcp-config.json` and add:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"mcpServers": {
|
|
268
|
+
"postman-api-http-server": {
|
|
269
|
+
"type": "http",
|
|
270
|
+
"url": "https://mcp.postman.com/minimal",
|
|
271
|
+
"headers": {
|
|
272
|
+
"Authorization": "Bearer YOUR_API_KEY"
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
By default, this uses **Minimal** mode. To access **Full** mode, change the `url` value to `https://mcp.postman.com/mcp`. To access **Code** mode, change the value to `https://mcp.postman.com/code`.
|
|
280
|
+
|
|
281
|
+
For more information, see the [Copilot CLI documentation](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli).
|
|
282
|
+
|
|
132
283
|
---
|
|
133
284
|
|
|
134
285
|
## Local server
|
|
@@ -147,7 +298,6 @@ The local server supports the following tool configurations:
|
|
|
147
298
|
|
|
148
299
|
**Note:** Use the `--region` flag to specify the Postman API region (`us` or `eu`), or set the `POSTMAN_API_BASE_URL` environment variable directly. By default, the server uses the `us` option.
|
|
149
300
|
|
|
150
|
-
|
|
151
301
|
### Install in Visual Studio Code
|
|
152
302
|
|
|
153
303
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=postman-api-mcp&inputs=%5B%7B%22id%22%3A%22postman-api-key%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Enter%20your%20Postman%20API%20key%22%7D%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22%40postman%2Fpostman-mcp-server%22%2C%22--full%22%5D%2C%22env%22%3A%7B%22POSTMAN_API_KEY%22%3A%22%24%7Binput%3Apostman-api-key%7D%22%7D%7D)
|
|
@@ -227,6 +377,87 @@ For **Full** mode:
|
|
|
227
377
|
claude mcp add postman --env POSTMAN_API_KEY=YOUR_KEY -- npx @postman/postman-mcp-server@latest --full
|
|
228
378
|
```
|
|
229
379
|
|
|
380
|
+
### Install in Windsurf
|
|
381
|
+
|
|
382
|
+
To manually install the MCP server in Windsurf, do the following:
|
|
383
|
+
|
|
384
|
+
1. Click **Open MCP Marketplace** in Windsurf.
|
|
385
|
+
1. Type "Postman" in the search text box to filter the marketplace results.
|
|
386
|
+
1. Click **Install**.
|
|
387
|
+
1. When prompted, enter a valid Postman API key.
|
|
388
|
+
1. Select the tools that you want to enable, or click **All Tools** to select all available tools.
|
|
389
|
+
1. Turn on **Enabled** to enable the Postman MCP server.
|
|
390
|
+
|
|
391
|
+
#### Manual installation
|
|
392
|
+
|
|
393
|
+
Copy the following JSON config into the `.codeium/windsurf/mcp_config.json` file:
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"mcpServers": {
|
|
398
|
+
"postman_mcp_server_stdio": {
|
|
399
|
+
"args": [
|
|
400
|
+
"@postman/postman-mcp-server"
|
|
401
|
+
],
|
|
402
|
+
"command": "npx",
|
|
403
|
+
"disabled": false,
|
|
404
|
+
"disabledTools": [],
|
|
405
|
+
"env": {
|
|
406
|
+
"POSTMAN_API_KEY": "XXXX"
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Install in Antigravity
|
|
414
|
+
|
|
415
|
+
To install the MCP server in Antigravity, click **Manage MCP servers > View raw config**. Then, copy the following JSON config into the `.codeium/windsurf/mcp_config.json` file:
|
|
416
|
+
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"mcpServers": {
|
|
420
|
+
"postman_mcp_server_stdio": {
|
|
421
|
+
"args": [
|
|
422
|
+
"@postman/postman-mcp-server"
|
|
423
|
+
],
|
|
424
|
+
"command": "npx",
|
|
425
|
+
"disabled": false,
|
|
426
|
+
"disabledTools": [],
|
|
427
|
+
"env": {
|
|
428
|
+
"POSTMAN_API_KEY": "XXXX"
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Install in GitHub Copilot CLI
|
|
436
|
+
|
|
437
|
+
Use the Copilot CLI to interactively add the MCP server:
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
/mcp add
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Alternatively, create or edit the configuration file `~/.copilot/mcp-config.json` and add:
|
|
444
|
+
|
|
445
|
+
```json
|
|
446
|
+
{
|
|
447
|
+
"mcpServers": {
|
|
448
|
+
"postman-api-mcp": {
|
|
449
|
+
"command": "npx",
|
|
450
|
+
"args": ["@postman/postman-mcp-server"],
|
|
451
|
+
"env": {
|
|
452
|
+
"POSTMAN_API_KEY": "YOUR_API_KEY"
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
For more information, see the [Copilot CLI documentation](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli).
|
|
460
|
+
|
|
230
461
|
### Use as a Gemini CLI extension
|
|
231
462
|
|
|
232
463
|
To install the MCP server as a Gemini CLI extension, run the following command in your terminal:
|
package/dist/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import { USER_AGENT } from '../constants.js';
|
|
3
|
+
import { env } from '../env.js';
|
|
3
4
|
export var ContentType;
|
|
4
5
|
(function (ContentType) {
|
|
5
6
|
ContentType["Json"] = "application/json";
|
|
@@ -10,7 +11,7 @@ export class PostmanAPIClient {
|
|
|
10
11
|
apiKey;
|
|
11
12
|
serverContext;
|
|
12
13
|
static instance = null;
|
|
13
|
-
constructor(apiKey, baseUrl =
|
|
14
|
+
constructor(apiKey, baseUrl = env.POSTMAN_API_BASE_URL, serverContext) {
|
|
14
15
|
this.apiKey = apiKey;
|
|
15
16
|
this.baseUrl = baseUrl;
|
|
16
17
|
this.serverContext = serverContext;
|
|
@@ -40,7 +41,7 @@ export class PostmanAPIClient {
|
|
|
40
41
|
return this.request(endpoint, { ...options, method: 'DELETE' });
|
|
41
42
|
}
|
|
42
43
|
async request(endpoint, options) {
|
|
43
|
-
const currentApiKey = this.apiKey ||
|
|
44
|
+
const currentApiKey = this.apiKey || env.POSTMAN_API_KEY;
|
|
44
45
|
if (!currentApiKey) {
|
|
45
46
|
throw new Error('API key is required for requests. Provide it via constructor parameter or set POSTMAN_API_KEY environment variable.');
|
|
46
47
|
}
|
package/dist/src/env.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const envSchema = z.object({
|
|
3
|
+
POSTMAN_API_KEY: z.string(),
|
|
4
|
+
POSTMAN_API_BASE_URL: z.string().url().default('https://api.postman.com'),
|
|
5
|
+
GIT_BRANCH: z.string().default('main'),
|
|
6
|
+
});
|
|
7
|
+
const parsedEnv = envSchema.safeParse(process.env);
|
|
8
|
+
if (!parsedEnv.success) {
|
|
9
|
+
console.error('Invalid environment variables for Postman MCP server:', parsedEnv.error.format());
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
export const env = parsedEnv.data;
|
package/dist/src/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import dotenv from 'dotenv';
|
|
3
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
4
|
import { ErrorCode, isInitializeRequest, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
6
5
|
import { readdir } from 'node:fs/promises';
|
|
7
6
|
import { join, dirname } from 'node:path';
|
|
8
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import dotenv from 'dotenv';
|
|
9
9
|
import { enabledResources } from './enabledResources.js';
|
|
10
10
|
import { PostmanAPIClient } from './clients/postman.js';
|
|
11
11
|
import { SERVER_NAME, APP_VERSION } from './constants.js';
|
|
12
|
+
import { env } from './env.js';
|
|
12
13
|
const SUPPORTED_REGIONS = {
|
|
13
14
|
us: 'https://api.postman.com',
|
|
14
15
|
eu: 'https://api.eu.postman.com',
|
|
@@ -20,7 +21,7 @@ function setRegionEnvironment(region) {
|
|
|
20
21
|
if (!isValidRegion(region)) {
|
|
21
22
|
throw new Error(`Invalid region: ${region}. Supported regions: us, eu`);
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
env.POSTMAN_API_BASE_URL = SUPPORTED_REGIONS[region];
|
|
24
25
|
}
|
|
25
26
|
function log(level, message, context) {
|
|
26
27
|
const timestamp = new Date().toISOString();
|
|
@@ -42,17 +43,17 @@ function logBoth(server, level, message, context) {
|
|
|
42
43
|
async function loadAllTools() {
|
|
43
44
|
const __filename = fileURLToPath(import.meta.url);
|
|
44
45
|
const __dirname = dirname(__filename);
|
|
45
|
-
const
|
|
46
|
+
const generatedToolsDir = join(__dirname, './tools');
|
|
47
|
+
const isWindows = process.platform === 'win32';
|
|
48
|
+
const tools = [];
|
|
46
49
|
try {
|
|
47
|
-
log('info', 'Loading tools from directory', { toolsDir });
|
|
48
|
-
const files = await readdir(
|
|
50
|
+
log('info', 'Loading tools from directory', { toolsDir: generatedToolsDir });
|
|
51
|
+
const files = await readdir(generatedToolsDir);
|
|
49
52
|
const toolFiles = files.filter((file) => file.endsWith('.js'));
|
|
50
53
|
log('debug', 'Discovered tool files', { count: toolFiles.length });
|
|
51
|
-
const tools = [];
|
|
52
54
|
for (const file of toolFiles) {
|
|
53
55
|
try {
|
|
54
|
-
const toolPath = join(
|
|
55
|
-
const isWindows = process.platform === 'win32';
|
|
56
|
+
const toolPath = join(generatedToolsDir, file);
|
|
56
57
|
const toolModule = await import(isWindows ? `file://${toolPath}` : toolPath);
|
|
57
58
|
if (toolModule.method &&
|
|
58
59
|
toolModule.description &&
|
|
@@ -72,16 +73,15 @@ async function loadAllTools() {
|
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
log('info', 'Tool loading completed', { totalLoaded: tools.length });
|
|
76
|
-
return tools;
|
|
77
76
|
}
|
|
78
77
|
catch (error) {
|
|
79
78
|
log('error', 'Failed to read tools directory', {
|
|
80
|
-
toolsDir,
|
|
79
|
+
toolsDir: generatedToolsDir,
|
|
81
80
|
error: String(error?.message || error),
|
|
82
81
|
});
|
|
83
|
-
return [];
|
|
84
82
|
}
|
|
83
|
+
log('info', 'Tool loading completed', { totalLoaded: tools.length });
|
|
84
|
+
return tools;
|
|
85
85
|
}
|
|
86
86
|
const dotEnvOutput = dotenv.config({ quiet: true });
|
|
87
87
|
if (dotEnvOutput.error) {
|
|
@@ -105,7 +105,7 @@ async function run() {
|
|
|
105
105
|
setRegionEnvironment(region);
|
|
106
106
|
log('info', `Using region: ${region}`, {
|
|
107
107
|
region,
|
|
108
|
-
baseUrl:
|
|
108
|
+
baseUrl: env.POSTMAN_API_BASE_URL,
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
else {
|
|
@@ -114,7 +114,7 @@ async function run() {
|
|
|
114
114
|
process.exit(1);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
const apiKey =
|
|
117
|
+
const apiKey = env.POSTMAN_API_KEY;
|
|
118
118
|
if (!apiKey) {
|
|
119
119
|
log('error', 'POSTMAN_API_KEY environment variable is required for STDIO mode');
|
|
120
120
|
process.exit(1);
|
|
@@ -9,9 +9,176 @@ export const parameters = z.object({
|
|
|
9
9
|
.string()
|
|
10
10
|
.describe('The folder ID in which to create the request. By default, the system will create the request at the collection level.')
|
|
11
11
|
.optional(),
|
|
12
|
-
name: z
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
name: z.string().describe('Name of the request').optional(),
|
|
13
|
+
description: z.string().nullable().optional(),
|
|
14
|
+
method: z
|
|
15
|
+
.enum([
|
|
16
|
+
'GET',
|
|
17
|
+
'PUT',
|
|
18
|
+
'POST',
|
|
19
|
+
'PATCH',
|
|
20
|
+
'DELETE',
|
|
21
|
+
'COPY',
|
|
22
|
+
'HEAD',
|
|
23
|
+
'OPTIONS',
|
|
24
|
+
'LINK',
|
|
25
|
+
'UNLINK',
|
|
26
|
+
'PURGE',
|
|
27
|
+
'LOCK',
|
|
28
|
+
'UNLOCK',
|
|
29
|
+
'PROPFIND',
|
|
30
|
+
'VIEW',
|
|
31
|
+
])
|
|
32
|
+
.nullable()
|
|
33
|
+
.optional(),
|
|
34
|
+
url: z.string().nullable().optional(),
|
|
35
|
+
headerData: z
|
|
36
|
+
.array(z.object({
|
|
37
|
+
key: z.string().optional(),
|
|
38
|
+
value: z.string().optional(),
|
|
39
|
+
description: z.string().nullable().optional(),
|
|
40
|
+
}))
|
|
41
|
+
.optional(),
|
|
42
|
+
queryParams: z
|
|
43
|
+
.array(z.object({
|
|
44
|
+
key: z.string().optional(),
|
|
45
|
+
value: z.string().optional(),
|
|
46
|
+
description: z.string().nullable().optional(),
|
|
47
|
+
enabled: z.boolean().optional(),
|
|
48
|
+
}))
|
|
49
|
+
.optional(),
|
|
50
|
+
dataMode: z.enum(['raw', 'urlencoded', 'formdata', 'binary', 'graphql']).nullable().optional(),
|
|
51
|
+
data: z
|
|
52
|
+
.array(z.object({
|
|
53
|
+
key: z.string().optional(),
|
|
54
|
+
value: z.string().optional(),
|
|
55
|
+
description: z.string().nullable().optional(),
|
|
56
|
+
enabled: z.boolean().optional(),
|
|
57
|
+
type: z.enum(['text', 'file']).optional(),
|
|
58
|
+
uuid: z.string().optional(),
|
|
59
|
+
}))
|
|
60
|
+
.nullable()
|
|
61
|
+
.optional(),
|
|
62
|
+
rawModeData: z.string().nullable().optional(),
|
|
63
|
+
graphqlModeData: z
|
|
64
|
+
.object({ query: z.string().optional(), variables: z.string().optional() })
|
|
65
|
+
.nullable()
|
|
66
|
+
.optional(),
|
|
67
|
+
dataOptions: z
|
|
68
|
+
.object({
|
|
69
|
+
raw: z.record(z.string(), z.unknown()).optional(),
|
|
70
|
+
urlencoded: z.record(z.string(), z.unknown()).optional(),
|
|
71
|
+
params: z.record(z.string(), z.unknown()).optional(),
|
|
72
|
+
binary: z.record(z.string(), z.unknown()).optional(),
|
|
73
|
+
graphql: z.record(z.string(), z.unknown()).optional(),
|
|
74
|
+
})
|
|
75
|
+
.nullable()
|
|
76
|
+
.optional(),
|
|
77
|
+
auth: z
|
|
78
|
+
.object({
|
|
79
|
+
type: z
|
|
80
|
+
.enum([
|
|
81
|
+
'noauth',
|
|
82
|
+
'basic',
|
|
83
|
+
'bearer',
|
|
84
|
+
'apikey',
|
|
85
|
+
'digest',
|
|
86
|
+
'oauth1',
|
|
87
|
+
'oauth2',
|
|
88
|
+
'hawk',
|
|
89
|
+
'awsv4',
|
|
90
|
+
'ntlm',
|
|
91
|
+
'edgegrid',
|
|
92
|
+
'jwt',
|
|
93
|
+
'asap',
|
|
94
|
+
])
|
|
95
|
+
.optional(),
|
|
96
|
+
apikey: z
|
|
97
|
+
.array(z.object({
|
|
98
|
+
key: z.string().optional(),
|
|
99
|
+
value: z.unknown().optional(),
|
|
100
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
101
|
+
}))
|
|
102
|
+
.optional(),
|
|
103
|
+
bearer: z
|
|
104
|
+
.array(z.object({
|
|
105
|
+
key: z.string().optional(),
|
|
106
|
+
value: z.unknown().optional(),
|
|
107
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
108
|
+
}))
|
|
109
|
+
.optional(),
|
|
110
|
+
basic: z
|
|
111
|
+
.array(z.object({
|
|
112
|
+
key: z.string().optional(),
|
|
113
|
+
value: z.unknown().optional(),
|
|
114
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
115
|
+
}))
|
|
116
|
+
.optional(),
|
|
117
|
+
digest: z
|
|
118
|
+
.array(z.object({
|
|
119
|
+
key: z.string().optional(),
|
|
120
|
+
value: z.unknown().optional(),
|
|
121
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
122
|
+
}))
|
|
123
|
+
.optional(),
|
|
124
|
+
oauth1: z
|
|
125
|
+
.array(z.object({
|
|
126
|
+
key: z.string().optional(),
|
|
127
|
+
value: z.unknown().optional(),
|
|
128
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
129
|
+
}))
|
|
130
|
+
.optional(),
|
|
131
|
+
oauth2: z
|
|
132
|
+
.array(z.object({
|
|
133
|
+
key: z.string().optional(),
|
|
134
|
+
value: z.unknown().optional(),
|
|
135
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
136
|
+
}))
|
|
137
|
+
.optional(),
|
|
138
|
+
hawk: z
|
|
139
|
+
.array(z.object({
|
|
140
|
+
key: z.string().optional(),
|
|
141
|
+
value: z.unknown().optional(),
|
|
142
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
143
|
+
}))
|
|
144
|
+
.optional(),
|
|
145
|
+
awsv4: z
|
|
146
|
+
.array(z.object({
|
|
147
|
+
key: z.string().optional(),
|
|
148
|
+
value: z.unknown().optional(),
|
|
149
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
150
|
+
}))
|
|
151
|
+
.optional(),
|
|
152
|
+
ntlm: z
|
|
153
|
+
.array(z.object({
|
|
154
|
+
key: z.string().optional(),
|
|
155
|
+
value: z.unknown().optional(),
|
|
156
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
157
|
+
}))
|
|
158
|
+
.optional(),
|
|
159
|
+
edgegrid: z
|
|
160
|
+
.array(z.object({
|
|
161
|
+
key: z.string().optional(),
|
|
162
|
+
value: z.unknown().optional(),
|
|
163
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
164
|
+
}))
|
|
165
|
+
.optional(),
|
|
166
|
+
jwt: z
|
|
167
|
+
.array(z.object({
|
|
168
|
+
key: z.string().optional(),
|
|
169
|
+
value: z.unknown().optional(),
|
|
170
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
171
|
+
}))
|
|
172
|
+
.optional(),
|
|
173
|
+
asap: z
|
|
174
|
+
.array(z.object({
|
|
175
|
+
key: z.string().optional(),
|
|
176
|
+
value: z.unknown().optional(),
|
|
177
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
178
|
+
}))
|
|
179
|
+
.optional(),
|
|
180
|
+
})
|
|
181
|
+
.nullable()
|
|
15
182
|
.optional(),
|
|
16
183
|
});
|
|
17
184
|
export const annotations = {
|
|
@@ -30,6 +197,28 @@ export async function handler(args, extra) {
|
|
|
30
197
|
const bodyPayload = {};
|
|
31
198
|
if (args.name !== undefined)
|
|
32
199
|
bodyPayload.name = args.name;
|
|
200
|
+
if (args.description !== undefined)
|
|
201
|
+
bodyPayload.description = args.description;
|
|
202
|
+
if (args.method !== undefined)
|
|
203
|
+
bodyPayload.method = args.method;
|
|
204
|
+
if (args.url !== undefined)
|
|
205
|
+
bodyPayload.url = args.url;
|
|
206
|
+
if (args.headerData !== undefined)
|
|
207
|
+
bodyPayload.headerData = args.headerData;
|
|
208
|
+
if (args.queryParams !== undefined)
|
|
209
|
+
bodyPayload.queryParams = args.queryParams;
|
|
210
|
+
if (args.dataMode !== undefined)
|
|
211
|
+
bodyPayload.dataMode = args.dataMode;
|
|
212
|
+
if (args.data !== undefined)
|
|
213
|
+
bodyPayload.data = args.data;
|
|
214
|
+
if (args.rawModeData !== undefined)
|
|
215
|
+
bodyPayload.rawModeData = args.rawModeData;
|
|
216
|
+
if (args.graphqlModeData !== undefined)
|
|
217
|
+
bodyPayload.graphqlModeData = args.graphqlModeData;
|
|
218
|
+
if (args.dataOptions !== undefined)
|
|
219
|
+
bodyPayload.dataOptions = args.dataOptions;
|
|
220
|
+
if (args.auth !== undefined)
|
|
221
|
+
bodyPayload.auth = args.auth;
|
|
33
222
|
const options = {
|
|
34
223
|
body: JSON.stringify(bodyPayload),
|
|
35
224
|
contentType: ContentType.Json,
|
|
@@ -2,11 +2,13 @@ import { z } from 'zod';
|
|
|
2
2
|
import { ContentType } from '../clients/postman.js';
|
|
3
3
|
import { asMcpError, McpError } from './utils/toolHelpers.js';
|
|
4
4
|
export const method = 'createSpec';
|
|
5
|
-
export const description = "Creates an API specification in Postman's [Spec Hub](https://learning.postman.com/docs/design-apis/specifications/overview/). Specifications can be single or multi-file.\n\n**Note:**\n- Postman supports OpenAPI 3.0 and AsyncAPI 2.0 specifications.\n- If the file path contains a \\`/\\` (forward slash) character, then a folder is created. For example, if the path is the \\`components/schemas.json\\` value, then a \\`components\\` folder is created with the \\`schemas.json\\` file inside.\n- Multi-file specifications can only have one root file.\n- Files cannot exceed a maximum of 10 MB in size.\n";
|
|
5
|
+
export const description = "Creates an API specification in Postman's [Spec Hub](https://learning.postman.com/docs/design-apis/specifications/overview/). Specifications can be single or multi-file.\n\n**Note:**\n- Postman supports OpenAPI 2.0, OpenAPI 3.0, OpenAPI 3.1, and AsyncAPI 2.0 specifications.\n- If the file path contains a \\`/\\` (forward slash) character, then a folder is created. For example, if the path is the \\`components/schemas.json\\` value, then a \\`components\\` folder is created with the \\`schemas.json\\` file inside.\n- Multi-file specifications can only have one root file.\n- Files cannot exceed a maximum of 10 MB in size.\n";
|
|
6
6
|
export const parameters = z.object({
|
|
7
7
|
workspaceId: z.string().describe("The workspace's ID."),
|
|
8
8
|
name: z.string().describe("The specification's name."),
|
|
9
|
-
type: z
|
|
9
|
+
type: z
|
|
10
|
+
.enum(['OPENAPI:2.0', 'OPENAPI:3.0', 'OPENAPI:3.1', 'ASYNCAPI:2.0'])
|
|
11
|
+
.describe("The specification's type."),
|
|
10
12
|
files: z
|
|
11
13
|
.array(z.union([
|
|
12
14
|
z.object({
|
|
@@ -24,7 +26,7 @@ export const parameters = z.object({
|
|
|
24
26
|
.describe("A list of the specification's files and their contents."),
|
|
25
27
|
});
|
|
26
28
|
export const annotations = {
|
|
27
|
-
title: "Creates an API specification in Postman's [Spec Hub](https://learning.postman.com/docs/design-apis/specifications/overview/). Specifications can be single or multi-file.\n\n**Note:**\n- Postman supports OpenAPI 3.0 and AsyncAPI 2.0 specifications.\n- If the file path contains a \\`/\\` (forward slash) character, then a folder is created. For example, if the path is the \\`components/schemas.json\\` value, then a \\`components\\` folder is created with the \\`schemas.json\\` file inside.\n- Multi-file specifications can only have one root file.\n- Files cannot exceed a maximum of 10 MB in size.\n",
|
|
29
|
+
title: "Creates an API specification in Postman's [Spec Hub](https://learning.postman.com/docs/design-apis/specifications/overview/). Specifications can be single or multi-file.\n\n**Note:**\n- Postman supports OpenAPI 2.0, OpenAPI 3.0, OpenAPI 3.1, and AsyncAPI 2.0 specifications.\n- If the file path contains a \\`/\\` (forward slash) character, then a folder is created. For example, if the path is the \\`components/schemas.json\\` value, then a \\`components\\` folder is created with the \\`schemas.json\\` file inside.\n- Multi-file specifications can only have one root file.\n- Files cannot exceed a maximum of 10 MB in size.\n",
|
|
28
30
|
readOnlyHint: false,
|
|
29
31
|
destructiveHint: false,
|
|
30
32
|
idempotentHint: false,
|
|
@@ -22,6 +22,7 @@ export const parameters = z.object({
|
|
|
22
22
|
limit: z
|
|
23
23
|
.number()
|
|
24
24
|
.int()
|
|
25
|
+
.lte(25)
|
|
25
26
|
.describe('The maximum number of rows to return in the response, up to a maximum value of 25. Any value greater than 25 returns a 400 Bad Request response.')
|
|
26
27
|
.default(25),
|
|
27
28
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { asMcpError, McpError } from './utils/toolHelpers.js';
|
|
3
3
|
export const method = 'getWorkspace';
|
|
4
|
-
export const description = "Gets information about a workspace.\n\n**Note:**\n\nThis endpoint's response contains the \\`visibility\\` field. [Visibility](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/managing-workspaces/#changing-workspace-visibility) determines who can access the workspace:\n- \\`personal\\` — Only you can access the workspace.\n- \\`team\\` — All team members can access the workspace.\n- \\`private\\` — Only invited team members can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n- \\`public\\` — Everyone can access the workspace.\n- \\`partner\\` — Only invited team members and [partners](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/partner-workspaces/) can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n
|
|
4
|
+
export const description = "Gets information about a workspace.\n\n**Note:**\n\nThis endpoint's response contains the \\`visibility\\` field. [Visibility](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/managing-workspaces/#changing-workspace-visibility) determines who can access the workspace:\n- \\`personal\\` — Only you can access the workspace.\n- \\`team\\` — All team members can access the workspace.\n- \\`private\\` — Only invited team members can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n- \\`public\\` — Everyone can access the workspace.\n- \\`partner\\` — Only invited team members and [partners](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/partner-workspaces/) can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n";
|
|
5
5
|
export const parameters = z.object({
|
|
6
6
|
workspaceId: z.string().describe("The workspace's ID."),
|
|
7
7
|
include: z
|
|
@@ -10,7 +10,7 @@ export const parameters = z.object({
|
|
|
10
10
|
.optional(),
|
|
11
11
|
});
|
|
12
12
|
export const annotations = {
|
|
13
|
-
title: "Gets information about a workspace.\n\n**Note:**\n\nThis endpoint's response contains the \\`visibility\\` field. [Visibility](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/managing-workspaces/#changing-workspace-visibility) determines who can access the workspace:\n- \\`personal\\` — Only you can access the workspace.\n- \\`team\\` — All team members can access the workspace.\n- \\`private\\` — Only invited team members can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n- \\`public\\` — Everyone can access the workspace.\n- \\`partner\\` — Only invited team members and [partners](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/partner-workspaces/) can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n
|
|
13
|
+
title: "Gets information about a workspace.\n\n**Note:**\n\nThis endpoint's response contains the \\`visibility\\` field. [Visibility](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/managing-workspaces/#changing-workspace-visibility) determines who can access the workspace:\n- \\`personal\\` — Only you can access the workspace.\n- \\`team\\` — All team members can access the workspace.\n- \\`private\\` — Only invited team members can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n- \\`public\\` — Everyone can access the workspace.\n- \\`partner\\` — Only invited team members and [partners](https://learning.postman.com/docs/collaborating-in-postman/using-workspaces/partner-workspaces/) can access the workspace ([**Professional** and **Enterprise** plans only](https://www.postman.com/pricing)).\n",
|
|
14
14
|
readOnlyHint: true,
|
|
15
15
|
destructiveHint: false,
|
|
16
16
|
idempotentHint: true,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RUNNER_ACCEPT_HEADER } from '../../constants.js';
|
|
2
|
+
import { env } from '../../env.js';
|
|
2
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
4
|
export function buildTelemetryPayload(collectionId, collectionName, result) {
|
|
4
5
|
const durationMs = result.durationMs;
|
|
@@ -98,7 +99,7 @@ export function buildTelemetryPayload(collectionId, collectionName, result) {
|
|
|
98
99
|
startedAt: result.startTime,
|
|
99
100
|
createdAt: result.endTime,
|
|
100
101
|
branchSource: 'local',
|
|
101
|
-
branch:
|
|
102
|
+
branch: env.GIT_BRANCH,
|
|
102
103
|
},
|
|
103
104
|
runOverview: {
|
|
104
105
|
collectionName: collectionName,
|
|
@@ -2,11 +2,11 @@ import { z } from 'zod';
|
|
|
2
2
|
import { ContentType } from '../clients/postman.js';
|
|
3
3
|
import { asMcpError, McpError } from './utils/toolHelpers.js';
|
|
4
4
|
export const method = 'updateCollectionRequest';
|
|
5
|
-
export const description = 'Updates a request in a collection. For a complete list of properties, refer to the **Request** entry in the [Postman Collection Format documentation](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html).\n\n**Note:**\n\n- You must pass a collection ID (\\`12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), not a collection(\\`12345678-12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), in this endpoint.\n- This endpoint does not support changing the folder of a request.\n';
|
|
5
|
+
export const description = 'Updates a request in a collection. For a complete list of properties, refer to the **Request** entry in the [Postman Collection Format documentation](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html).\n\n**Note:**\n\n- You must pass a collection ID (\\`12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), not a collection(\\`12345678-12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), in this endpoint.\n- This endpoint does not support changing the folder of a request.\n- This endpoint acts like a PATCH method. It only updates the values that you pass in the request body.';
|
|
6
6
|
export const parameters = z.object({
|
|
7
7
|
requestId: z.string().describe("The request's ID."),
|
|
8
8
|
collectionId: z.string().describe("The collection's ID."),
|
|
9
|
-
name: z.string().describe(
|
|
9
|
+
name: z.string().describe('Name of the request. Only provided fields are updated.').optional(),
|
|
10
10
|
method: z
|
|
11
11
|
.enum([
|
|
12
12
|
'GET',
|
|
@@ -25,11 +25,162 @@ export const parameters = z.object({
|
|
|
25
25
|
'PROPFIND',
|
|
26
26
|
'VIEW',
|
|
27
27
|
])
|
|
28
|
+
.nullable()
|
|
28
29
|
.describe("The request's method.")
|
|
29
30
|
.optional(),
|
|
31
|
+
description: z.string().nullable().optional(),
|
|
32
|
+
url: z.string().nullable().optional(),
|
|
33
|
+
headerData: z
|
|
34
|
+
.array(z.object({
|
|
35
|
+
key: z.string().optional(),
|
|
36
|
+
value: z.string().optional(),
|
|
37
|
+
description: z.string().nullable().optional(),
|
|
38
|
+
}))
|
|
39
|
+
.optional(),
|
|
40
|
+
queryParams: z
|
|
41
|
+
.array(z.object({
|
|
42
|
+
key: z.string().optional(),
|
|
43
|
+
value: z.string().optional(),
|
|
44
|
+
description: z.string().nullable().optional(),
|
|
45
|
+
enabled: z.boolean().optional(),
|
|
46
|
+
}))
|
|
47
|
+
.optional(),
|
|
48
|
+
dataMode: z.enum(['raw', 'urlencoded', 'formdata', 'binary', 'graphql']).nullable().optional(),
|
|
49
|
+
data: z
|
|
50
|
+
.array(z.object({
|
|
51
|
+
key: z.string().optional(),
|
|
52
|
+
value: z.string().optional(),
|
|
53
|
+
description: z.string().nullable().optional(),
|
|
54
|
+
enabled: z.boolean().optional(),
|
|
55
|
+
type: z.enum(['text', 'file']).optional(),
|
|
56
|
+
uuid: z.string().optional(),
|
|
57
|
+
}))
|
|
58
|
+
.nullable()
|
|
59
|
+
.optional(),
|
|
60
|
+
rawModeData: z.string().nullable().optional(),
|
|
61
|
+
graphqlModeData: z
|
|
62
|
+
.object({ query: z.string().optional(), variables: z.string().optional() })
|
|
63
|
+
.nullable()
|
|
64
|
+
.optional(),
|
|
65
|
+
dataOptions: z
|
|
66
|
+
.object({
|
|
67
|
+
raw: z.record(z.string(), z.unknown()).optional(),
|
|
68
|
+
urlencoded: z.record(z.string(), z.unknown()).optional(),
|
|
69
|
+
params: z.record(z.string(), z.unknown()).optional(),
|
|
70
|
+
binary: z.record(z.string(), z.unknown()).optional(),
|
|
71
|
+
graphql: z.record(z.string(), z.unknown()).optional(),
|
|
72
|
+
})
|
|
73
|
+
.nullable()
|
|
74
|
+
.optional(),
|
|
75
|
+
auth: z
|
|
76
|
+
.object({
|
|
77
|
+
type: z
|
|
78
|
+
.enum([
|
|
79
|
+
'noauth',
|
|
80
|
+
'basic',
|
|
81
|
+
'bearer',
|
|
82
|
+
'apikey',
|
|
83
|
+
'digest',
|
|
84
|
+
'oauth1',
|
|
85
|
+
'oauth2',
|
|
86
|
+
'hawk',
|
|
87
|
+
'awsv4',
|
|
88
|
+
'ntlm',
|
|
89
|
+
'edgegrid',
|
|
90
|
+
'jwt',
|
|
91
|
+
'asap',
|
|
92
|
+
])
|
|
93
|
+
.optional(),
|
|
94
|
+
apikey: z
|
|
95
|
+
.array(z.object({
|
|
96
|
+
key: z.string().optional(),
|
|
97
|
+
value: z.unknown().optional(),
|
|
98
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
99
|
+
}))
|
|
100
|
+
.optional(),
|
|
101
|
+
bearer: z
|
|
102
|
+
.array(z.object({
|
|
103
|
+
key: z.string().optional(),
|
|
104
|
+
value: z.unknown().optional(),
|
|
105
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
106
|
+
}))
|
|
107
|
+
.optional(),
|
|
108
|
+
basic: z
|
|
109
|
+
.array(z.object({
|
|
110
|
+
key: z.string().optional(),
|
|
111
|
+
value: z.unknown().optional(),
|
|
112
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
113
|
+
}))
|
|
114
|
+
.optional(),
|
|
115
|
+
digest: z
|
|
116
|
+
.array(z.object({
|
|
117
|
+
key: z.string().optional(),
|
|
118
|
+
value: z.unknown().optional(),
|
|
119
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
120
|
+
}))
|
|
121
|
+
.optional(),
|
|
122
|
+
oauth1: z
|
|
123
|
+
.array(z.object({
|
|
124
|
+
key: z.string().optional(),
|
|
125
|
+
value: z.unknown().optional(),
|
|
126
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
127
|
+
}))
|
|
128
|
+
.optional(),
|
|
129
|
+
oauth2: z
|
|
130
|
+
.array(z.object({
|
|
131
|
+
key: z.string().optional(),
|
|
132
|
+
value: z.unknown().optional(),
|
|
133
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
134
|
+
}))
|
|
135
|
+
.optional(),
|
|
136
|
+
hawk: z
|
|
137
|
+
.array(z.object({
|
|
138
|
+
key: z.string().optional(),
|
|
139
|
+
value: z.unknown().optional(),
|
|
140
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
141
|
+
}))
|
|
142
|
+
.optional(),
|
|
143
|
+
awsv4: z
|
|
144
|
+
.array(z.object({
|
|
145
|
+
key: z.string().optional(),
|
|
146
|
+
value: z.unknown().optional(),
|
|
147
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
148
|
+
}))
|
|
149
|
+
.optional(),
|
|
150
|
+
ntlm: z
|
|
151
|
+
.array(z.object({
|
|
152
|
+
key: z.string().optional(),
|
|
153
|
+
value: z.unknown().optional(),
|
|
154
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
155
|
+
}))
|
|
156
|
+
.optional(),
|
|
157
|
+
edgegrid: z
|
|
158
|
+
.array(z.object({
|
|
159
|
+
key: z.string().optional(),
|
|
160
|
+
value: z.unknown().optional(),
|
|
161
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
162
|
+
}))
|
|
163
|
+
.optional(),
|
|
164
|
+
jwt: z
|
|
165
|
+
.array(z.object({
|
|
166
|
+
key: z.string().optional(),
|
|
167
|
+
value: z.unknown().optional(),
|
|
168
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
169
|
+
}))
|
|
170
|
+
.optional(),
|
|
171
|
+
asap: z
|
|
172
|
+
.array(z.object({
|
|
173
|
+
key: z.string().optional(),
|
|
174
|
+
value: z.unknown().optional(),
|
|
175
|
+
type: z.enum(['string', 'boolean', 'number', 'array', 'object', 'any']).optional(),
|
|
176
|
+
}))
|
|
177
|
+
.optional(),
|
|
178
|
+
})
|
|
179
|
+
.nullable()
|
|
180
|
+
.optional(),
|
|
30
181
|
});
|
|
31
182
|
export const annotations = {
|
|
32
|
-
title: 'Updates a request in a collection. For a complete list of properties, refer to the **Request** entry in the [Postman Collection Format documentation](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html).\n\n**Note:**\n\n- You must pass a collection ID (\\`12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), not a collection(\\`12345678-12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), in this endpoint.\n- This endpoint does not support changing the folder of a request.\n',
|
|
183
|
+
title: 'Updates a request in a collection. For a complete list of properties, refer to the **Request** entry in the [Postman Collection Format documentation](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html).\n\n**Note:**\n\n- You must pass a collection ID (\\`12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), not a collection(\\`12345678-12ece9e1-2abf-4edc-8e34-de66e74114d2\\`), in this endpoint.\n- This endpoint does not support changing the folder of a request.\n- This endpoint acts like a PATCH method. It only updates the values that you pass in the request body.',
|
|
33
184
|
readOnlyHint: false,
|
|
34
185
|
destructiveHint: false,
|
|
35
186
|
idempotentHint: true,
|
|
@@ -44,6 +195,26 @@ export async function handler(args, extra) {
|
|
|
44
195
|
bodyPayload.name = args.name;
|
|
45
196
|
if (args.method !== undefined)
|
|
46
197
|
bodyPayload.method = args.method;
|
|
198
|
+
if (args.description !== undefined)
|
|
199
|
+
bodyPayload.description = args.description;
|
|
200
|
+
if (args.url !== undefined)
|
|
201
|
+
bodyPayload.url = args.url;
|
|
202
|
+
if (args.headerData !== undefined)
|
|
203
|
+
bodyPayload.headerData = args.headerData;
|
|
204
|
+
if (args.queryParams !== undefined)
|
|
205
|
+
bodyPayload.queryParams = args.queryParams;
|
|
206
|
+
if (args.dataMode !== undefined)
|
|
207
|
+
bodyPayload.dataMode = args.dataMode;
|
|
208
|
+
if (args.data !== undefined)
|
|
209
|
+
bodyPayload.data = args.data;
|
|
210
|
+
if (args.rawModeData !== undefined)
|
|
211
|
+
bodyPayload.rawModeData = args.rawModeData;
|
|
212
|
+
if (args.graphqlModeData !== undefined)
|
|
213
|
+
bodyPayload.graphqlModeData = args.graphqlModeData;
|
|
214
|
+
if (args.dataOptions !== undefined)
|
|
215
|
+
bodyPayload.dataOptions = args.dataOptions;
|
|
216
|
+
if (args.auth !== undefined)
|
|
217
|
+
bodyPayload.auth = args.auth;
|
|
47
218
|
const options = {
|
|
48
219
|
body: JSON.stringify(bodyPayload),
|
|
49
220
|
contentType: ContentType.Json,
|
|
@@ -15,6 +15,9 @@ export const parameters = z.object({
|
|
|
15
15
|
.describe('If true, the mock server is set private. By default, mock servers are public and can receive requests from anyone and anywhere.')
|
|
16
16
|
.default(false),
|
|
17
17
|
versionTag: z.string().describe("The API's version tag ID.").optional(),
|
|
18
|
+
collection: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("The associated collection's unique ID. This is a mandatory parameter."),
|
|
18
21
|
config: z
|
|
19
22
|
.object({
|
|
20
23
|
serverResponseId: z
|
|
@@ -25,9 +28,6 @@ export const parameters = z.object({
|
|
|
25
28
|
})
|
|
26
29
|
.describe("The mock server's configuration settings.")
|
|
27
30
|
.optional(),
|
|
28
|
-
collection: z
|
|
29
|
-
.string()
|
|
30
|
-
.describe("The associated collection's unique ID. This is a mandatory parameter."),
|
|
31
31
|
})
|
|
32
32
|
.optional(),
|
|
33
33
|
});
|
package/package.json
CHANGED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { asMcpError, McpError } from './utils/toolHelpers.js';
|
|
3
|
-
export const method = 'getCollectionMap';
|
|
4
|
-
export const description = `Get a Postman collection map with metadata and a complete recursive index of all folders and requests. Response includes collection metadata and description. Response includes itemRefs property (name and id only) instead of the full item array. After calling, present the collection summary and ask the user where they\'d like to explore next, calling getCollectionFolder and/or getCollectionRequest tools in parallel to get more data quickly.
|
|
5
|
-
Once you've called this tool, DO NOT call searchPostmanElements to find items in or related to this collection. Instead, use the map in itemRefs.
|
|
6
|
-
Only use searchPostmanElements to find the collection where a request may be. Then, stay in the collection and don't use the search.
|
|
7
|
-
When using the getCollectionRequest tool to look up request data, omit the populate parameter to avoid getting all response examples
|
|
8
|
-
back at once (can be very large). Instead, use the response ids from the return value and call getCollectionResponse for each one.
|
|
9
|
-
Prepend the collection's ownerId to the front of each response id when passing it to getCollectionResponse. This is the first part of the collection uid.
|
|
10
|
-
Infer the response schema from that information and remember it. Omit the raw response examples from the conversation going forward.`;
|
|
11
|
-
export const parameters = z.object({
|
|
12
|
-
collectionId: z
|
|
13
|
-
.string()
|
|
14
|
-
.describe('The collection ID must be in the form <OWNER_ID>-<UUID> (e.g. 12345-33823532ab9e41c9b6fd12d0fd459b8b).'),
|
|
15
|
-
access_key: z
|
|
16
|
-
.string()
|
|
17
|
-
.describe("A collection's read-only access key. Using this query parameter does not require an API key to call the endpoint.")
|
|
18
|
-
.optional(),
|
|
19
|
-
});
|
|
20
|
-
export const annotations = {
|
|
21
|
-
title: 'Get Postman Collection Map',
|
|
22
|
-
readOnlyHint: true,
|
|
23
|
-
destructiveHint: false,
|
|
24
|
-
idempotentHint: true,
|
|
25
|
-
};
|
|
26
|
-
function buildItemRefs(items) {
|
|
27
|
-
if (!Array.isArray(items) || items.length === 0) {
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
return items.map((item) => {
|
|
31
|
-
const itemId = item.uid || item.id || '';
|
|
32
|
-
const itemRef = {
|
|
33
|
-
name: item.name || '',
|
|
34
|
-
id: itemId,
|
|
35
|
-
};
|
|
36
|
-
if (item.item && Array.isArray(item.item)) {
|
|
37
|
-
const nestedRefs = buildItemRefs(item.item);
|
|
38
|
-
if (nestedRefs) {
|
|
39
|
-
itemRef.itemRefs = nestedRefs;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return itemRef;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
export async function handler(args, extra) {
|
|
46
|
-
try {
|
|
47
|
-
const endpoint = `/collections/${args.collectionId}`;
|
|
48
|
-
const query = new URLSearchParams();
|
|
49
|
-
if (args.access_key !== undefined)
|
|
50
|
-
query.set('access_key', String(args.access_key));
|
|
51
|
-
const url = query.toString() ? `${endpoint}?${query.toString()}` : endpoint;
|
|
52
|
-
const options = {
|
|
53
|
-
headers: extra.headers,
|
|
54
|
-
};
|
|
55
|
-
const result = await extra.client.get(url, options);
|
|
56
|
-
if (typeof result === 'string') {
|
|
57
|
-
return {
|
|
58
|
-
content: [
|
|
59
|
-
{
|
|
60
|
-
type: 'text',
|
|
61
|
-
text: result,
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
const response = result;
|
|
67
|
-
if (response.collection) {
|
|
68
|
-
const { item, ...collectionWithoutItems } = response.collection;
|
|
69
|
-
const itemRefs = buildItemRefs(item);
|
|
70
|
-
const processedResponse = {
|
|
71
|
-
...response,
|
|
72
|
-
collection: {
|
|
73
|
-
...collectionWithoutItems,
|
|
74
|
-
...(itemRefs && { itemRefs }),
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
return {
|
|
78
|
-
content: [
|
|
79
|
-
{
|
|
80
|
-
type: 'text',
|
|
81
|
-
text: JSON.stringify(processedResponse, null, 2),
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
content: [
|
|
88
|
-
{
|
|
89
|
-
type: 'text',
|
|
90
|
-
text: JSON.stringify(result, null, 2),
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
catch (e) {
|
|
96
|
-
if (e instanceof McpError) {
|
|
97
|
-
throw e;
|
|
98
|
-
}
|
|
99
|
-
throw asMcpError(e);
|
|
100
|
-
}
|
|
101
|
-
}
|