@smartbear/mcp 0.6.0 → 0.8.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.
Files changed (41) hide show
  1. package/README.md +37 -3
  2. package/dist/api-hub/client/api.js +387 -0
  3. package/dist/api-hub/client/configuration.js +27 -0
  4. package/dist/api-hub/client/index.js +5 -0
  5. package/dist/api-hub/client/portal-types.js +131 -0
  6. package/dist/api-hub/client/registry-types.js +69 -0
  7. package/dist/api-hub/client/tools.js +98 -0
  8. package/dist/api-hub/client.js +70 -404
  9. package/dist/bugsnag/client/api/CurrentUser.js +19 -13
  10. package/dist/bugsnag/client/api/Error.js +45 -57
  11. package/dist/bugsnag/client/api/Project.js +35 -30
  12. package/dist/bugsnag/client/api/base.js +24 -9
  13. package/dist/bugsnag/client/api/filters.js +9 -9
  14. package/dist/bugsnag/client.js +281 -373
  15. package/dist/common/info.js +1 -1
  16. package/dist/common/server.js +39 -28
  17. package/dist/index.js +18 -4
  18. package/dist/pactflow/client/ai.js +20 -20
  19. package/dist/pactflow/client/base.js +48 -13
  20. package/dist/pactflow/client/prompts.js +10 -12
  21. package/dist/pactflow/client/tools.js +18 -18
  22. package/dist/pactflow/client/utils.js +1 -1
  23. package/dist/pactflow/client.js +23 -15
  24. package/dist/qmetry/client/api/client-api.js +39 -0
  25. package/dist/qmetry/client/handlers.js +11 -0
  26. package/dist/qmetry/client/project.js +27 -0
  27. package/dist/qmetry/client/testcase.js +104 -0
  28. package/dist/qmetry/client/tools.js +222 -0
  29. package/dist/qmetry/client.js +95 -0
  30. package/dist/qmetry/config/constants.js +12 -0
  31. package/dist/qmetry/config/rest-endpoints.js +11 -0
  32. package/dist/qmetry/types/common.js +174 -0
  33. package/dist/qmetry/types/testcase.js +19 -0
  34. package/dist/reflect/client.js +14 -14
  35. package/dist/zephyr/client.js +16 -0
  36. package/dist/zephyr/common/api-client.js +27 -0
  37. package/dist/zephyr/common/auth-service.js +14 -0
  38. package/dist/zephyr/common/types.js +35 -0
  39. package/dist/zephyr/tool/project/get-projects.js +54 -0
  40. package/dist/zephyr/tool/zephyr-tool.js +1 -0
  41. package/package.json +8 -6
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ // Zod schemas for SwaggerHub Registry API validation
3
+ export const ApiSearchParamsSchema = z.object({
4
+ query: z
5
+ .string()
6
+ .optional()
7
+ .describe("Search query to filter APIs by name, description, or content"),
8
+ state: z
9
+ .enum(["ALL", "PUBLISHED", "UNPUBLISHED"])
10
+ .optional()
11
+ .describe("Filter APIs by publication state - ALL (default), PUBLISHED, or UNPUBLISHED"),
12
+ tag: z.string().optional().describe("Filter APIs by tag"),
13
+ offset: z
14
+ .number()
15
+ .min(0)
16
+ .optional()
17
+ .describe("Offset for pagination (0-based, default 0)"),
18
+ limit: z
19
+ .number()
20
+ .min(1)
21
+ .max(100)
22
+ .optional()
23
+ .describe("Number of results per page (1-100, default 20)"),
24
+ sort: z
25
+ .enum(["NAME", "UPDATED", "CREATED"])
26
+ .optional()
27
+ .describe("Sort field - NAME, UPDATED, or CREATED (default NAME)"),
28
+ order: z
29
+ .enum(["ASC", "DESC"])
30
+ .optional()
31
+ .describe("Sort order - ASC or DESC (default ASC)"),
32
+ owner: z
33
+ .string()
34
+ .optional()
35
+ .describe("Filter APIs by owner (organization or user)"),
36
+ specType: z
37
+ .enum(["API", "DOMAIN"])
38
+ .optional()
39
+ .describe("Filter by specification type - API or DOMAIN (default all types)"),
40
+ });
41
+ export const ApiDefinitionParamsSchema = z.object({
42
+ owner: z
43
+ .string()
44
+ .describe("API owner (organization or user, case-sensitive)"),
45
+ api: z.string().describe("API name (case-sensitive)"),
46
+ version: z.string().describe("Version identifier"),
47
+ resolved: z
48
+ .boolean()
49
+ .optional()
50
+ .describe("Set to true to get the resolved version with all external $refs included (default false)"),
51
+ flatten: z
52
+ .boolean()
53
+ .optional()
54
+ .describe("Set to true to create models from inline schemas in OpenAPI definition (default false)"),
55
+ });
56
+ export const CreateApiParamsSchema = z.object({
57
+ owner: z.string().describe("Organization name (owner of the API)"),
58
+ apiName: z.string().describe("API name"),
59
+ definition: z
60
+ .string()
61
+ .describe("API definition content (OpenAPI/AsyncAPI specification in JSON or YAML format). Format is automatically detected. API is created with fixed values: version 1.0.0, private visibility, automock disabled, and no project assignment."),
62
+ });
63
+ export const CreateApiFromTemplateParamsSchema = z.object({
64
+ owner: z.string().describe("Organization name (owner of the API)"),
65
+ apiName: z.string().describe("API name"),
66
+ template: z
67
+ .string()
68
+ .describe("Template name to use for creating the API. Format: owner/template-name/version (e.g., 'swagger-hub/petstore-template/1.0.0'). API is created with fixed values: private visibility, no project assignment, and reconciliation enabled."),
69
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * TOOLS
3
+ *
4
+ * Defines tool configurations for API Hub operations.
5
+ * Each tool includes parameters, descriptions, and handler method names.
6
+ * This follows the pattern established in the pactflow module.
7
+ */
8
+ import { CreatePortalArgsSchema, CreateProductArgsSchema, PortalArgsSchema, ProductArgsSchema, UpdatePortalArgsSchema, UpdateProductArgsSchema, } from "./portal-types.js";
9
+ import { ApiDefinitionParamsSchema, ApiSearchParamsSchema, CreateApiFromTemplateParamsSchema, CreateApiParamsSchema, } from "./registry-types.js";
10
+ export const TOOLS = [
11
+ {
12
+ title: "List Portals",
13
+ 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.",
14
+ parameters: [],
15
+ handler: "getPortals",
16
+ },
17
+ {
18
+ title: "Create Portal",
19
+ summary: "Create a new portal within API Hub.",
20
+ zodSchema: CreatePortalArgsSchema,
21
+ handler: "createPortal",
22
+ },
23
+ {
24
+ title: "Get Portal",
25
+ summary: "Retrieve information about a specific portal.",
26
+ zodSchema: PortalArgsSchema,
27
+ handler: "getPortal",
28
+ },
29
+ {
30
+ title: "Delete Portal",
31
+ summary: "Delete a specific portal.",
32
+ zodSchema: PortalArgsSchema,
33
+ handler: "deletePortal",
34
+ formatResponse: () => "Portal deleted successfully.",
35
+ },
36
+ {
37
+ title: "Update Portal",
38
+ summary: "Update a specific portal's configuration.",
39
+ zodSchema: UpdatePortalArgsSchema,
40
+ handler: "updatePortal",
41
+ },
42
+ {
43
+ title: "List Portal Products",
44
+ summary: "Get products for a specific portal that match your criteria.",
45
+ zodSchema: PortalArgsSchema,
46
+ handler: "getPortalProducts",
47
+ },
48
+ {
49
+ title: "Create Portal Product",
50
+ summary: "Create a new product for a specific portal.",
51
+ zodSchema: CreateProductArgsSchema,
52
+ handler: "createPortalProduct",
53
+ },
54
+ {
55
+ title: "Get Portal Product",
56
+ summary: "Retrieve information about a specific product resource.",
57
+ zodSchema: ProductArgsSchema,
58
+ handler: "getPortalProduct",
59
+ },
60
+ {
61
+ title: "Delete Portal Product",
62
+ summary: "Delete a product from a specific portal",
63
+ zodSchema: ProductArgsSchema,
64
+ handler: "deletePortalProduct",
65
+ formatResponse: () => "Product deleted successfully.",
66
+ },
67
+ {
68
+ title: "Update Portal Product",
69
+ summary: "Update a product's settings within a specific portal.",
70
+ zodSchema: UpdateProductArgsSchema,
71
+ handler: "updatePortalProduct",
72
+ },
73
+ // Registry API tools for SwaggerHub Design functionality
74
+ {
75
+ title: "Search APIs and Domains",
76
+ summary: "Search for APIs and Domains in SwaggerHub Registry using the comprehensive /specs endpoint and retrieve metadata including owner, name, description, summary, version, and specification.",
77
+ zodSchema: ApiSearchParamsSchema,
78
+ handler: "searchApis",
79
+ },
80
+ {
81
+ title: "Get API Definition",
82
+ summary: "Fetch resolved API definition from SwaggerHub Registry based on owner, API name, and version.",
83
+ zodSchema: ApiDefinitionParamsSchema,
84
+ handler: "getApiDefinition",
85
+ },
86
+ {
87
+ title: "Create or Update API",
88
+ summary: "Create a new API or update an existing API in SwaggerHub Registry for API Hub for Design. The API specification type (OpenAPI, AsyncAPI) is automatically detected from the definition content. APIs are always created with fixed values: version 1.0.0, private visibility, and automock disabled (these values cannot be changed). Returns HTTP 201 for creation, HTTP 200 for update. Response includes 'operation' field indicating whether it was a 'create' or 'update' operation along with API details and SwaggerHub URL.",
89
+ zodSchema: CreateApiParamsSchema,
90
+ handler: "createOrUpdateApi",
91
+ },
92
+ {
93
+ title: "Create API from Template",
94
+ summary: "Create a new API in SwaggerHub Registry using a predefined template. This endpoint creates APIs based on existing templates without requiring manual definition content. APIs are always created with fixed values: private visibility, no project assignment, and reconciliation enabled (these values cannot be changed). Returns HTTP 201 for creation, HTTP 200 for update. Response includes 'operation' field and API details with SwaggerHub URL.",
95
+ zodSchema: CreateApiFromTemplateParamsSchema,
96
+ handler: "createApiFromTemplate",
97
+ },
98
+ ];
@@ -1,429 +1,95 @@
1
- import { z } from "zod";
2
1
  import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../common/info.js";
2
+ import { ApiHubAPI, ApiHubConfiguration, TOOLS, } from "./client/index.js";
3
3
  // Tool definitions for API Hub API client
4
4
  export class ApiHubClient {
5
- headers;
5
+ config;
6
+ api;
6
7
  name = "API Hub";
7
8
  prefix = "api_hub";
8
9
  constructor(token) {
9
- this.headers = {
10
- "Authorization": `Bearer ${token}`,
11
- "Content-Type": "application/json",
12
- "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`,
13
- };
10
+ this.config = new ApiHubConfiguration({ token });
11
+ this.api = new ApiHubAPI(this.config, `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`);
14
12
  }
13
+ // Delegate API methods to the ApiHubAPI instance
15
14
  async getPortals() {
16
- const response = await fetch("https://api.portal.swaggerhub.com/v1/portals", {
17
- method: "GET",
18
- headers: this.headers,
19
- });
20
- return response.json();
15
+ return this.api.getPortals();
21
16
  }
22
17
  async createPortal(body) {
23
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/portals`, {
24
- method: "POST",
25
- headers: this.headers,
26
- body: JSON.stringify(body),
27
- });
28
- return response.json();
18
+ return this.api.createPortal(body);
29
19
  }
30
- async getPortal(portalId) {
31
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/portals/${portalId}`, {
32
- method: "GET",
33
- headers: this.headers,
34
- });
35
- return response.json();
20
+ async getPortal(args) {
21
+ return this.api.getPortal(args.portalId);
36
22
  }
37
- async deletePortal(portalId) {
38
- await fetch(`https://api.portal.swaggerhub.com/v1/portals/${portalId}`, {
39
- method: "DELETE",
40
- headers: this.headers,
41
- });
23
+ async deletePortal(args) {
24
+ return this.api.deletePortal(args.portalId);
42
25
  }
43
- async updatePortal(portalId, body) {
44
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/portals/${portalId}`, {
45
- method: "PATCH",
46
- headers: this.headers,
47
- body: JSON.stringify(body),
48
- });
49
- return response.json();
26
+ async updatePortal(args) {
27
+ const { portalId, ...body } = args;
28
+ return this.api.updatePortal(portalId, body);
50
29
  }
51
- async getPortalProducts(portalId) {
52
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/portals/${portalId}/products`, {
53
- method: "GET",
54
- headers: this.headers,
55
- });
56
- return response.json();
30
+ async getPortalProducts(args) {
31
+ return this.api.getPortalProducts(args.portalId);
57
32
  }
58
- async createPortalProduct(portalId, body) {
59
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/portals/${portalId}/products`, {
60
- method: "POST",
61
- headers: this.headers,
62
- body: JSON.stringify(body),
63
- });
64
- return response.json();
33
+ async createPortalProduct(args) {
34
+ const { portalId, ...body } = args;
35
+ return this.api.createPortalProduct(portalId, body);
65
36
  }
66
- async getPortalProduct(productId) {
67
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/products/${productId}`, {
68
- method: "GET",
69
- headers: this.headers,
70
- });
71
- return response.json();
37
+ async getPortalProduct(args) {
38
+ return this.api.getPortalProduct(args.productId);
72
39
  }
73
- async deletePortalProduct(productId) {
74
- await fetch(`https://api.portal.swaggerhub.com/v1/products/${productId}`, {
75
- method: "DELETE",
76
- headers: this.headers,
77
- });
40
+ async deletePortalProduct(args) {
41
+ return this.api.deletePortalProduct(args.productId);
78
42
  }
79
- async updatePortalProduct(productId, body) {
80
- const response = await fetch(`https://api.portal.swaggerhub.com/v1/products/${productId}`, {
81
- method: "PATCH",
82
- headers: this.headers,
83
- body: JSON.stringify(body),
84
- });
85
- return response.json();
43
+ async updatePortalProduct(args) {
44
+ const { productId, ...body } = args;
45
+ return this.api.updatePortalProduct(productId, body);
46
+ }
47
+ // Registry API methods for SwaggerHub Design functionality
48
+ async searchApis(args = {}) {
49
+ return this.api.searchApis(args);
50
+ }
51
+ async getApiDefinition(args) {
52
+ return this.api.getApiDefinition(args);
53
+ }
54
+ async createOrUpdateApi(args) {
55
+ return this.api.createOrUpdateApi(args);
56
+ }
57
+ async createApiFromTemplate(args) {
58
+ return this.api.createApiFromTemplate(args);
86
59
  }
87
60
  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) => {
93
- const response = await this.getPortals();
94
- return {
95
- content: [{ type: "text", text: JSON.stringify(response) }],
96
- };
97
- });
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.",
61
+ TOOLS.forEach((tool) => {
62
+ const { handler, formatResponse, ...toolParams } = tool;
63
+ register(toolParams, async (args, _extra) => {
64
+ try {
65
+ // Dynamic method invocation
66
+ const handlerFn = this[handler];
67
+ if (typeof handlerFn !== "function") {
68
+ throw new Error(`Handler '${handler}' not found on ApiHubClient`);
69
+ }
70
+ const result = await handlerFn.call(this, args);
71
+ // Use custom formatter if available, otherwise return JSON
72
+ const formattedResult = formatResponse
73
+ ? formatResponse(result)
74
+ : result;
75
+ const responseText = typeof formattedResult === "string"
76
+ ? formattedResult
77
+ : JSON.stringify(formattedResult);
78
+ return {
79
+ content: [{ type: "text", text: responseText }],
80
+ };
149
81
  }
150
- ],
151
- }, async (args, _extra) => {
152
- const createPortalArgs = args;
153
- const response = await this.createPortal(createPortalArgs);
154
- return {
155
- content: [{ type: "text", text: JSON.stringify(response) }],
156
- };
157
- });
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);
172
- return {
173
- content: [{ type: "text", text: JSON.stringify(response) }],
174
- };
175
- });
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);
190
- return {
191
- content: [{ type: "text", text: "Portal deleted successfully." }],
192
- };
193
- });
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
- ],
259
- }, async (args, _extra) => {
260
- const updatePortalArgs = args;
261
- const response = await this.updatePortal(updatePortalArgs.portalId, updatePortalArgs);
262
- return {
263
- content: [{ type: "text", text: JSON.stringify(response) }],
264
- };
265
- });
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);
280
- return {
281
- content: [{ type: "text", text: JSON.stringify(response) }],
282
- };
283
- });
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
- ],
337
- }, async (args, _extra) => {
338
- const createProductArgs = args;
339
- const response = await this.createPortalProduct(createProductArgs.portalId, createProductArgs);
340
- return {
341
- content: [{ type: "text", text: JSON.stringify(response) }],
342
- };
343
- });
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);
358
- return {
359
- content: [{ type: "text", text: JSON.stringify(response) }],
360
- };
361
- });
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);
376
- return {
377
- content: [{ type: "text", text: "Product deleted successfully." }],
378
- };
379
- });
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
82
+ catch (error) {
83
+ return {
84
+ content: [
85
+ {
86
+ type: "text",
87
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
88
+ },
89
+ ],
90
+ };
419
91
  }
420
- ],
421
- }, async (args, _extra) => {
422
- const updateProductArgs = args;
423
- const response = await this.updatePortalProduct(updateProductArgs.productId, updateProductArgs);
424
- return {
425
- content: [{ type: "text", text: JSON.stringify(response) }],
426
- };
92
+ });
427
93
  });
428
94
  }
429
95
  }