@smartbear/mcp 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -7
- package/dist/api-hub/client.js +298 -52
- package/dist/common/server.js +145 -0
- package/dist/index.js +31 -22
- package/dist/insight-hub/client.js +383 -385
- package/dist/package.json +3 -2
- package/dist/pactflow/client/ai.js +127 -0
- package/dist/pactflow/client/base.js +1 -0
- package/dist/pactflow/client/tools.js +46 -0
- package/dist/pactflow/client.js +132 -0
- package/dist/reflect/client.js +100 -18
- package/dist/tests/unit/common/server.test.js +319 -0
- package/dist/tests/unit/insight-hub/client.test.js +114 -182
- package/dist/tests/unit/pactflow/ai.test.js +21 -0
- package/dist/tests/unit/pactflow/client.test.js +67 -0
- package/dist/tests/unit/pactflow/tools.test.js +34 -0
- package/package.json +3 -2
- package/dist/common/templates.js +0 -57
- package/dist/tests/unit/common/templates.test.js +0 -149
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
<br />
|
|
20
20
|
|
|
21
|
-
A Model Context Protocol (MCP) server which provides AI assistants with seamless access to SmartBear's suite of testing and monitoring tools, including [Insight Hub](https://www.smartbear.com/insight-hub), [Reflect](https://reflect.run),
|
|
21
|
+
A Model Context Protocol (MCP) server which provides AI assistants with seamless access to SmartBear's suite of testing and monitoring tools, including [Insight Hub](https://www.smartbear.com/insight-hub), [Reflect](https://reflect.run), [API Hub](https://www.smartbear.com/api-hub), [PactFlow](https://pactflow.io/) and [Pact Broker](https://docs.pact.io/)
|
|
22
22
|
|
|
23
23
|
## What is MCP?
|
|
24
24
|
|
|
@@ -31,6 +31,7 @@ See individual guides for suggested prompts and supported tools and resources:
|
|
|
31
31
|
- [Insight Hub](https://developer.smartbear.com/smartbear-mcp/docs/insight-hub-integration) - Comprehensive error monitoring and debugging capabilities
|
|
32
32
|
- [Test Hub](https://developer.smartbear.com/smartbear-mcp/docs/test-hub-integration) - Test management and execution capabilities
|
|
33
33
|
- [API Hub](https://developer.smartbear.com/smartbear-mcp/docs/api-hub-integration) - Portal management capabilities
|
|
34
|
+
- [PactFlow](https://developer.smartbear.com/pactflow/default/getting-started) - Contract testing capabilities
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
## Prerequisites
|
|
@@ -68,7 +69,11 @@ Alternatively, you can use `npx` (or globally install) the `@smartbear/mcp` pack
|
|
|
68
69
|
"INSIGHT_HUB_AUTH_TOKEN": "${input:insight_hub_auth_token}",
|
|
69
70
|
"INSIGHT_HUB_PROJECT_API_KEY": "${input:insight_hub_project_api_key}",
|
|
70
71
|
"REFLECT_API_TOKEN": "${input:reflect_api_token}",
|
|
71
|
-
"API_HUB_API_KEY": "${input:api_hub_api_key}"
|
|
72
|
+
"API_HUB_API_KEY": "${input:api_hub_api_key}",
|
|
73
|
+
"PACT_BROKER_BASE_URL": "${input:pact_broker_base_url}",
|
|
74
|
+
"PACT_BROKER_TOKEN": "${input:pact_broker_token}",
|
|
75
|
+
"PACT_BROKER_USERNAME": "${input:pact_broker_username}",
|
|
76
|
+
"PACT_BROKER_PASSWORD": "${input:pact_broker_password}"
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
},
|
|
@@ -96,7 +101,31 @@ Alternatively, you can use `npx` (or globally install) the `@smartbear/mcp` pack
|
|
|
96
101
|
"type": "promptString",
|
|
97
102
|
"description": "API Hub API Key - leave blank to disable API Hub tools",
|
|
98
103
|
"password": true
|
|
99
|
-
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "pact_broker_base_url",
|
|
107
|
+
"type": "promptString",
|
|
108
|
+
"description": "PactFlow or Pact Broker base url - leave blank to disable the tools",
|
|
109
|
+
"password": true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "pact_broker_token",
|
|
113
|
+
"type": "promptString",
|
|
114
|
+
"description": "PactFlow Authentication Token",
|
|
115
|
+
"password": true
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "pact_broker_username",
|
|
119
|
+
"type": "promptString",
|
|
120
|
+
"description": "Pact Broker Username",
|
|
121
|
+
"password": true
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "pact_broker_password",
|
|
125
|
+
"type": "promptString",
|
|
126
|
+
"description": "Pact Broker Password",
|
|
127
|
+
"password": true
|
|
128
|
+
},
|
|
100
129
|
]
|
|
101
130
|
}
|
|
102
131
|
```
|
|
@@ -119,7 +148,11 @@ Add the following configuration to your `claude_desktop_config.json` to launch t
|
|
|
119
148
|
"INSIGHT_HUB_AUTH_TOKEN": "your_personal_auth_token",
|
|
120
149
|
"INSIGHT_HUB_PROJECT_API_KEY": "your_project_api_key",
|
|
121
150
|
"REFLECT_API_TOKEN": "your_reflect_token",
|
|
122
|
-
"API_HUB_API_KEY": "your_api_hub_key"
|
|
151
|
+
"API_HUB_API_KEY": "your_api_hub_key",
|
|
152
|
+
"PACT_BROKER_BASE_URL": "your_pactflow_or_pactbroker_base_url",
|
|
153
|
+
"PACT_BROKER_TOKEN": "your_pactflow_token",
|
|
154
|
+
"PACT_BROKER_USERNAME": "your_pact_broker_username",
|
|
155
|
+
"PACT_BROKER_PASSWORD": "your_pact_broker_password",
|
|
123
156
|
}
|
|
124
157
|
}
|
|
125
158
|
}
|
|
@@ -172,7 +205,11 @@ For developers who want to contribute to the SmartBear MCP server, customize its
|
|
|
172
205
|
"INSIGHT_HUB_AUTH_TOKEN": "${input:insight_hub_auth_token}",
|
|
173
206
|
"INSIGHT_HUB_PROJECT_API_KEY": "${input:insight_hub_project_api_key}",
|
|
174
207
|
"REFLECT_API_TOKEN": "${input:reflect_api_token}",
|
|
175
|
-
"API_HUB_API_KEY": "${input:api_hub_api_key}"
|
|
208
|
+
"API_HUB_API_KEY": "${input:api_hub_api_key}",
|
|
209
|
+
"PACT_BROKER_BASE_URL": "${input:pact_broker_base_url}",
|
|
210
|
+
"PACT_BROKER_TOKEN": "${input:pact_broker_token}",
|
|
211
|
+
"PACT_BROKER_USERNAME": "${input:pact_broker_username}",
|
|
212
|
+
"PACT_BROKER_PASSWORD": "${input:pact_broker_password}"
|
|
176
213
|
}
|
|
177
214
|
}
|
|
178
215
|
},
|
|
@@ -200,7 +237,31 @@ For developers who want to contribute to the SmartBear MCP server, customize its
|
|
|
200
237
|
"type": "promptString",
|
|
201
238
|
"description": "API Hub API Key - leave blank to disable API Hub tools",
|
|
202
239
|
"password": true
|
|
203
|
-
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"id": "pact_broker_base_url",
|
|
243
|
+
"type": "promptString",
|
|
244
|
+
"description": "PactFlow or Pact Broker base url - leave blank to disable PactFlow tools",
|
|
245
|
+
"password": true
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"id": "pact_broker_token",
|
|
249
|
+
"type": "promptString",
|
|
250
|
+
"description": "PactFlow Authentication Token",
|
|
251
|
+
"password": true
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"id": "pact_broker_username",
|
|
255
|
+
"type": "promptString",
|
|
256
|
+
"description": "Pact Broker Username",
|
|
257
|
+
"password": true
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"id": "pact_broker_password",
|
|
261
|
+
"type": "promptString",
|
|
262
|
+
"description": "Pact Broker Password",
|
|
263
|
+
"password": true
|
|
264
|
+
},
|
|
204
265
|
]
|
|
205
266
|
}
|
|
206
267
|
```
|
|
@@ -209,7 +270,7 @@ For developers who want to contribute to the SmartBear MCP server, customize its
|
|
|
209
270
|
5. **Local testing** using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) web interface:
|
|
210
271
|
|
|
211
272
|
```bash
|
|
212
|
-
INSIGHT_HUB_AUTH_TOKEN="your_token" REFLECT_API_TOKEN="your_reflect_token" API_HUB_API_KEY="your_api_hub_key" npx @modelcontextprotocol/inspector npx @smartbear/mcp@latest
|
|
273
|
+
INSIGHT_HUB_AUTH_TOKEN="your_token" REFLECT_API_TOKEN="your_reflect_token" API_HUB_API_KEY="your_api_hub_key" PACT_BROKER_BASE_URL="your-pactflow-url" PACT_BROKER_TOKEN="your-pactflow-token" PACT_BROKER_USERNAME="your-pact-broker-username" PACT_BROKER_PASSWORD="your-pact-broker-password" npx @modelcontextprotocol/inspector npx @smartbear/mcp@latest
|
|
213
274
|
```
|
|
214
275
|
|
|
215
276
|
## License
|
package/dist/api-hub/client.js
CHANGED
|
@@ -3,6 +3,8 @@ import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../common/info.js";
|
|
|
3
3
|
// Tool definitions for API Hub API client
|
|
4
4
|
export class ApiHubClient {
|
|
5
5
|
headers;
|
|
6
|
+
name = "API Hub";
|
|
7
|
+
prefix = "api_hub";
|
|
6
8
|
constructor(token) {
|
|
7
9
|
this.headers = {
|
|
8
10
|
"Authorization": `Bearer ${token}`,
|
|
@@ -82,99 +84,343 @@ export class ApiHubClient {
|
|
|
82
84
|
});
|
|
83
85
|
return response.json();
|
|
84
86
|
}
|
|
85
|
-
registerTools(
|
|
86
|
-
|
|
87
|
+
registerTools(register, _getInput) {
|
|
88
|
+
register({
|
|
89
|
+
title: "List Portals",
|
|
90
|
+
summary: "Search for available portals within API Hub. Only portals where you have at least a designer role, either at the product level or organization level, are returned.",
|
|
91
|
+
parameters: [],
|
|
92
|
+
}, async (_args, _extra) => {
|
|
87
93
|
const response = await this.getPortals();
|
|
88
94
|
return {
|
|
89
95
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
90
96
|
};
|
|
91
97
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
register({
|
|
99
|
+
title: "Create Portal",
|
|
100
|
+
summary: "Create a new portal within API Hub.",
|
|
101
|
+
parameters: [
|
|
102
|
+
{
|
|
103
|
+
name: "name",
|
|
104
|
+
type: z.string(),
|
|
105
|
+
required: false,
|
|
106
|
+
description: "The portal name.",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "subdomain",
|
|
110
|
+
type: z.string(),
|
|
111
|
+
required: true,
|
|
112
|
+
description: "The portal subdomain.",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: "offline",
|
|
116
|
+
type: z.boolean(),
|
|
117
|
+
required: false,
|
|
118
|
+
description: "If set to true the portal will not be visible to customers.",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "routing",
|
|
122
|
+
type: z.string(),
|
|
123
|
+
required: false,
|
|
124
|
+
description: "Determines the routing strategy ('browser' or 'proxy').",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "credentialsEnabled",
|
|
128
|
+
type: z.string(),
|
|
129
|
+
required: false,
|
|
130
|
+
description: "Indicates if credentials are enabled for the portal.",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "swaggerHubOrganizationId",
|
|
134
|
+
type: z.string(),
|
|
135
|
+
required: true,
|
|
136
|
+
description: "The corresponding API Hub (formerly SwaggerHub) organization UUID.",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "openapiRenderer",
|
|
140
|
+
type: z.string(),
|
|
141
|
+
required: false,
|
|
142
|
+
description: "Portal level setting for the OpenAPI renderer. SWAGGER_UI - Use the Swagger UI renderer. ELEMENTS - Use the Elements renderer. TOGGLE - Switch between the two renderers with elements set as the default.",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "pageContentFormat",
|
|
146
|
+
type: z.string(),
|
|
147
|
+
required: false,
|
|
148
|
+
description: "The format of the page content.",
|
|
149
|
+
}
|
|
150
|
+
],
|
|
101
151
|
}, async (args, _extra) => {
|
|
102
|
-
const
|
|
152
|
+
const createPortalArgs = args;
|
|
153
|
+
const response = await this.createPortal(createPortalArgs);
|
|
103
154
|
return {
|
|
104
155
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
105
156
|
};
|
|
106
157
|
});
|
|
107
|
-
|
|
108
|
-
|
|
158
|
+
register({
|
|
159
|
+
title: "Get Portal",
|
|
160
|
+
summary: "Retrieve information about a specific portal.",
|
|
161
|
+
parameters: [
|
|
162
|
+
{
|
|
163
|
+
name: "portalId",
|
|
164
|
+
type: z.string(),
|
|
165
|
+
description: "Portal UUID or subdomain.",
|
|
166
|
+
required: true
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
}, async (args, _extra) => {
|
|
170
|
+
const portalArgs = args;
|
|
171
|
+
const response = await this.getPortal(portalArgs.portalId);
|
|
109
172
|
return {
|
|
110
173
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
111
174
|
};
|
|
112
175
|
});
|
|
113
|
-
|
|
114
|
-
|
|
176
|
+
register({
|
|
177
|
+
title: "Delete Portal",
|
|
178
|
+
summary: "Delete a specific portal.",
|
|
179
|
+
parameters: [
|
|
180
|
+
{
|
|
181
|
+
name: "portalId",
|
|
182
|
+
type: z.string(),
|
|
183
|
+
description: "Portal UUID or subdomain.",
|
|
184
|
+
required: true
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
}, async (args, _extra) => {
|
|
188
|
+
const portalArgs = args;
|
|
189
|
+
await this.deletePortal(portalArgs.portalId);
|
|
115
190
|
return {
|
|
116
191
|
content: [{ type: "text", text: "Portal deleted successfully." }],
|
|
117
192
|
};
|
|
118
193
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
194
|
+
register({
|
|
195
|
+
title: "Update Portal",
|
|
196
|
+
summary: "Update a specific portal's configuration.",
|
|
197
|
+
parameters: [
|
|
198
|
+
{
|
|
199
|
+
name: "portalId",
|
|
200
|
+
type: z.string(),
|
|
201
|
+
description: "Portal UUID or subdomain.",
|
|
202
|
+
required: true
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "name",
|
|
206
|
+
type: z.string(),
|
|
207
|
+
description: "The portal name.",
|
|
208
|
+
required: false
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "subdomain",
|
|
212
|
+
type: z.string(),
|
|
213
|
+
description: "The portal subdomain.",
|
|
214
|
+
required: false
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "customDomain",
|
|
218
|
+
type: z.boolean(),
|
|
219
|
+
description: "Indicates if the portal has a custom domain.",
|
|
220
|
+
required: false
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "gtmKey",
|
|
224
|
+
type: z.string(),
|
|
225
|
+
description: "Google Tag Manager key for the portal.",
|
|
226
|
+
required: false
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
name: "offline",
|
|
230
|
+
type: z.boolean(),
|
|
231
|
+
description: "If set to true the portal will not be visible to customers.",
|
|
232
|
+
required: false
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: "routing",
|
|
236
|
+
type: z.string(),
|
|
237
|
+
description: "Determines the routing strategy ('browser' or 'proxy').",
|
|
238
|
+
required: false
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "credentialsEnabled",
|
|
242
|
+
type: z.boolean(),
|
|
243
|
+
description: "Indicates if credentials are enabled for the portal.",
|
|
244
|
+
required: false
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "openapiRenderer",
|
|
248
|
+
type: z.string(),
|
|
249
|
+
description: "Portal level setting for the OpenAPI renderer. SWAGGER_UI - Use the Swagger UI renderer. ELEMENTS - Use the Elements renderer. TOGGLE - Switch between the two renderers with elements set as the default.",
|
|
250
|
+
required: false
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "pageContentFormat",
|
|
254
|
+
type: z.string(),
|
|
255
|
+
description: "The format of the page content.",
|
|
256
|
+
required: false
|
|
257
|
+
}
|
|
258
|
+
],
|
|
130
259
|
}, async (args, _extra) => {
|
|
131
|
-
const
|
|
260
|
+
const updatePortalArgs = args;
|
|
261
|
+
const response = await this.updatePortal(updatePortalArgs.portalId, updatePortalArgs);
|
|
132
262
|
return {
|
|
133
263
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
134
264
|
};
|
|
135
265
|
});
|
|
136
|
-
|
|
137
|
-
|
|
266
|
+
register({
|
|
267
|
+
title: "List Portal Products",
|
|
268
|
+
summary: "Get products for a specific portal that match your criteria.",
|
|
269
|
+
parameters: [
|
|
270
|
+
{
|
|
271
|
+
name: "portalId",
|
|
272
|
+
type: z.string(),
|
|
273
|
+
description: "Portal UUID or subdomain.",
|
|
274
|
+
required: true
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
}, async (args, _extra) => {
|
|
278
|
+
const portalArgs = args;
|
|
279
|
+
const response = await this.getPortalProducts(portalArgs.portalId);
|
|
138
280
|
return {
|
|
139
281
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
140
282
|
};
|
|
141
283
|
});
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
284
|
+
register({
|
|
285
|
+
title: "Create Portal Product",
|
|
286
|
+
summary: "Create a new product for a specific portal.",
|
|
287
|
+
parameters: [
|
|
288
|
+
{
|
|
289
|
+
name: "portalId",
|
|
290
|
+
type: z.string(),
|
|
291
|
+
description: "Portal UUID or subdomain.",
|
|
292
|
+
required: true
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "type",
|
|
296
|
+
type: z.string(),
|
|
297
|
+
description: "Product type (Allowed values: 'new', 'copy').",
|
|
298
|
+
required: true
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "name",
|
|
302
|
+
type: z.string(),
|
|
303
|
+
description: "Product name.",
|
|
304
|
+
required: true
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: "slug",
|
|
308
|
+
type: z.string(),
|
|
309
|
+
description: "URL component for this product. Must be unique within the portal.",
|
|
310
|
+
required: true
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: "description",
|
|
314
|
+
type: z.string(),
|
|
315
|
+
description: "Product description.",
|
|
316
|
+
required: false
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: "public",
|
|
320
|
+
type: z.boolean(),
|
|
321
|
+
description: "Indicates if the product is public.",
|
|
322
|
+
required: false
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: "hidden",
|
|
326
|
+
type: z.string(),
|
|
327
|
+
description: "Indicates if the product is hidden.",
|
|
328
|
+
required: false
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: "role",
|
|
332
|
+
type: z.boolean(),
|
|
333
|
+
description: "Indicates if the product has a role.",
|
|
334
|
+
required: false
|
|
335
|
+
}
|
|
336
|
+
],
|
|
151
337
|
}, async (args, _extra) => {
|
|
152
|
-
const
|
|
338
|
+
const createProductArgs = args;
|
|
339
|
+
const response = await this.createPortalProduct(createProductArgs.portalId, createProductArgs);
|
|
153
340
|
return {
|
|
154
341
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
155
342
|
};
|
|
156
343
|
});
|
|
157
|
-
|
|
158
|
-
|
|
344
|
+
register({
|
|
345
|
+
title: "Get Portal Product",
|
|
346
|
+
summary: "Retrieve information about a specific product resource.",
|
|
347
|
+
parameters: [
|
|
348
|
+
{
|
|
349
|
+
name: "productId",
|
|
350
|
+
type: z.string(),
|
|
351
|
+
description: "Product UUID, or identifier in the format.",
|
|
352
|
+
required: true
|
|
353
|
+
}
|
|
354
|
+
],
|
|
355
|
+
}, async (args, _extra) => {
|
|
356
|
+
const productArgs = args;
|
|
357
|
+
const response = await this.getPortalProduct(productArgs.productId);
|
|
159
358
|
return {
|
|
160
359
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
161
360
|
};
|
|
162
361
|
});
|
|
163
|
-
|
|
164
|
-
|
|
362
|
+
register({
|
|
363
|
+
title: "Delete Portal Product",
|
|
364
|
+
summary: "Delete a product from a specific portal",
|
|
365
|
+
parameters: [
|
|
366
|
+
{
|
|
367
|
+
name: "productId",
|
|
368
|
+
type: z.string(),
|
|
369
|
+
description: "Product UUID, or identifier in the format.",
|
|
370
|
+
required: true
|
|
371
|
+
}
|
|
372
|
+
],
|
|
373
|
+
}, async (args, _extra) => {
|
|
374
|
+
const productArgs = args;
|
|
375
|
+
await this.deletePortalProduct(productArgs.productId);
|
|
165
376
|
return {
|
|
166
377
|
content: [{ type: "text", text: "Product deleted successfully." }],
|
|
167
378
|
};
|
|
168
379
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
380
|
+
register({
|
|
381
|
+
title: "Update Portal Product",
|
|
382
|
+
summary: "Update a product's settings within a specific portal.",
|
|
383
|
+
parameters: [
|
|
384
|
+
{
|
|
385
|
+
name: "productId",
|
|
386
|
+
type: z.string(),
|
|
387
|
+
description: "Product UUID, or identifier in the format.",
|
|
388
|
+
required: true
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
name: "name",
|
|
392
|
+
type: z.string(),
|
|
393
|
+
description: "Product name.",
|
|
394
|
+
required: false
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
name: "slug",
|
|
398
|
+
type: z.string(),
|
|
399
|
+
description: "URL component for this product. Must be unique within the portal.",
|
|
400
|
+
required: false
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: "description",
|
|
404
|
+
type: z.string(),
|
|
405
|
+
description: "Product description.",
|
|
406
|
+
required: false
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
name: "public",
|
|
410
|
+
type: z.boolean(),
|
|
411
|
+
description: "Indicates if the product is public.",
|
|
412
|
+
required: false
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
name: "hidden",
|
|
416
|
+
type: z.string(),
|
|
417
|
+
description: "Indicates if the product is hidden.",
|
|
418
|
+
required: false
|
|
419
|
+
}
|
|
420
|
+
],
|
|
176
421
|
}, async (args, _extra) => {
|
|
177
|
-
const
|
|
422
|
+
const updateProductArgs = args;
|
|
423
|
+
const response = await this.updatePortalProduct(updateProductArgs.productId, updateProductArgs);
|
|
178
424
|
return {
|
|
179
425
|
content: [{ type: "text", text: JSON.stringify(response) }],
|
|
180
426
|
};
|